summaryrefslogtreecommitdiffstats
path: root/lib/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil')
-rw-r--r--lib/libutil/Makefile6
-rw-r--r--lib/libutil/_secure_path.370
-rw-r--r--lib/libutil/_secure_path.c72
-rw-r--r--lib/libutil/libutil.h3
-rw-r--r--lib/libutil/login_auth.c715
-rw-r--r--lib/libutil/login_cap.c828
-rw-r--r--lib/libutil/login_cap.h115
-rw-r--r--lib/libutil/login_class.c499
-rw-r--r--lib/libutil/login_ok.c247
-rw-r--r--lib/libutil/login_times.c179
10 files changed, 1700 insertions, 1034 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index de882b0..8ac63d2 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -4,11 +4,13 @@ LIB= util
SHLIB_MAJOR= 2
SHLIB_MINOR= 2
CFLAGS+=-Wall -DLIBC_SCCS -I${.CURDIR} -I/sys
+#CFLAGS+=LOGIN_CAP_AUTH
SRCS= login.c login_tty.c logout.c logwtmp.c pty.c setproctitle.c \
login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
- uucplock.c
+ _secure_path.c uucplock.c
MAN3+= login.3 login_tty.3 logout.3 logwtmp.3 pty.3 setproctitle.3 \
- login_cap.3 login_class.3 login_times.3 login_ok.3 uucplock.3
+ login_cap.3 login_class.3 login_times.3 login_ok.3 \
+ _secure_path.3 uucplock.3
MAN5+= login.conf.5
MLINKS+= pty.3 openpty.3 pty.3 forkpty.3
MLINKS+=login_cap.3 login_getclassbyname.3 login_cap.3 login_close.3 \
diff --git a/lib/libutil/_secure_path.3 b/lib/libutil/_secure_path.3
new file mode 100644
index 0000000..6387b73
--- /dev/null
+++ b/lib/libutil/_secure_path.3
@@ -0,0 +1,70 @@
+.\" Copyright (c) 1997 David Nugent <davidn@blaze.net.au>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, is permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice immediately at the beginning of the file, without modification,
+.\" this list of conditions, and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. This work was done expressly for inclusion into FreeBSD. Other use
+.\" is permitted provided this notation is included.
+.\" 4. Absolutely no warranty of function or purpose is made by the author
+.\" David Nugent.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $Id$
+.\"
+.Dd May 2, 1997
+.Os FreeBSD
+.Dt _SECURE_PATH 3
+.Sh NAME
+.Nm _secure_path
+.Nd determine if a file appears to be secure
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn _secure_path "const char *path" "uid_t uid" "gid_t gid"
+.Pp
+.Sh DESCRIPTION
+This function does some basic security checking on a given path.
+It is intended to be used by processes running with root privileges
+in order to decide whether or not to trust the contents of a given
+file.
+It uses a method often used to detect system compromise.
+.Pp
+A file is considered 'secure' if it meets the following conditions:
+.Bl -enum
+.It
+The file exists, and is a regular file (not a symlink, device
+special or named pipe, etc.),
+.It
+Is not world writable.
+.It
+Is owned by the given uid, if uid is not -1,
+.It
+Is not group wriable or it has group ownership by the given
+gid, if gid is not -1.
+.El
+.Sh RETURN VALUES
+This function returns zero if the file exists and may be
+considered secure, -2 if the file does not exist, and
+-1 otherwise to indicate a security failure.
+.Xr syslog 3 ,
+is used to log any failure of this function, including the
+reason, at LOG_ERR priority.
+.Sh BUGS
+The checks carried out are rudamentary and no attempt is made
+to eliminate race conditions between use of this function and
+access to the file referenced.
+.Sh SEE ALSO
+.Xr lstat 3 ,
+.Xr syslog 3 .
+.Sh HISTORY
+Code from which this function was derived was contributed to the
+FreeBSD project by Berkeley Software Design, Inc.
diff --git a/lib/libutil/_secure_path.c b/lib/libutil/_secure_path.c
new file mode 100644
index 0000000..38a974e
--- /dev/null
+++ b/lib/libutil/_secure_path.c
@@ -0,0 +1,72 @@
+/*-
+ * Based on code copyright (c) 1995,1997 by
+ * Berkeley Software Design, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, is permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. This work was done expressly for inclusion into FreeBSD. Other use
+ * is permitted provided this notation is included.
+ * 4. Absolutely no warranty of function or purpose is made by the authors.
+ * 5. Modifications may be freely made to this file providing the above
+ * conditions are met.
+ *
+ * $Id$
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <errno.h>
+#include <libutil.h>
+
+/*
+ * Check for common security problems on a given path
+ * It must be:
+ * 1. A regular file, and exists
+ * 2. Owned and writaable only by root (or given owner)
+ * 3. Group ownership is given group or is non-group writable
+ *
+ * Returns: -2 if file does not exist,
+ * -1 if security test failure
+ * 0 otherwise
+ */
+
+int
+_secure_path(const char *path, uid_t uid, gid_t gid)
+{
+ int r = -1;
+ struct stat sb;
+ const char *msg = NULL;
+
+ if (lstat(path, &sb) < 0) {
+ if (errno == ENOENT) /* special case */
+ r = -2; /* if it is just missing, skip the log entry */
+ else
+ msg = "%s: cannot stat %s: %m";
+ }
+ else if (!S_ISREG(sb.st_mode))
+ msg = "%s: %s is not a regular file";
+ else if (sb.st_mode & S_IWOTH)
+ msg = "%s: %s is world writable";
+ else if (uid != -1 && sb.st_uid != uid) {
+ if (uid == 0)
+ msg = "%s: %s is not owned by root";
+ else
+ msg = "%s: %s is not owned by uid %d";
+ } else if (gid != -1 && sb.st_gid != gid && (sb.st_mode & S_IWGRP))
+ msg = "%s: %s is group writeable by non-authorised groups";
+ else
+ r = 0;
+ if (msg != NULL)
+ syslog(LOG_ERR, msg, "_secure_path", path, uid);
+ return r;
+}
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index 35c1163..3db5263 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file providing the above
* conditions are met.
*
- * $Id: libutil.h,v 1.5 1997/03/30 12:11:27 brian Exp $
+ * $Id: libutil.h,v 1.6 1997/03/31 22:47:53 brian Exp $
*/
#ifndef _LIBUTIL_H_
@@ -44,6 +44,7 @@ int forkpty __P((int *amaster, char *name,
char *uu_lockerr __P((int uu_lockresult));
int uu_lock __P((char *ttyname));
int uu_unlock __P((char *ttyname));
+int _secure_path __P((const char *path, uid_t uid, gid_t gid));
__END_DECLS
#define UU_LOCK_INUSE (1)
diff --git a/lib/libutil/login_auth.c b/lib/libutil/login_auth.c
index 565ddc3..695b006 100644
--- a/lib/libutil/login_auth.c
+++ b/lib/libutil/login_auth.c
@@ -4,6 +4,10 @@
* David Nugent <davidn@blaze.net.au>
* All rights reserved.
*
+ * Portions copyright (c) 1995,1997 by
+ * Berkeley Software Design, Inc.
+ * All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
@@ -21,17 +25,19 @@
*
* Low-level routines relating to the user capabilities database
*
- * $Id$
+ * $Id: login_auth.c,v 1.6 1997/02/22 15:08:18 peter Exp $
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
+#include <ctype.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
@@ -40,297 +46,575 @@
#include <login_cap.h>
#include <stdarg.h>
#include <paths.h>
+#include <sys/socket.h>
#include <sys/wait.h>
+#include <err.h>
+#include <libutil.h>
+
+#ifdef LOGIN_CAP_AUTH
+/*
+ * Comment from BSDI's authenticate.c module:
+ * NOTE: THIS MODULE IS TO BE DEPRECATED. FUTURE VERSIONS OF BSD/OS WILL
+ * HAVE AN UPDATED API, THOUGH THESE FUNCTIONS WILL CONTINUE TO BE AVAILABLE
+ * FOR BACKWARDS COMPATABILITY
+ */
-#ifdef RLIM_LONG
-# define STRTOV strtol
-#else
-# define STRTOV strtoq
-#endif
-#define AUTHMAXLINES 1024
-#define AUTHMAXARGS 16
+#define AUTHMAXSPOOL (8 * 1024) /* Max size of authentication data */
+#define AUTHCOMM_FD 3 /* Handle used to read/write auth data */
+
+struct rmfiles {
+ struct rmfiles *next;
+ char file[1];
+};
-struct auth_info {
- int reject;
- int auths;
- int env_count;
- char **env;
- int file_count;
- char **files;
+struct authopts {
+ struct authopts *next;
+ char opt[1];
};
-static struct auth_info auth_info;
+static char *spoolbuf = NULL;
+static int spoolidx = 0;
+static struct rmfiles *rmfirst = NULL;
+static struct authopts *optfirst = NULL;
+
/*
- * free_auth_info()
- * Go through the auth_info structure, and free() anything of interest.
- * This includes the string arrays, and any individual element.
- * All part of being environmentally conscious ;).
+ * Setup a known environment for all authentication scripts.
*/
-static void
-free_auth_info(void)
+static char *auth_environ[] = {
+ "PATH=" _PATH_DEFPATH,
+ "SHELL=" _PATH_BSHELL,
+ NULL,
+};
+
+
+
+/*
+ * nextline()
+ * Get the next line from the data buffer collected from
+ * the authentication program. This function relies on the
+ * fact that lines are nul terminated.
+ */
+
+static char *
+nextline(int *idx)
{
- int i;
-
- auth_info.reject = 0;
- auth_info.auths = 0;
- if (auth_info.env) {
- for (i = 0; i < auth_info.env_count; i++) {
- if (auth_info.env[i])
- free(auth_info.env[i]);
- }
- free(auth_info.env);
- auth_info.env = NULL;
- }
- if (auth_info.files) {
- for (i = 0; i < auth_info.file_count; i++) {
- if (auth_info.files[i])
- free(auth_info.files[i]);
+ char *ptr = NULL;
+
+ if (spoolbuf != NULL && *idx < spoolidx) {
+ ptr = spoolbuf + *idx;
+ *idx += strlen(ptr) + 1;
}
- free(auth_info.files);
- auth_info.files = NULL;
- }
+ return ptr;
}
/*
- * collect_info()
- * Read from <fd>, a list of authorization commands.
- * These commands are:
- * reject
- * authorize [root|secure]
- * setenv <name>[ <value>]
- * remove <file>
- * A single reject means the entire thing is bad;
- * multiple authorize statements can be present (it would be
- * silly, but that's what the spec says).
- * The commands are collected, and are accted upon by:
- * auth_scan() -- check for authorization or rejection
- * auth_rmfiles() -- remove the specified files
- * auth_env() -- set the specified environment variables
- * We only get up to AUTHMAXLINES lines of input from the program.
+ * spooldata()
+ * Read data returned on authentication backchannel and
+ * stuff it into our spool buffer. We also replace \n with nul
+ * to make parsing easier later.
*/
-#define STRSIZEOF(x) (sizeof(x)-1)
-static void
-collect_info(int fd)
+
+static int
+spooldata(int fd)
{
- char *line;
- FILE *fp;
- char *ptr;
- size_t len;
- int line_count = 0;
-
- fp = fdopen(fd, "r");
-
- while ((line = fgetln(fp, &len)) != NULL) {
- if (++line_count > AUTHMAXLINES)
- break;
- if (len && line[len-1] == '\n')
- --len;
- line[len] = '\0'; /* Terminate */
- if (strncasecmp(line, BI_REJECT, STRSIZEOF(BI_REJECT)) == 0) {
- auth_info.reject = 1;
- } else if (strncasecmp(line, BI_AUTH, STRSIZEOF(BI_AUTH)) == 0) {
- ptr = line + STRSIZEOF(BI_AUTH);
- ptr += strspn(ptr, " \t");
- if (!*ptr)
- auth_info.auths |= AUTH_OKAY;
- else if (strncasecmp(ptr, BI_ROOTOKAY, STRSIZEOF(BI_ROOTOKAY)) == 0)
- auth_info.auths |= AUTH_ROOTOKAY;
- else if (strncasecmp(ptr, BI_SECURE, STRSIZEOF(BI_SECURE)) == 0)
- auth_info.auths |= AUTH_SECURE;
- } else if (strncasecmp(line, BI_SETENV, STRSIZEOF(BI_SETENV)) == 0) {
- ptr = line + STRSIZEOF(BI_SETENV);
- ptr += strspn(ptr, " \t");
- if (*ptr) {
- char **tmp = realloc(auth_info.env, sizeof(char*) * (auth_info.env_count + 1));
- if (tmp != NULL) {
- auth_info.env = tmp;
- if ((auth_info.env[auth_info.env_count] = strdup(ptr)) != NULL)
- auth_info.env_count++;
- }
- }
- } else if (strncasecmp(line, BI_REMOVE, STRSIZEOF(BI_REMOVE)) == 0) {
- ptr = line + STRSIZEOF(BI_REMOVE);
- ptr += strspn(ptr, " \t");
- if (*ptr) {
- char **tmp = realloc(auth_info.files, sizeof(char*) * (auth_info.file_count + 1));
- if (tmp != NULL) {
- auth_info.files = tmp;
- if ((auth_info.files[auth_info.file_count] = strdup(ptr)) != NULL)
- auth_info.file_count++;
+
+ if (spoolbuf)
+ free(spoolbuf);
+ spoolidx = 0;
+
+ if (spoolbuf == NULL && (spoolbuf = malloc(AUTHMAXSPOOL)) == NULL)
+ syslog(LOG_ERR, "authbuffer malloc: %m");
+
+ else while (spoolidx < sizeof(spoolbuf) - 1) {
+ int r = read(fd, spoolbuf + spoolidx, sizeof(spoolbuf)-spoolidx);
+ char *b;
+
+ if (r <= 0) {
+ spoolbuf[spoolidx] = '\0';
+ return 0;
}
- }
+ /*
+ * Convert newlines into NULs to allow
+ * easier scanning of the file.
+ */
+ while ((b = memchr(spoolbuf + spoolidx, '\n', r)) != NULL)
+ *b = '\0';
+ spoolidx += r;
}
- }
- fclose(fp);
+ return -1;
}
-
+
/*
- * authenticate()
+ * auth_check()
* Starts an auth_script() for the given <user>, with a class <class>,
* style <style>, and service <service>. <style> is necessary,
* as are <user> and <class>, but <service> is optional -- it defaults
* to "login".
* Since auth_script() expects an execl'able program name, authenticate()
* also concatenates <style> to _PATH_AUTHPROG.
- * Lastly, calls auth_scan(AUTH_NONE) to see if there are any "reject" statements,
+ * Lastly, calls auth_scan(0) to see if there are any "reject" statements,
* or lack of "auth" statements.
* Returns -1 on error, 0 on rejection, and >0 on success.
* (See AUTH_* for the return values.)
*
*/
+
int
-authenticate(const char * name, const char * class, const char * style, const char *service)
+auth_check(const char *name, const char *clss, const char *style,
+ const char *service, int *status)
{
- int retval;
+ int _status;
- if (style == NULL || *style == '\0')
- retval = -1;
- else {
- char buf[sizeof(_PATH_AUTHPROG) + 64];
+ if (status == NULL)
+ status = &_status;
+ *status = 0;
- if (service == NULL || *service == '\0')
- service = LOGIN_DEFSERVICE;
+ if (style != NULL) {
+ char path[MAXPATHLEN];
- free_auth_info();
+ if (service == NULL)
+ service = LOGIN_DEFSERVICE;
- if (snprintf(buf, sizeof buf, _PATH_AUTHPROG "%s", style) >= sizeof buf)
- retval = -1;
- else {
- retval = auth_script(buf, style, "-s", service, name, class, NULL);
- if (retval >= 0)
- retval = auth_scan(AUTH_NONE);
+ snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
+ if (auth_script(path, style, "-s", service, name, clss, 0))
+ status = 0;
+ else
+ *status = auth_scan(0);
+
+ return *status & AUTH_ALLOW;
+ }
+ return -1;
+}
+
+
+int
+auth_response(const char *name, const char *class, const char *style,
+ const char *service, int *status,
+ const char *challenge, const char *response)
+{
+ int _status;
+
+ if (status == NULL)
+ status = &_status;
+ *status = 0;
+
+ if (style != NULL) {
+ int datalen;
+ char *data;
+
+ if (service == NULL)
+ service = LOGIN_DEFSERVICE;
+
+ datalen = strlen(challenge) + strlen(response) + 2;
+
+ if ((data = malloc(datalen)) == NULL) {
+ syslog(LOG_ERR, "auth_response: %m");
+ warnx("internal resource failure");
+ } else {
+ char path[MAXPATHLEN];
+
+ snprintf(data, datalen, "%s%c%s", challenge, 0, response);
+ snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
+ if (auth_script_data(data, datalen, path, style, "-s", service,
+ name, class, 0))
+ *status = 0;
+ else
+ *status = auth_scan(0);
+ free(data);
+ return (*status & AUTH_ALLOW);
+ }
+ }
+ return -1;
+}
+
+
+int
+auth_approve(login_cap_t *lc, const char *name, const char *service)
+{
+ int r = -1;
+ char path[MAXPATHLEN];
+
+ if (lc == NULL) {
+ if (strlen(name) > MAXPATHLEN) {
+ syslog(LOG_ERR, "%s: username too long", name);
+ warnx("username too long");
+ } else {
+ struct passwd *pwd;
+ char *p;
+
+ pwd = getpwnam(name);
+ if (pwd == NULL && (p = strchr(name, '.')) != NULL) {
+ int i = p - name;
+
+ if (i >= MAXPATHLEN)
+ i = MAXPATHLEN - 1;
+ strncpy(path, name, i);
+ path[i] = '\0';
+ pwd = getpwnam(path); /* Fixed bug in BSDI code... */
+ }
+ if ((lc = login_getpwclass(pwd ? pwd->pw_class : NULL)) == NULL)
+ warnx("unable to classify user '%s'", name);
+ }
+ }
+
+ if (lc != NULL) {
+ char *approve;
+ char *s;
+
+ if (service != NULL)
+ service = LOGIN_DEFSERVICE;
+
+ snprintf(path, sizeof(path), "approve-%s", service);
+
+ if ((approve = login_getcapstr(lc, s = path, NULL, NULL)) == NULL &&
+ (approve = login_getcapstr(lc, s = "approve", NULL, NULL)) == NULL)
+ r = AUTH_OKAY;
+ else {
+
+ if (approve[0] != '/') {
+ syslog(LOG_ERR, "Invalid %s script: %s", s, approve);
+ warnx("invalid path to approval script");
+ } else {
+ char *s;
+
+ s = strrchr(approve, '/') + 1;
+ if (auth_script(approve, s, name,
+ lc->lc_class, service, 0) == 0 &&
+ (r = auth_scan(AUTH_OKAY) & AUTH_ALLOW) != 0)
+ auth_env();
+ }
+ }
+ }
+ return r;
+}
+
+
+void
+auth_env(void)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_SETENV, sizeof(BI_SETENV)-1)) {
+ line += sizeof(BI_SETENV) - 1;
+ if (*line && isspace(*line)) {
+ char *name;
+ char ch, *p;
+
+ while (*line && isspace(*line))
+ ++line;
+ name = line;
+ while (*line && !isspace(*line))
+ ++line;
+ ch = *(p = line);
+ if (*line)
+ ++line;
+ if (setenv(name, line, 1))
+ warn("setenv(%s, %s)", name, line);
+ *p = ch;
+ }
+ }
+ }
+}
+
+
+char *
+auth_value(const char *what)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_VALUE, sizeof(BI_VALUE)-1)) {
+ char *name;
+
+ line += sizeof(BI_VALUE) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ name = line;
+ if (*line) {
+ int i;
+ char ch, *p;
+
+ ch = *(p = line);
+ *line++ = '\0';
+ i = strcmp(name, what);
+ *p = ch;
+ if (i == 0)
+ return auth_mkvalue(line);
+ }
+ }
+ }
+ return NULL;
+}
+
+char *
+auth_mkvalue(const char *value)
+{
+ char *big, *p;
+
+ big = malloc(strlen(value) * 4 + 1);
+ if (big != NULL) {
+ for (p = big; *value; ++value) {
+ switch (*value) {
+ case '\r':
+ *p++ = '\\';
+ *p++ = 'r';
+ break;
+ case '\n':
+ *p++ = '\\';
+ *p++ = 'n';
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = *value;
+ break;
+ case '\t':
+ case ' ':
+ if (p == big)
+ *p++ = '\\';
+ *p++ = *value;
+ break;
+ default:
+ if (!isprint(*value)) {
+ *p++ = '\\';
+ *p++ = ((*value >> 6) & 0x3) + '0';
+ *p++ = ((*value >> 3) & 0x7) + '0';
+ *p++ = ((*value ) & 0x7) + '0';
+ } else
+ *p++ = *value;
+ break;
+ }
+ }
+ *p = '\0';
+ big = realloc(big, strlen(big) + 1);
+ }
+ return big;
+}
+
+
+#define NARGC 63
+static int
+_auth_script(const char *data, int nbytes, const char *path, va_list ap)
+{
+ int r, argc, status;
+ int pfd[2];
+ pid_t pid;
+ struct authopts *e;
+ char *argv[NARGC+1];
+
+ r = -1;
+ argc = 0;
+ for (e = optfirst; argc < (NARGC - 1) && e != NULL; e = e->next) {
+ argv[argc++] = "-v";
+ argv[argc++] = e->opt;
+ }
+ while (argc < NARGC && (argv[argc] = va_arg(ap, char *)) != NULL)
+ ++argc;
+ argv[argc] = NULL;
+
+ if (argc >= NARGC && va_arg(ap, char *))
+ syslog(LOG_ERR, "too many arguments");
+ else if (_secure_path(path, 0, 0) < 0) {
+ syslog(LOG_ERR, "%s: path not secure", path);
+ warnx("invalid script: %s", path);
+ } else if (socketpair(PF_LOCAL, SOCK_STREAM, 0, pfd) < 0) {
+ syslog(LOG_ERR, "unable to create backchannel %m");
+ warnx("internal resource failure");
+ } else switch (pid = fork()) {
+ case -1: /* fork() failure */
+ close(pfd[0]);
+ close(pfd[1]);
+ syslog(LOG_ERR, "fork %s: %m", path);
+ warnx("internal resource failure");
+ break;
+ case 0: /* child process */
+ close(pfd[0]);
+ if (pfd[1] != AUTHCOMM_FD) {
+ if (dup2(pfd[1], AUTHCOMM_FD) < 0)
+ err(1, "dup backchannel");
+ close(pfd[1]);
+ }
+ for (r = getdtablesize(); --r > AUTHCOMM_FD; )
+ close(r);
+ execve(path, argv, auth_environ);
+ syslog(LOG_ERR, "exec %s: %m", path);
+ err(1, path);
+ default: /* parent */
+ close(pfd[1]);
+ if (data && nbytes)
+ write(pfd[0], data, nbytes);
+ r = spooldata(pfd[0]);
+ close(pfd[0]);
+ if (waitpid(pid, &status, 0) < 0) {
+ syslog(LOG_ERR, "%s: waitpid: %m", path);
+ warnx("internal failure");
+ r = -1;
+ } else {
+ if (r != 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ r = -1;
+ }
+ /* kill the buffer if it is of no use */
+ if (r != 0) {
+ free(spoolbuf);
+ spoolbuf = NULL;
+ spoolidx = 0;
+ }
+ break;
}
- }
- return retval;
+ return r;
}
+
/*
* auth_script()
* Runs an authentication program with specified arguments.
* It sets up file descriptor 3 for the program to write to;
* it stashes the output somewhere. The output of the program
* consists of statements:
- * reject
+ * reject [challenge|silent]
* authorize [root|secure]
* setenv <name> [<value>]
* remove <file>
*
- * Terribly exciting, isn't it? There is no limit specified in
- * BSDi's API for how much output can be present, but we should
- * keep it fairly small, I think.
- * No more than AUTHMAXLINES lines.
+ * Terribly exciting, isn't it?
+ * Output cannot exceed AUTHMAXSPOOL characters.
*/
int
-auth_script(const char * path, ...)
+auth_script(const char *path, ...)
{
- va_list ap;
- int pid, status;
- int argc = 0;
- int p[2]; /* pipes */
- char *argv[AUTHMAXARGS+1];
-
- va_start(ap, path);
- while (argc < AUTHMAXARGS && (argv[argc++] = va_arg(ap, char*)) != NULL)
- ;
- argv[argc] = NULL;
- va_end(ap);
-
- fflush(NULL);
-
- if (pipe(p) >= 0) {
- if ((pid = fork()) == -1) {
- close(p[0]);
- close(p[1]);
- } else if (pid == 0) { /* Child */
- close(p[0]);
- dup2(p[1], 3);
- if (setenv("PATH", _PATH_DEFPATH, 1)==0 && setenv("SHELL", _PATH_BSHELL, 1)==0)
- execv(path, argv);
- _exit(1);
- } else {
- close(p[1]);
- collect_info(p[0]);
- if (waitpid(pid, &status, 0) != -1 && WIFEXITED(status) && !WEXITSTATUS(status))
- return 0;
- }
- }
- return -1;
-}
+ int r;
+ va_list ap;
+ va_start(ap, path);
+ r = _auth_script(NULL, 0, path, ap);
+ va_end(ap);
+ return r;
+}
-/*
- * auth_env()
- * Processes the stored "setenv" lines from the stored authentication
- * output.
- */
int
-auth_env(void)
+auth_script_data(const char *data, int nbytes, const char *path, ...)
+{
+ int r;
+ va_list ap;
+
+ va_start(ap, path);
+ r = _auth_script(data, nbytes, path, ap);
+ va_end(ap);
+ return r;
+}
+
+
+static void
+add_rmlist(const char *file)
{
- int i;
-
- for (i = 0; i < auth_info.env_count; i++) {
- char *nam = auth_info.env[i];
- char *ptr = nam + strcspn(nam, " \t=");
- if (*ptr) {
- *ptr++ = '\0';
- ptr += strspn(ptr, " \t");
+ struct rmfiles *rm;
+
+ if ((rm = malloc(sizeof(struct rmfiles) + strlen(file) + 1)) == NULL)
+ syslog(LOG_ERR, "add_rmfile malloc: %m");
+ else {
+ strcpy(rm->file, file);
+ rm->next = rmfirst;
+ rmfirst = rm;
}
- setenv(nam, ptr, 1);
- }
- return 0;
}
-/*
- * auth_scan()
- * Goes through the output of the auth_script/authenticate, and
- * checks for a failure or authentication.
- * <ok> is a default authentication value -- if there are no
- * rejection or authentication statements, then it is returned
- * unmodified.
- * AUTH_NONE is returned if there were any reject statements
- * from the authentication program (invoked by auth_script()), and
- * AUTH, AUTH_ROOTOKAY, and/or AUTH_SECURE are returned if the
- * appropriate directives were found. Note that AUTH* are
- * *bitmasks*!
- */
+int
+auth_scan(int okay)
+{
+ int idx = 0;
+ char *line;
+
+ while ((line = nextline(&idx)) != NULL) {
+ if (!strncasecmp(line, BI_REJECT, sizeof(BI_REJECT)-1)) {
+ line += sizeof(BI_REJECT) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line) {
+ if (!strcasecmp(line, "silent"))
+ return AUTH_SILENT;
+ if (!strcasecmp(line, "challenge"))
+ return AUTH_CHALLENGE;
+ }
+ return 0;
+ } else if (!strncasecmp(line, BI_AUTH, sizeof(BI_AUTH)-1)) {
+ line += sizeof(BI_AUTH) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line == '\0')
+ okay |= AUTH_OKAY;
+ else if (!strcasecmp(line, "root"))
+ okay |= AUTH_ROOTOKAY;
+ else if (!strcasecmp(line, "secure"))
+ okay |= AUTH_SECURE;
+ }
+ else if (!strncasecmp(line, BI_REMOVE, sizeof(BI_REMOVE)-1)) {
+ line += sizeof(BI_REMOVE) - 1;
+ while (*line && isspace(*line))
+ ++line;
+ if (*line)
+ add_rmlist(line);
+ }
+ }
+
+ return okay;
+}
+
int
-auth_scan(int ok)
+auth_setopt(const char *n, const char *v)
{
- if (auth_info.reject)
- return 0;
- return ok | auth_info.auths;
+ int r;
+ struct authopts *e;
+
+ if ((e = malloc(sizeof(*e) + strlen(n) + strlen(v) + 1)) == NULL)
+ r = -1;
+ else {
+ sprintf(e->opt, "%s=%s", n, v);
+ e->next = optfirst;
+ optfirst = e;
+ r = 0;
+ }
+ return r;
}
-/*
- * auth_rmfiles()
- * Removes any files that the authentication program said needed to be
- * removed, said files having come from a previous execution of
- * auth_script().
- */
+void
+auth_clropts(void)
+{
+ struct authopts *e;
-int
+ while ((e = optfirst) != NULL) {
+ optfirst = e->next;
+ free(e);
+ }
+}
+
+
+void
auth_rmfiles(void)
{
- int i = auth_info.file_count;
- while (i-- > 0) {
- unlink(auth_info.files[i]);
- free(auth_info.files[i]);
- auth_info.files[i] = NULL;
- }
- return 0;
+ struct rmfiles *rm;
+
+ while ((rm = rmfirst) != NULL) {
+ unlink(rm->file);
+ rmfirst = rm->next;
+ free(rm);
+ }
}
+#endif
+
/*
* auth_checknologin()
@@ -370,6 +654,7 @@ auth_checknologin(login_cap_t *lc)
* reading, it prints it out to stdout, and then exits. Otherwise,
* it returns 0 (meaning no nologin file).
*/
+
int
auth_cat(const char *file)
{
@@ -379,7 +664,7 @@ auth_cat(const char *file)
if ((fd = open(file, O_RDONLY)) < 0)
return 0;
while ((count = read(fd, buf, sizeof(buf))) > 0)
- write(fileno(stdout), buf, count);
+ (void)write(fileno(stdout), buf, count);
close(fd);
return 1;
}
diff --git a/lib/libutil/login_cap.c b/lib/libutil/login_cap.c
index f507715..633da20 100644
--- a/lib/libutil/login_cap.c
+++ b/lib/libutil/login_cap.c
@@ -4,6 +4,10 @@
* David Nugent <davidn@blaze.net.au>
* All rights reserved.
*
+ * Portions copyright (c) 1995,1997
+ * Berkeley Software Design, Inc.
+ * All rights reserved.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
@@ -21,13 +25,14 @@
*
* Low-level routines relating to the user capabilities database
*
- * $Id: login_cap.c,v 1.10 1997/02/22 15:08:20 peter Exp $
+ * $Id: login_cap.c,v 1.11 1997/02/27 00:24:05 ache Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
@@ -35,13 +40,19 @@
#include <sys/resource.h>
#include <sys/param.h>
#include <pwd.h>
+#include <libutil.h>
+#include <syslog.h>
#include <login_cap.h>
-#ifdef RLIM_LONG
-# define STRTOV strtol
-#else
-# define STRTOV strtoq
-#endif
+/*
+ * allocstr()
+ * Manage a single static pointer for handling a local char* buffer,
+ * resizing as necessary to contain the string.
+ *
+ * allocarray()
+ * Manage a static array for handling a group of strings, resizing
+ * when necessary.
+ */
static int lc_object_count = 0;
@@ -51,30 +62,33 @@ static size_t internal_arraysz = 0;
static char ** internal_array = NULL;
static char *
-allocstr(char * str)
+allocstr(char *str)
{
- char * p;
- size_t sz = strlen(str) + 1; /* realloc() only if necessary */
- if (sz <= internal_stringsz)
- p = strcpy(internal_string, str);
- else if ((p = realloc(internal_string, sz)) != NULL) {
- internal_stringsz = sz;
- internal_string = strcpy(p, str);
- }
- return p;
+ char *p;
+
+ size_t sz = strlen(str) + 1; /* realloc() only if necessary */
+ if (sz <= internal_stringsz)
+ p = strcpy(internal_string, str);
+ else if ((p = realloc(internal_string, sz)) != NULL) {
+ internal_stringsz = sz;
+ internal_string = strcpy(p, str);
+ }
+ return p;
}
+
static char **
allocarray(size_t sz)
{
- char ** p;
- if (sz <= internal_arraysz)
- p = internal_array;
- else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) {
- internal_arraysz = sz;
- internal_array = p;
- }
- return p;
+ char **p;
+
+ if (sz <= internal_arraysz)
+ p = internal_array;
+ else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) {
+ internal_arraysz = sz;
+ internal_array = p;
+ }
+ return p;
}
@@ -89,38 +103,43 @@ allocarray(size_t sz)
static char **
arrayize(char *str, const char *chars, int *size)
{
- int i;
- char *ptr;
- char **res = NULL;
-
- for (i = 0, ptr = str; *ptr; i++) {
- int count = strcspn(ptr, chars);
- ptr += count;
- if (*ptr)
- ++ptr;
- }
-
- if ((ptr = allocstr(str)) == NULL) {
- res = NULL;
- i = 0;
- } else if ((res = allocarray(++i)) == NULL) {
- free(str);
+ int i;
+ char *ptr;
+ char **res = NULL;
+
+ /* count the sub-strings */
+ for (i = 0, ptr = str; *ptr; i++) {
+ int count = strcspn(ptr, chars);
+ ptr += count;
+ if (*ptr)
+ ++ptr;
+ }
+
i = 0;
- } else {
- for (i = 0; *ptr; i++) {
- int count = strcspn(ptr, chars);
- res[i] = ptr;
- ptr += count;
- if (*ptr)
- *ptr++ = '\0';
+ /* alloc the array */
+ if ((ptr = allocstr(str)) != NULL) {
+ if ((res = allocarray(++i)) == NULL)
+ free(str);
+ else {
+ /* now split the string */
+ while (*ptr) {
+ int count = strcspn(ptr, chars);
+ res[i++] = ptr;
+ ptr += count;
+ if (*ptr)
+ *ptr++ = '\0';
+ }
+ res[i] = NULL;
+ }
}
- res[i] = 0;
- }
- if (size)
- *size = i;
- return res;
+
+ if (size)
+ *size = i;
+
+ return res;
}
+
/*
* login_close()
* Frees up all resources relating to a login class
@@ -130,20 +149,20 @@ arrayize(char *str, const char *chars, int *size)
void
login_close(login_cap_t * lc)
{
- if (lc) {
- free(lc->lc_style);
- free(lc->lc_class);
- free(lc);
- if (--lc_object_count == 0) {
- free(internal_string);
- free(internal_array);
- internal_array = NULL;
- internal_arraysz = 0;
- internal_string = NULL;
- internal_stringsz = 0;
- cgetclose();
+ if (lc) {
+ free(lc->lc_style);
+ free(lc->lc_class);
+ free(lc);
+ if (--lc_object_count == 0) {
+ free(internal_string);
+ free(internal_array);
+ internal_array = NULL;
+ internal_arraysz = 0;
+ internal_string = NULL;
+ internal_stringsz = 0;
+ cgetclose();
+ }
}
- }
}
@@ -159,40 +178,101 @@ login_close(login_cap_t * lc)
*/
login_cap_t *
-login_getclassbyname(char const * name, char const * dir)
+login_getclassbyname(char const *name, const struct passwd *pwd)
{
- login_cap_t *lc = malloc(sizeof(login_cap_t));
+ login_cap_t *lc;
- if (lc != NULL) {
- int i = 0;
- char userpath[MAXPATHLEN];
- static char *login_dbarray[] = { NULL, NULL, NULL };
-
- if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, _FILE_LOGIN_CONF) < MAXPATHLEN)
- login_dbarray[i++] = userpath;
- else
- login_dbarray[i++] = _PATH_LOGIN_CONF;
- login_dbarray[i ] = NULL;
-
- lc->lc_cap = lc->lc_class = lc->lc_style = NULL;
-
- if ((name == NULL || cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0) &&
- cgetent(&lc->lc_cap, login_dbarray, (char*)(name = LOGIN_DEFCLASS)) != 0) {
+ if ((lc = malloc(sizeof(login_cap_t))) != NULL) {
+ int r, i = 0;
+ const char *msg = NULL;
+ const char *dir = (pwd == NULL) ? NULL : pwd->pw_dir;
+ char userpath[MAXPATHLEN];
+
+ static char *login_dbarray[] = { NULL, NULL, NULL };
+
+ 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 */
+ }
+ 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));
+ lc->lc_cap = lc->lc_class = lc->lc_style = NULL;
+
+ if (name == NULL || *name == '\0')
+ name = LOGIN_DEFCLASS;
+
+ switch (cgetent(&lc->lc_cap, login_dbarray, (char*)name)) {
+ case -1: /* Failed, entry does not exist */
+ if (strcmp(name, LOGIN_MECLASS) == 0)
+ break; /* Don't retry default on 'me' */
+ if (i == 0)
+ r = -1;
+ else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0)
+ close(r);
+ /*
+ * If there's at least one login class database,
+ * and we aren't searching for a default class
+ * then complain about a non-existent class.
+ */
+ if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0)
+ syslog(LOG_ERR, "login_getclass: unknown class '%s'", name);
+ /* 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)
+ break;
+ /* Fallthru - just return system defaults */
+ case 0: /* success! */
+ if ((lc->lc_class = strdup(name)) != NULL) {
+ ++lc_object_count;
+ return lc;
+ }
+ msg = "%s: strdup: %m";
+ break;
+ case -2:
+ msg = "%s: retrieving class information: %m";
+ break;
+ case -3:
+ msg = "%s: 'tc=' reference loop '%s'";
+ break;
+ case 1:
+ msg = "couldn't resolve 'tc=' reference in '%s'";
+ break;
+ default:
+ msg = "%s: unexpected cgetent() error '%s': %m";
+ break;
+ }
+ if (msg != NULL)
+ syslog(LOG_ERR, msg, "login_getclass", name);
free(lc);
- lc = NULL;
- } else {
- ++lc_object_count;
- lc->lc_class = strdup(name);
}
- }
- return lc;
+ return NULL;
}
/*
* login_getclass()
+ * Get the login class for the system (only) login class database.
+ * Return a filled-out login_cap_t structure, including
+ * class name, and the capability record buffer.
+ */
+
+login_cap_t *
+login_getclass(const char *cls)
+{
+ return login_getclassbyname(cls, NULL);
+}
+
+
+/*
+ * login_getclass()
* 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
@@ -203,14 +283,16 @@ login_getclassbyname(char const * name, char const * dir)
*/
login_cap_t *
-login_getclass(const struct passwd *pwd)
+login_getpwclass(const struct passwd *pwd)
{
- const char * class = NULL;
- if (pwd != NULL) {
- if ((class = pwd->pw_class) == NULL || *class == '\0')
- class = (pwd->pw_uid == 0) ? "root" : NULL;
- }
- return login_getclassbyname(class, 0);
+ const char *cls = NULL;
+
+ if (pwd != NULL) {
+ cls = pwd->pw_class;
+ if (cls == NULL || *cls == '\0')
+ cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
+ }
+ return login_getclassbyname(cls, pwd);
}
@@ -218,20 +300,12 @@ login_getclass(const struct passwd *pwd)
* login_getuserclass()
* Get the login class for a given password entry, allowing user
* overrides via ~/.login_conf.
- * ### WAS: If the password entry's class field is not set,
- * ####### or the class specified does not exist, then use
- * If an entry with the recordid "me" does not exist, then use
- * the default of LOGIN_DEFCLASS (ie. "default").
- * Return a filled-out login_cap_t structure, including
- * class name, and the capability record buffer.
*/
login_cap_t *
login_getuserclass(const struct passwd *pwd)
{
- const char * class = "me"; /* (pwd == NULL) ? NULL : pwd->pw_class; */
- const char * home = (pwd == NULL) ? NULL : pwd->pw_dir;
- return login_getclassbyname(class, home);
+ return login_getclassbyname(LOGIN_MECLASS, pwd);
}
@@ -246,18 +320,15 @@ login_getuserclass(const struct passwd *pwd)
char *
login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
{
- char *res;
- int ret;
+ char *res;
+ int ret;
- if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
- return def;
+ if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
+ return def;
- if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) {
- return def;
- } else if (ret >= 0)
- return res;
- else
- return error;
+ if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ return (ret >= 0) ? res : error;
}
@@ -269,15 +340,15 @@ login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
*/
char **
-login_getcaplist(login_cap_t *lc, const char * cap, const char * chars)
+login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
{
- char * lstring;
+ char *lstring;
- if (chars == NULL)
- chars = ", \t";
- if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL)
- return arrayize(lstring, chars, NULL);
- return NULL;
+ if (chars == NULL)
+ chars = ", \t";
+ if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL)
+ return arrayize(lstring, chars, NULL);
+ return NULL;
}
@@ -292,21 +363,124 @@ login_getcaplist(login_cap_t *lc, const char * cap, const char * chars)
char *
login_getpath(login_cap_t *lc, const char *cap, char * error)
{
- char *str = login_getcapstr(lc, (char*)cap, NULL, NULL);
-
- if (str == NULL)
- str = error;
- else {
- char *ptr = str;
-
- while (*ptr) {
- int count = strcspn(ptr, ", \t");
- ptr += count;
- if (*ptr)
- *ptr++ = ':';
+ char *str;
+
+ if ((str = login_getcapstr(lc, (char*)cap, NULL, NULL)) == NULL)
+ str = error;
+ else {
+ char *ptr = str;
+
+ while (*ptr) {
+ int count = strcspn(ptr, ", \t");
+ ptr += count;
+ if (*ptr)
+ *ptr++ = ':';
+ }
+ }
+ return str;
+}
+
+
+static int
+isinfinite(const char *s)
+{
+ static const char *infs[] = {
+ "infinity",
+ "inf",
+ "unlimited",
+ "unlimit",
+ "-1",
+ NULL
+ };
+ const char **i = &infs[0];
+
+ while (*i != NULL) {
+ if (strcasecmp(s, *i) == 0)
+ return 1;
+ ++i;
+ }
+ return 0;
+}
+
+
+static u_quad_t
+rmultiply(u_quad_t n1, u_quad_t n2)
+{
+ u_quad_t m, r;
+ int b1, b2;
+
+ static int bpw = 0;
+
+ /* Handle simple cases */
+ if (n1 == 0 || n2 == 0)
+ return 0;
+ if (n1 == 1)
+ return n2;
+ if (n2 == 1)
+ return n1;
+
+ /*
+ * sizeof() returns number of bytes needed for storage.
+ * This may be different from the actual number of useful bits.
+ */
+ if (!bpw) {
+ bpw = sizeof(u_quad_t) * 8;
+ while (((u_quad_t)1 << (bpw-1)) == 0)
+ --bpw;
}
- }
- return str;
+
+ /*
+ * First check the magnitude of each number. If the sum of the
+ * magnatude is way to high, reject the number. (If this test
+ * is not done then the first multiply below may overflow.)
+ */
+ for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1)
+ ;
+ for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2)
+ ;
+ if (b1 + b2 - 2 > bpw) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+
+ /*
+ * Decompose the multiplication to be:
+ * h1 = n1 & ~1
+ * h2 = n2 & ~1
+ * l1 = n1 & 1
+ * l2 = n2 & 1
+ * (h1 + l1) * (h2 + l2)
+ * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2)
+ *
+ * Since h1 && h2 do not have the low bit set, we can then say:
+ *
+ * (h1>>1 * h2>>1 * 4) + ...
+ *
+ * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will
+ * overflow.
+ *
+ * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2)
+ * then adding in residual amout will cause an overflow.
+ */
+
+ m = (n1 >> 1) * (n2 >> 1);
+ if (m >= ((u_quad_t)1 << (bpw-2))) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+ m *= 4;
+
+ r = (n1 & n2 & 1)
+ + (n2 & 1) * (n1 & ~(u_quad_t)1)
+ + (n1 & 1) * (n2 & ~(u_quad_t)1);
+
+ if ((u_quad_t)(m + r) < m) {
+ errno = ERANGE;
+ return (UQUAD_MAX);
+ }
+ m += r;
+
+ return (m);
}
@@ -321,70 +495,80 @@ login_getpath(login_cap_t *lc, const char *cap, char * error)
rlim_t
login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
{
- char *res, *ep;
- int ret;
- rlim_t tot;
-
- errno = 0;
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- /*
- * Look for <cap> in lc_cap.
- * If it's not there (-1), return <def>.
- * If there's an error, return <error>.
- */
-
- if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
- return def;
- else if (ret < 0)
- return error;
-
- /*
- * "inf" and "infinity" are two special cases for this.
- */
- if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf"))
- return RLIM_INFINITY;
-
- /*
- * Now go through the string, turning something like 1h2m3s into
- * an integral value. Whee.
- */
-
- errno = 0;
- tot = 0;
- while (*res) {
- rlim_t tim = STRTOV(res, &ep, 0);
- if ((ep == NULL) || (ep == res) || errno) {
- return error;
+ char *res, *ep, *oval;
+ int r;
+ rlim_t tot;
+
+ errno = 0;
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
+ /*
+ * Look for <cap> in lc_cap.
+ * If it's not there (-1), return <def>.
+ * If there's an error, return <error>.
+ */
+
+ if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ else if (r < 0) {
+ errno = ERANGE;
+ return error;
}
- /* Look for suffixes */
- switch (*ep++) {
- case 0:
- ep--; break; /* end of string */
- case 's': case 'S': /* seconds */
- break;
- case 'm': case 'M': /* minutes */
- tim *= 60L;
- break;
- case 'h': case 'H': /* hours */
- tim *= (60L * 60L);
- break;
- case 'd': case 'D': /* days */
- tim *= (60L * 60L * 24L);
- break;
- case 'w': case 'W': /* weeks */
- tim *= (60L * 60L * 24L * 7L);
- case 'y': case 'Y': /* Years */
- /* I refuse to take leap years into account here. Sue me. */
- tim *= (60L * 60L * 24L * 365L);
- default:
- return error;
+
+ /* "inf" and "infinity" are special cases */
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ /*
+ * Now go through the string, turning something like 1h2m3s into
+ * an integral value. Whee.
+ */
+
+ errno = 0;
+ tot = 0;
+ oval = res;
+ while (*res) {
+ rlim_t tim = strtoq(res, &ep, 0);
+ rlim_t mult = 1;
+
+ if (ep == NULL || ep == res || errno != 0) {
+ invalid:
+ syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s",
+ lc->lc_class, cap, oval);
+ errno = ERANGE;
+ return error;
+ }
+ /* Look for suffixes */
+ switch (*ep++) {
+ case 0:
+ ep--;
+ break; /* end of string */
+ case 's': case 'S': /* seconds */
+ break;
+ case 'm': case 'M': /* minutes */
+ mult = 60;
+ break;
+ case 'h': case 'H': /* hours */
+ mult = 60L * 60L;
+ break;
+ case 'd': case 'D': /* days */
+ mult = 60L * 60L * 24L;
+ break;
+ case 'w': case 'W': /* weeks */
+ mult = 60L * 60L * 24L * 7L;
+ case 'y': case 'Y': /* 365-day years */
+ mult = 60L * 60L * 24L * 365L;
+ default:
+ goto invalid;
+ }
+ res = ep;
+ tot += rmultiply(tim, mult);
+ if (errno)
+ goto invalid;
}
- res = ep;
- tot += tim;
- }
- return tot;
+
+ return tot;
}
@@ -400,41 +584,47 @@ login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
rlim_t
login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
{
- char *ep, *res;
- int ret;
- rlim_t val;
-
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- /*
- * For BSDI compatibility, try for the tag=<val> first
- */
- if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) {
- long lval;
+ char *ep, *res;
+ int r;
+ rlim_t val;
+
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
/*
- * String capability not present, so try for tag#<val> as numeric
+ * For BSDI compatibility, try for the tag=<val> first
*/
- if ((ret = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1)
- return def; /* Not there, so return default */
- else if (ret < 0)
- return error;
- return (rlim_t)lval;
- }
- else if (ret < 0)
- return error;
-
- if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf"))
- return RLIM_INFINITY;
-
- errno = 0;
- val = STRTOV(res, &ep, 0);
- if ((ep == NULL) || (ep == res) || errno)
- return error;
- return val;
+ if ((r = cgetstr(lc->lc_cap, (char *)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)
+ return def; /* Not there, so return default */
+ else if (r >= 0)
+ return (rlim_t)lval;
+ }
+
+ if (r < 0) {
+ errno = ERANGE;
+ return error;
+ }
+
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ errno = 0;
+ val = strtoq(res, &ep, 0);
+ if (ep == NULL || ep == res || errno != 0) {
+ syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s",
+ lc->lc_class, cap, res);
+ errno = ERANGE;
+ return error;
+ }
+
+ return val;
}
+
/*
* login_getcapsize()
* From the login_cap_t <lc>, extract the capability <cap>, which is
@@ -444,55 +634,68 @@ login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
*/
rlim_t
-login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) {
- char *ep, *res;
- int ret;
- rlim_t tot, mult;
-
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
-
- if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
- return def;
- else if (ret < 0)
- return error;
-
- /*
- * "inf" and "infinity" are two special cases for this.
- */
- if (!strcasecmp(res, "infinity") || !strcasecmp(res, "inf"))
- return RLIM_INFINITY;
-
- errno = 0;
- tot = 0;
- while (*res) {
- rlim_t val = STRTOV(res, &ep, 0);
- if ((res == NULL) || (res == ep) || errno)
- return error;
- switch (*ep++) {
- case 0: /* end of string */
- ep--;
- mult = 1;
- break;
- case 'b': case 'B': /* 512-byte blocks */
- mult = 512; break;
- case 'k': case 'K': /* 1024-byte Kilobytes */
- mult = 1024; break;
- case 'm': case 'M': /* 1024-k kbytes */
- mult = 1024 * 1024; break;
- case 'g': case 'G': /* 1Gbyte */
- mult = 1024 * 1024 * 1024; break;
-#ifndef RLIM_LONG
- case 't': case 'T': /* 1TBte */
- mult = 1024LL * 1024LL * 1024LL * 1024LL; break;
-#endif
- default:
- return error;
+login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
+{
+ char *ep, *res, *oval;
+ int r;
+ rlim_t tot;
+
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+
+ if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+ return def;
+ else if (r < 0) {
+ errno = ERANGE;
+ return error;
+ }
+
+ if (isinfinite(res))
+ return RLIM_INFINITY;
+
+ errno = 0;
+ tot = 0;
+ oval = res;
+ while (*res) {
+ rlim_t siz = strtoq(res, &ep, 0);
+ rlim_t mult = 1;
+
+ if (ep == NULL || ep == res || errno != 0) {
+ invalid:
+ syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s",
+ lc->lc_class, cap, oval);
+ errno = ERANGE;
+ return error;
+ }
+ switch (*ep++) {
+ case 0: /* end of string */
+ ep--;
+ break;
+ case 'b': case 'B': /* 512-byte blocks */
+ mult = 512;
+ break;
+ case 'k': case 'K': /* 1024-byte Kilobytes */
+ mult = 1024;
+ break;
+ case 'm': case 'M': /* 1024-k kbytes */
+ mult = 1024 * 1024;
+ break;
+ case 'g': case 'G': /* 1Gbyte */
+ mult = 1024 * 1024 * 1024;
+ break;
+ case 't': case 'T': /* 1TBte */
+ mult = 1024LL * 1024LL * 1024LL * 1024LL;
+ break;
+ default:
+ goto invalid;
+ }
+ res = ep;
+ tot += rmultiply(siz, mult);
+ if (errno)
+ goto invalid;
}
- res = ep;
- tot += (val * mult);
- }
- return tot;
+
+ return tot;
}
@@ -506,9 +709,9 @@ login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) {
int
login_getcapbool(login_cap_t *lc, const char *cap, int def)
{
- if (lc == NULL || lc->lc_cap == NULL)
- return def;
- return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL);
+ if (lc == NULL || lc->lc_cap == NULL)
+ return def;
+ return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL);
}
@@ -535,38 +738,41 @@ login_getcapbool(login_cap_t *lc, const char *cap, int def)
char *
login_getstyle(login_cap_t *lc, char *style, const char *auth)
{
- int i;
- char **authtypes = NULL;
- char *auths= NULL;
- char realauth[64];
-
- static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
-
- if (auth != NULL && *auth != '\0' &&
- snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth)
- authtypes = login_getcaplist(lc, realauth, NULL);
-
- if (authtypes == NULL)
- authtypes = login_getcaplist(lc, "auth", NULL);
-
- if (authtypes == NULL)
- authtypes = defauthtypes;
-
- /*
- * We have at least one authtype now; auths is a comma-seperated
- * (or space-separated) list of authentication types. We have to
- * convert from this to an array of char*'s; authtypes then gets this.
- */
- i = 0;
- if (style != NULL && *style != '\0') {
- while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0)
- i++;
- }
- lc->lc_style = NULL;
- if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL)
- lc->lc_style = auths;
-
- return lc->lc_style;
-}
+ int i;
+ char **authtypes = NULL;
+ char *auths= NULL;
+ char realauth[64];
+ static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
+ if (auth != NULL && *auth != '\0') {
+ if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < sizeof realauth)
+ authtypes = login_getcaplist(lc, realauth, NULL);
+ }
+
+ if (authtypes == NULL)
+ authtypes = login_getcaplist(lc, "auth", NULL);
+
+ if (authtypes == NULL)
+ authtypes = defauthtypes;
+
+ /*
+ * We have at least one authtype now; auths is a comma-seperated
+ * (or space-separated) list of authentication types. We have to
+ * convert from this to an array of char*'s; authtypes then gets this.
+ */
+ i = 0;
+ if (style != NULL && *style != '\0') {
+ while (authtypes[i] != NULL && strcmp(style, authtypes[i]) != 0)
+ i++;
+ }
+
+ lc->lc_style = NULL;
+ if (authtypes[i] != NULL && (auths = strdup(authtypes[i])) != NULL)
+ lc->lc_style = auths;
+
+ if (lc->lc_style != NULL)
+ lc->lc_style = strdup(lc->lc_style);
+
+ return lc->lc_style;
+}
diff --git a/lib/libutil/login_cap.h b/lib/libutil/login_cap.h
index 4c92f0a..f380936 100644
--- a/lib/libutil/login_cap.h
+++ b/lib/libutil/login_cap.h
@@ -22,13 +22,15 @@
* Low-level routines relating to the user capabilities database
*
* Was login_cap.h,v 1.9 1997/05/07 20:00:01 eivind Exp
- * $Id$
+ * $Id: login_cap.h,v 1.1 1997/05/10 12:49:30 davidn Exp $
*/
#ifndef _LOGIN_CAP_H_
#define _LOGIN_CAP_H_
#define LOGIN_DEFCLASS "default"
+#define LOGIN_DEFROOTCLASS "root"
+#define LOGIN_MECLASS "me"
#define LOGIN_DEFSTYLE "passwd"
#define LOGIN_DEFSERVICE "login"
#define LOGIN_DEFUMASK 022
@@ -37,53 +39,57 @@
#define _FILE_LOGIN_CONF ".login_conf"
#define _PATH_AUTHPROG "/usr/libexec/login_"
-#define LOGIN_SETGROUP 0x0001 /* set group */
-#define LOGIN_SETLOGIN 0x0002 /* set login (via setlogin) */
-#define LOGIN_SETPATH 0x0004 /* set path */
-#define LOGIN_SETPRIORITY 0x0008 /* set priority */
-#define LOGIN_SETRESOURCES 0x0010 /* set resources (cputime, etc.) */
-#define LOGIN_SETUMASK 0x0020 /* set umask, obviously */
-#define LOGIN_SETUSER 0x0040 /* set user (via setuid) */
-#define LOGIN_SETENV 0x0080 /* set user environment */
-#define LOGIN_SETALL 0x00ff /* set everything */
-
-#define BI_AUTH "authorize"
-#define BI_AUTH2 "authorise"
-#define BI_REJECT "reject"
-#define BI_REMOVE "remove"
-#define BI_ROOTOKAY "root"
-#define BI_SECURE "secure"
-#define BI_SETENV "setenv"
-
-#ifndef AUTH_NONE /* Protect against <rpc/auth.h> */
-#define AUTH_NONE 0x00
-#endif
-#define AUTH_OKAY 0x01
-#define AUTH_ROOTOKAY 0x02 /* root login okay */
-#define AUTH_SECURE 0x04 /* secure login */
+#define LOGIN_SETGROUP 0x0001 /* set group */
+#define LOGIN_SETLOGIN 0x0002 /* set login (via setlogin) */
+#define LOGIN_SETPATH 0x0004 /* set path */
+#define LOGIN_SETPRIORITY 0x0008 /* set priority */
+#define LOGIN_SETRESOURCES 0x0010 /* set resources (cputime, etc.) */
+#define LOGIN_SETUMASK 0x0020 /* set umask, obviously */
+#define LOGIN_SETUSER 0x0040 /* set user (via setuid) */
+#define LOGIN_SETENV 0x0080 /* set user environment */
+#define LOGIN_SETALL 0x00ff /* set everything */
+
+#define BI_AUTH "authorize" /* accepted authentication */
+#define BI_REJECT "reject" /* rejected authentication */
+#define BI_CHALLENG "reject challenge" /* reject with a challenge */
+#define BI_SILENT "reject silent" /* reject silently */
+#define BI_REMOVE "remove" /* remove file on error */
+#define BI_ROOTOKAY "authorize root" /* root authenticated */
+#define BI_SECURE "authorize secure" /* okay on non-secure line */
+#define BI_SETENV "setenv" /* set environment variable */
+#define BI_VALUE "value" /* set local variable */
+
+#define AUTH_OKAY 0x01 /* user authenticated */
+#define AUTH_ROOTOKAY 0x02 /* root login okay */
+#define AUTH_SECURE 0x04 /* secure login */
+#define AUTH_SILENT 0x08 /* silent rejection */
+#define AUTH_CHALLENGE 0x10 /* a chellenge was given */
+
+#define AUTH_ALLOW (AUTH_OKAY | AUTH_ROOTOKAY | AUTH_SECURE)
typedef struct login_cap {
- char *lc_class;
- char *lc_cap;
- char *lc_style;
+ char *lc_class;
+ char *lc_cap;
+ char *lc_style;
} login_cap_t;
typedef struct login_time {
- u_short lt_start; /* Start time */
- u_short lt_end; /* End time */
- #define LTM_NONE 0x00
- #define LTM_SUN 0x01
- #define LTM_MON 0x02
- #define LTM_TUE 0x04
- #define LTM_WED 0x08
- #define LTM_THU 0x10
- #define LTM_FRI 0x20
- #define LTM_SAT 0x40
- #define LTM_ANY 0x7F
- #define LTM_WK 0x3E
- #define LTM_WD 0x41
- u_char lt_dow; /* Days of week */
+ u_short lt_start; /* Start time */
+ u_short lt_end; /* End time */
+#define LTM_NONE 0x00
+#define LTM_SUN 0x01
+#define LTM_MON 0x02
+#define LTM_TUE 0x04
+#define LTM_WED 0x08
+#define LTM_THU 0x10
+#define LTM_FRI 0x20
+#define LTM_SAT 0x40
+#define LTM_ANY 0x7F
+#define LTM_WK 0x3E
+#define LTM_WD 0x41
+ u_char lt_dow; /* Days of week */
} login_time_t;
+
#define LC_MAXTIMES 64
#include <sys/cdefs.h>
@@ -91,8 +97,9 @@ __BEGIN_DECLS
struct passwd;
void login_close __P((login_cap_t *));
-login_cap_t *login_getclassbyname __P((const char *, const char *homedir));
-login_cap_t *login_getclass __P((const struct passwd *));
+login_cap_t *login_getclassbyname __P((const char *, const struct passwd *));
+login_cap_t *login_getclass __P((const char *));
+login_cap_t *login_getpwclass __P((const struct passwd *));
login_cap_t *login_getuserclass __P((const struct passwd *));
char *login_getcapstr __P((login_cap_t*, const char *, char *, char *));
@@ -109,11 +116,20 @@ int setusercontext __P((login_cap_t*, const struct passwd*, uid_t, unsigned int)
void setclassresources __P((login_cap_t *));
void setclassenvironment __P((login_cap_t *, const struct passwd *, int));
-int authenticate __P((const char*, const char*, const char*, const char*));
-int auth_script __P((const char*, ...));
-int auth_env __P((void));
+/* Most of these functions are deprecated */
+int auth_approve __P((login_cap_t*, const char*, const char*));
+int auth_check __P((const char *, const char *, const char *, const char *, int *));
+void auth_env __P((void));
+char *auth_mkvalue __P((const char *n));
+int auth_response __P((const char *, const char *, const char *, const char *, int *, const char *, const char *));
+void auth_rmfiles __P((void));
int auth_scan __P((int));
-int auth_rmfiles __P((void));
+int auth_script __P((const char*, ...));
+int auth_script_data __P((const char *, int, const char *, ...));
+char *auth_valud __P((const char *));
+int auth_setopt __P((const char *, const char *));
+void auth_clropts __P((void));
+
void auth_checknologin __P((login_cap_t*));
int auth_cat __P((const char*));
@@ -127,7 +143,7 @@ login_time_t parse_lt __P((const char *));
int in_ltm __P((const login_time_t *, struct tm *, time_t *));
int in_ltms __P((const login_time_t *, struct tm *, time_t *));
-/* auxiliary functions */
+/* helper functions */
int login_strinlist __P((char **, char const *, int));
int login_str2inlist __P((char **, const char *, const char *, int));
@@ -138,4 +154,3 @@ int login_hostok __P((login_cap_t *, const char *, const char *, const char *, c
__END_DECLS
#endif /* _LOGIN_CAP_H_ */
-
diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c
index cf6d6d6..73190e9 100644
--- a/lib/libutil/login_class.c
+++ b/lib/libutil/login_class.c
@@ -21,7 +21,7 @@
*
* High-level routines relating to use of the user capabilities database
*
- * $Id$
+ * $Id: login_class.c,v 1.5 1997/02/22 15:08:22 peter Exp $
*/
#include <stdio.h>
@@ -45,202 +45,197 @@
static struct login_res {
- const char * what;
- rlim_t (*who)(login_cap_t *, const char *, rlim_t, rlim_t);
- int why;
+ const char *what;
+ rlim_t (*who)(login_cap_t *, const char *, rlim_t, rlim_t);
+ int why;
} resources[] = {
- { "cputime", login_getcaptime, RLIMIT_CPU },
- { "filesize", login_getcapsize, RLIMIT_FSIZE },
- { "datasize", login_getcapsize, RLIMIT_DATA },
- { "stacksize", login_getcapsize, RLIMIT_STACK },
- { "coredumpsize", login_getcapsize, RLIMIT_CORE },
- { "memoryuse", login_getcapsize, RLIMIT_RSS },
- { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK },
- { "maxproc", login_getcapnum, RLIMIT_NPROC },
- { "openfiles", login_getcapnum, RLIMIT_NOFILE },
- { NULL, 0, 0 }
+ { "cputime", login_getcaptime, RLIMIT_CPU },
+ { "filesize", login_getcapsize, RLIMIT_FSIZE },
+ { "datasize", login_getcapsize, RLIMIT_DATA },
+ { "stacksize", login_getcapsize, RLIMIT_STACK },
+ { "memoryuse", login_getcapsize, RLIMIT_RSS },
+ { "memorylocked", login_getcapsize, RLIMIT_MEMLOCK },
+ { "maxproc", login_getcapnum, RLIMIT_NPROC },
+ { "openfiles", login_getcapnum, RLIMIT_NOFILE },
+ { "coredumpsize", login_getcapsize, RLIMIT_CORE },
+ { NULL, 0, 0 }
};
-
void
setclassresources(login_cap_t *lc)
{
- struct login_res *lr = resources;
-
- if (lc == NULL)
- return;
+ struct login_res *lr;
- while (lr->what != NULL) {
- struct rlimit rlim,
- newlim;
- char cur[40],
- max[40];
- rlim_t rcur,
- rmax;
+ if (lc == NULL)
+ return;
- sprintf(cur, "%s-cur", lr->what);
- sprintf(max, "%s-max", lr->what);
+ for (lr = resources; lr->what != NULL; ++lr) {
+ struct rlimit rlim;
- /*
- * The login.conf file can have <limit>, <limit>-max, and
- * <limit>-cur entries.
- * What we do is get the current current- and maximum- limits.
- * Then, we try to get an entry for <limit> from the capability,
- * using the current and max limits we just got as the
- * default/error values.
- * *Then*, we try looking for <limit>-cur and <limit>-max,
- * again using the appropriate values as the default/error
- * conditions.
- */
-
- getrlimit(lr->why, &rlim);
- rcur = rlim.rlim_cur;
- rmax = rlim.rlim_max;
+ /*
+ * The login.conf file can have <limit>, <limit>-max, and
+ * <limit>-cur entries.
+ * What we do is get the current current- and maximum- limits.
+ * Then, we try to get an entry for <limit> from the capability,
+ * using the current and max limits we just got as the
+ * default/error values.
+ * *Then*, we try looking for <limit>-cur and <limit>-max,
+ * again using the appropriate values as the default/error
+ * conditions.
+ */
- rcur = (*lr->who)(lc, lr->what, rcur, rcur);
- rmax = (*lr->who)(lc, lr->what, rmax, rmax);
- newlim.rlim_cur = (*lr->who)(lc, cur, rcur, rcur);
- newlim.rlim_max = (*lr->who)(lc, max, rmax, rmax);
+ if (getrlimit(lr->why, &rlim) != 0)
+ syslog(LOG_ERR, "getting %s resource limit: %m", lr->what);
+ else {
+ char name_cur[40];
+ char name_max[40];
+ rlim_t rcur = rlim.rlim_cur;
+ rlim_t rmax = rlim.rlim_max;
+
+ sprintf(name_cur, "%s-cur", lr->what);
+ sprintf(name_max, "%s-max", lr->what);
+
+ rcur = (*lr->who)(lc, lr->what, rcur, rcur);
+ rmax = (*lr->who)(lc, lr->what, rmax, rmax);
+ rlim.rlim_cur = (*lr->who)(lc, name_cur, rcur, rcur);
+ rlim.rlim_max = (*lr->who)(lc, name_max, rmax, rmax);
- if (setrlimit(lr->why, &newlim) == -1)
- syslog(LOG_WARNING, "set class '%s' resource limit %s: %m", lc->lc_class, lr->what);
-
- ++lr;
- }
+ if (setrlimit(lr->why, &rlim) == -1)
+ syslog(LOG_WARNING, "set class '%s' resource limit %s: %m", lc->lc_class, lr->what);
+ }
+ }
}
+
+
static struct login_vars {
- const char * tag;
- const char * var;
- const char * def;
+ const char *tag;
+ const char *var;
+ const char *def;
} pathvars[] = {
- { "path", "PATH", NULL },
- { "manpath", "MANPATH", NULL },
- { NULL, NULL, NULL }
+ { "path", "PATH", NULL },
+ { "cdpath", "CDPATH", NULL },
+ { "manpath", "MANPATH", NULL },
+ { NULL, NULL, NULL }
}, envars[] = {
- { "lang", "LANG", NULL },
- { "charset", "MM_CHARSET", NULL },
- { "timezone", "TZ", NULL },
- { "term", "TERM", UNKNOWN },
- { NULL, NULL, NULL }
+ { "lang", "LANG", NULL },
+ { "charset", "MM_CHARSET", NULL },
+ { "timezone", "TZ", NULL },
+ { "term", "TERM", UNKNOWN },
+ { NULL, NULL, NULL }
};
static char *
substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
{
- char * np = NULL;
-
- if (var != NULL) {
- int tildes = 0;
- int dollas = 0;
- char * p;
-
- if (pwd != NULL) {
- /*
- * Count the number of ~'s in var to substitute
- */
- p = var;
- while ((p = strchr(p, '~')) != NULL) {
- ++tildes;
- ++p;
- }
-
- /*
- * Count the number of $'s in var to substitute
- */
- p = var;
- while ((p = strchr(p, '$')) != NULL) {
- ++dollas;
- ++p;
- }
- }
-
- np = malloc(strlen(var) + (dollas * nlen) - dollas + (tildes * (pch+hlen)) - tildes + 1);
-
- if (np != NULL) {
- p = strcpy(np, var);
+ char *np = NULL;
+
+ if (var != NULL) {
+ int tildes = 0;
+ int dollas = 0;
+ char *p;
+
+ if (pwd != NULL) {
+ /* Count the number of ~'s in var to substitute */
+ p = var;
+ for (p = var; (p = strchr(p, '~')) != NULL; p++)
+ ++tildes;
+ /* Count the number of $'s in var to substitute */
+ p = var;
+ for (p = var; (p = strchr(p, '$')) != NULL; p++)
+ ++dollas;
+ }
- if (pwd != NULL) {
- /*
- * This loop does user username and homedir substitutions
- * for unescaped $ (username) and ~ (homedir)
- */
- while (*(p += strcspn(p, "~$")) != '\0') {
- int l = strlen(p);
-
- if (p > var && *(p-1) == '\\') /* Escaped: */
- memmove(p - 1, p, l + 1); /* Slide-out the backslash */
- else if (*p == '~') {
- int v = pch && *(p+1) != '/'; /* Avoid double // */
- memmove(p + hlen + v, p + 1, l); /* Subst homedir */
- memmove(p, pwd->pw_dir, hlen);
- if (v)
- p[hlen] = '/';
- p += hlen + v;
- }
- else /* if (*p == '$') */ {
- memmove(p + nlen, p + 1, l); /* Subst username */
- memmove(p, pwd->pw_name, nlen);
- p += nlen;
- }
+ np = malloc(strlen(var) + (dollas * nlen)
+ - dollas + (tildes * (pch+hlen))
+ - tildes + 1);
+
+ if (np != NULL) {
+ p = strcpy(np, var);
+
+ if (pwd != NULL) {
+ /*
+ * This loop does user username and homedir substitutions
+ * for unescaped $ (username) and ~ (homedir)
+ */
+ while (*(p += strcspn(p, "~$")) != '\0') {
+ int l = strlen(p);
+
+ if (p > var && *(p-1) == '\\') /* Escaped: */
+ memmove(p - 1, p, l + 1); /* Slide-out the backslash */
+ else if (*p == '~') {
+ int v = pch && *(p+1) != '/'; /* Avoid double // */
+ memmove(p + hlen + v, p + 1, l); /* Subst homedir */
+ memmove(p, pwd->pw_dir, hlen);
+ if (v)
+ p[hlen] = '/';
+ p += hlen + v;
+ }
+ else /* if (*p == '$') */ {
+ memmove(p + nlen, p + 1, l); /* Subst username */
+ memmove(p, pwd->pw_name, nlen);
+ p += nlen;
+ }
+ }
+ }
}
- }
}
- }
- return np;
+
+ return np;
}
void
setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
{
- struct login_vars * vars = paths ? pathvars : envars;
- int hlen = pwd ? strlen(pwd->pw_dir) : 0;
- int nlen = pwd ? strlen(pwd->pw_name) : 0;
- char pch = 0;
+ struct login_vars *vars = paths ? pathvars : envars;
+ int hlen = pwd ? strlen(pwd->pw_dir) : 0;
+ int nlen = pwd ? strlen(pwd->pw_name) : 0;
+ char pch = 0;
- if (hlen && pwd->pw_dir[hlen-1] != '/')
- ++pch;
+ if (hlen && pwd->pw_dir[hlen-1] != '/')
+ ++pch;
- while (vars->tag != NULL) {
- char * var = paths ? login_getpath(lc, vars->tag, NULL)
- : login_getcapstr(lc, vars->tag, NULL, NULL);
+ while (vars->tag != NULL) {
+ char * var = paths ? login_getpath(lc, vars->tag, NULL)
+ : login_getcapstr(lc, vars->tag, NULL, NULL);
- char * np = substvar(var, pwd, hlen, pch, nlen);
+ char * np = substvar(var, pwd, hlen, pch, nlen);
- if (np != NULL) {
- setenv(vars->var, np, 1);
- free(np);
- } else if (vars->def != NULL) {
- setenv(vars->var, vars->def, 0);
- }
- ++vars;
- }
-
- /*
- * If we're not processing paths, then see if there is a setenv list by
- * which the admin and/or user may set an arbitrary set of env vars.
- */
- if (!paths) {
- char ** set_env = login_getcaplist(lc, "setenv", ",");
-
- if (set_env != NULL) {
- while (*set_env != NULL) {
- char *p = strchr(*set_env, '=');
- if (p != NULL) { /* Discard invalid entries */
- char * np;
-
- *p++ = '\0';
- if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) {
- setenv(*set_env, np, 1);
+ if (np != NULL) {
+ setenv(vars->var, np, 1);
free(np);
- }
+ } else if (vars->def != NULL) {
+ setenv(vars->var, vars->def, 0);
+ }
+ ++vars;
+ }
+
+ /*
+ * If we're not processing paths, then see if there is a setenv list by
+ * which the admin and/or user may set an arbitrary set of env vars.
+ */
+ if (!paths) {
+ char **set_env = login_getcaplist(lc, "setenv", ",");
+
+ if (set_env != NULL) {
+ while (*set_env != NULL) {
+ char *p = strchr(*set_env, '=');
+
+ if (p != NULL) { /* Discard invalid entries */
+ char *np;
+
+ *p++ = '\0';
+ if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) {
+ setenv(*set_env, np, 1);
+ free(np);
+ }
+ }
+ ++set_env;
+ }
}
- ++set_env;
- }
}
- }
}
@@ -258,15 +253,48 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
int
setclasscontext(const char *classname, unsigned int flags)
{
- int rc;
- login_cap_t * lc = login_getclassbyname(classname, NULL);
- flags &= (LOGIN_SETRESOURCES| LOGIN_SETPRIORITY|LOGIN_SETUMASK);
- rc = setusercontext(lc, NULL, 0, flags);
- login_close(lc);
- return rc;
+ int rc;
+ login_cap_t *lc;
+
+ lc = login_getclassbyname(classname, NULL);
+
+ flags &= LOGIN_SETRESOURCES | LOGIN_SETPRIORITY |
+ LOGIN_SETUMASK | LOGIN_SETPATH;
+
+ rc = lc ? setusercontext(lc, NULL, 0, flags) : -1;
+ login_close(lc);
+ return rc;
+}
+
+
+
+/*
+ * Private functionw which takes care of processing
+ */
+
+static mode_t
+setlogincontext(login_cap_t *lc, const struct passwd *pwd,
+ mode_t mymask, unsigned long flags)
+{
+ if (lc) {
+ /* Set resources */
+ if (flags & LOGIN_SETRESOURCES)
+ setclassresources(lc);
+ /* See if there's a umask override */
+ if (flags & LOGIN_SETUMASK)
+ mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask);
+ /* Set paths */
+ if (flags & LOGIN_SETPATH)
+ setclassenvironment(lc, pwd, 1);
+ /* Set environment */
+ if (flags & LOGIN_SETENV)
+ setclassenvironment(lc, pwd, 0);
+ }
+ return mymask;
}
+
/*
* setusercontext()
*
@@ -284,93 +312,76 @@ setclasscontext(const char *classname, unsigned int flags)
int
setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned int flags)
{
- int i;
- login_cap_t * llc = NULL;
-
- if (lc == NULL)
- {
- if (pwd != NULL && (lc = login_getclass(pwd)) != NULL)
- llc = lc; /* free this when we're done */
- }
-
- if (flags & LOGIN_SETPATH)
- pathvars[0].def = uid ? _PATH_DEFPATH : _PATH_STDPATH;
-
- /*
- * Set the process priority
- */
- if (flags & LOGIN_SETPRIORITY) {
- int pri = (int)login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI);
- pri = (pri < PRIO_MIN) ? PRIO_MIN : (pri > PRIO_MAX) ? PRIO_MAX : pri;
- if (setpriority(PRIO_PROCESS, 0, pri) != 0)
- syslog(LOG_WARNING, "setpriority '%s': %m", pwd->pw_name);
- }
-
- /*
- * Set resources
- */
- if (flags & LOGIN_SETRESOURCES)
- setclassresources(lc);
-
- /*
- * Set the sessions login
- */
- if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
- syslog(LOG_ERR, "setlogin '%s': %m", pwd->pw_name);
- login_close(llc);
- return -1;
- }
-
- /*
- * Setup the user's group permissions
- */
- if (flags & LOGIN_SETGROUP) {
- if (setgid(pwd->pw_gid) != 0)
- syslog(LOG_WARNING, "setgid %ld: %m", (long)pwd->pw_gid);
- if (initgroups(pwd->pw_name, pwd->pw_gid) == -1)
- syslog(LOG_WARNING, "initgroups '%s': %m", pwd->pw_name);
- }
-
- /*
- * FreeBSD extension: here we (might) loop and do this twice.
- * First, for the class we have been given, and next for
- * any user overrides in ~/.login.conf the user's home directory.
- */
- if (flags & LOGIN_SETUMASK)
- umask(LOGIN_DEFUMASK); /* Set default umask up front */
-
- i = 0;
- while (i < 2 && lc != NULL) {
-
- if (flags & LOGIN_SETUMASK) {
- rlim_t tmp = login_getcapnum(lc, "umask", RLIM_INFINITY, RLIM_INFINITY);
- if (tmp != RLIM_INFINITY)
- umask((mode_t)tmp);
+ quad_t p;
+ mode_t mymask;
+ login_cap_t *llc = NULL;
+
+ if (lc == NULL) {
+ if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL)
+ llc = lc; /* free this when we're done */
}
if (flags & LOGIN_SETPATH)
- setclassenvironment(lc, pwd, 1);
+ pathvars[0].def = uid ? _PATH_DEFPATH : _PATH_STDPATH;
- if (flags & LOGIN_SETENV)
- setclassenvironment(lc, pwd, 0);
+ /* we need a passwd entry to set these */
+ if (pwd == NULL)
+ flags &= ~(LOGIN_SETGROUP | LOGIN_SETLOGIN);
- if (i++ == 0) /* Play it again, Sam */
- lc = (pwd == NULL) ? NULL : login_getuserclass(pwd);
- }
+ /* Set the process priority */
+ if (flags & LOGIN_SETPRIORITY) {
+ p = login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI);
- login_close(lc); /* User's private 'me' class */
- login_close(llc); /* Class we opened */
+ p = (p < PRIO_MIN || p > PRIO_MAX) ? LOGIN_DEFPRI : p;
+ if (setpriority(PRIO_PROCESS, 0, (int)p) != 0)
+ syslog(LOG_WARNING, "setpriority '%s' (%s): %m",
+ pwd->pw_name, lc ? lc->lc_class : LOGIN_DEFCLASS);
+ }
- /*
- * This needs to be done after all of the above.
- * Do it last so we avoid getting killed and dropping core
- */
- if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) {
- syslog(LOG_ERR, "setuid %ld: %m", uid);
+ /* Setup the user's group permissions */
+ if (flags & LOGIN_SETGROUP) {
+ if (setgid(pwd->pw_gid) != 0) {
+ syslog(LOG_ERR, "setgid(%ld): %m", (long)pwd->pw_gid);
+ login_close(llc);
+ return -1;
+ }
+ if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
+ syslog(LOG_ERR, "initgroups(%s,%ld): %m", pwd->pw_name,
+ pwd->pw_gid);
+ login_close(llc);
+ return -1;
+ }
+ }
+
+ /* Set the sessions login */
+ if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
+ syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name);
+ login_close(llc);
+ return -1;
+ }
+
+ mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
+ mymask = setlogincontext(lc, pwd, mymask, flags);
login_close(llc);
- return -1; /* Paranoia again */
- }
- return 0;
+ /* This needs to be done after anything that needs root privs */
+ if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) {
+ syslog(LOG_ERR, "setuid(%ld): %m", uid);
+ return -1; /* Paranoia again */
+ }
+
+ /*
+ * Now, we repeat some of the above for the user's private entries
+ */
+ if ((lc = login_getuserclass(pwd)) != NULL) {
+ mymask = setlogincontext(lc, pwd, mymask, flags);
+ login_close(lc);
+ }
+
+ /* Finally, set any umask we've found */
+ if (flags & LOGIN_SETUMASK)
+ umask(mymask);
+
+ return 0;
}
diff --git a/lib/libutil/login_ok.c b/lib/libutil/login_ok.c
index cf778da..88b6f4e 100644
--- a/lib/libutil/login_ok.c
+++ b/lib/libutil/login_ok.c
@@ -20,7 +20,7 @@
*
* Support allow/deny lists in login class capabilities
*
- * $Id$
+ * $Id: login_ok.c,v 1.3 1997/02/22 15:08:25 peter Exp $
*/
#include <stdio.h>
@@ -40,7 +40,8 @@
/* -- support functions -- */
-/* login_strinlist()
+/*
+ * login_strinlist()
* This function is intentionally public - reused by TAS.
* Returns TRUE (non-zero) if a string matches a pattern
* in a given array of patterns. 'flags' is passed directly
@@ -50,106 +51,111 @@
int
login_strinlist(char **list, char const *str, int flags)
{
- int rc = 0;
-
- if (str != NULL && *str != '\0')
- {
- int i = 0;
- while (rc == 0 && list[i] != NULL)
- rc = fnmatch(list[i], str, flags) == 0;
- }
- return rc;
+ int rc = 0;
+
+ if (str != NULL && *str != '\0') {
+ int i = 0;
+
+ while (rc == 0 && list[i] != NULL)
+ rc = fnmatch(list[i], str, flags) == 0;
+ }
+ return rc;
}
-/* login_str2inlist()
+/*
+ * login_str2inlist()
* Locate either or two strings in a given list
*/
int
login_str2inlist(char **ttlst, const char *str1, const char *str2, int flags)
{
- int rc = 0;
+ int rc = 0;
- if (login_strinlist(ttlst, str1, flags))
- rc = 1;
- else if (login_strinlist(ttlst, str2, flags))
- rc = 1;
- return rc;
+ if (login_strinlist(ttlst, str1, flags))
+ rc = 1;
+ else if (login_strinlist(ttlst, str2, flags))
+ rc = 1;
+ return rc;
}
-/* login_timelist()
+/*
+ * login_timelist()
* This function is intentinoally public - reused by TAS.
* Returns an allocated list of time periods given an array
* of time periods in ascii form.
*/
login_time_t *
-login_timelist(login_cap_t *lc, char const *cap, int *ltno, login_time_t **ltptr)
+login_timelist(login_cap_t *lc, char const *cap, int *ltno,
+ login_time_t **ltptr)
{
- int j = 0;
- struct login_time * lt = NULL;
- char **tl = login_getcaplist(lc, cap, NULL);
-
- if (tl)
- {
- while (tl[j++] != NULL)
- ;
- if (*ltno >= j)
- lt = *ltptr;
- else if ((lt = realloc(*ltptr, j)) != NULL)
- {
- *ltno = j;
- *ltptr = lt;
- }
- if (lt != NULL)
- {
- int i = 0;
- --j;
- while (i < j)
- {
- lt[i] = parse_lt(tl[i]);
- ++i;
- }
- lt[i].lt_dow = LTM_NONE;
+ int j = 0;
+ struct login_time *lt = NULL;
+ char **tl;
+
+ if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
+
+ while (tl[j++] != NULL)
+ ;
+ if (*ltno >= j)
+ lt = *ltptr;
+ else if ((lt = realloc(*ltptr, j)) != NULL) {
+ *ltno = j;
+ *ltptr = lt;
+ }
+ if (lt != NULL) {
+ int i = 0;
+
+ for (--j; i < j; i++)
+ lt[i] = parse_lt(tl[i]);
+ lt[i].lt_dow = LTM_NONE;
+ }
}
- }
- return lt;
+ return lt;
}
-/* login_ttyok()
+/*
+ * login_ttyok()
* This function is a variation of auth_ttyok(), but it checks two
* arbitrary capability lists not necessarily related to access.
* This hook is provided for the accounted/exclude accounting lists.
*/
int
-login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap, const char *denycap)
+login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
+ const char *denycap)
{
- int rc = 1;
-
- if (lc != NULL && tty != NULL && *tty != '\0')
- {
- struct ttyent * te = getttynam(tty); /* Need group name */
- char * grp = te ? te->ty_group : NULL;
- char **ttl = login_getcaplist(lc, allowcap, NULL);
-
- if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
- rc = 0; /* tty or ttygroup not in allow list */
- else
- {
- ttl = login_getcaplist(lc, denycap, NULL);
- if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
- rc = 0; /* tty or ttygroup in deny list */
+ int rc = 1;
+
+ if (lc != NULL && tty != NULL && *tty != '\0') {
+ struct ttyent *te;
+ char *grp;
+ char **ttl;
+
+ te = getttynam(tty); /* Need group name */
+ grp = te ? te->ty_group : NULL;
+ ttl = login_getcaplist(lc, allowcap, NULL);
+
+ if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0))
+ rc = 0; /* tty or ttygroup not in allow list */
+ else {
+
+ ttl = login_getcaplist(lc, denycap, NULL);
+ if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0))
+ rc = 0; /* tty or ttygroup in deny list */
+ }
}
- }
- return rc;
+
+ return rc;
}
-/* auth_ttyok()
+/*
+ * auth_ttyok()
* Determine whether or not login on a tty is accessible for
* a login class
*/
@@ -157,86 +163,89 @@ login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap, const char *
int
auth_ttyok(login_cap_t *lc, const char * tty)
{
- return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
+ return login_ttyok(lc, tty, "ttys.allow", "ttys.deny");
}
-/* login_hostok()
+/*
+ * login_hostok()
* This function is a variation of auth_hostok(), but it checks two
* arbitrary capability lists not necessarily related to access.
* This hook is provided for the accounted/exclude accounting lists.
*/
int
-login_hostok(login_cap_t *lc, const char *host, const char *ip, const char *allowcap, const char *denycap)
+login_hostok(login_cap_t *lc, const char *host, const char *ip,
+ const char *allowcap, const char *denycap)
{
- int rc = 1; /* Default is ok */
-
- if (lc != NULL && ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0')))
- {
- char **hl = login_getcaplist(lc, allowcap, NULL);
-
- if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
- rc = 0; /* host or IP not in allow list */
- else
- {
- hl = login_getcaplist(lc, "host.deny", NULL);
- if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
- rc = 0; /* host or IP in deny list */
+ int rc = 1; /* Default is ok */
+
+ if (lc != NULL &&
+ ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
+ char **hl;
+
+ hl = login_getcaplist(lc, allowcap, NULL);
+ if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
+ rc = 0; /* host or IP not in allow list */
+ else {
+
+ hl = login_getcaplist(lc, "host.deny", NULL);
+ if (hl != NULL && login_str2inlist(hl, host, ip, FNM_CASEFOLD))
+ rc = 0; /* host or IP in deny list */
+ }
}
- }
- return rc;
+
+ return rc;
}
-/* auth_hostok()
+/*
+ * auth_hostok()
* Determine whether or not login from a host is ok
*/
int
auth_hostok(login_cap_t *lc, const char *host, const char *ip)
{
- return login_hostok(lc, host, ip, "host.allow", "host.deny");
+ return login_hostok(lc, host, ip, "host.allow", "host.deny");
}
-/* auth_timeok()
+/*
+ * auth_timeok()
* Determine whether or not login is ok at a given time
*/
int
auth_timeok(login_cap_t *lc, time_t t)
{
- int rc = 1; /* Default is ok */
-
- if (lc != NULL && t != (time_t)0 && t != (time_t)-1)
- {
- struct tm * tptr = localtime(&t);
-
- static int ltimesno = 0;
- static struct login_time * ltimes = NULL;
-
- if (tptr != NULL)
- {
- struct login_time *lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
-
- if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
- rc = 0; /* not in allowed times list */
- else
- {
- lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
-
- if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
- rc = 0; /* in deny times list */
- }
- if (ltimes)
- {
- free(ltimes);
- ltimes = NULL;
- ltimesno = 0;
- }
+ int rc = 1; /* Default is ok */
+
+ if (lc != NULL && t != (time_t)0 && t != (time_t)-1) {
+ struct tm *tptr;
+
+ static int ltimesno = 0;
+ static struct login_time *ltimes = NULL;
+
+ if ((tptr = localtime(&t)) != NULL) {
+ struct login_time *lt;
+
+ lt = login_timelist(lc, "times.allow", &ltimesno, &ltimes);
+ if (lt != NULL && in_ltms(lt, tptr, NULL) == -1)
+ rc = 0; /* not in allowed times list */
+ else {
+
+ lt = login_timelist(lc, "times.deny", &ltimesno, &ltimes);
+ if (lt != NULL && in_ltms(lt, tptr, NULL) != -1)
+ rc = 0; /* in deny times list */
+ }
+ if (ltimes) {
+ free(ltimes);
+ ltimes = NULL;
+ ltimesno = 0;
+ }
+ }
}
- }
- return rc;
-}
+ return rc;
+}
diff --git a/lib/libutil/login_times.c b/lib/libutil/login_times.c
index c21524c..598592b 100644
--- a/lib/libutil/login_times.c
+++ b/lib/libutil/login_times.c
@@ -20,7 +20,7 @@
*
* Login period parsing and comparison functions.
*
- * $Id$
+ * $Id: login_times.c,v 1.4 1997/02/22 15:08:27 peter Exp $
*/
#include <stdio.h>
@@ -34,134 +34,129 @@
static struct
{
- const char * dw;
- u_char cn;
- u_char fl;
+ const char *dw;
+ u_char cn;
+ u_char fl;
} dws[] =
{
- { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
- { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
- { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
- { "wk", 2, LTM_WK }, { "wd", 2, LTM_WD }, { NULL, 0, 0 }
+ { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
+ { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
+ { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
+ { "wk", 2, LTM_WK }, { "wd", 2, LTM_WD }, { NULL, 0, 0 }
};
static char *
parse_time(char * ptr, u_short * t)
{
- u_short val;
+ u_short val;
- for (val = 0; *ptr && isdigit(*ptr); ptr++)
- val = (u_short)(val * 10 + (*ptr - '0'));
+ for (val = 0; *ptr && isdigit(*ptr); ptr++)
+ val = (u_short)(val * 10 + (*ptr - '0'));
- *t = (u_short)((val / 100) * 60 + (val % 100));
- return ptr;
+ *t = (u_short)((val / 100) * 60 + (val % 100));
+
+ return ptr;
}
+
login_time_t
parse_lt(const char * str)
{
- login_time_t t;
-
- memset(&t, 0, sizeof t);
- t.lt_dow = LTM_NONE;
- if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0)
- {
- int i;
- login_time_t m = t;
- char * p;
- char buf[64];
-
- /* Make local copy and force lowercase to simplify parsing
- */
- p = strncpy(buf, str, sizeof buf);
- buf[sizeof buf - 1] = '\0';
- for (i = 0; buf[i]; i++)
- buf[i] = (char)tolower(buf[i]);
-
- while (isalpha(*p))
- {
- for (i = 0; dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0 ; i++)
- ;
- if (dws[i].dw == NULL)
- break;
- m.lt_dow |= dws[i].fl;
- p += dws[i].cn;
- }
+ login_time_t t;
+
+ memset(&t, 0, sizeof t);
+ t.lt_dow = LTM_NONE;
+ if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
+ int i;
+ login_time_t m = t;
+ char *p;
+ char buf[64];
+
+ /* Make local copy and force lowercase to simplify parsing */
+ p = strncpy(buf, str, sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ for (i = 0; buf[i]; i++)
+ buf[i] = (char)tolower(buf[i]);
+
+ while (isalpha(*p)) {
+
+ i = 0;
+ while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
+ i++;
+ if (dws[i].dw == NULL)
+ break;
+ m.lt_dow |= dws[i].fl;
+ p += dws[i].cn;
+ }
+
+ if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
+ m.lt_dow |= LTM_ANY;
- if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
- m.lt_dow |= LTM_ANY;
-
- if (isdigit(*p))
- p = parse_time(p, &m.lt_start);
- else
- m.lt_start = 0;
- if (*p == '-')
- p = parse_time(++p, &m.lt_end);
- else
- m.lt_end = 1440;
-
- t = m;
- }
- return t;
+ if (isdigit(*p))
+ p = parse_time(p, &m.lt_start);
+ else
+ m.lt_start = 0;
+ if (*p == '-')
+ p = parse_time(++p, &m.lt_end);
+ else
+ m.lt_end = 1440;
+
+ t = m;
+ }
+ return t;
}
int
in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
{
- int rc = 0;
-
- if (tt != NULL)
- {
- /* First, examine the day of the week
- */
- if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow)
- {
- /* Convert `current' time to minute of the day
- */
- u_short now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
- if (tt->tm_sec > 30)
- ++now;
- if (now >= ltm->lt_start && now < ltm->lt_end)
- {
- rc = 2;
- if (ends != NULL)
- {
- /* If requested, return ending time for this period
- */
- tt->tm_hour = (int)(ltm->lt_end / 60);
- tt->tm_min = (int)(ltm->lt_end % 60);
- *ends = mktime(tt);
+ int rc = 0;
+
+ if (tt != NULL) {
+ /* First, examine the day of the week */
+ if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
+ /* Convert `current' time to minute of the day */
+ u_short now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
+
+ if (tt->tm_sec > 30)
+ ++now;
+ if (now >= ltm->lt_start && now < ltm->lt_end) {
+ rc = 2;
+ if (ends != NULL) {
+ /* If requested, return ending time for this period */
+ tt->tm_hour = (int)(ltm->lt_end / 60);
+ tt->tm_min = (int)(ltm->lt_end % 60);
+ *ends = mktime(tt);
+ }
+ }
}
- }
}
- }
- return rc;
+ return rc;
}
+
int
in_lt(const login_time_t * ltm, time_t * t)
{
- return in_ltm(ltm, localtime(t), t);
+ return in_ltm(ltm, localtime(t), t);
}
int
in_ltms(const login_time_t * ltm, struct tm * tm, time_t * t)
{
- int i = 0;
-
- while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE)
- {
- if (in_ltm(ltm + i, tm, t))
- return i;
- i++;
- }
- return -1;
+ int i = 0;
+
+ while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
+ if (in_ltm(ltm + i, tm, t))
+ return i;
+ i++;
+ }
+ return -1;
}
int
in_lts(const login_time_t * ltm, time_t * t)
{
- return in_ltms(ltm, localtime(t), t);
+ return in_ltms(ltm, localtime(t), t);
}
OpenPOWER on IntegriCloud