X-Git-Url: https://git.cameronkatri.com/pw-darwin.git/blobdiff_plain/0b3bc144008c93d61f3720daf8aeff915df65ede..c512562447150349fbae74f1aa42ad893e56bb17:/libutil/login_cap.c diff --git a/libutil/login_cap.c b/libutil/login_cap.c index 30a36f0..6d965e3 100644 --- a/libutil/login_cap.c +++ b/libutil/login_cap.c @@ -4,6 +4,10 @@ * David Nugent * All rights reserved. * + * Portions copyright (c) 1995,1997 + * Berkeley Software Design, Inc. + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, is permitted provided that the following conditions * are met: @@ -20,117 +24,120 @@ * conditions are met. * * Low-level routines relating to the user capabilities database - * - * $FreeBSD$ */ -#include -#include -#include -#include -#include +#include +__FBSDID("$FreeBSD$"); #include #include #include #include -#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include -#ifdef RLIM_LONG -# define STRTOV strtol -#else -# define STRTOV strtoq -#endif +/* + * allocstr() + * Manage a single static pointer for handling a local char* buffer, + * resizing as necessary to contain the string. + * + * allocarray() + * Manage a static array for handling a group of strings, resizing + * when necessary. + */ 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 * -allocstr(char * str) +allocstr(const char *str) { - char * p; - size_t sz = strlen(str) + 1; /* realloc() only if necessary */ - if (sz <= internal_stringsz) - p = strcpy(internal_string, str); - else if ((p = realloc(internal_string, sz)) != NULL) { - internal_stringsz = sz; - internal_string = strcpy(p, str); - } - return p; + char *p; + + size_t sz = strlen(str) + 1; /* realloc() only if necessary */ + if (sz <= internal_stringsz) + p = strcpy(internal_string, str); + else if ((p = realloc(internal_string, sz)) != NULL) { + internal_stringsz = sz; + internal_string = strcpy(p, str); + } + return p; } -static char ** + +static const char ** allocarray(size_t sz) { - char ** p; - if (sz <= internal_arraysz) - p = internal_array; - else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) { - internal_arraysz = sz; - internal_array = p; - } - return p; + static const char **p; + + if (sz <= internal_arraysz) + p = internal_array; + else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) { + internal_arraysz = sz; + internal_array = p; + } + return p; } /* * arrayize() - * Turn a simple string seperated by any of + * Turn a simple string separated by any of * the set of into an array. The last element * of the array will be NULL, as is proper. * 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; - - for (i = 0, ptr = str; *ptr; i++) { - int count = strcspn(ptr, chars); - ptr += count; - if (*ptr) - ++ptr; - } - - if ((ptr = allocstr(str)) == NULL) { - res = NULL; - i = 0; - } else if ((res = allocarray(++i)) == NULL) { - free(str); - i = 0; - } else { - for (i = 0; *ptr; i++) { - int count = strcspn(ptr, chars); - res[i] = ptr; - ptr += count; - if (*ptr) - *ptr++ = '\0'; + int i; + char *ptr; + const char *cptr; + const char **res = NULL; + + /* count the sub-strings */ + for (i = 0, cptr = str; *cptr; i++) { + int count = strcspn(cptr, chars); + cptr += count; + if (*cptr) + ++cptr; } - res[i] = 0; - } - if (size) - *size = i; - return res; -} -static void -freearraystr(char ** array) -{ - /* - * the array[0] should be free'd, and then array. - */ - if (array) { - free(array[0]); - free(array); - } + /* alloc the array */ + if ((ptr = allocstr(str)) != NULL) { + if ((res = allocarray(++i)) == NULL) + free((void *)(uintptr_t)(const void *)str); + else { + /* now split the string */ + i = 0; + while (*ptr) { + int count = strcspn(ptr, chars); + res[i++] = ptr; + ptr += count; + if (*ptr) + *ptr++ = '\0'; + } + res[i] = NULL; + } + } + + if (size) + *size = i; + + return res; } @@ -143,18 +150,21 @@ freearraystr(char ** array) void login_close(login_cap_t * lc) { - if (lc) { - free(lc->lc_style); - free(lc->lc_class); - free(lc); - if (--lc_object_count == 0) { - free(internal_string); - free(internal_array); - internal_array = NULL; - internal_string = NULL; - cgetclose(); + if (lc) { + free(lc->lc_style); + free(lc->lc_class); + free(lc->lc_cap); + free(lc); + if (--lc_object_count == 0) { + free(internal_string); + free(internal_array); + internal_array = NULL; + internal_arraysz = 0; + internal_string = NULL; + internal_stringsz = 0; + cgetclose(); + } } - } } @@ -162,46 +172,133 @@ login_close(login_cap_t * lc) * 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. + * '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. * Return a filled-out login_cap_t structure, including * class name, and the capability record buffer. */ login_cap_t * -login_getclassbyname(char const * name, char const * dir) +login_getclassbyname(char const *name, const struct passwd *pwd) { - login_cap_t *lc = malloc(sizeof(login_cap_t)); + login_cap_t *lc; - if (lc != NULL) { - int i = 0; - char userpath[MAXPATHLEN]; - static char *login_dbarray[] = { NULL, NULL, NULL }; - - if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, _FILE_LOGIN_CONF) < MAXPATHLEN) - login_dbarray[i++] = userpath; - else - login_dbarray[i++] = _PATH_LOGIN_CONF; - login_dbarray[i ] = NULL; - - lc->lc_cap = lc->lc_class = lc->lc_style = NULL; - - if ((name == NULL || cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0) && - cgetent(&lc->lc_cap, login_dbarray, (char*)(name = LOGIN_DEFCLASS)) != 0) { + if ((lc = malloc(sizeof(login_cap_t))) != NULL) { + int r, me, i = 0; + uid_t euid = 0; + gid_t egid = 0; + const char *msg = NULL; + const char *dir; + char userpath[MAXPATHLEN]; + + static char *login_dbarray[] = { NULL, NULL, NULL }; + + me = (name != NULL && strcmp(name, LOGIN_MECLASS) == 0); + dir = (!me || pwd == NULL) ? NULL : pwd->pw_dir; + /* + * Switch to user mode before checking/reading its ~/.login_conf + * - some NFSes have root read access disabled. + * + * XXX: This fails to configure additional groups. + */ + if (dir) { + euid = geteuid(); + egid = getegid(); + (void)setegid(pwd->pw_gid); + (void)seteuid(pwd->pw_uid); + } + + 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 */ + } + 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)); + lc->lc_cap = lc->lc_class = lc->lc_style = NULL; + + if (name == NULL || *name == '\0') + name = LOGIN_DEFCLASS; + + 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) + close(r); + /* + * If there's at least one login class database, + * and we aren't searching for a default class + * then complain about a non-existent class. + */ + if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0) + syslog(LOG_ERR, "login_getclass: unknown class '%s'", name); + /* fall-back to default class */ + name = LOGIN_DEFCLASS; + msg = "%s: no default/fallback class '%s'"; + if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0) + break; + /* FALLTHROUGH - just return system defaults */ + case 0: /* success! */ + if ((lc->lc_class = strdup(name)) != NULL) { + if (dir) { + (void)seteuid(euid); + (void)setegid(egid); + } + ++lc_object_count; + return lc; + } + msg = "%s: strdup: %m"; + break; + case -2: + msg = "%s: retrieving class information: %m"; + break; + case -3: + msg = "%s: 'tc=' reference loop '%s'"; + break; + case 1: + msg = "couldn't resolve 'tc=' reference in '%s'"; + break; + default: + msg = "%s: unexpected cgetent() error '%s': %m"; + break; + } + if (dir) { + (void)seteuid(euid); + (void)setegid(egid); + } + if (msg != NULL) + syslog(LOG_ERR, msg, "login_getclass", name); free(lc); - lc = NULL; - } else { - ++lc_object_count; - lc->lc_class = strdup(name); } - } - return lc; + return NULL; } +/* + * login_getclass() + * Get the login class for the system (only) login class database. + * Return a filled-out login_cap_t structure, including + * class name, and the capability record buffer. + */ + +login_cap_t * +login_getclass(const char *cls) +{ + return login_getclassbyname(cls, NULL); +} + + /* * login_getclass() * Get the login class for a given password entry from @@ -214,14 +311,16 @@ login_getclassbyname(char const * name, char const * dir) */ login_cap_t * -login_getclass(const struct passwd *pwd) +login_getpwclass(const struct passwd *pwd) { - const char * class = NULL; - if (pwd != NULL) { - if ((class = pwd->pw_class) == NULL || *class == '\0') - class = (pwd->pw_uid == 0) ? "root" : NULL; - } - return login_getclassbyname(class, 0); + const char *cls = NULL; + + if (pwd != NULL) { + cls = pwd->pw_class; + if (cls == NULL || *cls == '\0') + cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; + } + return login_getclassbyname(cls, pwd); } @@ -229,20 +328,12 @@ login_getclass(const struct passwd *pwd) * login_getuserclass() * Get the login class for a given password entry, allowing user * overrides via ~/.login_conf. - * ### WAS: If the password entry's class field is not set, - * ####### or the class specified does not exist, then use - * If an entry with the recordid "me" does not exist, then use - * the default of LOGIN_DEFCLASS (ie. "default"). - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. */ login_cap_t * login_getuserclass(const struct passwd *pwd) { - const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */ - const char * home = (pwd == NULL) ? NULL : pwd->pw_dir; - return login_getclassbyname(class, home); + return login_getclassbyname(LOGIN_MECLASS, pwd); } @@ -250,25 +341,22 @@ 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. */ -char * -login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error) +const char * +login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *error) { - char *res; - int ret; + char *res; + int ret; - if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') - return def; + if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') + return def; - if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { - return def; - } else if (ret >= 0) - return res; - else - return error; + if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1) + return def; + return (ret >= 0) ? res : error; } @@ -279,16 +367,16 @@ login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error) * strings. */ -char ** -login_getcaplist(login_cap_t *lc, const char * cap, const char * chars) +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 = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL) - return arrayize(lstring, chars, NULL); - return NULL; + if (chars == NULL) + chars = ", \t"; + if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL) + return arrayize(lstring, chars, NULL); + return NULL; } @@ -300,24 +388,127 @@ login_getcaplist(login_cap_t *lc, const char * cap, const char * chars) * If there is an error of any kind, return . */ -char * -login_getpath(login_cap_t *lc, const char *cap, char * error) +const char * +login_getpath(login_cap_t *lc, const char *cap, const char *error) { - char *str = login_getcapstr(lc, (char*)cap, NULL, NULL); + const char *str; + char *ptr; + int count; + + 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; +} - if (str == NULL) - str = error; - else { - char *ptr = str; - while (*ptr) { - int count = strcspn(ptr, ", \t"); - ptr += count; - if (*ptr) - *ptr++ = ':'; +static int +isinfinite(const char *s) +{ + static const char *infs[] = { + "infinity", + "inf", + "unlimited", + "unlimit", + "-1", + NULL + }; + const char **i = &infs[0]; + + while (*i != NULL) { + if (strcasecmp(s, *i) == 0) + return 1; + ++i; } - } - return str; + return 0; +} + + +static u_quad_t +rmultiply(u_quad_t n1, u_quad_t n2) +{ + u_quad_t m, r; + int b1, b2; + + static int bpw = 0; + + /* Handle simple cases */ + if (n1 == 0 || n2 == 0) + return 0; + if (n1 == 1) + return n2; + if (n2 == 1) + return n1; + + /* + * sizeof() returns number of bytes needed for storage. + * This may be different from the actual number of useful bits. + */ + if (!bpw) { + bpw = sizeof(u_quad_t) * 8; + while (((u_quad_t)1 << (bpw-1)) == 0) + --bpw; + } + + /* + * First check the magnitude of each number. If the sum of the + * magnatude is way to high, reject the number. (If this test + * is not done then the first multiply below may overflow.) + */ + for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1) + ; + for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2) + ; + if (b1 + b2 - 2 > bpw) { + errno = ERANGE; + return (UQUAD_MAX); + } + + /* + * Decompose the multiplication to be: + * h1 = n1 & ~1 + * h2 = n2 & ~1 + * l1 = n1 & 1 + * l2 = n2 & 1 + * (h1 + l1) * (h2 + l2) + * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2) + * + * Since h1 && h2 do not have the low bit set, we can then say: + * + * (h1>>1 * h2>>1 * 4) + ... + * + * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will + * overflow. + * + * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2) + * then adding in residual amout will cause an overflow. + */ + + m = (n1 >> 1) * (n2 >> 1); + if (m >= ((u_quad_t)1 << (bpw-2))) { + errno = ERANGE; + return (UQUAD_MAX); + } + m *= 4; + + r = (n1 & n2 & 1) + + (n2 & 1) * (n1 & ~(u_quad_t)1) + + (n1 & 1) * (n2 & ~(u_quad_t)1); + + if ((u_quad_t)(m + r) < m) { + errno = ERANGE; + return (UQUAD_MAX); + } + m += r; + + return (m); } @@ -332,69 +523,82 @@ login_getpath(login_cap_t *lc, const char *cap, char * error) rlim_t login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { - char *res, *ep; - int ret; - rlim_t tot = 0, tim; - - errno = 0; - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * Look for in lc_cap. - * If it's not there (-1), return . - * If there's an error, return . - */ - - if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) - return def; - else if (ret < 0) - return error; - - /* - * "inf" and "infinity" are two special cases for this. - */ - if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) - return RLIM_INFINITY; - - /* - * Now go through the string, turning something like 1h2m3s into - * an integral value. Whee. - */ - - errno = 0; - while (*res) { - tim = STRTOV(res, &ep, 0); - if ((ep == NULL) || (ep == res) || errno) { - return error; + char *res, *ep, *oval; + int r; + rlim_t tot; + + errno = 0; + if (lc == NULL || lc->lc_cap == NULL) + return def; + + /* + * Look for in lc_cap. + * If it's not there (-1), return . + * If there's an error, return . + */ + + if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) + return def; + else if (r < 0) { + errno = ERANGE; + return error; } - /* Look for suffixes */ - switch (*ep++) { - case 0: - ep--; break; /* end of string */ - case 's': case 'S': /* seconds */ - break; - case 'm': case 'M': /* minutes */ - tim *= 60L; - break; - case 'h': case 'H': /* hours */ - tim *= (60L * 60L); - break; - case 'd': case 'D': /* days */ - tim *= (60L * 60L * 24L); - break; - case 'w': case 'W': /* weeks */ - tim *= (60L * 60L * 24L * 7L); - case 'y': case 'Y': /* Years */ - /* I refuse to take leap years into account here. Sue me. */ - tim *= (60L * 60L * 24L * 365L); - default: - return error; + + /* "inf" and "infinity" are special cases */ + if (isinfinite(res)) + return RLIM_INFINITY; + + /* + * Now go through the string, turning something like 1h2m3s into + * an integral value. Whee. + */ + + errno = 0; + tot = 0; + oval = res; + while (*res) { + rlim_t tim = strtoq(res, &ep, 0); + rlim_t mult = 1; + + if (ep == NULL || ep == res || errno != 0) { + invalid: + syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s", + lc->lc_class, cap, oval); + errno = ERANGE; + return error; + } + /* Look for suffixes */ + switch (*ep++) { + case 0: + ep--; + break; /* end of string */ + case 's': case 'S': /* seconds */ + break; + case 'm': case 'M': /* minutes */ + mult = 60; + break; + case 'h': case 'H': /* hours */ + mult = 60L * 60L; + break; + case 'd': case 'D': /* days */ + mult = 60L * 60L * 24L; + break; + case 'w': case 'W': /* weeks */ + mult = 60L * 60L * 24L * 7L; + break; + case 'y': case 'Y': /* 365-day years */ + mult = 60L * 60L * 24L * 365L; + break; + default: + goto invalid; + } + res = ep; + tot += rmultiply(tim, mult); + if (errno) + goto invalid; } - res = ep; - tot += tim; - } - return tot; + + return tot; } @@ -410,41 +614,47 @@ login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) rlim_t login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { - char *ep, *res; - int ret; - rlim_t val; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * For BSDI compatibility, try for the tag= first - */ - if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { - long lval; + char *ep, *res; + int r; + rlim_t val; + + if (lc == NULL || lc->lc_cap == NULL) + return def; + /* - * String capability not present, so try for tag# as numeric + * For BSDI compatibility, try for the tag= first */ - if ((ret = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1) - return def; /* Not there, so return default */ - else if (ret < 0) - return error; - return (rlim_t)lval; - } - else if (ret < 0) - return error; - - if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) - return RLIM_INFINITY; - - errno = 0; - val = STRTOV(res, &ep, 0); - if ((ep == NULL) || (ep == res) || errno) - return error; - return val; + 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, cap, &lval)) == -1) + return def; /* Not there, so return default */ + else if (r >= 0) + return (rlim_t)lval; + } + + if (r < 0) { + errno = ERANGE; + return error; + } + + if (isinfinite(res)) + return RLIM_INFINITY; + + errno = 0; + val = strtoq(res, &ep, 0); + if (ep == NULL || ep == res || errno != 0) { + syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s", + lc->lc_class, cap, res); + errno = ERANGE; + return error; + } + + return val; } + /* * login_getcapsize() * From the login_cap_t , extract the capability , which is @@ -454,43 +664,68 @@ login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) */ rlim_t -login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { - char *ep, *res; - int ret; - rlim_t val; - rlim_t mult; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) - return def; - else if (ret < 0) - return error; - - errno = 0; - val = STRTOV(res, &ep, 0); - if ((res == NULL) || (res == ep) || errno) - return error; - switch (*ep) { - case 0: /* end of string */ - mult = 1; break; - case 'b': case 'B': /* 512-byte blocks */ - mult = 512; break; - case 'k': case 'K': /* 1024-byte Kilobytes */ - mult = 1024; break; - case 'm': case 'M': /* 1024-k kbytes */ - mult = 1024 * 1024; break; - case 'g': case 'G': /* 1Gbyte */ - mult = 1024 * 1024 * 1024; break; -#ifndef RLIM_LONG - case 't': case 'T': /* 1TBte */ - mult = 1024LL * 1024LL * 1024LL * 1024LL; break; -#endif - default: - return error; - } - return val * mult; +login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) +{ + char *ep, *res, *oval; + int r; + rlim_t tot; + + if (lc == NULL || lc->lc_cap == NULL) + return def; + + if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) + return def; + else if (r < 0) { + errno = ERANGE; + return error; + } + + if (isinfinite(res)) + return RLIM_INFINITY; + + errno = 0; + tot = 0; + oval = res; + while (*res) { + rlim_t siz = strtoq(res, &ep, 0); + rlim_t mult = 1; + + if (ep == NULL || ep == res || errno != 0) { + invalid: + syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s", + lc->lc_class, cap, oval); + errno = ERANGE; + return error; + } + switch (*ep++) { + case 0: /* end of string */ + ep--; + break; + case 'b': case 'B': /* 512-byte blocks */ + mult = 512; + break; + case 'k': case 'K': /* 1024-byte Kilobytes */ + mult = 1024; + break; + case 'm': case 'M': /* 1024-k kbytes */ + mult = 1024 * 1024; + break; + case 'g': case 'G': /* 1Gbyte */ + mult = 1024 * 1024 * 1024; + break; + case 't': case 'T': /* 1TBte */ + mult = 1024LL * 1024LL * 1024LL * 1024LL; + break; + default: + goto invalid; + } + res = ep; + tot += rmultiply(siz, mult); + if (errno) + goto invalid; + } + + return tot; } @@ -504,9 +739,9 @@ login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { int 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); + if (lc == NULL || lc->lc_cap == NULL) + return def; + return (cgetcap(lc->lc_cap, cap, ':') != NULL); } @@ -530,41 +765,44 @@ login_getcapbool(login_cap_t *lc, const char *cap, int def) * login_getstyle(lc, "skey", "network"); */ -char * -login_getstyle(login_cap_t *lc, char *style, const char *auth) +const char * +login_getstyle(login_cap_t *lc, const char *style, const char *auth) { - int i; - char **authtypes = NULL; - char *auths= NULL; - char realauth[64]; - - static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; - - if (auth != NULL && *auth != '\0' && - snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth) - authtypes = login_getcaplist(lc, realauth, NULL); - - if (authtypes == NULL) - authtypes = login_getcaplist(lc, "auth", NULL); - - if (authtypes == NULL) - authtypes = defauthtypes; - - /* - * We have at least one authtype now; auths is a comma-seperated - * (or space-separated) list of authentication types. We have to - * convert from this to an array of char*'s; authtypes then gets this. - */ - i = 0; - if (style != NULL && *style != '\0') { - while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0) - i++; - } - lc->lc_style = NULL; - if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL) - lc->lc_style = auths; - - return lc->lc_style; -} + int i; + const char **authtypes = NULL; + char *auths= NULL; + char realauth[64]; + + static const char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; + + if (auth != NULL && *auth != '\0') { + if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < (int)sizeof(realauth)) + authtypes = login_getcaplist(lc, realauth, NULL); + } + + if (authtypes == NULL) + authtypes = login_getcaplist(lc, "auth", NULL); + + if (authtypes == NULL) + authtypes = defauthtypes; + /* + * We have at least one authtype now; auths is a comma-separated + * (or space-separated) list of authentication types. We have to + * convert from this to an array of char*'s; authtypes then gets this. + */ + i = 0; + if (style != NULL && *style != '\0') { + while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0) + i++; + } + lc->lc_style = NULL; + if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL) + lc->lc_style = auths; + + if (lc->lc_style != NULL) + lc->lc_style = strdup(lc->lc_style); + + return lc->lc_style; +}