View | Details | Raw Unified | Return to bug 276570
Collapse All | Expand All

(-)b/lib/libutil/login.conf.5 (-6 / +21 lines)
Lines 181-189 are considered infinite values. Link Here
181
The usual convention to interpolate capability entries using the special
181
The usual convention to interpolate capability entries using the special
182
.Em tc=value
182
.Em tc=value
183
notation may be used.
183
notation may be used.
184
.Pp
185
Default values are specified under the
186
.Ql Default
187
column.
188
An absence of value there means that, unless otherwise indicated, the context
189
related to the capability is left unchanged and thus inherited from the process
190
setting up the login environment.
184
.Sh RESOURCE LIMITS
191
.Sh RESOURCE LIMITS
185
.Bl -column pseudoterminals indent indent
192
.Bl -column pseudoterminals indent indent
186
.It Sy "Name	Type	Notes	Description"
193
.It Sy "Name	Type	Default	Description"
187
.It "coredumpsize	size		Maximum coredump size limit."
194
.It "coredumpsize	size		Maximum coredump size limit."
188
.It "cputime	time		CPU usage limit."
195
.It "cputime	time		CPU usage limit."
189
.It "datasize	size		Maximum data size limit."
196
.It "datasize	size		Maximum data size limit."
Lines 209-215 The maximum and current limits may be specified individually by appending a Link Here
209
-max or -cur to the capability name.
216
-max or -cur to the capability name.
210
.Sh ENVIRONMENT
217
.Sh ENVIRONMENT
211
.Bl -column ignorenologin indent xbinxxusrxbin
218
.Bl -column ignorenologin indent xbinxxusrxbin
212
.It Sy "Name	Type	Notes	Description"
219
.It Sy "Name	Type	Default	Description"
213
.It "charset	string		Set $MM_CHARSET environment variable to the specified"
220
.It "charset	string		Set $MM_CHARSET environment variable to the specified"
214
value.
221
value.
215
.It "cpumask	string		List of cpus to bind the user to."
222
.It "cpumask	string		List of cpus to bind the user to."
Lines 241-247 for details. Link Here
241
.It "nologin	file		If the file exists it will be displayed and"
248
.It "nologin	file		If the file exists it will be displayed and"
242
the login session will be terminated.
249
the login session will be terminated.
243
.It "path	path	/bin /usr/bin	Default search path."
250
.It "path	path	/bin /usr/bin	Default search path."
244
.It "priority	number		Initial priority (nice) level."
251
.It "priority	number	0	Initial priority level."
252
A value in the nice range (-20 to 20 included) extended below with the 32
253
real-time class priorities and above with the 32 idle class priorities.
254
Special value
255
.Ql inherit
256
prevents resetting the priority.
245
.It "requirehome 	bool	false	Require a valid home directory to login."
257
.It "requirehome 	bool	false	Require a valid home directory to login."
246
.It "setenv	list		A comma-separated list of environment variables and"
258
.It "setenv	list		A comma-separated list of environment variables and"
247
values to which they are to be set.
259
values to which they are to be set.
Lines 253-265 contain the shell specified in the password file. Link Here
253
.It "term	string		Default terminal type if not able to determine"
265
.It "term	string		Default terminal type if not able to determine"
254
from other means.
266
from other means.
255
.It "timezone	string		Default value of $TZ environment variable."
267
.It "timezone	string		Default value of $TZ environment variable."
256
.It "umask	number	022	Initial umask. Should always have a leading 0 to"
268
.It "umask	number		Initial umask. Should always have a leading 0 to"
257
ensure octal interpretation.
269
ensure octal interpretation.
270
Special value
271
.Ql inherit
272
explicitly indicates not to change the umask.
258
.It "welcome	file	/etc/motd	File containing welcome message."
273
.It "welcome	file	/etc/motd	File containing welcome message."
259
.El
274
.El
260
.Sh AUTHENTICATION
275
.Sh AUTHENTICATION
261
.Bl -column passwd_prompt indent indent
276
.Bl -column passwd_prompt indent indent
262
.It Sy "Name	Type	Notes	Description"
277
.It Sy "Name	Type	Default	Description"
263
.\" .It "approve	program 	Program to approve login.
278
.\" .It "approve	program 	Program to approve login.
264
.It "copyright	file		File containing additional copyright information"
279
.It "copyright	file		File containing additional copyright information"
265
.It "host.allow	list		List of remote host wildcards from which users in"
280
.It "host.allow	list		List of remote host wildcards from which users in"
Lines 403-409 The following capabilities are reserved for the purposes indicated and Link Here
403
may be supported by third-party software.
418
may be supported by third-party software.
404
They are not implemented in the base system.
419
They are not implemented in the base system.
405
.Bl -column host.accounted indent indent
420
.Bl -column host.accounted indent indent
406
.It Sy "Name	Type	Notes	Description"
421
.It Sy "Name	Type	Default	Description"
407
.It "accounted	bool	false	Enable session time accounting for all users"
422
.It "accounted	bool	false	Enable session time accounting for all users"
408
in this class.
423
in this class.
409
.It "auth	list	passwd	Allowed authentication styles."
424
.It "auth	list	passwd	Allowed authentication styles."
(-)b/lib/libutil/login_cap.3 (+28 lines)
Lines 25-30 Link Here
25
.Nm login_getcapbool ,
25
.Nm login_getcapbool ,
26
.Nm login_getcaplist ,
26
.Nm login_getcaplist ,
27
.Nm login_getcapnum ,
27
.Nm login_getcapnum ,
28
.Nm login_getcapenum ,
28
.Nm login_getcapstr ,
29
.Nm login_getcapstr ,
29
.Nm login_getcapsize ,
30
.Nm login_getcapsize ,
30
.Nm login_getcaptime ,
31
.Nm login_getcaptime ,
Lines 60-65 Link Here
60
.Fn login_getcaptime "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
61
.Fn login_getcaptime "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
61
.Ft rlim_t
62
.Ft rlim_t
62
.Fn login_getcapnum "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
63
.Fn login_getcapnum "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
64
.Ft int
65
.Fn login_getcapenum "login_cap_t *lc" "const char *cap" "const char * const *values"
63
.Ft rlim_t
66
.Ft rlim_t
64
.Fn login_getcapsize "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
67
.Fn login_getcapsize "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
65
.Ft int
68
.Ft int
Lines 459-464 If the given capability tag cannot be found, the Link Here
459
parameter is returned, and if an error occurs, the
462
parameter is returned, and if an error occurs, the
460
.Fa error
463
.Fa error
461
parameter is returned.
464
parameter is returned.
465
.It Fn login_getcapenum
466
This function returns whether the searched capability is a string with value
467
among a predefined set passed in argument
468
.Fa values
469
as a NULL-terminated array of strings.
470
.Pp
471
A non-negative value indicates a match and is the index of the capability's
472
value in array
473
.Fa values .
474
Other possible return values are:
475
.Bl -tag -width "-4"
476
.It -4
477
Returned if
478
.Fa lc
479
or
480
.Fa cap
481
are insufficiently initialized or invalid.
482
.It -3
483
Returned on allocation failure (out of memory).
484
.It -2
485
Returned if the capability isn't specified or its value is not a string.
486
.It -1
487
Returned if the capability is specified and a string but its value is not among
488
.Fa values .
489
.El
462
.It Fn login_getcapsize
490
.It Fn login_getcapsize
463
.Fn login_getcapsize
491
.Fn login_getcapsize
464
returns a value representing a size (typically, file or memory)
492
returns a value representing a size (typically, file or memory)
(-)b/lib/libutil/login_cap.c (+46 lines)
Lines 760-765 login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) Link Here
760
    return val;
