summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorguido <guido@FreeBSD.org>1994-08-21 19:26:22 +0000
committerguido <guido@FreeBSD.org>1994-08-21 19:26:22 +0000
commitcec2fb9e659008b040493c48cd67ddbabfe892d9 (patch)
tree2a64077f9871e464ae6f709a8bf4e1b2cc63c8d9 /lib
parent06cda8b161f5aecccf1bfe68bf046a1129a9eb2b (diff)
downloadFreeBSD-src-cec2fb9e659008b040493c48cd67ddbabfe892d9.zip
FreeBSD-src-cec2fb9e659008b040493c48cd67ddbabfe892d9.tar.gz
Add skey supprot
Reviewed by: Submitted by: guido
Diffstat (limited to 'lib')
-rw-r--r--lib/libpam/modules/pam_login_access/login.access.550
-rw-r--r--lib/libpam/modules/pam_login_access/login_access.c236
2 files changed, 286 insertions, 0 deletions
diff --git a/lib/libpam/modules/pam_login_access/login.access.5 b/lib/libpam/modules/pam_login_access/login.access.5
new file mode 100644
index 0000000..28d423c
--- /dev/null
+++ b/lib/libpam/modules/pam_login_access/login.access.5
@@ -0,0 +1,50 @@
+.\" this is comment
+.Dd April 30, 1994
+.Dt SKEY.ACCESS 5
+.Os FreeBSD 1.2
+.Sh NAME
+.Nm login.access
+.Nd Login access control table
+.Sh DESCRIPTION
+The
+.Nm login.access
+file specifies (user, host) combinations and/or (user, tty)
+combinations for which a login will be either accepted or refused.
+.Pp
+When someone logs in, the
+.Nm login.access
+is scanned for the first entry that
+matches the (user, host) combination, or, in case of non-networked
+logins, the first entry that matches the (user, tty) combination. The
+permissions field of that table entry determines whether the login will
+be accepted or refused.
+.Pp
+Each line of the login access control table has three fields separated by a
+":" character: permission : users : origins
+
+The first field should be a "+" (access granted) or "-" (access denied)
+character. The second field should be a list of one or more login names,
+group names, or ALL (always matches). The third field should be a list
+of one or more tty names (for non-networked logins), host names, domain
+names (begin with "."), host addresses, internet network numbers (end
+with "."), ALL (always matches) or LOCAL (matches any string that does
+not contain a "." character). If you run NIS you can use @netgroupname
+in host or user patterns.
+
+The EXCEPT operator makes it possible to write very compact rules.
+
+The group file is searched only when a name does not match that of the
+logged-in user. Only groups are matched in which users are explicitly
+listed: the program does not look at a user's primary group id value.
+.Sh FILES
+.Bl -tag -width /etc/login.access -compact
+.It Pa /etc/login.access
+The
+.Nm login.access
+file resides in
+.Pa /etc .
+.El
+.Sh SEE ALSO
+.Xr login 1
+.Sh AUTHOR
+Guido van Rooij
diff --git a/lib/libpam/modules/pam_login_access/login_access.c b/lib/libpam/modules/pam_login_access/login_access.c
new file mode 100644
index 0000000..90de8e0
--- /dev/null
+++ b/lib/libpam/modules/pam_login_access/login_access.c
@@ -0,0 +1,236 @@
+ /*
+ * This module implements a simple but effective form of login access
+ * control based on login names and on host (or domain) names, internet
+ * addresses (or network numbers), or on terminal line names in case of
+ * non-networked logins. Diagnostics are reported through syslog(3).
+ *
+ * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ */
+
+#ifdef LOGIN_ACCESS
+#ifndef lint
+static char sccsid[] = "%Z% %M% %I% %E% %U%";
+#endif
+
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "pathnames.h"
+
+ /* Delimiters for fields and for lists of users, ttys or hosts. */
+
+static char fs[] = ":"; /* field separator */
+static char sep[] = ", \t"; /* list-element separator */
+
+ /* Constants to be used in assignments only, not in comparisons... */
+
+#define YES 1
+#define NO 0
+
+static int list_match();
+static int user_match();
+static int from_match();
+static int string_match();
+
+/* login_access - match username/group and host/tty with access control file */
+
+login_access(user, from)
+char *user;
+char *from;
+{
+ FILE *fp;
+ char line[BUFSIZ];
+ char *perm; /* becomes permission field */
+ char *users; /* becomes list of login names */
+ char *froms; /* becomes list of terminals or hosts */
+ int match = NO;
+ int end;
+ int lineno = 0; /* for diagnostics */
+
+ /*
+ * Process the table one line at a time and stop at the first match.
+ * Blank lines and lines that begin with a '#' character are ignored.
+ * Non-comment lines are broken at the ':' character. All fields are
+ * mandatory. The first field should be a "+" or "-" character. A
+ * non-existing table means no access control.
+ */
+
+ if (fp = fopen(_PATH_LOGACCESS, "r")) {
+ while (!match && fgets(line, sizeof(line), fp)) {
+ lineno++;
+ if (line[end = strlen(line) - 1] != '\n') {
+ syslog(LOG_ERR, "%s: line %d: missing newline or line too long",
+ _PATH_LOGACCESS, lineno);
+ continue;
+ }
+ if (line[0] == '#')
+ continue; /* comment line */
+ while (end > 0 && isspace(line[end - 1]))
+ end--;
+ line[end] = 0; /* strip trailing whitespace */
+ if (line[0] == 0) /* skip blank lines */
+ continue;
+ if (!(perm = strtok(line, fs))
+ || !(users = strtok((char *) 0, fs))
+ || !(froms = strtok((char *) 0, fs))
+ || strtok((char *) 0, fs)) {
+ syslog(LOG_ERR, "%s: line %d: bad field count", _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ if (perm[0] != '+' && perm[0] != '-') {
+ syslog(LOG_ERR, "%s: line %d: bad first field", _PATH_LOGACCESS,
+ lineno);
+ continue;
+ }
+ match = (list_match(froms, from, from_match)
+ && list_match(users, user, user_match));
+ }
+ (void) fclose(fp);
+ } else if (errno != ENOENT) {
+ syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS);
+ }
+ return (match == 0 || (line[0] == '+'));
+}
+
+/* list_match - match an item against a list of tokens with exceptions */
+
+static int list_match(list, item, match_fn)
+char *list;
+char *item;
+int (*match_fn) ();
+{
+ char *tok;
+ int match = NO;
+
+ /*
+ * Process tokens one at a time. We have exhausted all possible matches
+ * when we reach an "EXCEPT" token or the end of the list. If we do find
+ * a match, look for an "EXCEPT" list and recurse to determine whether
+ * the match is affected by any exceptions.
+ */
+
+ for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
+ if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
+ break;
+ if (match = (*match_fn) (tok, item)) /* YES */
+ break;
+ }
+ /* Process exceptions to matches. */
+
+ if (match != NO) {
+ while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
+ /* VOID */ ;
+ if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
+ return (match);
+ }
+ return (NO);
+}
+
+/* netgroup_match - match group against machine or user */
+
+static int netgroup_match(group, machine, user)
+char *machine;
+char *user;
+{
+#ifdef NIS
+ static char *mydomain = 0;
+
+ if (mydomain == 0)
+ yp_get_default_domain(&mydomain);
+ return (innetgr(group, machine, user, mydomain));
+#else
+ syslog(LOG_ERR, "NIS netgroup support not configured");
+#endif
+}
+
+/* user_match - match a username against one token */
+
+static int user_match(tok, string)
+char *tok;
+char *string;
+{
+ struct group *group;
+ int i;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the username, or if
+ * the token is a group that contains the username.
+ */
+
+ if (tok[0] == '@') { /* netgroup */
+ return (netgroup_match(tok + 1, (char *) 0, string));
+ } else if (string_match(tok, string)) { /* ALL or exact match */
+ return (YES);
+ } else if (group = getgrnam(tok)) { /* try group membership */
+ for (i = 0; group->gr_mem[i]; i++)
+ if (strcasecmp(string, group->gr_mem[i]) == 0)
+ return (YES);
+ }
+ return (NO);
+}
+
+/* from_match - match a host or tty against a list of tokens */
+
+static int from_match(tok, string)
+char *tok;
+char *string;
+{
+ int tok_len;
+ int str_len;
+
+ /*
+ * If a token has the magic value "ALL" the match always succeeds. Return
+ * YES if the token fully matches the string. If the token is a domain
+ * name, return YES if it matches the last fields of the string. If the
+ * token has the magic value "LOCAL", return YES if the string does not
+ * contain a "." character. If the token is a network number, return YES
+ * if it matches the head of the string.
+ */
+
+ if (tok[0] == '@') { /* netgroup */
+ return (netgroup_match(tok + 1, string, (char *) 0));
+ } else if (string_match(tok, string)) { /* ALL or exact match */
+ return (YES);
+ } else if (tok[0] == '.') { /* domain: match last fields */
+ if ((str_len = strlen(string)) > (tok_len = strlen(tok))
+ && strcasecmp(tok, string + str_len - tok_len) == 0)
+ return (YES);
+ } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
+ if (strchr(string, '.') == 0)
+ return (YES);
+ } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */
+ && strncmp(tok, string, tok_len) == 0) {
+ return (YES);
+ }
+ return (NO);
+}
+
+/* string_match - match a string against one token */
+
+static int string_match(tok, string)
+char *tok;
+char *string;
+{
+
+ /*
+ * If the token has the magic value "ALL" the match always succeeds.
+ * Otherwise, return YES if the token fully matches the string.
+ */
+
+ if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
+ return (YES);
+ } else if (strcasecmp(tok, string) == 0) { /* try exact match */
+ return (YES);
+ }
+ return (NO);
+}
+#endif /* LOGIN_ACCES */
OpenPOWER on IntegriCloud