168bbf3adSDavid Nugent /*- 268bbf3adSDavid Nugent * Copyright (c) 1996 by 368bbf3adSDavid Nugent * Sean Eric Fagan <sef@kithrup.com> 468bbf3adSDavid Nugent * David Nugent <davidn@blaze.net.au> 568bbf3adSDavid Nugent * All rights reserved. 668bbf3adSDavid Nugent * 768bbf3adSDavid Nugent * Redistribution and use in source and binary forms, with or without 868bbf3adSDavid Nugent * modification, is permitted provided that the following conditions 968bbf3adSDavid Nugent * are met: 1068bbf3adSDavid Nugent * 1. Redistributions of source code must retain the above copyright 1168bbf3adSDavid Nugent * notice immediately at the beginning of the file, without modification, 1268bbf3adSDavid Nugent * this list of conditions, and the following disclaimer. 1368bbf3adSDavid Nugent * 2. Redistributions in binary form must reproduce the above copyright 1468bbf3adSDavid Nugent * notice, this list of conditions and the following disclaimer in the 1568bbf3adSDavid Nugent * documentation and/or other materials provided with the distribution. 1668bbf3adSDavid Nugent * 3. This work was done expressly for inclusion into FreeBSD. Other use 1768bbf3adSDavid Nugent * is permitted provided this notation is included. 1868bbf3adSDavid Nugent * 4. Absolutely no warranty of function or purpose is made by the authors. 1968bbf3adSDavid Nugent * 5. Modifications may be freely made to this file providing the above 2068bbf3adSDavid Nugent * conditions are met. 2168bbf3adSDavid Nugent * 2268bbf3adSDavid Nugent * Low-level routines relating to the user capabilities database 2368bbf3adSDavid Nugent * 241130b656SJordan K. Hubbard * $FreeBSD$ 2568bbf3adSDavid Nugent */ 2668bbf3adSDavid Nugent 2768bbf3adSDavid Nugent #include <stdio.h> 2868bbf3adSDavid Nugent #include <stdlib.h> 2968bbf3adSDavid Nugent #include <string.h> 3068bbf3adSDavid Nugent #include <errno.h> 3168bbf3adSDavid Nugent #include <unistd.h> 3268bbf3adSDavid Nugent 3368bbf3adSDavid Nugent #include <sys/types.h> 3468bbf3adSDavid Nugent #include <sys/time.h> 3568bbf3adSDavid Nugent #include <sys/resource.h> 3668bbf3adSDavid Nugent #include <sys/param.h> 3768bbf3adSDavid Nugent #include <pwd.h> 3868bbf3adSDavid Nugent #include <login_cap.h> 3968bbf3adSDavid Nugent 4068bbf3adSDavid Nugent #ifdef RLIM_LONG 4168bbf3adSDavid Nugent # define STRTOV strtol 4268bbf3adSDavid Nugent #else 4368bbf3adSDavid Nugent # define STRTOV strtoq 4468bbf3adSDavid Nugent #endif 4568bbf3adSDavid Nugent 4668bbf3adSDavid Nugent static int lc_object_count = 0; 4768bbf3adSDavid Nugent 4868bbf3adSDavid Nugent static size_t internal_stringsz = 0; 4968bbf3adSDavid Nugent static char * internal_string = NULL; 5068bbf3adSDavid Nugent static size_t internal_arraysz = 0; 5168bbf3adSDavid Nugent static char ** internal_array = NULL; 5268bbf3adSDavid Nugent 5368bbf3adSDavid Nugent static char * 5468bbf3adSDavid Nugent allocstr(char * str) 5568bbf3adSDavid Nugent { 5668bbf3adSDavid Nugent char * p; 5768bbf3adSDavid Nugent size_t sz = strlen(str) + 1; /* realloc() only if necessary */ 5868bbf3adSDavid Nugent if (sz <= internal_stringsz) 591c594de5SDavid Nugent p = strcpy(internal_string, str); 6068bbf3adSDavid Nugent else if ((p = realloc(internal_string, sz)) != NULL) { 6168bbf3adSDavid Nugent internal_stringsz = sz; 6268bbf3adSDavid Nugent internal_string = strcpy(p, str); 6368bbf3adSDavid Nugent } 6468bbf3adSDavid Nugent return p; 6568bbf3adSDavid Nugent } 6668bbf3adSDavid Nugent 6768bbf3adSDavid Nugent static char ** 6868bbf3adSDavid Nugent allocarray(size_t sz) 6968bbf3adSDavid Nugent { 7068bbf3adSDavid Nugent char ** p; 7168bbf3adSDavid Nugent if (sz <= internal_arraysz) 7268bbf3adSDavid Nugent p = internal_array; 7368bbf3adSDavid Nugent else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) { 7468bbf3adSDavid Nugent internal_arraysz = sz; 7568bbf3adSDavid Nugent internal_array = p; 7668bbf3adSDavid Nugent } 7768bbf3adSDavid Nugent return p; 7868bbf3adSDavid Nugent } 7968bbf3adSDavid Nugent 8068bbf3adSDavid Nugent 8168bbf3adSDavid Nugent /* 8268bbf3adSDavid Nugent * arrayize() 8368bbf3adSDavid Nugent * Turn a simple string <str> seperated by any of 8468bbf3adSDavid Nugent * the set of <chars> into an array. The last element 8568bbf3adSDavid Nugent * of the array will be NULL, as is proper. 8668bbf3adSDavid Nugent * Free using freearraystr() 8768bbf3adSDavid Nugent */ 8868bbf3adSDavid Nugent 8968bbf3adSDavid Nugent static char ** 9068bbf3adSDavid Nugent arrayize(char *str, const char *chars, int *size) 9168bbf3adSDavid Nugent { 9268bbf3adSDavid Nugent int i; 9368bbf3adSDavid Nugent char *ptr; 9468bbf3adSDavid Nugent char **res = NULL; 9568bbf3adSDavid Nugent 9668bbf3adSDavid Nugent for (i = 0, ptr = str; *ptr; i++) { 9768bbf3adSDavid Nugent int count = strcspn(ptr, chars); 981c594de5SDavid Nugent ptr += count; 991c594de5SDavid Nugent if (*ptr) 1001c594de5SDavid Nugent ++ptr; 10168bbf3adSDavid Nugent } 10268bbf3adSDavid Nugent 10368bbf3adSDavid Nugent if ((ptr = allocstr(str)) == NULL) { 10468bbf3adSDavid Nugent res = NULL; 10568bbf3adSDavid Nugent i = 0; 10668bbf3adSDavid Nugent } else if ((res = allocarray(++i)) == NULL) { 10768bbf3adSDavid Nugent free(str); 10868bbf3adSDavid Nugent i = 0; 10968bbf3adSDavid Nugent } else { 11068bbf3adSDavid Nugent for (i = 0; *ptr; i++) { 11168bbf3adSDavid Nugent int count = strcspn(ptr, chars); 11268bbf3adSDavid Nugent res[i] = ptr; 11368bbf3adSDavid Nugent ptr += count; 11468bbf3adSDavid Nugent if (*ptr) 11568bbf3adSDavid Nugent *ptr++ = '\0'; 11668bbf3adSDavid Nugent } 11768bbf3adSDavid Nugent res[i] = 0; 11868bbf3adSDavid Nugent } 11968bbf3adSDavid Nugent if (size) 12068bbf3adSDavid Nugent *size = i; 12168bbf3adSDavid Nugent return res; 12268bbf3adSDavid Nugent } 12368bbf3adSDavid Nugent 12468bbf3adSDavid Nugent static void 12568bbf3adSDavid Nugent freearraystr(char ** array) 12668bbf3adSDavid Nugent { 12768bbf3adSDavid Nugent /* 12868bbf3adSDavid Nugent * the array[0] should be free'd, and then array. 12968bbf3adSDavid Nugent */ 13068bbf3adSDavid Nugent if (array) { 13168bbf3adSDavid Nugent free(array[0]); 132f01e3989SDavid Nugent array[0] = NULL; 13368bbf3adSDavid Nugent free(array); 13468bbf3adSDavid Nugent } 13568bbf3adSDavid Nugent } 13668bbf3adSDavid Nugent 13768bbf3adSDavid Nugent 13868bbf3adSDavid Nugent /* 13968bbf3adSDavid Nugent * login_close() 14068bbf3adSDavid Nugent * Frees up all resources relating to a login class 14168bbf3adSDavid Nugent * 14268bbf3adSDavid Nugent */ 14368bbf3adSDavid Nugent 14468bbf3adSDavid Nugent void 14568bbf3adSDavid Nugent login_close(login_cap_t * lc) 14668bbf3adSDavid Nugent { 14768bbf3adSDavid Nugent if (lc) { 14868bbf3adSDavid Nugent free(lc->lc_style); 14968bbf3adSDavid Nugent free(lc->lc_class); 15068bbf3adSDavid Nugent free(lc); 15168bbf3adSDavid Nugent if (--lc_object_count == 0) { 15268bbf3adSDavid Nugent free(internal_string); 15351706563SDavid Nugent freearraystr(internal_array); 15468bbf3adSDavid Nugent internal_array = NULL; 15551706563SDavid Nugent internal_arraysz = 0; 15668bbf3adSDavid Nugent internal_string = NULL; 15751706563SDavid Nugent internal_stringsz = 0; 15868bbf3adSDavid Nugent cgetclose(); 15968bbf3adSDavid Nugent } 16068bbf3adSDavid Nugent } 16168bbf3adSDavid Nugent } 16268bbf3adSDavid Nugent 16368bbf3adSDavid Nugent 16468bbf3adSDavid Nugent /* 16568bbf3adSDavid Nugent * login_getclassbyname() get the login class by its name. 16668bbf3adSDavid Nugent * If the name given is NULL or empty, the default class 16768bbf3adSDavid Nugent * LOGIN_DEFCLASS (ie. "default") is fetched. If the 16868bbf3adSDavid Nugent * 'dir' argument contains a non-NULL non-empty string, 16968bbf3adSDavid Nugent * then the file _FILE_LOGIN_CONF is picked up from that 17068bbf3adSDavid Nugent * directory instead of the system login database. 17168bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 17268bbf3adSDavid Nugent * class name, and the capability record buffer. 17368bbf3adSDavid Nugent */ 17468bbf3adSDavid Nugent 17568bbf3adSDavid Nugent login_cap_t * 17668bbf3adSDavid Nugent login_getclassbyname(char const * name, char const * dir) 17768bbf3adSDavid Nugent { 17868bbf3adSDavid Nugent login_cap_t *lc = malloc(sizeof(login_cap_t)); 17968bbf3adSDavid Nugent 18068bbf3adSDavid Nugent if (lc != NULL) { 18168bbf3adSDavid Nugent int i = 0; 18268bbf3adSDavid Nugent char userpath[MAXPATHLEN]; 18368bbf3adSDavid Nugent static char *login_dbarray[] = { NULL, NULL, NULL }; 18468bbf3adSDavid Nugent 18568bbf3adSDavid Nugent if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, _FILE_LOGIN_CONF) < MAXPATHLEN) 18668bbf3adSDavid Nugent login_dbarray[i++] = userpath; 18768bbf3adSDavid Nugent else 18868bbf3adSDavid Nugent login_dbarray[i++] = _PATH_LOGIN_CONF; 18968bbf3adSDavid Nugent login_dbarray[i ] = NULL; 19068bbf3adSDavid Nugent 19168bbf3adSDavid Nugent lc->lc_cap = lc->lc_class = lc->lc_style = NULL; 19268bbf3adSDavid Nugent 19368bbf3adSDavid Nugent if ((name == NULL || cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0) && 19468bbf3adSDavid Nugent cgetent(&lc->lc_cap, login_dbarray, (char*)(name = LOGIN_DEFCLASS)) != 0) { 19568bbf3adSDavid Nugent free(lc); 19668bbf3adSDavid Nugent lc = NULL; 19768bbf3adSDavid Nugent } else { 19868bbf3adSDavid Nugent ++lc_object_count; 19968bbf3adSDavid Nugent lc->lc_class = strdup(name); 20068bbf3adSDavid Nugent } 20168bbf3adSDavid Nugent } 20268bbf3adSDavid Nugent 20368bbf3adSDavid Nugent return lc; 20468bbf3adSDavid Nugent } 20568bbf3adSDavid Nugent 20668bbf3adSDavid Nugent 20768bbf3adSDavid Nugent 20868bbf3adSDavid Nugent /* 20968bbf3adSDavid Nugent * login_getclass() 21068bbf3adSDavid Nugent * Get the login class for a given password entry from 21168bbf3adSDavid Nugent * the system (only) login class database. 21268bbf3adSDavid Nugent * If the password entry's class field is not set, or 21368bbf3adSDavid Nugent * the class specified does not exist, then use the 21468bbf3adSDavid Nugent * default of LOGIN_DEFCLASS (ie. "default"). 21568bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 21668bbf3adSDavid Nugent * class name, and the capability record buffer. 21768bbf3adSDavid Nugent */ 21868bbf3adSDavid Nugent 21968bbf3adSDavid Nugent login_cap_t * 22068bbf3adSDavid Nugent login_getclass(const struct passwd *pwd) 22168bbf3adSDavid Nugent { 2222dc7d862SDavid Nugent const char * class = NULL; 2231c594de5SDavid Nugent if (pwd != NULL) { 22465fa0ae1SDavid Nugent if ((class = pwd->pw_class) == NULL || *class == '\0') 2252dc7d862SDavid Nugent class = (pwd->pw_uid == 0) ? "root" : NULL; 2262dc7d862SDavid Nugent } 22768bbf3adSDavid Nugent return login_getclassbyname(class, 0); 22868bbf3adSDavid Nugent } 22968bbf3adSDavid Nugent 23068bbf3adSDavid Nugent 23168bbf3adSDavid Nugent /* 23268bbf3adSDavid Nugent * login_getuserclass() 23368bbf3adSDavid Nugent * Get the login class for a given password entry, allowing user 23468bbf3adSDavid Nugent * overrides via ~/.login_conf. 23568bbf3adSDavid Nugent * ### WAS: If the password entry's class field is not set, 23668bbf3adSDavid Nugent * ####### or the class specified does not exist, then use 23768bbf3adSDavid Nugent * If an entry with the recordid "me" does not exist, then use 23868bbf3adSDavid Nugent * the default of LOGIN_DEFCLASS (ie. "default"). 23968bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 24068bbf3adSDavid Nugent * class name, and the capability record buffer. 24168bbf3adSDavid Nugent */ 24268bbf3adSDavid Nugent 24368bbf3adSDavid Nugent login_cap_t * 24468bbf3adSDavid Nugent login_getuserclass(const struct passwd *pwd) 24568bbf3adSDavid Nugent { 24668bbf3adSDavid Nugent const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */ 24768bbf3adSDavid Nugent const char * home = (pwd == NULL) ? NULL : pwd->pw_dir; 24868bbf3adSDavid Nugent return login_getclassbyname(class, home); 24968bbf3adSDavid Nugent } 25068bbf3adSDavid Nugent 25168bbf3adSDavid Nugent 25268bbf3adSDavid Nugent 25368bbf3adSDavid Nugent /* 25468bbf3adSDavid Nugent * login_getcapstr() 25568bbf3adSDavid Nugent * Given a login_cap entry, and a capability name, return the 25668bbf3adSDavid Nugent * value defined for that capability, a defualt if not found, or 25768bbf3adSDavid Nugent * an error string on error. 25868bbf3adSDavid Nugent */ 25968bbf3adSDavid Nugent 26068bbf3adSDavid Nugent char * 26168bbf3adSDavid Nugent login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error) 26268bbf3adSDavid Nugent { 26368bbf3adSDavid Nugent char *res; 26468bbf3adSDavid Nugent int ret; 26568bbf3adSDavid Nugent 26668bbf3adSDavid Nugent if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') 26768bbf3adSDavid Nugent return def; 26868bbf3adSDavid Nugent 26968bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { 27068bbf3adSDavid Nugent return def; 27168bbf3adSDavid Nugent } else if (ret >= 0) 27268bbf3adSDavid Nugent return res; 27368bbf3adSDavid Nugent else 27468bbf3adSDavid Nugent return error; 27568bbf3adSDavid Nugent } 27668bbf3adSDavid Nugent 27768bbf3adSDavid Nugent 27868bbf3adSDavid Nugent /* 27968bbf3adSDavid Nugent * login_getcaplist() 28068bbf3adSDavid Nugent * Given a login_cap entry, and a capability name, return the 28168bbf3adSDavid Nugent * value defined for that capability split into an array of 28268bbf3adSDavid Nugent * strings. 28368bbf3adSDavid Nugent */ 28468bbf3adSDavid Nugent 28568bbf3adSDavid Nugent char ** 28668bbf3adSDavid Nugent login_getcaplist(login_cap_t *lc, const char * cap, const char * chars) 28768bbf3adSDavid Nugent { 28868bbf3adSDavid Nugent char * lstring; 28968bbf3adSDavid Nugent 29068bbf3adSDavid Nugent if (chars == NULL) 291f01e3989SDavid Nugent chars = ", \t"; 29268bbf3adSDavid Nugent if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL) 29368bbf3adSDavid Nugent return arrayize(lstring, chars, NULL); 29468bbf3adSDavid Nugent return NULL; 29568bbf3adSDavid Nugent } 29668bbf3adSDavid Nugent 29768bbf3adSDavid Nugent 29868bbf3adSDavid Nugent /* 29968bbf3adSDavid Nugent * login_getpath() 30068bbf3adSDavid Nugent * From the login_cap_t <lc>, get the capability <cap> which is 30168bbf3adSDavid Nugent * formatted as either a space or comma delimited list of paths 30268bbf3adSDavid Nugent * and append them all into a string and separate by semicolons. 30368bbf3adSDavid Nugent * If there is an error of any kind, return <error>. 30468bbf3adSDavid Nugent */ 30568bbf3adSDavid Nugent 30668bbf3adSDavid Nugent char * 30768bbf3adSDavid Nugent login_getpath(login_cap_t *lc, const char *cap, char * error) 30868bbf3adSDavid Nugent { 3091c594de5SDavid Nugent char *str = login_getcapstr(lc, (char*)cap, NULL, NULL); 31068bbf3adSDavid Nugent 3111c594de5SDavid Nugent if (str == NULL) 31268bbf3adSDavid Nugent str = error; 31368bbf3adSDavid Nugent else { 3141c594de5SDavid Nugent char *ptr = str; 3151c594de5SDavid Nugent 31668bbf3adSDavid Nugent while (*ptr) { 31768bbf3adSDavid Nugent int count = strcspn(ptr, ", \t"); 31868bbf3adSDavid Nugent ptr += count; 31968bbf3adSDavid Nugent if (*ptr) 32068bbf3adSDavid Nugent *ptr++ = ':'; 32168bbf3adSDavid Nugent } 32268bbf3adSDavid Nugent } 32368bbf3adSDavid Nugent return str; 32468bbf3adSDavid Nugent } 32568bbf3adSDavid Nugent 32668bbf3adSDavid Nugent 32768bbf3adSDavid Nugent /* 32868bbf3adSDavid Nugent * login_getcaptime() 32968bbf3adSDavid Nugent * From the login_cap_t <lc>, get the capability <cap>, which is 33068bbf3adSDavid Nugent * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not 33168bbf3adSDavid Nugent * present in <lc>, return <def>; if there is an error of some kind, 33268bbf3adSDavid Nugent * return <error>. 33368bbf3adSDavid Nugent */ 33468bbf3adSDavid Nugent 33568bbf3adSDavid Nugent rlim_t 33668bbf3adSDavid Nugent login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) 33768bbf3adSDavid Nugent { 33868bbf3adSDavid Nugent char *res, *ep; 33968bbf3adSDavid Nugent int ret; 34051706563SDavid Nugent rlim_t tot; 34168bbf3adSDavid Nugent 34268bbf3adSDavid Nugent errno = 0; 34368bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 34468bbf3adSDavid Nugent return def; 34568bbf3adSDavid Nugent 34668bbf3adSDavid Nugent /* 34768bbf3adSDavid Nugent * Look for <cap> in lc_cap. 34868bbf3adSDavid Nugent * If it's not there (-1), return <def>. 34968bbf3adSDavid Nugent * If there's an error, return <error>. 35068bbf3adSDavid Nugent */ 35168bbf3adSDavid Nugent 35268bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) 35368bbf3adSDavid Nugent return def; 35468bbf3adSDavid Nugent else if (ret < 0) 35568bbf3adSDavid Nugent return error; 35668bbf3adSDavid Nugent 35768bbf3adSDavid Nugent /* 35868bbf3adSDavid Nugent * "inf" and "infinity" are two special cases for this. 35968bbf3adSDavid Nugent */ 36068bbf3adSDavid Nugent if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) 36168bbf3adSDavid Nugent return RLIM_INFINITY; 36268bbf3adSDavid Nugent 36368bbf3adSDavid Nugent /* 36468bbf3adSDavid Nugent * Now go through the string, turning something like 1h2m3s into 36568bbf3adSDavid Nugent * an integral value. Whee. 36668bbf3adSDavid Nugent */ 36768bbf3adSDavid Nugent 36868bbf3adSDavid Nugent errno = 0; 36951706563SDavid Nugent tot = 0; 37068bbf3adSDavid Nugent while (*res) { 37151706563SDavid Nugent rlim_t tim = STRTOV(res, &ep, 0); 37268bbf3adSDavid Nugent if ((ep == NULL) || (ep == res) || errno) { 37368bbf3adSDavid Nugent return error; 37468bbf3adSDavid Nugent } 37568bbf3adSDavid Nugent /* Look for suffixes */ 37668bbf3adSDavid Nugent switch (*ep++) { 37768bbf3adSDavid Nugent case 0: 37868bbf3adSDavid Nugent ep--; break; /* end of string */ 37968bbf3adSDavid Nugent case 's': case 'S': /* seconds */ 38068bbf3adSDavid Nugent break; 38168bbf3adSDavid Nugent case 'm': case 'M': /* minutes */ 38268bbf3adSDavid Nugent tim *= 60L; 38368bbf3adSDavid Nugent break; 38468bbf3adSDavid Nugent case 'h': case 'H': /* hours */ 38568bbf3adSDavid Nugent tim *= (60L * 60L); 38668bbf3adSDavid Nugent break; 38768bbf3adSDavid Nugent case 'd': case 'D': /* days */ 38868bbf3adSDavid Nugent tim *= (60L * 60L * 24L); 38968bbf3adSDavid Nugent break; 39068bbf3adSDavid Nugent case 'w': case 'W': /* weeks */ 39168bbf3adSDavid Nugent tim *= (60L * 60L * 24L * 7L); 39268bbf3adSDavid Nugent case 'y': case 'Y': /* Years */ 39368bbf3adSDavid Nugent /* I refuse to take leap years into account here. Sue me. */ 39468bbf3adSDavid Nugent tim *= (60L * 60L * 24L * 365L); 39568bbf3adSDavid Nugent default: 39668bbf3adSDavid Nugent return error; 39768bbf3adSDavid Nugent } 39868bbf3adSDavid Nugent res = ep; 39968bbf3adSDavid Nugent tot += tim; 40068bbf3adSDavid Nugent } 40168bbf3adSDavid Nugent return tot; 40268bbf3adSDavid Nugent } 40368bbf3adSDavid Nugent 40468bbf3adSDavid Nugent 40568bbf3adSDavid Nugent /* 40668bbf3adSDavid Nugent * login_getcapnum() 40768bbf3adSDavid Nugent * From the login_cap_t <lc>, extract the numerical value <cap>. 40868bbf3adSDavid Nugent * If it is not present, return <def> for a default, and return 40968bbf3adSDavid Nugent * <error> if there is an error. 41068bbf3adSDavid Nugent * Like login_getcaptime(), only it only converts to a number, not 41168bbf3adSDavid Nugent * to a time; "infinity" and "inf" are 'special.' 41268bbf3adSDavid Nugent */ 41368bbf3adSDavid Nugent 41468bbf3adSDavid Nugent rlim_t 41568bbf3adSDavid Nugent login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) 41668bbf3adSDavid Nugent { 41768bbf3adSDavid Nugent char *ep, *res; 41868bbf3adSDavid Nugent int ret; 41968bbf3adSDavid Nugent rlim_t val; 42068bbf3adSDavid Nugent 42168bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 42268bbf3adSDavid Nugent return def; 42368bbf3adSDavid Nugent 42468bbf3adSDavid Nugent /* 42568bbf3adSDavid Nugent * For BSDI compatibility, try for the tag=<val> first 42668bbf3adSDavid Nugent */ 42768bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { 42868bbf3adSDavid Nugent long lval; 42968bbf3adSDavid Nugent /* 43068bbf3adSDavid Nugent * String capability not present, so try for tag#<val> as numeric 43168bbf3adSDavid Nugent */ 43268bbf3adSDavid Nugent if ((ret = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1) 43368bbf3adSDavid Nugent return def; /* Not there, so return default */ 43468bbf3adSDavid Nugent else if (ret < 0) 43568bbf3adSDavid Nugent return error; 43668bbf3adSDavid Nugent return (rlim_t)lval; 43768bbf3adSDavid Nugent } 43868bbf3adSDavid Nugent else if (ret < 0) 43968bbf3adSDavid Nugent return error; 44068bbf3adSDavid Nugent 44168bbf3adSDavid Nugent if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) 44268bbf3adSDavid Nugent return RLIM_INFINITY; 44368bbf3adSDavid Nugent 44468bbf3adSDavid Nugent errno = 0; 44568bbf3adSDavid Nugent val = STRTOV(res, &ep, 0); 44668bbf3adSDavid Nugent if ((ep == NULL) || (ep == res) || errno) 44768bbf3adSDavid Nugent return error; 44868bbf3adSDavid Nugent return val; 44968bbf3adSDavid Nugent } 45068bbf3adSDavid Nugent 45168bbf3adSDavid Nugent 45268bbf3adSDavid Nugent /* 45368bbf3adSDavid Nugent * login_getcapsize() 45468bbf3adSDavid Nugent * From the login_cap_t <lc>, extract the capability <cap>, which is 45568bbf3adSDavid Nugent * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity". 45668bbf3adSDavid Nugent * If not present, return <def>, or <error> if there is an error of 45768bbf3adSDavid Nugent * some sort. 45868bbf3adSDavid Nugent */ 45968bbf3adSDavid Nugent 46068bbf3adSDavid Nugent rlim_t 46168bbf3adSDavid Nugent login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { 46268bbf3adSDavid Nugent char *ep, *res; 46368bbf3adSDavid Nugent int ret; 46451706563SDavid Nugent rlim_t tot, mult; 46568bbf3adSDavid Nugent 46668bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 46768bbf3adSDavid Nugent return def; 46868bbf3adSDavid Nugent 46968bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) 47068bbf3adSDavid Nugent return def; 47168bbf3adSDavid Nugent else if (ret < 0) 47268bbf3adSDavid Nugent return error; 47368bbf3adSDavid Nugent 47468bbf3adSDavid Nugent errno = 0; 47551706563SDavid Nugent tot = 0; 47651706563SDavid Nugent while (*res) { 47751706563SDavid Nugent rlim_t val = STRTOV(res, &ep, 0); 47868bbf3adSDavid Nugent if ((res == NULL) || (res == ep) || errno) 47968bbf3adSDavid Nugent return error; 480f9074e29SDavid Nugent switch (*ep++) { 48168bbf3adSDavid Nugent case 0: /* end of string */ 48251706563SDavid Nugent ep--; 48351706563SDavid Nugent mult = 1; 48451706563SDavid Nugent break; 48568bbf3adSDavid Nugent case 'b': case 'B': /* 512-byte blocks */ 48668bbf3adSDavid Nugent mult = 512; break; 48768bbf3adSDavid Nugent case 'k': case 'K': /* 1024-byte Kilobytes */ 48868bbf3adSDavid Nugent mult = 1024; break; 48968bbf3adSDavid Nugent case 'm': case 'M': /* 1024-k kbytes */ 49068bbf3adSDavid Nugent mult = 1024 * 1024; break; 49168bbf3adSDavid Nugent case 'g': case 'G': /* 1Gbyte */ 49268bbf3adSDavid Nugent mult = 1024 * 1024 * 1024; break; 49368bbf3adSDavid Nugent #ifndef RLIM_LONG 49468bbf3adSDavid Nugent case 't': case 'T': /* 1TBte */ 49568bbf3adSDavid Nugent mult = 1024LL * 1024LL * 1024LL * 1024LL; break; 49668bbf3adSDavid Nugent #endif 49768bbf3adSDavid Nugent default: 49868bbf3adSDavid Nugent return error; 49968bbf3adSDavid Nugent } 500f9074e29SDavid Nugent res = ep; 50151706563SDavid Nugent tot += (val * mult); 50251706563SDavid Nugent } 50351706563SDavid Nugent return tot; 50468bbf3adSDavid Nugent } 50568bbf3adSDavid Nugent 50668bbf3adSDavid Nugent 50768bbf3adSDavid Nugent /* 50868bbf3adSDavid Nugent * login_getcapbool() 50968bbf3adSDavid Nugent * From the login_cap_t <lc>, check for the existance of the capability 51068bbf3adSDavid Nugent * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return 51168bbf3adSDavid Nugent * the whether or not <cap> exists there. 51268bbf3adSDavid Nugent */ 51368bbf3adSDavid Nugent 51468bbf3adSDavid Nugent int 51568bbf3adSDavid Nugent login_getcapbool(login_cap_t *lc, const char *cap, int def) 51668bbf3adSDavid Nugent { 51768bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 51868bbf3adSDavid Nugent return def; 51968bbf3adSDavid Nugent return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL); 52068bbf3adSDavid Nugent } 52168bbf3adSDavid Nugent 52268bbf3adSDavid Nugent 52368bbf3adSDavid Nugent /* 52468bbf3adSDavid Nugent * login_getstyle() 52568bbf3adSDavid Nugent * Given a login_cap entry <lc>, and optionally a type of auth <auth>, 52668bbf3adSDavid Nugent * and optionally a style <style>, find the style that best suits these 52768bbf3adSDavid Nugent * rules: 52868bbf3adSDavid Nugent * 1. If <auth> is non-null, look for an "auth-<auth>=" string 52968bbf3adSDavid Nugent * in the capability; if not present, default to "auth=". 53068bbf3adSDavid Nugent * 2. If there is no auth list found from (1), default to 53168bbf3adSDavid Nugent * "passwd" as an authorization list. 53268bbf3adSDavid Nugent * 3. If <style> is non-null, look for <style> in the list of 53368bbf3adSDavid Nugent * authorization methods found from (2); if <style> is NULL, default 53468bbf3adSDavid Nugent * to LOGIN_DEFSTYLE ("passwd"). 53568bbf3adSDavid Nugent * 4. If the chosen style is found in the chosen list of authorization 53668bbf3adSDavid Nugent * methods, return that; otherwise, return NULL. 53768bbf3adSDavid Nugent * E.g.: 53868bbf3adSDavid Nugent * login_getstyle(lc, NULL, "ftp"); 53968bbf3adSDavid Nugent * login_getstyle(lc, "login", NULL); 54068bbf3adSDavid Nugent * login_getstyle(lc, "skey", "network"); 54168bbf3adSDavid Nugent */ 54268bbf3adSDavid Nugent 54368bbf3adSDavid Nugent char * 54468bbf3adSDavid Nugent login_getstyle(login_cap_t *lc, char *style, const char *auth) 54568bbf3adSDavid Nugent { 54668bbf3adSDavid Nugent int i; 54768bbf3adSDavid Nugent char **authtypes = NULL; 54868bbf3adSDavid Nugent char *auths= NULL; 54968bbf3adSDavid Nugent char realauth[64]; 55068bbf3adSDavid Nugent 55168bbf3adSDavid Nugent static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; 55268bbf3adSDavid Nugent 55368bbf3adSDavid Nugent if (auth != NULL && *auth != '\0' && 55468bbf3adSDavid Nugent snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth) 55568bbf3adSDavid Nugent authtypes = login_getcaplist(lc, realauth, NULL); 55668bbf3adSDavid Nugent 55768bbf3adSDavid Nugent if (authtypes == NULL) 55868bbf3adSDavid Nugent authtypes = login_getcaplist(lc, "auth", NULL); 55968bbf3adSDavid Nugent 56068bbf3adSDavid Nugent if (authtypes == NULL) 56168bbf3adSDavid Nugent authtypes = defauthtypes; 56268bbf3adSDavid Nugent 56368bbf3adSDavid Nugent /* 56468bbf3adSDavid Nugent * We have at least one authtype now; auths is a comma-seperated 56568bbf3adSDavid Nugent * (or space-separated) list of authentication types. We have to 56668bbf3adSDavid Nugent * convert from this to an array of char*'s; authtypes then gets this. 56768bbf3adSDavid Nugent */ 56868bbf3adSDavid Nugent i = 0; 56968bbf3adSDavid Nugent if (style != NULL && *style != '\0') { 57068bbf3adSDavid Nugent while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0) 57168bbf3adSDavid Nugent i++; 57268bbf3adSDavid Nugent } 57368bbf3adSDavid Nugent lc->lc_style = NULL; 57468bbf3adSDavid Nugent if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL) 57568bbf3adSDavid Nugent lc->lc_style = auths; 57668bbf3adSDavid Nugent 57768bbf3adSDavid Nugent return lc->lc_style; 57868bbf3adSDavid Nugent } 57968bbf3adSDavid Nugent 58068bbf3adSDavid Nugent 581