]>
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
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
)
59 p
= strcpy(internal_string
, str
);
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
);
103 if ((ptr
= allocstr(str
)) == NULL
) {
106 } else if ((res
= allocarray(++i
)) == NULL
) {
110 for (i
= 0; *ptr
; i
++) {
111 int count
= strcspn(ptr
, chars
);
125 freearraystr(char ** array
)
128 * the array[0] should be free'd, and then array.
139 * Frees up all resources relating to a login class
144 login_close(login_cap_t
* lc
)
150 if (--lc_object_count
== 0) {
151 free(internal_string
);
152 free(internal_array
);
153 internal_array
= NULL
;
154 internal_string
= NULL
;
162 * login_getclassbyname() get the login class by its name.
163 * If the name given is NULL or empty, the default class
164 * LOGIN_DEFCLASS (ie. "default") is fetched. If the
165 * 'dir' argument contains a non-NULL non-empty string,
166 * then the file _FILE_LOGIN_CONF is picked up from that
167 * directory instead of the system login database.
168 * Return a filled-out login_cap_t structure, including
169 * class name, and the capability record buffer.
173 login_getclassbyname(char const * name
, char const * dir
)
175 login_cap_t
*lc
= malloc(sizeof(login_cap_t
));
179 char userpath
[MAXPATHLEN
];
180 static char *login_dbarray
[] = { NULL
, NULL
, NULL
};
182 if (dir
&& snprintf(userpath
, MAXPATHLEN
, "%s/%s", dir
, _FILE_LOGIN_CONF
) < MAXPATHLEN
)
183 login_dbarray
[i
++] = userpath
;
185 login_dbarray
[i
++] = _PATH_LOGIN_CONF
;
186 login_dbarray
[i
] = NULL
;
188 lc
->lc_cap
= lc
->lc_class
= lc
->lc_style
= NULL
;
190 if ((name
== NULL
|| cgetent(&lc
->lc_cap
, login_dbarray
, (char*)name
) != 0) &&
191 cgetent(&lc
->lc_cap
, login_dbarray
, (char*)(name
= LOGIN_DEFCLASS
)) != 0) {
196 lc
->lc_class
= strdup(name
);
207 * Get the login class for a given password entry from
208 * the system (only) login class database.
209 * If the password entry's class field is not set, or
210 * the class specified does not exist, then use the
211 * default of LOGIN_DEFCLASS (ie. "default").
212 * Return a filled-out login_cap_t structure, including
213 * class name, and the capability record buffer.
217 login_getclass(const struct passwd
*pwd
)
219 const char * class = NULL
;
221 if ((class = pwd
->pw_class
) == NULL
|| *class == '\0')
222 class = (pwd
->pw_uid
== 0) ? "root" : NULL
;
224 return login_getclassbyname(class, 0);
229 * login_getuserclass()
230 * Get the login class for a given password entry, allowing user
231 * overrides via ~/.login_conf.
232 * ### WAS: If the password entry's class field is not set,
233 * ####### or the class specified does not exist, then use
234 * If an entry with the recordid "me" does not exist, then use
235 * the default of LOGIN_DEFCLASS (ie. "default").
236 * Return a filled-out login_cap_t structure, including
237 * class name, and the capability record buffer.
241 login_getuserclass(const struct passwd
*pwd
)
243 const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */
244 const char * home
= (pwd
== NULL
) ? NULL
: pwd
->pw_dir
;
245 return login_getclassbyname(class, home
);
252 * Given a login_cap entry, and a capability name, return the
253 * value defined for that capability, a defualt if not found, or
254 * an error string on error.
258 login_getcapstr(login_cap_t
*lc
, const char *cap
, char *def
, char *error
)
263 if (lc
== NULL
|| cap
== NULL
|| lc
->lc_cap
== NULL
|| *cap
== '\0')
266 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1) {
277 * Given a login_cap entry, and a capability name, return the
278 * value defined for that capability split into an array of
283 login_getcaplist(login_cap_t
*lc
, const char * cap
, const char * chars
)
289 if ((lstring
= login_getcapstr(lc
, (char*)cap
, NULL
, NULL
)) != NULL
)
290 return arrayize(lstring
, chars
, NULL
);
297 * From the login_cap_t <lc>, get the capability <cap> which is
298 * formatted as either a space or comma delimited list of paths
299 * and append them all into a string and separate by semicolons.
300 * If there is an error of any kind, return <error>.
304 login_getpath(login_cap_t
*lc
, const char *cap
, char * error
)
306 char *str
= login_getcapstr(lc
, (char*)cap
, NULL
, NULL
);
314 int count
= strcspn(ptr
, ", \t");
326 * From the login_cap_t <lc>, get the capability <cap>, which is
327 * formatted as a time (e.g., "<cap>=10h3m2s"). If <cap> is not
328 * present in <lc>, return <def>; if there is an error of some kind,
333 login_getcaptime(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
)
340 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
344 * Look for <cap> in lc_cap.
345 * If it's not there (-1), return <def>.
346 * If there's an error, return <error>.
349 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1)
355 * "inf" and "infinity" are two special cases for this.
357 if (!strcasecmp(res
, "infinity") || !strcasecmp(res
, "inf"))
358 return RLIM_INFINITY
;
361 * Now go through the string, turning something like 1h2m3s into
362 * an integral value. Whee.
367 tim
= STRTOV(res
, &ep
, 0);
368 if ((ep
== NULL
) || (ep
== res
) || errno
) {
371 /* Look for suffixes */
374 ep
--; break; /* end of string */
375 case 's': case 'S': /* seconds */
377 case 'm': case 'M': /* minutes */
380 case 'h': case 'H': /* hours */
383 case 'd': case 'D': /* days */
384 tim
*= (60L * 60L * 24L);
386 case 'w': case 'W': /* weeks */
387 tim
*= (60L * 60L * 24L * 7L);
388 case 'y': case 'Y': /* Years */
389 /* I refuse to take leap years into account here. Sue me. */
390 tim
*= (60L * 60L * 24L * 365L);
403 * From the login_cap_t <lc>, extract the numerical value <cap>.
404 * If it is not present, return <def> for a default, and return
405 * <error> if there is an error.
406 * Like login_getcaptime(), only it only converts to a number, not
407 * to a time; "infinity" and "inf" are 'special.'
411 login_getcapnum(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
)
417 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
421 * For BSDI compatibility, try for the tag=<val> first
423 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1) {
426 * String capability not present, so try for tag#<val> as numeric
428 if ((ret
= cgetnum(lc
->lc_cap
, (char *)cap
, &lval
)) == -1)
429 return def
; /* Not there, so return default */
437 if (!strcasecmp(res
, "infinity") || !strcasecmp(res
, "inf"))
438 return RLIM_INFINITY
;
441 val
= STRTOV(res
, &ep
, 0);
442 if ((ep
== NULL
) || (ep
== res
) || errno
)
450 * From the login_cap_t <lc>, extract the capability <cap>, which is
451 * formatted as a size (e.g., "<cap>=10M"); it can also be "infinity".
452 * If not present, return <def>, or <error> if there is an error of
457 login_getcapsize(login_cap_t
*lc
, const char *cap
, rlim_t def
, rlim_t error
) {
463 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
466 if ((ret
= cgetstr(lc
->lc_cap
, (char *)cap
, &res
)) == -1)
472 val
= STRTOV(res
, &ep
, 0);
473 if ((res
== NULL
) || (res
== ep
) || errno
)
476 case 0: /* end of string */
478 case 'b': case 'B': /* 512-byte blocks */
480 case 'k': case 'K': /* 1024-byte Kilobytes */
482 case 'm': case 'M': /* 1024-k kbytes */
483 mult
= 1024 * 1024; break;
484 case 'g': case 'G': /* 1Gbyte */
485 mult
= 1024 * 1024 * 1024; break;
487 case 't': case 'T': /* 1TBte */
488 mult
= 1024LL * 1024LL * 1024LL * 1024LL; break;
499 * From the login_cap_t <lc>, check for the existance of the capability
500 * of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return
501 * the whether or not <cap> exists there.
505 login_getcapbool(login_cap_t
*lc
, const char *cap
, int def
)
507 if (lc
== NULL
|| lc
->lc_cap
== NULL
)
509 return (cgetcap(lc
->lc_cap
, (char *)cap
, ':') != NULL
);
515 * Given a login_cap entry <lc>, and optionally a type of auth <auth>,
516 * and optionally a style <style>, find the style that best suits these
518 * 1. If <auth> is non-null, look for an "auth-<auth>=" string
519 * in the capability; if not present, default to "auth=".
520 * 2. If there is no auth list found from (1), default to
521 * "passwd" as an authorization list.
522 * 3. If <style> is non-null, look for <style> in the list of
523 * authorization methods found from (2); if <style> is NULL, default
524 * to LOGIN_DEFSTYLE ("passwd").
525 * 4. If the chosen style is found in the chosen list of authorization
526 * methods, return that; otherwise, return NULL.
528 * login_getstyle(lc, NULL, "ftp");
529 * login_getstyle(lc, "login", NULL);
530 * login_getstyle(lc, "skey", "network");
534 login_getstyle(login_cap_t
*lc
, char *style
, const char *auth
)
537 char **authtypes
= NULL
;
541 static char *defauthtypes
[] = { LOGIN_DEFSTYLE
, NULL
};
543 if (auth
!= NULL
&& *auth
!= '\0' &&
544 snprintf(realauth
, sizeof realauth
, "auth-%s", auth
) < sizeof realauth
)
545 authtypes
= login_getcaplist(lc
, realauth
, NULL
);
547 if (authtypes
== NULL
)
548 authtypes
= login_getcaplist(lc
, "auth", NULL
);
550 if (authtypes
== NULL
)
551 authtypes
= defauthtypes
;
554 * We have at least one authtype now; auths is a comma-seperated
555 * (or space-separated) list of authentication types. We have to
556 * convert from this to an array of char*'s; authtypes then gets this.
559 if (style
!= NULL
&& *style
!= '\0') {
560 while (authtypes
[i
] != NULL
&& strcmp(style
, authtypes
[i
]) != 0)
564 if (authtypes
[i
] != NULL
&& (auths
= strdup(authtypes
[i
])) != NULL
)
565 lc
->lc_style
= auths
;