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 * 2465f50b7fSAndrey A. Chernov * $Id: login_cap.c,v 1.10 1997/02/22 15:08:20 peter Exp $ 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 /* 12568bbf3adSDavid Nugent * login_close() 12668bbf3adSDavid Nugent * Frees up all resources relating to a login class 12768bbf3adSDavid Nugent * 12868bbf3adSDavid Nugent */ 12968bbf3adSDavid Nugent 13068bbf3adSDavid Nugent void 13168bbf3adSDavid Nugent login_close(login_cap_t * lc) 13268bbf3adSDavid Nugent { 13368bbf3adSDavid Nugent if (lc) { 13468bbf3adSDavid Nugent free(lc->lc_style); 13568bbf3adSDavid Nugent free(lc->lc_class); 13668bbf3adSDavid Nugent free(lc); 13768bbf3adSDavid Nugent if (--lc_object_count == 0) { 13868bbf3adSDavid Nugent free(internal_string); 1392955fda4SDavid Nugent free(internal_array); 14068bbf3adSDavid Nugent internal_array = NULL; 14151706563SDavid Nugent internal_arraysz = 0; 14268bbf3adSDavid Nugent internal_string = NULL; 14351706563SDavid Nugent internal_stringsz = 0; 14468bbf3adSDavid Nugent cgetclose(); 14568bbf3adSDavid Nugent } 14668bbf3adSDavid Nugent } 14768bbf3adSDavid Nugent } 14868bbf3adSDavid Nugent 14968bbf3adSDavid Nugent 15068bbf3adSDavid Nugent /* 15168bbf3adSDavid Nugent * login_getclassbyname() get the login class by its name. 15268bbf3adSDavid Nugent * If the name given is NULL or empty, the default class 15368bbf3adSDavid Nugent * LOGIN_DEFCLASS (ie. "default") is fetched. If the 15468bbf3adSDavid Nugent * 'dir' argument contains a non-NULL non-empty string, 15568bbf3adSDavid Nugent * then the file _FILE_LOGIN_CONF is picked up from that 15668bbf3adSDavid Nugent * directory instead of the system login database. 15768bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 15868bbf3adSDavid Nugent * class name, and the capability record buffer. 15968bbf3adSDavid Nugent */ 16068bbf3adSDavid Nugent 16168bbf3adSDavid Nugent login_cap_t * 16268bbf3adSDavid Nugent login_getclassbyname(char const * name, char const * dir) 16368bbf3adSDavid Nugent { 16468bbf3adSDavid Nugent login_cap_t *lc = malloc(sizeof(login_cap_t)); 16568bbf3adSDavid Nugent 16668bbf3adSDavid Nugent if (lc != NULL) { 16768bbf3adSDavid Nugent int i = 0; 16868bbf3adSDavid Nugent char userpath[MAXPATHLEN]; 16968bbf3adSDavid Nugent static char *login_dbarray[] = { NULL, NULL, NULL }; 17068bbf3adSDavid Nugent 17168bbf3adSDavid Nugent if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, _FILE_LOGIN_CONF) < MAXPATHLEN) 17268bbf3adSDavid Nugent login_dbarray[i++] = userpath; 17368bbf3adSDavid Nugent else 17468bbf3adSDavid Nugent login_dbarray[i++] = _PATH_LOGIN_CONF; 17568bbf3adSDavid Nugent login_dbarray[i ] = NULL; 17668bbf3adSDavid Nugent 17768bbf3adSDavid Nugent lc->lc_cap = lc->lc_class = lc->lc_style = NULL; 17868bbf3adSDavid Nugent 17968bbf3adSDavid Nugent if ((name == NULL || cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0) && 18068bbf3adSDavid Nugent cgetent(&lc->lc_cap, login_dbarray, (char*)(name = LOGIN_DEFCLASS)) != 0) { 18168bbf3adSDavid Nugent free(lc); 18268bbf3adSDavid Nugent lc = NULL; 18368bbf3adSDavid Nugent } else { 18468bbf3adSDavid Nugent ++lc_object_count; 18568bbf3adSDavid Nugent lc->lc_class = strdup(name); 18668bbf3adSDavid Nugent } 18768bbf3adSDavid Nugent } 18868bbf3adSDavid Nugent 18968bbf3adSDavid Nugent return lc; 19068bbf3adSDavid Nugent } 19168bbf3adSDavid Nugent 19268bbf3adSDavid Nugent 19368bbf3adSDavid Nugent 19468bbf3adSDavid Nugent /* 19568bbf3adSDavid Nugent * login_getclass() 19668bbf3adSDavid Nugent * Get the login class for a given password entry from 19768bbf3adSDavid Nugent * the system (only) login class database. 19868bbf3adSDavid Nugent * If the password entry's class field is not set, or 19968bbf3adSDavid Nugent * the class specified does not exist, then use the 20068bbf3adSDavid Nugent * default of LOGIN_DEFCLASS (ie. "default"). 20168bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 20268bbf3adSDavid Nugent * class name, and the capability record buffer. 20368bbf3adSDavid Nugent */ 20468bbf3adSDavid Nugent 20568bbf3adSDavid Nugent login_cap_t * 20668bbf3adSDavid Nugent login_getclass(const struct passwd *pwd) 20768bbf3adSDavid Nugent { 2082dc7d862SDavid Nugent const char * class = NULL; 2091c594de5SDavid Nugent if (pwd != NULL) { 21065fa0ae1SDavid Nugent if ((class = pwd->pw_class) == NULL || *class == '\0') 2112dc7d862SDavid Nugent class = (pwd->pw_uid == 0) ? "root" : NULL; 2122dc7d862SDavid Nugent } 21368bbf3adSDavid Nugent return login_getclassbyname(class, 0); 21468bbf3adSDavid Nugent } 21568bbf3adSDavid Nugent 21668bbf3adSDavid Nugent 21768bbf3adSDavid Nugent /* 21868bbf3adSDavid Nugent * login_getuserclass() 21968bbf3adSDavid Nugent * Get the login class for a given password entry, allowing user 22068bbf3adSDavid Nugent * overrides via ~/.login_conf. 22168bbf3adSDavid Nugent * ### WAS: If the password entry's class field is not set, 22268bbf3adSDavid Nugent * ####### or the class specified does not exist, then use 22368bbf3adSDavid Nugent * If an entry with the recordid "me" does not exist, then use 22468bbf3adSDavid Nugent * the default of LOGIN_DEFCLASS (ie. "default"). 22568bbf3adSDavid Nugent * Return a filled-out login_cap_t structure, including 22668bbf3adSDavid Nugent * class name, and the capability record buffer. 22768bbf3adSDavid Nugent */ 22868bbf3adSDavid Nugent 22968bbf3adSDavid Nugent login_cap_t * 23068bbf3adSDavid Nugent login_getuserclass(const struct passwd *pwd) 23168bbf3adSDavid Nugent { 23268bbf3adSDavid Nugent const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */ 23368bbf3adSDavid Nugent const char * home = (pwd == NULL) ? NULL : pwd->pw_dir; 23468bbf3adSDavid Nugent return login_getclassbyname(class, home); 23568bbf3adSDavid Nugent } 23668bbf3adSDavid Nugent 23768bbf3adSDavid Nugent 23868bbf3adSDavid Nugent 23968bbf3adSDavid Nugent /* 24068bbf3adSDavid Nugent * login_getcapstr() 24168bbf3adSDavid Nugent * Given a login_cap entry, and a capability name, return the 24268bbf3adSDavid Nugent * value defined for that capability, a defualt if not found, or 24368bbf3adSDavid Nugent * an error string on error. 24468bbf3adSDavid Nugent */ 24568bbf3adSDavid Nugent 24668bbf3adSDavid Nugent char * 24768bbf3adSDavid Nugent login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error) 24868bbf3adSDavid Nugent { 24968bbf3adSDavid Nugent char *res; 25068bbf3adSDavid Nugent int ret; 25168bbf3adSDavid Nugent 25268bbf3adSDavid Nugent if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') 25368bbf3adSDavid Nugent return def; 25468bbf3adSDavid Nugent 25568bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { 25668bbf3adSDavid Nugent return def; 25768bbf3adSDavid Nugent } else if (ret >= 0) 25868bbf3adSDavid Nugent return res; 25968bbf3adSDavid Nugent else 26068bbf3adSDavid Nugent return error; 26168bbf3adSDavid Nugent } 26268bbf3adSDavid Nugent 26368bbf3adSDavid Nugent 26468bbf3adSDavid Nugent /* 26568bbf3adSDavid Nugent * login_getcaplist() 26668bbf3adSDavid Nugent * Given a login_cap entry, and a capability name, return the 26768bbf3adSDavid Nugent * value defined for that capability split into an array of 26868bbf3adSDavid Nugent * strings. 26968bbf3adSDavid Nugent */ 27068bbf3adSDavid Nugent 27168bbf3adSDavid Nugent char ** 27268bbf3adSDavid Nugent login_getcaplist(login_cap_t *lc, const char * cap, const char * chars) 27368bbf3adSDavid Nugent { 27468bbf3adSDavid Nugent char * lstring; 27568bbf3adSDavid Nugent 27668bbf3adSDavid Nugent if (chars == NULL) 277f01e3989SDavid Nugent chars = ", \t"; 27868bbf3adSDavid Nugent if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL) 27968bbf3adSDavid Nugent return arrayize(lstring, chars, NULL); 28068bbf3adSDavid Nugent return NULL; 28168bbf3adSDavid Nugent } 28268bbf3adSDavid Nugent 28368bbf3adSDavid Nugent 28468bbf3adSDavid Nugent /* 28568bbf3adSDavid Nugent * login_getpath() 28668bbf3adSDavid Nugent * From the login_cap_t <lc>, get the capability <cap> which is 28768bbf3adSDavid Nugent * formatted as either a space or comma delimited list of paths 28868bbf3adSDavid Nugent * and append them all into a string and separate by semicolons. 28968bbf3adSDavid Nugent * If there is an error of any kind, return <error>. 29068bbf3adSDavid Nugent */ 29168bbf3adSDavid Nugent 29268bbf3adSDavid Nugent char * 29368bbf3adSDavid Nugent login_getpath(login_cap_t *lc, const char *cap, char * error) 29468bbf3adSDavid Nugent { 2951c594de5SDavid Nugent char *str = login_getcapstr(lc, (char*)cap, NULL, NULL); 29668bbf3adSDavid Nugent 2971c594de5SDavid Nugent if (str == NULL) 29868bbf3adSDavid Nugent str = error; 29968bbf3adSDavid Nugent else { 3001c594de5SDavid Nugent char *ptr = str; 3011c594de5SDavid Nugent 30268bbf3adSDavid Nugent while (*ptr) { 30368bbf3adSDavid Nugent int count = strcspn(ptr, ", \t"); 30468bbf3adSDavid Nugent ptr += count; 30568bbf3adSDavid Nugent if (*ptr) 30668bbf3adSDavid Nugent *ptr++ = ':'; 30768bbf3adSDavid Nugent } 30868bbf3adSDavid Nugent } 30968bbf3adSDavid Nugent return str; 31068bbf3adSDavid Nugent } 31168bbf3adSDavid Nugent 31268bbf3adSDavid Nugent 31368bbf3adSDavid Nugent /* 31468bbf3adSDavid Nugent * login_getcaptime() 31568bbf3adSDavid Nugent * From the login_cap_t <lc>, get the capability <cap>, which is 31668bbf3adSDavid Nugent * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not 31768bbf3adSDavid Nugent * present in <lc>, return <def>; if there is an error of some kind, 31868bbf3adSDavid Nugent * return <error>. 31968bbf3adSDavid Nugent */ 32068bbf3adSDavid Nugent 32168bbf3adSDavid Nugent rlim_t 32268bbf3adSDavid Nugent login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) 32368bbf3adSDavid Nugent { 32468bbf3adSDavid Nugent char *res, *ep; 32568bbf3adSDavid Nugent int ret; 32651706563SDavid Nugent rlim_t tot; 32768bbf3adSDavid Nugent 32868bbf3adSDavid Nugent errno = 0; 32968bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 33068bbf3adSDavid Nugent return def; 33168bbf3adSDavid Nugent 33268bbf3adSDavid Nugent /* 33368bbf3adSDavid Nugent * Look for <cap> in lc_cap. 33468bbf3adSDavid Nugent * If it's not there (-1), return <def>. 33568bbf3adSDavid Nugent * If there's an error, return <error>. 33668bbf3adSDavid Nugent */ 33768bbf3adSDavid Nugent 33868bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) 33968bbf3adSDavid Nugent return def; 34068bbf3adSDavid Nugent else if (ret < 0) 34168bbf3adSDavid Nugent return error; 34268bbf3adSDavid Nugent 34368bbf3adSDavid Nugent /* 34468bbf3adSDavid Nugent * "inf" and "infinity" are two special cases for this. 34568bbf3adSDavid Nugent */ 34668bbf3adSDavid Nugent if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) 34768bbf3adSDavid Nugent return RLIM_INFINITY; 34868bbf3adSDavid Nugent 34968bbf3adSDavid Nugent /* 35068bbf3adSDavid Nugent * Now go through the string, turning something like 1h2m3s into 35168bbf3adSDavid Nugent * an integral value. Whee. 35268bbf3adSDavid Nugent */ 35368bbf3adSDavid Nugent 35468bbf3adSDavid Nugent errno = 0; 35551706563SDavid Nugent tot = 0; 35668bbf3adSDavid Nugent while (*res) { 35751706563SDavid Nugent rlim_t tim = STRTOV(res, &ep, 0); 35868bbf3adSDavid Nugent if ((ep == NULL) || (ep == res) || errno) { 35968bbf3adSDavid Nugent return error; 36068bbf3adSDavid Nugent } 36168bbf3adSDavid Nugent /* Look for suffixes */ 36268bbf3adSDavid Nugent switch (*ep++) { 36368bbf3adSDavid Nugent case 0: 36468bbf3adSDavid Nugent ep--; break; /* end of string */ 36568bbf3adSDavid Nugent case 's': case 'S': /* seconds */ 36668bbf3adSDavid Nugent break; 36768bbf3adSDavid Nugent case 'm': case 'M': /* minutes */ 36868bbf3adSDavid Nugent tim *= 60L; 36968bbf3adSDavid Nugent break; 37068bbf3adSDavid Nugent case 'h': case 'H': /* hours */ 37168bbf3adSDavid Nugent tim *= (60L * 60L); 37268bbf3adSDavid Nugent break; 37368bbf3adSDavid Nugent case 'd': case 'D': /* days */ 37468bbf3adSDavid Nugent tim *= (60L * 60L * 24L); 37568bbf3adSDavid Nugent break; 37668bbf3adSDavid Nugent case 'w': case 'W': /* weeks */ 37768bbf3adSDavid Nugent tim *= (60L * 60L * 24L * 7L); 37868bbf3adSDavid Nugent case 'y': case 'Y': /* Years */ 37968bbf3adSDavid Nugent /* I refuse to take leap years into account here. Sue me. */ 38068bbf3adSDavid Nugent tim *= (60L * 60L * 24L * 365L); 38168bbf3adSDavid Nugent default: 38268bbf3adSDavid Nugent return error; 38368bbf3adSDavid Nugent } 38468bbf3adSDavid Nugent res = ep; 38568bbf3adSDavid Nugent tot += tim; 38668bbf3adSDavid Nugent } 38768bbf3adSDavid Nugent return tot; 38868bbf3adSDavid Nugent } 38968bbf3adSDavid Nugent 39068bbf3adSDavid Nugent 39168bbf3adSDavid Nugent /* 39268bbf3adSDavid Nugent * login_getcapnum() 39368bbf3adSDavid Nugent * From the login_cap_t <lc>, extract the numerical value <cap>. 39468bbf3adSDavid Nugent * If it is not present, return <def> for a default, and return 39568bbf3adSDavid Nugent * <error> if there is an error. 39668bbf3adSDavid Nugent * Like login_getcaptime(), only it only converts to a number, not 39768bbf3adSDavid Nugent * to a time; "infinity" and "inf" are 'special.' 39868bbf3adSDavid Nugent */ 39968bbf3adSDavid Nugent 40068bbf3adSDavid Nugent rlim_t 40168bbf3adSDavid Nugent login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) 40268bbf3adSDavid Nugent { 40368bbf3adSDavid Nugent char *ep, *res; 40468bbf3adSDavid Nugent int ret; 40568bbf3adSDavid Nugent rlim_t val; 40668bbf3adSDavid Nugent 40768bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 40868bbf3adSDavid Nugent return def; 40968bbf3adSDavid Nugent 41068bbf3adSDavid Nugent /* 41168bbf3adSDavid Nugent * For BSDI compatibility, try for the tag=<val> first 41268bbf3adSDavid Nugent */ 41368bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) { 41468bbf3adSDavid Nugent long lval; 41568bbf3adSDavid Nugent /* 41668bbf3adSDavid Nugent * String capability not present, so try for tag#<val> as numeric 41768bbf3adSDavid Nugent */ 41868bbf3adSDavid Nugent if ((ret = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1) 41968bbf3adSDavid Nugent return def; /* Not there, so return default */ 42068bbf3adSDavid Nugent else if (ret < 0) 42168bbf3adSDavid Nugent return error; 42268bbf3adSDavid Nugent return (rlim_t)lval; 42368bbf3adSDavid Nugent } 42468bbf3adSDavid Nugent else if (ret < 0) 42568bbf3adSDavid Nugent return error; 42668bbf3adSDavid Nugent 42768bbf3adSDavid Nugent if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) 42868bbf3adSDavid Nugent return RLIM_INFINITY; 42968bbf3adSDavid Nugent 43068bbf3adSDavid Nugent errno = 0; 43168bbf3adSDavid Nugent val = STRTOV(res, &ep, 0); 43268bbf3adSDavid Nugent if ((ep == NULL) || (ep == res) || errno) 43368bbf3adSDavid Nugent return error; 43468bbf3adSDavid Nugent return val; 43568bbf3adSDavid Nugent } 43668bbf3adSDavid Nugent 43768bbf3adSDavid Nugent 43868bbf3adSDavid Nugent /* 43968bbf3adSDavid Nugent * login_getcapsize() 44068bbf3adSDavid Nugent * From the login_cap_t <lc>, extract the capability <cap>, which is 44168bbf3adSDavid Nugent * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity". 44268bbf3adSDavid Nugent * If not present, return <def>, or <error> if there is an error of 44368bbf3adSDavid Nugent * some sort. 44468bbf3adSDavid Nugent */ 44568bbf3adSDavid Nugent 44668bbf3adSDavid Nugent rlim_t 44768bbf3adSDavid Nugent login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) { 44868bbf3adSDavid Nugent char *ep, *res; 44968bbf3adSDavid Nugent int ret; 45051706563SDavid Nugent rlim_t tot, mult; 45168bbf3adSDavid Nugent 45268bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 45368bbf3adSDavid Nugent return def; 45468bbf3adSDavid Nugent 45568bbf3adSDavid Nugent if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) 45668bbf3adSDavid Nugent return def; 45768bbf3adSDavid Nugent else if (ret < 0) 45868bbf3adSDavid Nugent return error; 45968bbf3adSDavid Nugent 46065f50b7fSAndrey A. Chernov /* 46165f50b7fSAndrey A. Chernov * "inf" and "infinity" are two special cases for this. 46265f50b7fSAndrey A. Chernov */ 46365f50b7fSAndrey A. Chernov if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf")) 46465f50b7fSAndrey A. Chernov return RLIM_INFINITY; 46565f50b7fSAndrey A. Chernov 46668bbf3adSDavid Nugent errno = 0; 46751706563SDavid Nugent tot = 0; 46851706563SDavid Nugent while (*res) { 46951706563SDavid Nugent rlim_t val = STRTOV(res, &ep, 0); 47068bbf3adSDavid Nugent if ((res == NULL) || (res == ep) || errno) 47168bbf3adSDavid Nugent return error; 472f9074e29SDavid Nugent switch (*ep++) { 47368bbf3adSDavid Nugent case 0: /* end of string */ 47451706563SDavid Nugent ep--; 47551706563SDavid Nugent mult = 1; 47651706563SDavid Nugent break; 47768bbf3adSDavid Nugent case 'b': case 'B': /* 512-byte blocks */ 47868bbf3adSDavid Nugent mult = 512; break; 47968bbf3adSDavid Nugent case 'k': case 'K': /* 1024-byte Kilobytes */ 48068bbf3adSDavid Nugent mult = 1024; break; 48168bbf3adSDavid Nugent case 'm': case 'M': /* 1024-k kbytes */ 48268bbf3adSDavid Nugent mult = 1024 * 1024; break; 48368bbf3adSDavid Nugent case 'g': case 'G': /* 1Gbyte */ 48468bbf3adSDavid Nugent mult = 1024 * 1024 * 1024; break; 48568bbf3adSDavid Nugent #ifndef RLIM_LONG 48668bbf3adSDavid Nugent case 't': case 'T': /* 1TBte */ 48768bbf3adSDavid Nugent mult = 1024LL * 1024LL * 1024LL * 1024LL; break; 48868bbf3adSDavid Nugent #endif 48968bbf3adSDavid Nugent default: 49068bbf3adSDavid Nugent return error; 49168bbf3adSDavid Nugent } 492f9074e29SDavid Nugent res = ep; 49351706563SDavid Nugent tot += (val * mult); 49451706563SDavid Nugent } 49551706563SDavid Nugent return tot; 49668bbf3adSDavid Nugent } 49768bbf3adSDavid Nugent 49868bbf3adSDavid Nugent 49968bbf3adSDavid Nugent /* 50068bbf3adSDavid Nugent * login_getcapbool() 50168bbf3adSDavid Nugent * From the login_cap_t <lc>, check for the existance of the capability 50268bbf3adSDavid Nugent * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return 50368bbf3adSDavid Nugent * the whether or not <cap> exists there. 50468bbf3adSDavid Nugent */ 50568bbf3adSDavid Nugent 50668bbf3adSDavid Nugent int 50768bbf3adSDavid Nugent login_getcapbool(login_cap_t *lc, const char *cap, int def) 50868bbf3adSDavid Nugent { 50968bbf3adSDavid Nugent if (lc == NULL || lc->lc_cap == NULL) 51068bbf3adSDavid Nugent return def; 51168bbf3adSDavid Nugent return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL); 51268bbf3adSDavid Nugent } 51368bbf3adSDavid Nugent 51468bbf3adSDavid Nugent 51568bbf3adSDavid Nugent /* 51668bbf3adSDavid Nugent * login_getstyle() 51768bbf3adSDavid Nugent * Given a login_cap entry <lc>, and optionally a type of auth <auth>, 51868bbf3adSDavid Nugent * and optionally a style <style>, find the style that best suits these 51968bbf3adSDavid Nugent * rules: 52068bbf3adSDavid Nugent * 1. If <auth> is non-null, look for an "auth-<auth>=" string 52168bbf3adSDavid Nugent * in the capability; if not present, default to "auth=". 52268bbf3adSDavid Nugent * 2. If there is no auth list found from (1), default to 52368bbf3adSDavid Nugent * "passwd" as an authorization list. 52468bbf3adSDavid Nugent * 3. If <style> is non-null, look for <style> in the list of 52568bbf3adSDavid Nugent * authorization methods found from (2); if <style> is NULL, default 52668bbf3adSDavid Nugent * to LOGIN_DEFSTYLE ("passwd"). 52768bbf3adSDavid Nugent * 4. If the chosen style is found in the chosen list of authorization 52868bbf3adSDavid Nugent * methods, return that; otherwise, return NULL. 52968bbf3adSDavid Nugent * E.g.: 53068bbf3adSDavid Nugent * login_getstyle(lc, NULL, "ftp"); 53168bbf3adSDavid Nugent * login_getstyle(lc, "login", NULL); 53268bbf3adSDavid Nugent * login_getstyle(lc, "skey", "network"); 53368bbf3adSDavid Nugent */ 53468bbf3adSDavid Nugent 53568bbf3adSDavid Nugent char * 53668bbf3adSDavid Nugent login_getstyle(login_cap_t *lc, char *style, const char *auth) 53768bbf3adSDavid Nugent { 53868bbf3adSDavid Nugent int i; 53968bbf3adSDavid Nugent char **authtypes = NULL; 54068bbf3adSDavid Nugent char *auths= NULL; 54168bbf3adSDavid Nugent char realauth[64]; 54268bbf3adSDavid Nugent 54368bbf3adSDavid Nugent static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL }; 54468bbf3adSDavid Nugent 54568bbf3adSDavid Nugent if (auth != NULL && *auth != '\0' && 54668bbf3adSDavid Nugent snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth) 54768bbf3adSDavid Nugent authtypes = login_getcaplist(lc, realauth, NULL); 54868bbf3adSDavid Nugent 54968bbf3adSDavid Nugent if (authtypes == NULL) 55068bbf3adSDavid Nugent authtypes = login_getcaplist(lc, "auth", NULL); 55168bbf3adSDavid Nugent 55268bbf3adSDavid Nugent if (authtypes == NULL) 55368bbf3adSDavid Nugent authtypes = defauthtypes; 55468bbf3adSDavid Nugent 55568bbf3adSDavid Nugent /* 55668bbf3adSDavid Nugent * We have at least one authtype now; auths is a comma-seperated 55768bbf3adSDavid Nugent * (or space-separated) list of authentication types. We have to 55868bbf3adSDavid Nugent * convert from this to an array of char*'s; authtypes then gets this. 55968bbf3adSDavid Nugent */ 56068bbf3adSDavid Nugent i = 0; 56168bbf3adSDavid Nugent if (style != NULL && *style != '\0') { 56268bbf3adSDavid Nugent while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0) 56368bbf3adSDavid Nugent i++; 56468bbf3adSDavid Nugent } 56568bbf3adSDavid Nugent lc->lc_style = NULL; 56668bbf3adSDavid Nugent if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL) 56768bbf3adSDavid Nugent lc->lc_style = auths; 56868bbf3adSDavid Nugent 56968bbf3adSDavid Nugent return lc->lc_style; 57068bbf3adSDavid Nugent } 57168bbf3adSDavid Nugent 57268bbf3adSDavid Nugent 573