760
    return val;
761
}
761
}
762
762
763
/*
764
 * Extract a string capability expected to hold a specific value from a list.
765
 *
766
 * 'values' must be a NULL-terminated array of strings listing the possible
767
 * values.
768
 *
769
 * A non-negative return code indicates success, and is the index of the value
770
 * in 'values' the capability is set to.
771
 *
772
 * Negative return codes indicate an error:
773
 * -4: 'lc' or 'cap' insufficiently initialized or not valid.
774
 * -3: System error (allocation failure).
775
 * -2: Capability not found or not a string.
776
 * -1: Capability has a string value, but not one listed in 'values'.
777
 */
778
int
779
login_getcapenum(login_cap_t *lc, const char *cap, const char * const *values)
780
{
781
    int ret, i;
782
    char *cand;
783
    const char * const *val;
784
785
    if (lc == NULL || lc->lc_cap == NULL || cap == NULL || *cap == '\0')
786
	return (-4);
787
788
    ret = cgetstr(lc->lc_cap, cap, &cand);
789
790
    if (ret == -1)
791
	/* Cap not found. */
792
	return (-2);
793
    else if (ret < 0)
794
	/* System error (normally, allocation failure). */
795
	return (-3);
796
797
    ret = -1;
798
799
    for (i = 0, val = values; *val != NULL; val++)
800
	if (strcmp(cand, *val) == 0) {
801
	    ret = i;
802
	    break;
803
	}
804
805
    free(cand);
806
    return (ret);
807
}
808
763
809
764
810
765
/*
811
/*
(-)b/lib/libutil/login_cap.h (-2 / +2 lines)
Lines 32-39 Link Here
32
#define LOGIN_MECLASS		"me"
32
#define LOGIN_MECLASS		"me"
33
#define LOGIN_DEFSTYLE		"passwd"
33
#define LOGIN_DEFSTYLE		"passwd"
34
#define LOGIN_DEFSERVICE	"login"
34
#define LOGIN_DEFSERVICE	"login"
35
#define LOGIN_DEFUMASK		022
36
#define LOGIN_DEFPRI		0
37
#define _PATH_LOGIN_CONF	"/etc/login.conf"
35
#define _PATH_LOGIN_CONF	"/etc/login.conf"
38
#define _FILE_LOGIN_CONF	".login_conf"
36
#define _FILE_LOGIN_CONF	".login_conf"
39
#define _PATH_AUTHPROG		"/usr/libexec/login_"
37
#define _PATH_AUTHPROG		"/usr/libexec/login_"
Lines 110-115 const char **login_getcaplist(login_cap_t *, const char *, const char *); Link Here
110
const char *login_getstyle(login_cap_t *, const char *, const char *);
108
const char *login_getstyle(login_cap_t *, const char *, const char *);
111
rlim_t login_getcaptime(login_cap_t *, const char *, rlim_t, rlim_t);
109
rlim_t login_getcaptime(login_cap_t *, const char *, rlim_t, rlim_t);
112
rlim_t login_getcapnum(login_cap_t *, const char *, rlim_t, rlim_t);
110
rlim_t login_getcapnum(login_cap_t *, const char *, rlim_t, rlim_t);
111
int login_getcapenum(login_cap_t *lc, const char *cap,
112
    const char * const *values);
113
rlim_t login_getcapsize(login_cap_t *, const char *, rlim_t, rlim_t);
113
rlim_t login_getcapsize(login_cap_t *, const char *, rlim_t, rlim_t);
114
const char *login_getpath(login_cap_t *, const char *, const char *);
114
const char *login_getpath(login_cap_t *, const char *, const char *);
115
int login_getcapbool(login_cap_t *, const char *, int);
115
int login_getcapbool(login_cap_t *, const char *, int);
(-)b/lib/libutil/login_class.c (-57 / +129 lines)
Lines 37-42 Link Here
37
#include <login_cap.h>
37
#include <login_cap.h>
38
#include <paths.h>
38
#include <paths.h>
39
#include <pwd.h>
39
#include <pwd.h>
40
#include <stdint.h>
40
#include <stdio.h>
41
#include <stdio.h>
41
#include <stdlib.h>
42
#include <stdlib.h>
42
#include <string.h>
43
#include <string.h>
Lines 379-414 setclasscontext(const char *classname, unsigned int flags) Link Here
379
}
380
}
380
381
381
382
383
static const char * const inherit_enum[] = {
384
    "inherit",
385
    NULL
386
};
387
388
/*
389
 * Private function setting umask from the login class.
390
 */
