X-Git-Url: https://git.cameronkatri.com/pw-darwin.git/blobdiff_plain/f703811f3616465f8de1ffaedb33ab419afc2fc1..4094297a53a478f9ed7c4160ed63842a19717ba9:/libutil/login_cap.c diff --git a/libutil/login_cap.c b/libutil/login_cap.c index 7d50128..9c8d4a6 100644 --- a/libutil/login_cap.c +++ b/libutil/login_cap.c @@ -29,21 +29,20 @@ #include __FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include - #include #include #include #include -#include +#include +#include #include -#include #include +#include +#include +#include +#include +#include +#include /* * allocstr() @@ -60,10 +59,12 @@ static int lc_object_count = 0; static size_t internal_stringsz = 0; static char * internal_string = NULL; static size_t internal_arraysz = 0; -static char ** internal_array = NULL; +static const char ** internal_array = NULL; + +static char path_login_conf[] = _PATH_LOGIN_CONF; static char * -allocstr(char *str) +allocstr(const char *str) { char *p; @@ -78,10 +79,10 @@ allocstr(char *str) } -static char ** +static const char ** allocarray(size_t sz) { - char **p; + static const char **p; if (sz <= internal_arraysz) p = internal_array; @@ -101,25 +102,26 @@ allocarray(size_t sz) * Free using freearraystr() */ -static char ** -arrayize(char *str, const char *chars, int *size) +static const char ** +arrayize(const char *str, const char *chars, int *size) { int i; - char *ptr; - char **res = NULL; + char *ptr; + const char *cptr; + const char **res = NULL; /* count the sub-strings */ - for (i = 0, ptr = str; *ptr; i++) { - int count = strcspn(ptr, chars); - ptr += count; - if (*ptr) - ++ptr; + for (i = 0, cptr = str; *cptr; i++) { + int count = strcspn(cptr, chars); + cptr += count; + if (*cptr) + ++cptr; } /* alloc the array */ if ((ptr = allocstr(str)) != NULL) { if ((res = allocarray(++i)) == NULL) - free(str); + free((void *)(uintptr_t)(const void *)str); else { /* now split the string */ i = 0; @@ -169,12 +171,16 @@ login_close(login_cap_t * lc) /* - * login_getclassbyname() get the login class by its name. + * login_getclassbyname() + * Get the login class by its name. * If the name given is NULL or empty, the default class - * LOGIN_DEFCLASS (ie. "default") is fetched. If the - * 'dir' argument contains a non-NULL non-empty string, - * then the file _FILE_LOGIN_CONF is picked up from that - * directory instead of the system login database. + * LOGIN_DEFCLASS (i.e., "default") is fetched. + * If the name given is LOGIN_MECLASS and + * 'pwd' argument is non-NULL and contains an non-NULL + * dir entry, then the file _FILE_LOGIN_CONF is picked + * up from that directory and used before the system + * login database. In that case the system login database + * is looked up using LOGIN_MECLASS, too, which is a bug. * Return a filled-out login_cap_t structure, including * class name, and the capability record buffer. */ @@ -211,12 +217,14 @@ login_getclassbyname(char const *name, const struct passwd *pwd) if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, _FILE_LOGIN_CONF) < MAXPATHLEN) { - login_dbarray[i] = userpath; if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1) - i++; /* only use 'secure' data */ + login_dbarray[i++] = userpath; } - if (_secure_path(_PATH_LOGIN_CONF, 0, 0) != -1) - login_dbarray[i++] = _PATH_LOGIN_CONF; + /* + * XXX: Why to add the system database if the class is `me'? + */ + if (_secure_path(path_login_conf, 0, 0) != -1) + login_dbarray[i++] = path_login_conf; login_dbarray[i] = NULL; memset(lc, 0, sizeof(login_cap_t)); @@ -225,13 +233,13 @@ login_getclassbyname(char const *name, const struct passwd *pwd) if (name == NULL || *name == '\0') name = LOGIN_DEFCLASS; - switch (cgetent(&lc->lc_cap, login_dbarray, (char*)name)) { + switch (cgetent(&lc->lc_cap, login_dbarray, name)) { case -1: /* Failed, entry does not exist */ if (me) break; /* Don't retry default on 'me' */ if (i == 0) r = -1; - else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0) + else if ((r = open(login_dbarray[0], O_RDONLY | O_CLOEXEC)) >= 0) close(r); /* * If there's at least one login class database, @@ -243,7 +251,7 @@ login_getclassbyname(char const *name, const struct passwd *pwd) /* fall-back to default class */ name = LOGIN_DEFCLASS; msg = "%s: no default/fallback class '%s'"; - if (cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0 && r >= 0) + if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0) break; /* FALLTHROUGH - just return system defaults */ case 0: /* success! */ @@ -299,12 +307,13 @@ login_getclass(const char *cls) /* - * login_getclass() + * login_getpwclass() * Get the login class for a given password entry from * the system (only) login class database. * If the password entry's class field is not set, or * the class specified does not exist, then use the - * default of LOGIN_DEFCLASS (ie. "default"). + * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged + * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user. * Return a filled-out login_cap_t structure, including * class name, and the capability record buffer. */ @@ -319,14 +328,18 @@ login_getpwclass(const struct passwd *pwd) if (cls == NULL || *cls == '\0') cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; } + /* + * XXX: pwd should be unused by login_getclassbyname() unless cls is `me', + * so NULL can be passed instead of pwd for more safety. + */ return login_getclassbyname(cls, pwd); } /* * login_getuserclass() - * Get the login class for a given password entry, allowing user - * overrides via ~/.login_conf. + * Get the `me' login class, allowing user overrides via ~/.login_conf. + * Note that user overrides are allowed only in the `me' class. */ login_cap_t * @@ -336,11 +349,10 @@ login_getuserclass(const struct passwd *pwd) } - /* * login_getcapstr() * Given a login_cap entry, and a capability name, return the - * value defined for that capability, a defualt if not found, or + * value defined for that capability, a default if not found, or * an error string on error. */ @@ -353,7 +365,7 @@ login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *e if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') return def; - if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) + if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1) return def; return (ret >= 0) ? res : error; } @@ -366,14 +378,14 @@ login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *e * strings. */ -char ** +const char ** login_getcaplist(login_cap_t *lc, const char *cap, const char *chars) { - char *lstring; + const char *lstring; if (chars == NULL) chars = ", \t"; - if ((lstring = (char *)login_getcapstr(lc, cap, NULL, NULL)) != NULL) + if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL) return arrayize(lstring, chars, NULL); return NULL; } @@ -391,18 +403,18 @@ const char * login_getpath(login_cap_t *lc, const char *cap, const char *error) { const char *str; + char *ptr; + int count; - if ((str = login_getcapstr(lc, cap, NULL, NULL)) == NULL) - str = error; - else { - char *ptr = (char *)str; - - while (*ptr) { - int count = strcspn(ptr, ", \t"); - ptr += count; - if (*ptr) - *ptr++ = ':'; - } + str = login_getcapstr(lc, cap, NULL, NULL); + if (str == NULL) + return error; + ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */ + while (*ptr) { + count = strcspn(ptr, ", \t"); + ptr += count; + if (*ptr) + *ptr++ = ':'; } return str; } @@ -536,7 +548,7 @@ login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) * If there's an error, return . */ - if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) + if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) return def; else if (r < 0) { errno = ERANGE; @@ -623,10 +635,10 @@ login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) /* * For BSDI compatibility, try for the tag= first */ - if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { + if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) { long lval; /* string capability not present, so try for tag# as numeric */ - if ((r = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1) + if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1) return def; /* Not there, so return default */ else if (r >= 0) return (rlim_t)lval; @@ -672,7 +684,7 @@ login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) if (lc == NULL || lc->lc_cap == NULL) return def; - if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) + if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) return def; else if (r < 0) { errno = ERANGE; @@ -730,7 +742,7 @@ login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) /* * login_getcapbool() - * From the login_cap_t , check for the existance of the capability + * From the login_cap_t , check for the existence of the capability * of . Return if ->lc_cap is NULL, otherwise return * the whether or not exists there. */ @@ -740,7 +752,7 @@ login_getcapbool(login_cap_t *lc, const char *cap, int def) { if (lc == NULL || lc->lc_cap == NULL) return def; - return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL); + return (cgetcap(lc->lc_cap, cap, ':') != NULL); } @@ -768,14 +780,14 @@ const char * login_getstyle(login_cap_t *lc, const char *style, const char *auth) { int i; - char **authtypes = NULL; + const char **authtypes = NULL; char *auths= NULL; char realauth[64]; - static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; + static const char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; if (auth != NULL && *auth != '\0') { - if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth) + if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < (int)sizeof(realauth)) authtypes = login_getcaplist(lc, realauth, NULL); }