]>
git.cameronkatri.com Git - pw-darwin.git/blob - libutil/login_cap.c
2 * Copyright (c) 1996 by
3 * Sean Eric Fagan <sef@kithrup.com>
4 * David Nugent <davidn@blaze.net.au>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, is permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice immediately at the beginning of the file, without modification,
12 * this list of conditions, and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. This work was done expressly for inclusion into FreeBSD. Other use
17 * is permitted provided this notation is included.
18 * 4. Absolutely no warranty of function or purpose is made by the authors.
19 * 5. Modifications may be freely made to this file providing the above
22 * Low-level routines relating to the user capabilities database
24 * $Id: login_cap.c,v 1.2 1997/01/07 13:29:21 davidn Exp $
33 #include <sys/types.h>
35 #include <sys/resource.h>
36 #include <sys/param.h>
38 #include <login_cap.h>
41 # define STRTOV strtol
43 # define STRTOV strtoq
46 static int lc_object_count
= 0;
48 static size_t internal_stringsz
= 0;
49 static char * internal_string
= NULL
;
50 static size_t internal_arraysz
= 0;
51 static char ** internal_array
= NULL
;
57 size_t sz
= strlen(str
) + 1; /* realloc() only if necessary */
58 if (sz
<= internal_stringsz
)
60 else if ((p
= realloc(internal_string
, sz
)) != NULL
) {
61 internal_stringsz
= sz
;
62 internal_string
= strcpy(p
, str
);
71 if (sz
<= internal_arraysz
)
73 else if ((p
= realloc(internal_array
, sz
* sizeof(char*))) != NULL
) {
74 internal_arraysz
= sz
;
83 * Turn a simple string <str> seperated by any of
84 * the set of <chars> into an array. The last element
85 * of the array will be NULL, as is proper.
86 * Free using freearraystr()
90 arrayize(char *str
, const char *chars
, int *size
)
96 for (i
= 0, ptr
= str
; *ptr
; i
++) {
97 int count
= strcspn(ptr
, chars
);
98 ptr
= ptr
+ count
+ 1;
101 if ((ptr
= allocstr(str
)) == NULL
) {
104 } else if ((res
= allocarray(++i
)) == NULL
) {
108 for (i
= 0; *ptr
; i
++) {
109 int count
= strcspn(ptr
, chars
);
123 freearraystr(char ** array
)
126 * the array[0] should be free'd, and then array.
137 * Frees up all resources relating to a login class
142 login_close(login_cap_t
* lc
)
148 if (--lc_object_count
== 0) {
149 free(internal_string
);
150 free(internal_array
);
151 internal_array
= NULL
;
152 internal_string
= NULL
;
160 * login_getclassbyname() get the login class by its name.
161 * If the name given is NULL or empty, the default class
162 * LOGIN_DEFCLASS (ie. "default") is fetched. If the
163 * 'dir' argument contains a non-NULL non-empty string,
164 * then the file _FILE_LOGIN_CONF is picked up from that
165 * directory instead of the system login database.
166 * Return a filled-out login_cap_t structure, including
167 * class name, and the capability record buffer.
171 login_getclassbyname(char const * name
, char const * dir
)
173 login_cap_t
*lc
= malloc(sizeof(login_cap_t
));
177 char userpath
[MAXPATHLEN
];
178 static char *login_dbarray
[] = { NULL
, NULL
, NULL
};
180 if (dir
&& snprintf(userpath
, MAXPATHLEN
, "%s/%s", dir
, _FILE_LOGIN_CONF
) < MAXPATHLEN
)
181 login_dbarray
[i
++] = userpath
;
183 login_dbarray
[i
++] = _PATH_LOGIN_CONF
;
184 login_dbarray
[i
] = NULL
;
186 lc
->lc_cap
= lc
->lc_class
= lc
->lc_style
= NULL
;
188 if ((name
== NULL
|| cgetent(&lc
->lc_cap
, login_dbarray
, (char*)name
) != 0) &&
189 cgetent(&lc
->lc_cap
, login_dbarray
, (char*)(name
= LOGIN_DEFCLASS
)) != 0) {
194 lc
->lc_class
= strdup(name
);
205 * Get the login class for a given password entry from
206 * the system (only) login class database.
207 * If the password entry's class field is not set, or
208 * the class specified does not exist, then use the
209 * default of LOGIN_DEFCLASS (ie. "default").
210 * Return a filled-out login_cap_t structure, including
211 * class name, and the capability record buffer.
215 login_getclass(const struct passwd
*pwd
)
217 const char * class = NULL
;
219 if ((class = pwd
->pw_class
) == NULL
|| *class == '\0')
220 class = (pwd
->pw_uid
== 0) ? "root" : NULL
;
222 return login_getclassbyname(class, 0);
227 * login_getuserclass()
228 * Get the login class for a given password entry, allowing user
229 * overrides via ~/.login_conf.
230 * ### WAS: If the password entry's class field is not set,
231 * ####### or the class specified does not exist, then use
232 * If an entry with the recordid "me" does not exist, then use
233 * the default of LOGIN_DEFCLASS (ie. "default").
234 * Return a filled-out login_cap_t structure, including
235 * class name, and the capability record buffer.
239 login_getuserclass(const struct passwd
*pwd
)
241 const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */
242 const char * home
= (pwd
== NULL
) ? NULL
: pwd
->pw_dir
;
243 return login_getclassbyname(class, home
);
250 * Given a login_cap entry, and a capability name, return the
251 * value defined for that capability, a defualt if not found, or
252 * an error string on error.
256 login_getcapstr(login_cap_t
*lc
, const char *cap
, char *def
, char *error
)
261 if (lc
== NULL
|| cap
== NULL
|| lc
->lc_cap
== NULL
|| *cap
== '\0')
264 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1) {
275 * Given a login_cap entry, and a capability name, return the
276 * value defined for that capability split into an array of
281 login_getcaplist(login_cap_t
*lc
, const char * cap
, const char * chars
)
287 if ((lstring
= login_getcapstr(lc
, (char*)cap
, NULL
, NULL
)) != NULL
)
288 return arrayize(lstring
, chars
, NULL
);
295 * From the login_cap_t <lc>, get the capability <cap> which is
296 * formatted as either a space or comma delimited list of paths
297 * and append them all into a string and separate by semicolons.
298 * If there is an error of any kind, return <error>.
302 login_getpath(login_cap_t
*lc
, const char *cap
, char * error
)
304 char *ptr
, *str
= login_getcapstr(lc
, (char*)cap
, NULL
, NULL
);
306 if (str
== NULL
|| (ptr
= allocstr(str
)) == NULL
)
310 int count
= strcspn(ptr
, ", \t");
322 * From the login_cap_t <lc>, get the capability <cap>, which is
323 * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not
324 * present in <lc>, return <def>; if there is an error of some kind,
329 login_getcaptime(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
)
336 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
340 * Look for <cap> in lc_cap.
341 * If it's not there (-1), return <def>.
342 * If there's an error, return <error>.
345 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1)
351 * "inf" and "infinity" are two special cases for this.
353 if (!strcasecmp(res
, "infinity") || !strcasecmp(res
, "inf"))
354 return RLIM_INFINITY
;
357 * Now go through the string, turning something like 1h2m3s into
358 * an integral value. Whee.
363 tim
= STRTOV(res
, &ep
, 0);
364 if ((ep
== NULL
) || (ep
== res
) || errno
) {
367 /* Look for suffixes */
370 ep
--; break; /* end of string */
371 case 's': case 'S': /* seconds */
373 case 'm': case 'M': /* minutes */
376 case 'h': case 'H': /* hours */
379 case 'd': case 'D': /* days */
380 tim
*= (60L * 60L * 24L);
382 case 'w': case 'W': /* weeks */
383 tim
*= (60L * 60L * 24L * 7L);
384 case 'y': case 'Y': /* Years */
385 /* I refuse to take leap years into account here. Sue me. */
386 tim
*= (60L * 60L * 24L * 365L);
399 * From the login_cap_t <lc>, extract the numerical value <cap>.
400 * If it is not present, return <def> for a default, and return
401 * <error> if there is an error.
402 * Like login_getcaptime(), only it only converts to a number, not
403 * to a time; "infinity" and "inf" are 'special.'
407 login_getcapnum(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
)
413 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
417 * For BSDI compatibility, try for the tag=<val> first
419 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1) {
422 * String capability not present, so try for tag#<val> as numeric
424 if ((ret
= cgetnum(lc
->lc_cap
, (char *)cap
, &lval
)) == -1)
425 return def
; /* Not there, so return default */
433 if (!strcasecmp(res
, "infinity") || !strcasecmp(res
, "inf"))
434 return RLIM_INFINITY
;
437 val
= STRTOV(res
, &ep
, 0);
438 if ((ep
== NULL
) || (ep
== res
) || errno
)
446 * From the login_cap_t <lc>, extract the capability <cap>, which is
447 * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity".
448 * If not present, return <def>, or <error> if there is an error of
453 login_getcapsize(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
) {
459 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
462 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1)
468 val
= STRTOV(res
, &ep
, 0);
469 if ((res
== NULL
) || (res
== ep
) || errno
)
472 case 0: /* end of string */
474 case 'b': case 'B': /* 512-byte blocks */
476 case 'k': case 'K': /* 1024-byte Kilobytes */
478 case 'm': case 'M': /* 1024-k kbytes */
479 mult
= 1024 * 1024; break;
480 case 'g': case 'G': /* 1Gbyte */
481 mult
= 1024 * 1024 * 1024; break;
483 case 't': case 'T': /* 1TBte */
484 mult
= 1024LL * 1024LL * 1024LL * 1024LL; break;
495 * From the login_cap_t <lc>, check for the existance of the capability
496 * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return
497 * the whether or not <cap> exists there.
501 login_getcapbool(login_cap_t
*lc
, const char *cap
, int def
)
503 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
505 return (cgetcap(lc
->lc_cap
, (char *)cap
, ':') != NULL
);
511 * Given a login_cap entry <lc>, and optionally a type of auth <auth>,
512 * and optionally a style <style>, find the style that best suits these
514 * 1. If <auth> is non-null, look for an "auth-<auth>=" string
515 * in the capability; if not present, default to "auth=".
516 * 2. If there is no auth list found from (1), default to
517 * "passwd" as an authorization list.
518 * 3. If <style> is non-null, look for <style> in the list of
519 * authorization methods found from (2); if <style> is NULL, default
520 * to LOGIN_DEFSTYLE ("passwd").
521 * 4. If the chosen style is found in the chosen list of authorization
522 * methods, return that; otherwise, return NULL.
524 * login_getstyle(lc, NULL, "ftp");
525 * login_getstyle(lc, "login", NULL);
526 * login_getstyle(lc, "skey", "network");
530 login_getstyle(login_cap_t
*lc
, char *style
, const char *auth
)
533 char **authtypes
= NULL
;
537 static char *defauthtypes
[] = { LOGIN_DEFSTYLE
, NULL
};
539 if (auth
!= NULL
&& *auth
!= '\0' &&
540 snprintf(realauth
, sizeof realauth
, "auth-%s", auth
) < sizeof realauth
)
541 authtypes
= login_getcaplist(lc
, realauth
, NULL
);
543 if (authtypes
== NULL
)
544 authtypes
= login_getcaplist(lc
, "auth", NULL
);
546 if (authtypes
== NULL
)
547 authtypes
= defauthtypes
;
550 * We have at least one authtype now; auths is a comma-seperated
551 * (or space-separated) list of authentication types. We have to
552 * convert from this to an array of char*'s; authtypes then gets this.
555 if (style
!= NULL
&& *style
!= '\0') {
556 while (authtypes
[i
] != NULL
&& strcmp(style
, authtypes
[i
]) != 0)
560 if (authtypes
[i
] != NULL
&& (auths
= strdup(authtypes
[i
])) != NULL
)
561 lc
->lc_style
= auths
;