391
static void
392
setclassumask(login_cap_t *lc, const struct passwd *pwd)
393
{
394
	/*
395
	 * Make it unlikely that someone would input our default sentinel
396
	 * indicating no specification.
397
	 */
398
	const rlim_t def_val = INT64_MIN + 1, err_val = INT64_MIN;
399
	rlim_t val;
400
401
	if (login_getcapenum(lc, "umask", inherit_enum) == 0)
402
		/* Found "inherit". */
403
		return;
404
405
	val = login_getcapnum(lc, "umask", def_val, err_val);
406
407
	if (val != def_val) {
408
		if (val < 0 || val > UINT16_MAX) {
409
			/* We get here also on 'err_val'. */
410
			syslog(LOG_WARNING,
411
			    "%s%s%sLogin class '%s': "
412
			    "Invalid umask specification: '%s'",
413
			    pwd ? "Login '" : "",
414
			    pwd ? pwd->pw_name : "",
415
			    pwd ? "': " : "",
416
			    lc->lc_class,
417
			    login_getcapstr(lc, "umask", "", ""));
418
		} else {
419
			const mode_t mode = val;
420
421
			umask(mode);
422
		}
423
	}
424
}
382
425
383
/*
426
/*
384
 * Private function which takes care of processing
427
 * Private function which takes care of processing
385
 */
