login_class.c revision 184081
121288Sdavidn/*- 221288Sdavidn * Copyright (c) 1996 by 321288Sdavidn * Sean Eric Fagan <sef@kithrup.com> 421288Sdavidn * David Nugent <davidn@blaze.net.au> 521288Sdavidn * All rights reserved. 621288Sdavidn * 721288Sdavidn * Redistribution and use in source and binary forms, with or without 821288Sdavidn * modification, is permitted provided that the following conditions 921288Sdavidn * are met: 1021288Sdavidn * 1. Redistributions of source code must retain the above copyright 1121288Sdavidn * notice immediately at the beginning of the file, without modification, 1221288Sdavidn * this list of conditions, and the following disclaimer. 1321288Sdavidn * 2. Redistributions in binary form must reproduce the above copyright 1421288Sdavidn * notice, this list of conditions and the following disclaimer in the 1521288Sdavidn * documentation and/or other materials provided with the distribution. 1621288Sdavidn * 3. This work was done expressly for inclusion into FreeBSD. Other use 1721288Sdavidn * is permitted provided this notation is included. 1821288Sdavidn * 4. Absolutely no warranty of function or purpose is made by the authors. 1921288Sdavidn * 5. Modifications may be freely made to this file providing the above 2021288Sdavidn * conditions are met. 2121288Sdavidn * 2221288Sdavidn * High-level routines relating to use of the user capabilities database 2321288Sdavidn */ 2421288Sdavidn 2584225Sdillon#include <sys/cdefs.h> 2684225Sdillon__FBSDID("$FreeBSD: head/lib/libutil/login_class.c 184081 2008-10-20 16:48:18Z des $"); 2784225Sdillon 28180815Sbrooks#include <sys/param.h> 29180815Sbrooks#include <sys/cpuset.h> 30116344Smarkm#include <sys/mac.h> 31184081Sdes#include <sys/resource.h> 32116344Smarkm#include <sys/rtprio.h> 33184081Sdes#include <sys/stat.h> 34184081Sdes#include <sys/time.h> 35184081Sdes 36184081Sdes#include <ctype.h> 37184081Sdes#include <err.h> 38116344Smarkm#include <errno.h> 3921288Sdavidn#include <fcntl.h> 40116344Smarkm#include <login_cap.h> 41116344Smarkm#include <paths.h> 4221288Sdavidn#include <pwd.h> 43116344Smarkm#include <stdio.h> 44116344Smarkm#include <stdlib.h> 45116344Smarkm#include <string.h> 4621288Sdavidn#include <syslog.h> 47116344Smarkm#include <unistd.h> 4821288Sdavidn 4921288Sdavidn 5021288Sdavidnstatic struct login_res { 5125670Sdavidn const char *what; 5225670Sdavidn rlim_t (*who)(login_cap_t *, const char *, rlim_t, rlim_t); 5325670Sdavidn int why; 5421288Sdavidn} resources[] = { 55181905Sed { "cputime", login_getcaptime, RLIMIT_CPU }, 56181905Sed { "filesize", login_getcapsize, RLIMIT_FSIZE }, 57181905Sed { "datasize", login_getcapsize, RLIMIT_DATA }, 58181905Sed { "stacksize", login_getcapsize, RLIMIT_STACK }, 59181905Sed { "memoryuse", login_getcapsize, RLIMIT_RSS }, 60181905Sed { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK }, 61181905Sed { "maxproc", login_getcapnum, RLIMIT_NPROC }, 62181905Sed { "openfiles", login_getcapnum, RLIMIT_NOFILE }, 63181905Sed { "coredumpsize", login_getcapsize, RLIMIT_CORE }, 64181905Sed { "sbsize", login_getcapsize, RLIMIT_SBSIZE }, 65181905Sed { "vmemoryuse", login_getcapsize, RLIMIT_VMEM }, 66181905Sed { "pseudoterminals", login_getcapnum, RLIMIT_NPTS }, 67181905Sed { NULL, 0, 0 } 6821288Sdavidn}; 6921288Sdavidn 7021288Sdavidn 7121288Sdavidnvoid 7221288Sdavidnsetclassresources(login_cap_t *lc) 7321288Sdavidn{ 7425670Sdavidn struct login_res *lr; 7521288Sdavidn 7625670Sdavidn if (lc == NULL) 7725670Sdavidn return; 7821402Sdavidn 7925670Sdavidn for (lr = resources; lr->what != NULL; ++lr) { 8025670Sdavidn struct rlimit rlim; 8121288Sdavidn 8225670Sdavidn /* 8325670Sdavidn * The login.conf file can have <limit>, <limit>-max, and 8425670Sdavidn * <limit>-cur entries. 8525670Sdavidn * What we do is get the current current- and maximum- limits. 8625670Sdavidn * Then, we try to get an entry for <limit> from the capability, 8725670Sdavidn * using the current and max limits we just got as the 8825670Sdavidn * default/error values. 8925670Sdavidn * *Then*, we try looking for <limit>-cur and <limit>-max, 9025670Sdavidn * again using the appropriate values as the default/error 9125670Sdavidn * conditions. 9225670Sdavidn */ 9321288Sdavidn 9425670Sdavidn if (getrlimit(lr->why, &rlim) != 0) 9525670Sdavidn syslog(LOG_ERR, "getting %s resource limit: %m", lr->what); 9625670Sdavidn else { 97184081Sdes char name_cur[40]; 9825670Sdavidn char name_max[40]; 9925670Sdavidn rlim_t rcur = rlim.rlim_cur; 10025670Sdavidn rlim_t rmax = rlim.rlim_max; 10121288Sdavidn 10225670Sdavidn sprintf(name_cur, "%s-cur", lr->what); 10325670Sdavidn sprintf(name_max, "%s-max", lr->what); 10421288Sdavidn 10525670Sdavidn rcur = (*lr->who)(lc, lr->what, rcur, rcur); 10625670Sdavidn rmax = (*lr->who)(lc, lr->what, rmax, rmax); 10725670Sdavidn rlim.rlim_cur = (*lr->who)(lc, name_cur, rcur, rcur); 10825670Sdavidn rlim.rlim_max = (*lr->who)(lc, name_max, rmax, rmax); 109184081Sdes 11025670Sdavidn if (setrlimit(lr->why, &rlim) == -1) 11125670Sdavidn syslog(LOG_WARNING, "set class '%s' resource limit %s: %m", lc->lc_class, lr->what); 11225670Sdavidn } 11325670Sdavidn } 11421288Sdavidn} 11521288Sdavidn 11625670Sdavidn 11725670Sdavidn 11821288Sdavidnstatic struct login_vars { 11925670Sdavidn const char *tag; 12025670Sdavidn const char *var; 12125670Sdavidn const char *def; 12298977Sache int overwrite; 12321288Sdavidn} pathvars[] = { 12498977Sache { "path", "PATH", NULL, 1}, 12598977Sache { "cdpath", "CDPATH", NULL, 1}, 12698977Sache { "manpath", "MANPATH", NULL, 1}, 12798977Sache { NULL, NULL, NULL, 0} 12821288Sdavidn}, envars[] = { 12998977Sache { "lang", "LANG", NULL, 1}, 13098977Sache { "charset", "MM_CHARSET", NULL, 1}, 13198977Sache { "timezone", "TZ", NULL, 1}, 13298977Sache { "term", "TERM", NULL, 0}, 13398977Sache { NULL, NULL, NULL, 0} 13421288Sdavidn}; 13521288Sdavidn 13621288Sdavidnstatic char * 13794202Srusubstvar(const char * var, const struct passwd * pwd, int hlen, int pch, int nlen) 13821288Sdavidn{ 13925670Sdavidn char *np = NULL; 14021288Sdavidn 14125670Sdavidn if (var != NULL) { 14225670Sdavidn int tildes = 0; 14325670Sdavidn int dollas = 0; 14425670Sdavidn char *p; 14521288Sdavidn 14625670Sdavidn if (pwd != NULL) { 14725670Sdavidn /* Count the number of ~'s in var to substitute */ 14894202Sru for (p = (char *)var; (p = strchr(p, '~')) != NULL; p++) 14925670Sdavidn ++tildes; 15025670Sdavidn /* Count the number of $'s in var to substitute */ 15194202Sru for (p = (char *)var; (p = strchr(p, '$')) != NULL; p++) 15225670Sdavidn ++dollas; 15325670Sdavidn } 15421288Sdavidn 15525670Sdavidn np = malloc(strlen(var) + (dollas * nlen) 15625670Sdavidn - dollas + (tildes * (pch+hlen)) 15725670Sdavidn - tildes + 1); 15821288Sdavidn 15925670Sdavidn if (np != NULL) { 16025670Sdavidn p = strcpy(np, var); 16121288Sdavidn 16225670Sdavidn if (pwd != NULL) { 16325670Sdavidn /* 16425670Sdavidn * This loop does user username and homedir substitutions 16525670Sdavidn * for unescaped $ (username) and ~ (homedir) 16625670Sdavidn */ 16725670Sdavidn while (*(p += strcspn(p, "~$")) != '\0') { 16825670Sdavidn int l = strlen(p); 16921288Sdavidn 17047118Sache if (p > np && *(p-1) == '\\') /* Escaped: */ 17125670Sdavidn memmove(p - 1, p, l + 1); /* Slide-out the backslash */ 17225670Sdavidn else if (*p == '~') { 17325670Sdavidn int v = pch && *(p+1) != '/'; /* Avoid double // */ 17425670Sdavidn memmove(p + hlen + v, p + 1, l); /* Subst homedir */ 17525670Sdavidn memmove(p, pwd->pw_dir, hlen); 17625670Sdavidn if (v) 17725670Sdavidn p[hlen] = '/'; 17825670Sdavidn p += hlen + v; 17925670Sdavidn } 18025670Sdavidn else /* if (*p == '$') */ { 18125670Sdavidn memmove(p + nlen, p + 1, l); /* Subst username */ 18225670Sdavidn memmove(p, pwd->pw_name, nlen); 18325670Sdavidn p += nlen; 18425670Sdavidn } 18525670Sdavidn } 18625670Sdavidn } 18721288Sdavidn } 18821288Sdavidn } 18925670Sdavidn 19025670Sdavidn return np; 19121288Sdavidn} 19221288Sdavidn 19321288Sdavidn 19421288Sdavidnvoid 19521288Sdavidnsetclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths) 19621288Sdavidn{ 19725670Sdavidn struct login_vars *vars = paths ? pathvars : envars; 19825670Sdavidn int hlen = pwd ? strlen(pwd->pw_dir) : 0; 19925670Sdavidn int nlen = pwd ? strlen(pwd->pw_name) : 0; 20025670Sdavidn char pch = 0; 20121288Sdavidn 20225670Sdavidn if (hlen && pwd->pw_dir[hlen-1] != '/') 20325670Sdavidn ++pch; 20421288Sdavidn 20525670Sdavidn while (vars->tag != NULL) { 20694202Sru const char * var = paths ? login_getpath(lc, vars->tag, NULL) 20794202Sru : login_getcapstr(lc, vars->tag, NULL, NULL); 20821288Sdavidn 20925670Sdavidn char * np = substvar(var, pwd, hlen, pch, nlen); 21021288Sdavidn 21125670Sdavidn if (np != NULL) { 21298977Sache setenv(vars->var, np, vars->overwrite); 21325670Sdavidn free(np); 21425670Sdavidn } else if (vars->def != NULL) { 21525670Sdavidn setenv(vars->var, vars->def, 0); 21625670Sdavidn } 21725670Sdavidn ++vars; 21821288Sdavidn } 21921288Sdavidn 22025670Sdavidn /* 22125670Sdavidn * If we're not processing paths, then see if there is a setenv list by 22225670Sdavidn * which the admin and/or user may set an arbitrary set of env vars. 22325670Sdavidn */ 22425670Sdavidn if (!paths) { 225121193Smarkm const char **set_env = login_getcaplist(lc, "setenv", ","); 22621402Sdavidn 22725670Sdavidn if (set_env != NULL) { 22825670Sdavidn while (*set_env != NULL) { 22925670Sdavidn char *p = strchr(*set_env, '='); 23021402Sdavidn 23125670Sdavidn if (p != NULL) { /* Discard invalid entries */ 23225670Sdavidn char *np; 23325670Sdavidn 23425670Sdavidn *p++ = '\0'; 23525670Sdavidn if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) { 23625670Sdavidn setenv(*set_env, np, 1); 23725670Sdavidn free(np); 23825670Sdavidn } 23925670Sdavidn } 24025670Sdavidn ++set_env; 24125670Sdavidn } 24221288Sdavidn } 24321288Sdavidn } 24421288Sdavidn} 24521288Sdavidn 24621288Sdavidn 247180815Sbrooksstatic int 248180815Sbrookslist2cpuset(const char *list, cpuset_t *mask) 249180815Sbrooks{ 250180815Sbrooks enum { NONE, NUM, DASH } state; 251180815Sbrooks int lastnum; 252180815Sbrooks int curnum; 253180815Sbrooks const char *l; 254180815Sbrooks 255180815Sbrooks state = NONE; 256180815Sbrooks curnum = lastnum = 0; 257180815Sbrooks for (l = list; *l != '\0';) { 258180815Sbrooks if (isdigit(*l)) { 259180815Sbrooks curnum = atoi(l); 260180815Sbrooks if (curnum > CPU_SETSIZE) 261180815Sbrooks errx(EXIT_FAILURE, 262180815Sbrooks "Only %d cpus supported", CPU_SETSIZE); 263180815Sbrooks while (isdigit(*l)) 264180815Sbrooks l++; 265180815Sbrooks switch (state) { 266180815Sbrooks case NONE: 267180815Sbrooks lastnum = curnum; 268180815Sbrooks state = NUM; 269180815Sbrooks break; 270180815Sbrooks case DASH: 271180815Sbrooks for (; lastnum <= curnum; lastnum++) 272180815Sbrooks CPU_SET(lastnum, mask); 273180815Sbrooks state = NONE; 274180815Sbrooks break; 275180815Sbrooks case NUM: 276180815Sbrooks default: 277180815Sbrooks return (0); 278180815Sbrooks } 279180815Sbrooks continue; 280180815Sbrooks } 281180815Sbrooks switch (*l) { 282180815Sbrooks case ',': 283180815Sbrooks switch (state) { 284180815Sbrooks case NONE: 285180815Sbrooks break; 286180815Sbrooks case NUM: 287180815Sbrooks CPU_SET(curnum, mask); 288180815Sbrooks state = NONE; 289180815Sbrooks break; 290180815Sbrooks case DASH: 291180815Sbrooks return (0); 292180815Sbrooks break; 293180815Sbrooks } 294180815Sbrooks break; 295180815Sbrooks case '-': 296180815Sbrooks if (state != NUM) 297180815Sbrooks return (0); 298180815Sbrooks state = DASH; 299180815Sbrooks break; 300180815Sbrooks default: 301180815Sbrooks return (0); 302180815Sbrooks } 303180815Sbrooks l++; 304180815Sbrooks } 305180815Sbrooks switch (state) { 306180815Sbrooks case NONE: 307180815Sbrooks break; 308180815Sbrooks case NUM: 309180815Sbrooks CPU_SET(curnum, mask); 310180815Sbrooks break; 311180815Sbrooks case DASH: 312180815Sbrooks return (0); 313180815Sbrooks } 314180815Sbrooks return 1; 315180815Sbrooks} 316180815Sbrooks 317180815Sbrooks 318180815Sbrooksvoid 319180815Sbrookssetclasscpumask(login_cap_t *lc) 320180815Sbrooks{ 321180815Sbrooks const char *maskstr; 322180815Sbrooks cpuset_t maskset; 323180815Sbrooks cpusetid_t setid; 324180815Sbrooks 325180815Sbrooks maskstr = login_getcapstr(lc, "cpumask", NULL, NULL); 326180815Sbrooks CPU_ZERO(&maskset); 327180815Sbrooks if (maskstr == NULL) 328180815Sbrooks return; 329180815Sbrooks if (strcasecmp("default", maskstr) == 0) 330180815Sbrooks return; 331180815Sbrooks if (!list2cpuset(maskstr, &maskset)) { 332180815Sbrooks syslog(LOG_WARNING, 333180815Sbrooks "list2cpuset(%s) invalid mask specification", maskstr); 334180815Sbrooks return; 335180815Sbrooks } 336180815Sbrooks 337180815Sbrooks if (cpuset(&setid) != 0) { 338180815Sbrooks syslog(LOG_ERR, "cpuset(): %s", strerror(errno)); 339180815Sbrooks return; 340180815Sbrooks } 341180815Sbrooks 342180815Sbrooks if (cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, 343180815Sbrooks sizeof(maskset), &maskset) != 0) 344180815Sbrooks syslog(LOG_ERR, "cpuset_setaffinity(%s): %s", maskstr, 345180815Sbrooks strerror(errno)); 346180815Sbrooks} 347180815Sbrooks 348180815Sbrooks 34921288Sdavidn/* 35021288Sdavidn * setclasscontext() 35121288Sdavidn * 35221288Sdavidn * For the login class <class>, set various class context values 35321288Sdavidn * (limits, mainly) to the values for that class. Which values are 35421288Sdavidn * set are controlled by <flags> -- see <login_class.h> for the 35521288Sdavidn * possible values. 35621288Sdavidn * 35721288Sdavidn * setclasscontext() can only set resources, priority, and umask. 35821288Sdavidn */ 35921288Sdavidn 36021288Sdavidnint 36121288Sdavidnsetclasscontext(const char *classname, unsigned int flags) 36221288Sdavidn{ 36325670Sdavidn int rc; 36425670Sdavidn login_cap_t *lc; 36525670Sdavidn 36625670Sdavidn lc = login_getclassbyname(classname, NULL); 36725670Sdavidn 36825670Sdavidn flags &= LOGIN_SETRESOURCES | LOGIN_SETPRIORITY | 36925670Sdavidn LOGIN_SETUMASK | LOGIN_SETPATH; 37025670Sdavidn 37125670Sdavidn rc = lc ? setusercontext(lc, NULL, 0, flags) : -1; 37225670Sdavidn login_close(lc); 37325670Sdavidn return rc; 37421288Sdavidn} 37521288Sdavidn 37621288Sdavidn 37725670Sdavidn 37821288Sdavidn/* 379169189Syar * Private function which takes care of processing 38025670Sdavidn */ 38125670Sdavidn 38225670Sdavidnstatic mode_t 38325670Sdavidnsetlogincontext(login_cap_t *lc, const struct passwd *pwd, 38425670Sdavidn mode_t mymask, unsigned long flags) 38525670Sdavidn{ 38625670Sdavidn if (lc) { 38725670Sdavidn /* Set resources */ 38825670Sdavidn if (flags & LOGIN_SETRESOURCES) 38925670Sdavidn setclassresources(lc); 39025670Sdavidn /* See if there's a umask override */ 39125670Sdavidn if (flags & LOGIN_SETUMASK) 39225670Sdavidn mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask); 39325670Sdavidn /* Set paths */ 39425670Sdavidn if (flags & LOGIN_SETPATH) 39525670Sdavidn setclassenvironment(lc, pwd, 1); 39625670Sdavidn /* Set environment */ 39725670Sdavidn if (flags & LOGIN_SETENV) 39825670Sdavidn setclassenvironment(lc, pwd, 0); 399180815Sbrooks /* Set cpu affinity */ 400180815Sbrooks if (flags & LOGIN_SETCPUMASK) 401180815Sbrooks setclasscpumask(lc); 40225670Sdavidn } 40325670Sdavidn return mymask; 40425670Sdavidn} 40525670Sdavidn 40625670Sdavidn 40725670Sdavidn 40825670Sdavidn/* 40921288Sdavidn * setusercontext() 41021288Sdavidn * 41121288Sdavidn * Given a login class <lc> and a user in <pwd>, with a uid <uid>, 41221288Sdavidn * set the context as in setclasscontext(). <flags> controls which 41321288Sdavidn * values are set. 41421288Sdavidn * 41521288Sdavidn * The difference between setclasscontext() and setusercontext() is 41621288Sdavidn * that the former sets things up for an already-existing process, 41721288Sdavidn * while the latter sets things up from a root context. Such as might 41821288Sdavidn * be called from login(1). 41921288Sdavidn * 42021288Sdavidn */ 42121288Sdavidn 42221288Sdavidnint 42321288Sdavidnsetusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags) 42421288Sdavidn{ 42525670Sdavidn quad_t p; 42625670Sdavidn mode_t mymask; 42725670Sdavidn login_cap_t *llc = NULL; 42836351Ssteve struct rtprio rtp; 429105757Srwatson int error; 43021288Sdavidn 43125670Sdavidn if (lc == NULL) { 43225670Sdavidn if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL) 43325670Sdavidn llc = lc; /* free this when we're done */ 43425670Sdavidn } 43521288Sdavidn 43625670Sdavidn if (flags & LOGIN_SETPATH) 43725670Sdavidn pathvars[0].def = uid ? _PATH_DEFPATH : _PATH_STDPATH; 43821288Sdavidn 43925670Sdavidn /* we need a passwd entry to set these */ 44025670Sdavidn if (pwd == NULL) 441106831Srwatson flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN | LOGIN_SETMAC); 44221288Sdavidn 44325670Sdavidn /* Set the process priority */ 44425670Sdavidn if (flags & LOGIN_SETPRIORITY) { 44525670Sdavidn p = login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI); 44621288Sdavidn 447169189Syar if (p > PRIO_MAX) { 44836351Ssteve rtp.type = RTP_PRIO_IDLE; 44936351Ssteve rtp.prio = p - PRIO_MAX - 1; 45036351Ssteve p = (rtp.prio > RTP_PRIO_MAX) ? 31 : p; 451169189Syar if (rtprio(RTP_SET, 0, &rtp)) 45236351Ssteve syslog(LOG_WARNING, "rtprio '%s' (%s): %m", 45336351Ssteve pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); 454169189Syar } else if (p < PRIO_MIN) { 45536351Ssteve rtp.type = RTP_PRIO_REALTIME; 45636351Ssteve rtp.prio = abs(p - PRIO_MIN + RTP_PRIO_MAX); 45736351Ssteve p = (rtp.prio > RTP_PRIO_MAX) ? 1 : p; 458169189Syar if (rtprio(RTP_SET, 0, &rtp)) 45936351Ssteve syslog(LOG_WARNING, "rtprio '%s' (%s): %m", 46036351Ssteve pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); 46136351Ssteve } else { 46236351Ssteve if (setpriority(PRIO_PROCESS, 0, (int)p) != 0) 46336351Ssteve syslog(LOG_WARNING, "setpriority '%s' (%s): %m", 46436351Ssteve pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS); 46536351Ssteve } 46625670Sdavidn } 46721288Sdavidn 46825670Sdavidn /* Setup the user's group permissions */ 46925670Sdavidn if (flags & LOGIN_SETGROUP) { 47025670Sdavidn if (setgid(pwd->pw_gid) != 0) { 47137947Sache syslog(LOG_ERR, "setgid(%lu): %m", (u_long)pwd->pw_gid); 47225670Sdavidn login_close(llc); 47325670Sdavidn return -1; 47425670Sdavidn } 47525670Sdavidn if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { 47637947Sache syslog(LOG_ERR, "initgroups(%s,%lu): %m", pwd->pw_name, 47737947Sache (u_long)pwd->pw_gid); 47825670Sdavidn login_close(llc); 47925670Sdavidn return -1; 48025670Sdavidn } 48125670Sdavidn } 48221288Sdavidn 483105757Srwatson /* Set up the user's MAC label. */ 484105757Srwatson if ((flags & LOGIN_SETMAC) && mac_is_present(NULL) == 1) { 485105757Srwatson const char *label_string; 486105757Srwatson mac_t label; 487105757Srwatson 488105757Srwatson label_string = login_getcapstr(lc, "label", NULL, NULL); 489105757Srwatson if (label_string != NULL) { 490105757Srwatson if (mac_from_text(&label, label_string) == -1) { 491105757Srwatson syslog(LOG_ERR, "mac_from_text('%s') for %s: %m", 492105757Srwatson pwd->pw_name, label_string); 493105757Srwatson return -1; 494105757Srwatson } 495105757Srwatson if (mac_set_proc(label) == -1) 496105757Srwatson error = errno; 497105757Srwatson else 498105757Srwatson error = 0; 499105757Srwatson mac_free(label); 500105757Srwatson if (error != 0) { 501105757Srwatson syslog(LOG_ERR, "mac_set_proc('%s') for %s: %s", 502105757Srwatson label_string, pwd->pw_name, strerror(error)); 503105757Srwatson return -1; 504105757Srwatson } 505105757Srwatson } 506105757Srwatson } 507105757Srwatson 50825670Sdavidn /* Set the sessions login */ 50925670Sdavidn if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) { 51025670Sdavidn syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name); 51125670Sdavidn login_close(llc); 51225670Sdavidn return -1; 51325670Sdavidn } 51421288Sdavidn 51525670Sdavidn mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0; 51625670Sdavidn mymask = setlogincontext(lc, pwd, mymask, flags); 51725670Sdavidn login_close(llc); 51821288Sdavidn 51925670Sdavidn /* This needs to be done after anything that needs root privs */ 52025670Sdavidn if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) { 52137947Sache syslog(LOG_ERR, "setuid(%lu): %m", (u_long)uid); 52225670Sdavidn return -1; /* Paranoia again */ 52321288Sdavidn } 52421288Sdavidn 52525670Sdavidn /* 52625670Sdavidn * Now, we repeat some of the above for the user's private entries 52725670Sdavidn */ 52825670Sdavidn if ((lc = login_getuserclass(pwd)) != NULL) { 52925670Sdavidn mymask = setlogincontext(lc, pwd, mymask, flags); 53025670Sdavidn login_close(lc); 53125670Sdavidn } 53221288Sdavidn 53325670Sdavidn /* Finally, set any umask we've found */ 53425670Sdavidn if (flags & LOGIN_SETUMASK) 53525670Sdavidn umask(mymask); 53621288Sdavidn 53725670Sdavidn return 0; 53821288Sdavidn} 539