static size_t internal_stringsz = 0;
static char * internal_string = NULL;
static size_t internal_arraysz = 0;
-static char ** internal_array = NULL;
+static const char ** internal_array = NULL;
+
+static char path_login_conf[] = _PATH_LOGIN_CONF;
static char *
-allocstr(char *str)
+allocstr(const char *str)
{
char *p;
}
-static char **
+static const char **
allocarray(size_t sz)
{
- char **p;
+ static const char **p;
if (sz <= internal_arraysz)
p = internal_array;
* Free using freearraystr()
*/
-static char **
-arrayize(char *str, const char *chars, int *size)
+static const char **
+arrayize(const char *str, const char *chars, int *size)
{
int i;
- char *ptr;
- char **res = NULL;
+ char *ptr;
+ const char *cptr;
+ const char **res = NULL;
/* count the sub-strings */
- for (i = 0, ptr = str; *ptr; i++) {
- int count = strcspn(ptr, chars);
- ptr += count;
- if (*ptr)
- ++ptr;
+ for (i = 0, cptr = str; *cptr; i++) {
+ int count = strcspn(cptr, chars);
+ cptr += count;
+ if (*cptr)
+ ++cptr;
}
/* alloc the array */
if ((ptr = allocstr(str)) != NULL) {
if ((res = allocarray(++i)) == NULL)
- free(str);
+ free((void *)(uintptr_t)(const void *)str);
else {
/* now split the string */
i = 0;
/*
- * login_getclassbyname() get the login class by its name.
+ * login_getclassbyname()
+ * Get the login class by its name.
* If the name given is NULL or empty, the default class
- * LOGIN_DEFCLASS (ie. "default") is fetched. If the
- * 'dir' argument contains a non-NULL non-empty string,
- * then the file _FILE_LOGIN_CONF is picked up from that
- * directory instead of the system login database.
+ * LOGIN_DEFCLASS (i.e., "default") is fetched.
+ * If the name given is LOGIN_MECLASS and
+ * 'pwd' argument is non-NULL and contains an non-NULL
+ * dir entry, then the file _FILE_LOGIN_CONF is picked
+ * up from that directory and used before the system
+ * login database. In that case the system login database
+ * is looked up using LOGIN_MECLASS, too, which is a bug.
* Return a filled-out login_cap_t structure, including
* class name, and the capability record buffer.
*/
if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir,
_FILE_LOGIN_CONF) < MAXPATHLEN) {
- login_dbarray[i] = userpath;
if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1)
- i++; /* only use 'secure' data */
+ login_dbarray[i++] = userpath;
}
- if (_secure_path(_PATH_LOGIN_CONF, 0, 0) != -1)
- login_dbarray[i++] = _PATH_LOGIN_CONF;
+ /*
+ * XXX: Why to add the system database if the class is `me'?
+ */
+ if (_secure_path(path_login_conf, 0, 0) != -1)
+ login_dbarray[i++] = path_login_conf;
login_dbarray[i] = NULL;
memset(lc, 0, sizeof(login_cap_t));
if (name == NULL || *name == '\0')
name = LOGIN_DEFCLASS;
- switch (cgetent(&lc->lc_cap, login_dbarray, (char*)name)) {
+ switch (cgetent(&lc->lc_cap, login_dbarray, name)) {
case -1: /* Failed, entry does not exist */
if (me)
break; /* Don't retry default on 'me' */
if (i == 0)
r = -1;
- else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0)
+ else if ((r = open(login_dbarray[0], O_RDONLY | O_CLOEXEC)) >= 0)
close(r);
/*
* If there's at least one login class database,
/* fall-back to default class */
name = LOGIN_DEFCLASS;
msg = "%s: no default/fallback class '%s'";
- if (cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0 && r >= 0)
+ if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0)
break;
/* FALLTHROUGH - just return system defaults */
case 0: /* success! */
/*
- * login_getclass()
+ * login_getpwclass()
* Get the login class for a given password entry from
* the system (only) login class database.
* If the password entry's class field is not set, or
* the class specified does not exist, then use the
- * default of LOGIN_DEFCLASS (ie. "default").
+ * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged
+ * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user.
* Return a filled-out login_cap_t structure, including
* class name, and the capability record buffer.
*/
if (cls == NULL || *cls == '\0')
cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
}
+ /*
+ * XXX: pwd should be unused by login_getclassbyname() unless cls is `me',
+ * so NULL can be passed instead of pwd for more safety.
+ */
return login_getclassbyname(cls, pwd);
}
/*
* login_getuserclass()
- * Get the login class for a given password entry, allowing user
- * overrides via ~/.login_conf.
+ * Get the `me' login class, allowing user overrides via ~/.login_conf.
+ * Note that user overrides are allowed only in the `me' class.
*/
login_cap_t *
}
-
/*
* login_getcapstr()
* Given a login_cap entry, and a capability name, return the
- * value defined for that capability, a defualt if not found, or
+ * value defined for that capability, a default if not found, or
* an error string on error.
*/
if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
return def;
- if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1)
return def;
return (ret >= 0) ? res : error;
}
* strings.
*/
-char **
+const char **
login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
{
- char *lstring;
+ const char *lstring;
if (chars == NULL)
chars = ", \t";
- if ((lstring = (char *)login_getcapstr(lc, cap, NULL, NULL)) != NULL)
+ if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL)
return arrayize(lstring, chars, NULL);
return NULL;
}
login_getpath(login_cap_t *lc, const char *cap, const char *error)
{
const char *str;
+ char *ptr;
+ int count;
- if ((str = login_getcapstr(lc, cap, NULL, NULL)) == NULL)
- str = error;
- else {
- char *ptr = (char *)str;
-
- while (*ptr) {
- int count = strcspn(ptr, ", \t");
- ptr += count;
- if (*ptr)
- *ptr++ = ':';
- }
+ str = login_getcapstr(lc, cap, NULL, NULL);
+ if (str == NULL)
+ return error;
+ ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */
+ while (*ptr) {
+ count = strcspn(ptr, ", \t");
+ ptr += count;
+ if (*ptr)
+ *ptr++ = ':';
}
return str;
}
* If there's an error, return <error>.
*/
- if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
return def;
else if (r < 0) {
errno = ERANGE;
/*
* For BSDI compatibility, try for the tag=<val> first
*/
- if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) {
+ if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) {
long lval;
/* string capability not present, so try for tag#<val> as numeric */
- if ((r = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1)
+ if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1)
return def; /* Not there, so return default */
else if (r >= 0)
return (rlim_t)lval;
if (lc == NULL || lc->lc_cap == NULL)
return def;
- if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
return def;
else if (r < 0) {
errno = ERANGE;
/*
* login_getcapbool()
- * From the login_cap_t <lc>, check for the existance of the capability
+ * From the login_cap_t <lc>, check for the existence of the capability
* of <cap>. Return <def> if <lc>->lc_cap is NULL, otherwise return
* the whether or not <cap> exists there.
*/
{
if (lc == NULL || lc->lc_cap == NULL)
return def;
- return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL);
+ return (cgetcap(lc->lc_cap, cap, ':') != NULL);
}
login_getstyle(login_cap_t *lc, const char *style, const char *auth)
{
int i;
- char **authtypes = NULL;
+ const char **authtypes = NULL;
char *auths= NULL;
char realauth[64];
- static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
+ static const char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
if (auth != NULL && *auth != '\0') {
- if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth)
+ if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < (int)sizeof(realauth))
authtypes = login_getcaplist(lc, realauth, NULL);
}