428
 */
386
429
387
static mode_t
430
static void
388
setlogincontext(login_cap_t *lc, const struct passwd *pwd,
431
setlogincontext(login_cap_t *lc, const struct passwd *pwd, unsigned long flags)
389
		mode_t mymask, unsigned long flags)
390
{
432
{
391
    if (lc) {
433
	if (lc == NULL)
392
	/* Set resources */
434
		return;
393
	if (flags & LOGIN_SETRESOURCES)
435
394
	    setclassresources(lc);
436
	/* Set resources. */
395
	/* See if there's a umask override */
437
	if ((flags & LOGIN_SETRESOURCES) != 0)
396
	if (flags & LOGIN_SETUMASK)
438
		setclassresources(lc);
397
	    mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask);
439
398
	/* Set paths */
440
	/* See if there's a umask override. */
399
	if (flags & LOGIN_SETPATH)
441
	if ((flags & LOGIN_SETUMASK) != 0)
400
	    setclassenvironment(lc, pwd, 1);
442
		setclassumask(lc, pwd);
401
	/* Set environment */
443
402
	if (flags & LOGIN_SETENV)
444
	/* Set paths. */
403
	    setclassenvironment(lc, pwd, 0);
445
	if ((flags & LOGIN_SETPATH) != 0)
404
	/* Set cpu affinity */
446
		setclassenvironment(lc, pwd, 1);
405
	if (flags & LOGIN_SETCPUMASK)
447
406
	    setclasscpumask(lc);
448
	/* Set environment. */
407
    }
449
	if ((flags & LOGIN_SETENV) != 0)
408
    return (mymask);
450
		setclassenvironment(lc, pwd, 0);
451
452
	/* Set cpu affinity. */
453
	if ((flags & LOGIN_SETCPUMASK) != 0)
454
		setclasscpumask(lc);
409
}
455
}
410
456
411
457
458
/*
459
 * Private function to set process priority.
460
 */
461
static void
462
setclasspriority(login_cap_t * const lc, struct passwd const * const pwd)
463
{
464
	const rlim_t def_val = 0, err_val = INT64_MIN;
465
	rlim_t p;
466
	int rc;
467
468
	if (login_getcapenum(lc, "priority", inherit_enum) == 0)
469
		/* Found "inherit". */
470
		return;
471
472
	p = login_getcapnum(lc, "priority", def_val, err_val);
473
474
	if (p == err_val) {
475
		/* Invariant: 'lc' != NULL. */
476
		syslog(LOG_WARNING,
477
		    "%s%s%sLogin class '%s': "
478
		    "Invalid priority specification: '%s'",
479
		    pwd ? "Login '" : "",
480
		    pwd ? pwd->pw_name : "",
481
		    pwd ? "': " : "",
482
		    lc->lc_class,
483
		    login_getcapstr(lc, "priority", "", ""));
484
		/* Reset the priority, as if the capability was not present. */
485
		p = def_val;
486
	}
487
488
	if (p > PRIO_MAX) {
489
		struct rtprio rtp;
490
491
		rtp.type = RTP_PRIO_IDLE;
492
		p += RTP_PRIO_MIN - (PRIO_MAX + 1);
493
		rtp.prio = p > RTP_PRIO_MAX ? RTP_PRIO_MAX : p;
494
		rc = rtprio(RTP_SET, 0, &rtp);
495
	} else if (p < PRIO_MIN) {
496
		struct rtprio rtp;
497
498
		rtp.type = RTP_PRIO_REALTIME;
499
		p += RTP_PRIO_MAX - (PRIO_MIN - 1);
500
		rtp.prio = p < RTP_PRIO_MIN ? RTP_PRIO_MIN : p;
501
		rc = rtprio(RTP_SET, 0, &rtp);
502
	} else
503
		rc = setpriority(PRIO_PROCESS, 0, (int)p);
504
505
	if (rc != 0)
506
		syslog(LOG_WARNING,
507
		    "%s%s%sLogin class '%s': "
508
		    "Setting priority failed: %m",
509
		    pwd ? "Login '" : "",
510
		    pwd ? pwd->pw_name : "",
511
		    pwd ? "': " : "",
512
		    lc ? lc->lc_class : "<none>");
513
}
412
514
413
/*
515
/*
414
 * setusercontext()
516
 * setusercontext()
Lines 427-436 setlogincontext(login_cap_t *lc, const struct passwd *pwd, Link Here
427
int
529
int
428
setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags)
530
setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags)
429
{
531
{
430
    rlim_t	p;
431
    mode_t	mymask;
432
    login_cap_t *llc = NULL;
532
    login_cap_t *llc = NULL;
433
    struct rtprio rtp;
434
    int error;
533
    int error;
435
534
436
    if (lc == NULL) {
535
    if (lc == NULL) {
Lines 446-477 setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in Link Here
446
	flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN | LOGIN_SETMAC);
545
	flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN | LOGIN_SETMAC);
447
546
448
    /* Set the process priority */
