xref: /freebsd/lib/libutil/login_cap.c (revision f01e39893b93ef5fd9595edcbbd3cc9cdcf55fd2)
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