547
    /* Set the process priority */
449
    if (flags & LOGIN_SETPRIORITY) {
548
    if (flags & LOGIN_SETPRIORITY)
450
	p = login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI);
549
	setclasspriority(lc, pwd);
451
452
	if (p > PRIO_MAX) {
453
	    rtp.type = RTP_PRIO_IDLE;
454
	    p += RTP_PRIO_MIN - (PRIO_MAX + 1);
455
	    rtp.prio = p > RTP_PRIO_MAX ? RTP_PRIO_MAX : p;
456
	    if (rtprio(RTP_SET, 0, &rtp))
457
		syslog(LOG_WARNING, "rtprio '%s' (%s): %m",
458
		    pwd ? pwd->pw_name : "-",
459
		    lc ? lc->lc_class : LOGIN_DEFCLASS);
460
	} else if (p < PRIO_MIN) {
461
	    rtp.type = RTP_PRIO_REALTIME;
462
	    p += RTP_PRIO_MAX - (PRIO_MIN - 1);
463
	    rtp.prio = p < RTP_PRIO_MIN ? RTP_PRIO_MIN : p;
464
	    if (rtprio(RTP_SET, 0, &rtp))
465
		syslog(LOG_WARNING, "rtprio '%s' (%s): %m",
466
		    pwd ? pwd->pw_name : "-",
467
		    lc ? lc->lc_class : LOGIN_DEFCLASS);
468
	} else {
469
	    if (setpriority(PRIO_PROCESS, 0, (int)p) != 0)
470
		syslog(LOG_WARNING, "setpriority '%s' (%s): %m",
471
		    pwd ? pwd->pw_name : "-",
472
		    lc ? lc->lc_class : LOGIN_DEFCLASS);
473
	}
474
    }
475
550
476
    /* Setup the user's group permissions */
551
    /* Setup the user's group permissions */
477
    if (flags & LOGIN_SETGROUP) {
552
    if (flags & LOGIN_SETGROUP) {
Lines 532-539 setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in Link Here
532
	}
607
	}
533
    }
608
    }
534
609
535
    mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
610
    setlogincontext(lc, pwd, flags);
536
    mymask = setlogincontext(lc, pwd, mymask, flags);
537
    login_close(llc);
611
    login_close(llc);
538
612
539
    /* This needs to be done after anything that needs root privs */
613
    /* This needs to be done after anything that needs root privs */
Lines 546-558 setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in Link Here
546
     * Now, we repeat some of the above for the user's private entries
620
     * Now, we repeat some of the above for the user's private entries
547
     */
621
     */
548
    if (geteuid() == uid && (lc = login_getuserclass(pwd)) != NULL) {
622
    if (geteuid() == uid && (lc = login_getuserclass(pwd)) != NULL) {
549
	mymask = setlogincontext(lc, pwd, mymask, flags);
623
	setlogincontext(lc, pwd, flags);
624
	if (flags & LOGIN_SETPRIORITY)
625
	    setclasspriority(lc, pwd);
550
	login_close(lc);
626
	login_close(lc);
551
    }
627
    }
552
628
553
    /* Finally, set any umask we've found */
554
    if (flags & LOGIN_SETUMASK)
555
	umask(mymask);
556
557
    return (0);
629
    return (0);
558
}
630
}

Return to bug 276570