Index: stable/11/lib/libpam/modules/pam_login_access/login.access.5 =================================================================== --- stable/11/lib/libpam/modules/pam_login_access/login.access.5 (revision 359116) +++ stable/11/lib/libpam/modules/pam_login_access/login.access.5 (revision 359117) @@ -1,61 +1,68 @@ .\" .\" $FreeBSD$ .\" -.Dd January 27, 2020 +.Dd January 30, 2020 .Dt LOGIN.ACCESS 5 .Os .Sh NAME .Nm login.access .Nd login access control table .Sh SYNOPSIS .Pa /etc/login.access .Sh DESCRIPTION The .Nm 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 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 .Ql \&: character: .Ar permission : Ns Ar users : Ns Ar origins .Pp The first field should be a "+" (access granted) or "-" (access denied) character. .Pp The second field should be a list of one or more login names, group names, or ALL (always matches). +Group names must be enclosed in +parentheses if the pam module specification for +.Pa pam_login_access +specifies the +.Pa nodefgroup +option. +Otherwise, group names will only match if no usernames match. .Pp 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. .Pp The EXCEPT operator makes it possible to write very compact rules. .Pp 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 login access control table .El .Sh SEE ALSO .Xr login 1 , .Xr pam_login_access 8 .Sh AUTHORS .An Guido van Rooij Index: stable/11/lib/libpam/modules/pam_login_access/login_access.c =================================================================== --- stable/11/lib/libpam/modules/pam_login_access/login_access.c (revision 359116) +++ stable/11/lib/libpam/modules/pam_login_access/login_access.c (revision 359117) @@ -1,281 +1,297 @@ /* * 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. */ #if 0 #ifndef lint static char sccsid[] = "%Z% %M% %I% %E% %U%"; #endif #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "pam_login_access.h" -#define _PATH_LOGACCESS "/etc/login.access" - - /* 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 from_match(const char *, const char *); +static int from_match(const char *, const char *, struct pam_login_access_options *); static int list_match(char *, const char *, - int (*)(const char *, const char *)); + int (*)(const char *, const char *, + struct pam_login_access_options *), + struct pam_login_access_options *); static int netgroup_match(const char *, const char *, const char *); static int string_match(const char *, const char *); -static int user_match(const char *, const char *); +static int user_match(const char *, const char *, struct pam_login_access_options *); +static int group_match(const char *, const char *); /* login_access - match username/group and host/tty with access control file */ int -login_access(const char *user, const char *from) +login_access(const char *user, const char *from, + struct pam_login_access_options *login_access_opts) { 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 */ + const char *fieldsep = login_access_opts->fieldsep; /* * 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")) != NULL) { + if ((fp = fopen(login_access_opts->accessfile, "r")) != NULL) { 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); + login_access_opts->accessfile, 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, + if (!(perm = strtok(line, fieldsep)) + || !(users = strtok((char *) 0, fieldsep)) + || !(froms = strtok((char *) 0, fieldsep)) + || strtok((char *) 0, fieldsep)) { + syslog(LOG_ERR, "%s: line %d: bad field count", login_access_opts->accessfile, lineno); continue; } if (perm[0] != '+' && perm[0] != '-') { - syslog(LOG_ERR, "%s: line %d: bad first field", _PATH_LOGACCESS, + syslog(LOG_ERR, "%s: line %d: bad first field", login_access_opts->accessfile, lineno); continue; } - match = (list_match(froms, from, from_match) - && list_match(users, user, user_match)); + match = (list_match(froms, from, from_match, login_access_opts) + && list_match(users, user, user_match, login_access_opts)); } (void) fclose(fp); } else if (errno != ENOENT) { - syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS); + syslog(LOG_ERR, "cannot open %s: %m", login_access_opts->accessfile); } return (match == 0 || (line[0] == '+')); } /* list_match - match an item against a list of tokens with exceptions */ static int list_match(char *list, const char *item, - int (*match_fn)(const char *, const char *)) + int (*match_fn)(const char *, const char *, struct pam_login_access_options *), + struct pam_login_access_options *login_access_opts) { char *tok; int match = NO; + const char *listsep = login_access_opts->listsep; /* * 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 != NULL; tok = strtok((char *) 0, sep)) { + for (tok = strtok(list, listsep); tok != NULL; tok = strtok((char *) 0, listsep)) { if (strcmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ break; - if ((match = (*match_fn)(tok, item)) != 0) /* YES */ + if ((match = (*match_fn)(tok, item, login_access_opts)) != 0) /* YES */ break; } /* Process exceptions to matches. */ if (match != NO) { - while ((tok = strtok((char *) 0, sep)) && strcmp(tok, "EXCEPT")) + while ((tok = strtok((char *) 0, listsep)) && strcmp(tok, "EXCEPT")) { /* VOID */ ; - if (tok == NULL || list_match((char *) 0, item, match_fn) == NO) - return (match); + if (tok == NULL || list_match((char *) 0, item, match_fn, + login_access_opts) == NO) { + return (match); + } + } } return (NO); } /* netgroup_match - match group against machine or user */ static int netgroup_match(const char *group, const char *machine, const char *user) { char domain[1024]; unsigned int i; if (getdomainname(domain, sizeof(domain)) != 0 || *domain == '\0') { syslog(LOG_ERR, "NIS netgroup support disabled: no NIS domain"); return (NO); } /* getdomainname() does not reliably terminate the string */ for (i = 0; i < sizeof(domain); ++i) if (domain[i] == '\0') break; if (i == sizeof(domain)) { syslog(LOG_ERR, "NIS netgroup support disabled: invalid NIS domain"); return (NO); } if (innetgr(group, machine, user, domain) == 1) return (YES); return (NO); } -/* user_match - match a username against one token */ +/* group_match - match a group against one token */ -static int -user_match(const char *tok, const char *string) +int +group_match(const char *tok, const char *username) { struct group *group; struct passwd *passwd; gid_t *grouplist; - int ngroups = NGROUPS; - int i; + int i, ret, ngroups = NGROUPS; + if ((passwd = getpwnam(username)) == NULL) + return (NO); + errno = 0; + if ((group = getgrnam(tok)) == NULL) { + if (errno != 0) + syslog(LOG_ERR, "getgrnam() failed for %s: %s", username, strerror(errno)); + else + syslog(LOG_NOTICE, "group not found: %s", username); + return (NO); + } + if ((grouplist = calloc(ngroups, sizeof(gid_t))) == NULL) { + syslog(LOG_ERR, "cannot allocate memory for grouplist: %s", username); + return (NO); + } + ret = NO; + if (getgrouplist(username, passwd->pw_gid, grouplist, &ngroups) != 0) + syslog(LOG_ERR, "getgrouplist() failed for %s", username); + for (i = 0; i < ngroups; i++) + if (grouplist[i] == group->gr_gid) + ret = YES; + free(grouplist); + return (ret); +} + +/* user_match - match a username against one token */ + +static int +user_match(const char *tok, const char *string, + struct pam_login_access_options *login_access_opts) +{ + size_t stringlen; + char *grpstr; + int rc; + /* * 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 ((passwd = getpwnam(string)) == NULL) - return (NO); - errno = 0; - if ((group = getgrnam(tok)) == NULL) {/* try group membership */ - if (errno != 0) { - syslog(LOG_ERR, "getgrnam() failed for %s: %s", string, strerror(errno)); - } else { - syslog(LOG_NOTICE, "group not found: %s", string); - } + } else if (tok[0] == '(' && tok[(stringlen = strlen(&tok[1]))] == ')') { /* group */ + if ((grpstr = strndup(&tok[1], stringlen - 1)) == NULL) { + syslog(LOG_ERR, "cannot allocate memory for %s", string); return (NO); } - errno = 0; - if ((grouplist = calloc(ngroups, sizeof(gid_t))) == NULL) { - if (errno == ENOMEM) { - syslog(LOG_ERR, "cannot allocate memory for grouplist: %s", string); - } - return (NO); - } - if (getgrouplist(string, passwd->pw_gid, grouplist, &ngroups) != 0) { - syslog(LOG_ERR, "getgrouplist() failed for %s", string); - free(grouplist); - return (NO); - } - for (i = 0; i < ngroups; i++) { - if (grouplist[i] == group->gr_gid) { - free(grouplist); - return (YES); - } - } - free(grouplist); + rc = group_match(grpstr, string); + free(grpstr); + return (rc); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if (login_access_opts->defgroup == true) {/* try group membership */ + return (group_match(tok, string)); } return (NO); } /* from_match - match a host or tty against a list of tokens */ static int -from_match(const char *tok, const char *string) +from_match(const char *tok, const char *string, + struct pam_login_access_options *login_access_opts __unused) { 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 (strcmp(tok, "LOCAL") == 0) { /* local: no dots */ if (strchr(string, '.') == NULL) 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(const char *tok, const 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 (strcmp(tok, "ALL") == 0) { /* all: always matches */ return (YES); } else if (strcasecmp(tok, string) == 0) { /* try exact match */ return (YES); } return (NO); } Index: stable/11/lib/libpam/modules/pam_login_access/pam_login_access.8 =================================================================== --- stable/11/lib/libpam/modules/pam_login_access/pam_login_access.8 (revision 359116) +++ stable/11/lib/libpam/modules/pam_login_access/pam_login_access.8 (revision 359117) @@ -1,89 +1,122 @@ .\" Copyright (c) 2001 Mark R V Murray .\" All rights reserved. .\" Copyright (c) 2001 Networks Associates Technology, Inc. .\" All rights reserved. .\" .\" Portions of this software were developed for the FreeBSD Project by .\" ThinkSec AS and NAI Labs, the Security Research Division of Network .\" Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 .\" ("CBOSS"), as part of the DARPA CHATS research program. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, 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. The name of the author may not be used to endorse or promote .\" products derived from this software without specific prior written .\" permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd January 24, 2002 +.Dd January 30, 2020 .Dt PAM_LOGIN_ACCESS 8 .Os .Sh NAME .Nm pam_login_access .Nd login.access PAM module .Sh SYNOPSIS .Op Ar service-name .Ar module-type .Ar control-flag .Pa pam_login_access .Op Ar options .Sh DESCRIPTION The .Pa login.access service module for PAM, .Nm provides functionality for only one PAM category: account management. In terms of the .Ar module-type parameter, this is the .Dq Li account feature. .Ss Login.access Account Management Module The .Pa login.access account management component .Pq Fn pam_sm_acct_mgmt , -returns success if and only the user is allowed to log in on the +returns success if and only the user is allowed to login on the specified tty (in the case of a local login) or from the specified remote host (in the case of a remote login), according to the restrictions listed in .Xr login.access 5 . +.Bl -tag -width ".Cm accessfile=pathname" +.It Cm accessfile Ns = Ns Ar pathname +specifies a non-standard location for the +.Pa login.access +configuration file +(normally located in +.Pa /etc/login.access ) . +.It Cm nodefgroup +makes tokens not enclosed in parentheses only match users, requiring groups +to be specified in parentheses. +Without +.Cm nodefgroup +user and group names are intermingled, with user entries taking precedence +over group entries. +This is not backwards compatible with legacy +.Pa login.access +configuration files. +However this mitigates confusion between users and +groups of the same name. +.It Cm fieldsep Ns = Ns Ar separators +changes the field separator from the default ":". +More than one separator +may be specified. +.It Cm listsep Ns = Ns Ar separators +changes the field separator from the default space (''), tab (\\t) and +comma (,). +More than one separator may be specified. +For example, listsep=; +will replace the default with a semicolon (;). +This option may be useful when specifying Active Directory groupnames which +typically contain spaces. +.El .Sh SEE ALSO .Xr pam 3 , +.Xr syslog 3 , .Xr login.access 5 , .Xr pam.conf 5 .Sh AUTHORS The .Xr login.access 5 access control scheme was designed and implemented by .An Wietse Venema . .Pp The .Nm module and this manual page were developed for the .Fx Project by ThinkSec AS and NAI Labs, the Security Research Division of Network Associates, Inc.\& under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. Index: stable/11/lib/libpam/modules/pam_login_access/pam_login_access.c =================================================================== --- stable/11/lib/libpam/modules/pam_login_access/pam_login_access.c (revision 359116) +++ stable/11/lib/libpam/modules/pam_login_access/pam_login_access.c (revision 359117) @@ -1,108 +1,129 @@ /*- * Copyright (c) 2001 Mark R V Murray * All rights reserved. * Copyright (c) 2001 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define _BSD_SOURCE #include +#include #include #include #define PAM_SM_ACCOUNT #include #include #include +#include #include "pam_login_access.h" +#define OPT_ACCESSFILE "accessfile" +#define OPT_NOAUDIT "noaudit" +#define OPT_FIELDSEP "fieldsep" +#define OPT_LISTSEP "listsep" +#define OPT_NODEFGROUP "nodefgroup" + +#define _PATH_LOGACCESS "/etc/login.access" +#define _FIELD_SEPARATOR ":" +#define _LIST_SEPARATOR ", \t" + PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, int argc __unused, const char *argv[] __unused) { + struct pam_login_access_options login_access_opts; const void *rhost, *tty, *user; char hostname[MAXHOSTNAMELEN]; int pam_err; pam_err = pam_get_item(pamh, PAM_USER, &user); if (pam_err != PAM_SUCCESS) return (pam_err); if (user == NULL) return (PAM_SERVICE_ERR); PAM_LOG("Got user: %s", (const char *)user); pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); if (pam_err != PAM_SUCCESS) return (pam_err); pam_err = pam_get_item(pamh, PAM_TTY, &tty); if (pam_err != PAM_SUCCESS) return (pam_err); gethostname(hostname, sizeof hostname); + login_access_opts.defgroup = openpam_get_option(pamh, OPT_NODEFGROUP) == NULL ? true : false; + login_access_opts.audit = openpam_get_option(pamh, OPT_NOAUDIT) == NULL ? true : false; + if ((login_access_opts.accessfile = openpam_get_option(pamh, OPT_ACCESSFILE)) == NULL) + login_access_opts.accessfile = _PATH_LOGACCESS; + if ((login_access_opts.fieldsep = openpam_get_option(pamh, OPT_FIELDSEP)) == NULL) + login_access_opts.fieldsep = _FIELD_SEPARATOR; + if ((login_access_opts.listsep = openpam_get_option(pamh, OPT_LISTSEP)) == NULL) + login_access_opts.listsep = _LIST_SEPARATOR; if (rhost != NULL && *(const char *)rhost != '\0') { PAM_LOG("Checking login.access for user %s from host %s", (const char *)user, (const char *)rhost); - if (login_access(user, rhost) != 0) + if (login_access(user, rhost, &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in from %s", (const char *)user, (const char *)rhost); } else if (tty != NULL && *(const char *)tty != '\0') { PAM_LOG("Checking login.access for user %s on tty %s", (const char *)user, (const char *)tty); - if (login_access(user, tty) != 0) + if (login_access(user, tty, &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in on %s", (const char *)user, (const char *)tty); } else { PAM_LOG("Checking login.access for user %s", (const char *)user); - if (login_access(user, "***unknown***") != 0) + if (login_access(user, "***unknown***", &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in", (const char *)user); } return (PAM_AUTH_ERR); } PAM_MODULE_ENTRY("pam_login_access"); Index: stable/11/lib/libpam/modules/pam_login_access/pam_login_access.h =================================================================== --- stable/11/lib/libpam/modules/pam_login_access/pam_login_access.h (revision 359116) +++ stable/11/lib/libpam/modules/pam_login_access/pam_login_access.h (revision 359117) @@ -1,39 +1,50 @@ /*- * Copyright (c) 2001 Mark R V Murray * All rights reserved. * Copyright (c) 2001 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -extern int login_access(const char *, const char *); +#include + +struct pam_login_access_options { + bool defgroup; + bool audit; + const char *accessfile; + /* Delimiters for fields and for lists of users, ttys or hosts. */ + const char *fieldsep; /* field separator */ + const char *listsep; /* list-element separator */ +}; + +extern int login_access(const char *, const char *, struct pam_login_access_options *); Index: stable/11 =================================================================== --- stable/11 (revision 359116) +++ stable/11 (revision 359117) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r358070 Index: stable/12/lib/libpam/modules/pam_login_access/login.access.5 =================================================================== --- stable/12/lib/libpam/modules/pam_login_access/login.access.5 (revision 359116) +++ stable/12/lib/libpam/modules/pam_login_access/login.access.5 (revision 359117) @@ -1,61 +1,68 @@ .\" .\" $FreeBSD$ .\" -.Dd January 27, 2020 +.Dd January 30, 2020 .Dt LOGIN.ACCESS 5 .Os .Sh NAME .Nm login.access .Nd login access control table .Sh SYNOPSIS .Pa /etc/login.access .Sh DESCRIPTION The .Nm 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 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 .Ql \&: character: .Ar permission : Ns Ar users : Ns Ar origins .Pp The first field should be a "+" (access granted) or "-" (access denied) character. .Pp The second field should be a list of one or more login names, group names, or ALL (always matches). +Group names must be enclosed in +parentheses if the pam module specification for +.Pa pam_login_access +specifies the +.Pa nodefgroup +option. +Otherwise, group names will only match if no usernames match. .Pp 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. .Pp The EXCEPT operator makes it possible to write very compact rules. .Pp 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 login access control table .El .Sh SEE ALSO .Xr login 1 , .Xr pam_login_access 8 .Sh AUTHORS .An Guido van Rooij Index: stable/12/lib/libpam/modules/pam_login_access/login_access.c =================================================================== --- stable/12/lib/libpam/modules/pam_login_access/login_access.c (revision 359116) +++ stable/12/lib/libpam/modules/pam_login_access/login_access.c (revision 359117) @@ -1,281 +1,297 @@ /* * 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. */ #if 0 #ifndef lint static char sccsid[] = "%Z% %M% %I% %E% %U%"; #endif #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "pam_login_access.h" -#define _PATH_LOGACCESS "/etc/login.access" - - /* 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 from_match(const char *, const char *); +static int from_match(const char *, const char *, struct pam_login_access_options *); static int list_match(char *, const char *, - int (*)(const char *, const char *)); + int (*)(const char *, const char *, + struct pam_login_access_options *), + struct pam_login_access_options *); static int netgroup_match(const char *, const char *, const char *); static int string_match(const char *, const char *); -static int user_match(const char *, const char *); +static int user_match(const char *, const char *, struct pam_login_access_options *); +static int group_match(const char *, const char *); /* login_access - match username/group and host/tty with access control file */ int -login_access(const char *user, const char *from) +login_access(const char *user, const char *from, + struct pam_login_access_options *login_access_opts) { 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 */ + const char *fieldsep = login_access_opts->fieldsep; /* * 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")) != NULL) { + if ((fp = fopen(login_access_opts->accessfile, "r")) != NULL) { 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); + login_access_opts->accessfile, 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, + if (!(perm = strtok(line, fieldsep)) + || !(users = strtok((char *) 0, fieldsep)) + || !(froms = strtok((char *) 0, fieldsep)) + || strtok((char *) 0, fieldsep)) { + syslog(LOG_ERR, "%s: line %d: bad field count", login_access_opts->accessfile, lineno); continue; } if (perm[0] != '+' && perm[0] != '-') { - syslog(LOG_ERR, "%s: line %d: bad first field", _PATH_LOGACCESS, + syslog(LOG_ERR, "%s: line %d: bad first field", login_access_opts->accessfile, lineno); continue; } - match = (list_match(froms, from, from_match) - && list_match(users, user, user_match)); + match = (list_match(froms, from, from_match, login_access_opts) + && list_match(users, user, user_match, login_access_opts)); } (void) fclose(fp); } else if (errno != ENOENT) { - syslog(LOG_ERR, "cannot open %s: %m", _PATH_LOGACCESS); + syslog(LOG_ERR, "cannot open %s: %m", login_access_opts->accessfile); } return (match == 0 || (line[0] == '+')); } /* list_match - match an item against a list of tokens with exceptions */ static int list_match(char *list, const char *item, - int (*match_fn)(const char *, const char *)) + int (*match_fn)(const char *, const char *, struct pam_login_access_options *), + struct pam_login_access_options *login_access_opts) { char *tok; int match = NO; + const char *listsep = login_access_opts->listsep; /* * 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 != NULL; tok = strtok((char *) 0, sep)) { + for (tok = strtok(list, listsep); tok != NULL; tok = strtok((char *) 0, listsep)) { if (strcmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ break; - if ((match = (*match_fn)(tok, item)) != 0) /* YES */ + if ((match = (*match_fn)(tok, item, login_access_opts)) != 0) /* YES */ break; } /* Process exceptions to matches. */ if (match != NO) { - while ((tok = strtok((char *) 0, sep)) && strcmp(tok, "EXCEPT")) + while ((tok = strtok((char *) 0, listsep)) && strcmp(tok, "EXCEPT")) { /* VOID */ ; - if (tok == NULL || list_match((char *) 0, item, match_fn) == NO) - return (match); + if (tok == NULL || list_match((char *) 0, item, match_fn, + login_access_opts) == NO) { + return (match); + } + } } return (NO); } /* netgroup_match - match group against machine or user */ static int netgroup_match(const char *group, const char *machine, const char *user) { char domain[1024]; unsigned int i; if (getdomainname(domain, sizeof(domain)) != 0 || *domain == '\0') { syslog(LOG_ERR, "NIS netgroup support disabled: no NIS domain"); return (NO); } /* getdomainname() does not reliably terminate the string */ for (i = 0; i < sizeof(domain); ++i) if (domain[i] == '\0') break; if (i == sizeof(domain)) { syslog(LOG_ERR, "NIS netgroup support disabled: invalid NIS domain"); return (NO); } if (innetgr(group, machine, user, domain) == 1) return (YES); return (NO); } -/* user_match - match a username against one token */ +/* group_match - match a group against one token */ -static int -user_match(const char *tok, const char *string) +int +group_match(const char *tok, const char *username) { struct group *group; struct passwd *passwd; gid_t *grouplist; - int ngroups = NGROUPS; - int i; + int i, ret, ngroups = NGROUPS; + if ((passwd = getpwnam(username)) == NULL) + return (NO); + errno = 0; + if ((group = getgrnam(tok)) == NULL) { + if (errno != 0) + syslog(LOG_ERR, "getgrnam() failed for %s: %s", username, strerror(errno)); + else + syslog(LOG_NOTICE, "group not found: %s", username); + return (NO); + } + if ((grouplist = calloc(ngroups, sizeof(gid_t))) == NULL) { + syslog(LOG_ERR, "cannot allocate memory for grouplist: %s", username); + return (NO); + } + ret = NO; + if (getgrouplist(username, passwd->pw_gid, grouplist, &ngroups) != 0) + syslog(LOG_ERR, "getgrouplist() failed for %s", username); + for (i = 0; i < ngroups; i++) + if (grouplist[i] == group->gr_gid) + ret = YES; + free(grouplist); + return (ret); +} + +/* user_match - match a username against one token */ + +static int +user_match(const char *tok, const char *string, + struct pam_login_access_options *login_access_opts) +{ + size_t stringlen; + char *grpstr; + int rc; + /* * 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 ((passwd = getpwnam(string)) == NULL) - return (NO); - errno = 0; - if ((group = getgrnam(tok)) == NULL) {/* try group membership */ - if (errno != 0) { - syslog(LOG_ERR, "getgrnam() failed for %s: %s", string, strerror(errno)); - } else { - syslog(LOG_NOTICE, "group not found: %s", string); - } + } else if (tok[0] == '(' && tok[(stringlen = strlen(&tok[1]))] == ')') { /* group */ + if ((grpstr = strndup(&tok[1], stringlen - 1)) == NULL) { + syslog(LOG_ERR, "cannot allocate memory for %s", string); return (NO); } - errno = 0; - if ((grouplist = calloc(ngroups, sizeof(gid_t))) == NULL) { - if (errno == ENOMEM) { - syslog(LOG_ERR, "cannot allocate memory for grouplist: %s", string); - } - return (NO); - } - if (getgrouplist(string, passwd->pw_gid, grouplist, &ngroups) != 0) { - syslog(LOG_ERR, "getgrouplist() failed for %s", string); - free(grouplist); - return (NO); - } - for (i = 0; i < ngroups; i++) { - if (grouplist[i] == group->gr_gid) { - free(grouplist); - return (YES); - } - } - free(grouplist); + rc = group_match(grpstr, string); + free(grpstr); + return (rc); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if (login_access_opts->defgroup == true) {/* try group membership */ + return (group_match(tok, string)); } return (NO); } /* from_match - match a host or tty against a list of tokens */ static int -from_match(const char *tok, const char *string) +from_match(const char *tok, const char *string, + struct pam_login_access_options *login_access_opts __unused) { 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 (strcmp(tok, "LOCAL") == 0) { /* local: no dots */ if (strchr(string, '.') == NULL) 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(const char *tok, const 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 (strcmp(tok, "ALL") == 0) { /* all: always matches */ return (YES); } else if (strcasecmp(tok, string) == 0) { /* try exact match */ return (YES); } return (NO); } Index: stable/12/lib/libpam/modules/pam_login_access/pam_login_access.8 =================================================================== --- stable/12/lib/libpam/modules/pam_login_access/pam_login_access.8 (revision 359116) +++ stable/12/lib/libpam/modules/pam_login_access/pam_login_access.8 (revision 359117) @@ -1,89 +1,122 @@ .\" Copyright (c) 2001 Mark R V Murray .\" All rights reserved. .\" Copyright (c) 2001 Networks Associates Technology, Inc. .\" All rights reserved. .\" .\" Portions of this software were developed for the FreeBSD Project by .\" ThinkSec AS and NAI Labs, the Security Research Division of Network .\" Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 .\" ("CBOSS"), as part of the DARPA CHATS research program. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, 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. The name of the author may not be used to endorse or promote .\" products derived from this software without specific prior written .\" permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd January 24, 2002 +.Dd January 30, 2020 .Dt PAM_LOGIN_ACCESS 8 .Os .Sh NAME .Nm pam_login_access .Nd login.access PAM module .Sh SYNOPSIS .Op Ar service-name .Ar module-type .Ar control-flag .Pa pam_login_access .Op Ar options .Sh DESCRIPTION The .Pa login.access service module for PAM, .Nm provides functionality for only one PAM category: account management. In terms of the .Ar module-type parameter, this is the .Dq Li account feature. .Ss Login.access Account Management Module The .Pa login.access account management component .Pq Fn pam_sm_acct_mgmt , -returns success if and only the user is allowed to log in on the +returns success if and only the user is allowed to login on the specified tty (in the case of a local login) or from the specified remote host (in the case of a remote login), according to the restrictions listed in .Xr login.access 5 . +.Bl -tag -width ".Cm accessfile=pathname" +.It Cm accessfile Ns = Ns Ar pathname +specifies a non-standard location for the +.Pa login.access +configuration file +(normally located in +.Pa /etc/login.access ) . +.It Cm nodefgroup +makes tokens not enclosed in parentheses only match users, requiring groups +to be specified in parentheses. +Without +.Cm nodefgroup +user and group names are intermingled, with user entries taking precedence +over group entries. +This is not backwards compatible with legacy +.Pa login.access +configuration files. +However this mitigates confusion between users and +groups of the same name. +.It Cm fieldsep Ns = Ns Ar separators +changes the field separator from the default ":". +More than one separator +may be specified. +.It Cm listsep Ns = Ns Ar separators +changes the field separator from the default space (''), tab (\\t) and +comma (,). +More than one separator may be specified. +For example, listsep=; +will replace the default with a semicolon (;). +This option may be useful when specifying Active Directory groupnames which +typically contain spaces. +.El .Sh SEE ALSO .Xr pam 3 , +.Xr syslog 3 , .Xr login.access 5 , .Xr pam.conf 5 .Sh AUTHORS The .Xr login.access 5 access control scheme was designed and implemented by .An Wietse Venema . .Pp The .Nm module and this manual page were developed for the .Fx Project by ThinkSec AS and NAI Labs, the Security Research Division of Network Associates, Inc.\& under DARPA/SPAWAR contract N66001-01-C-8035 .Pq Dq CBOSS , as part of the DARPA CHATS research program. Index: stable/12/lib/libpam/modules/pam_login_access/pam_login_access.c =================================================================== --- stable/12/lib/libpam/modules/pam_login_access/pam_login_access.c (revision 359116) +++ stable/12/lib/libpam/modules/pam_login_access/pam_login_access.c (revision 359117) @@ -1,110 +1,131 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2001 Mark R V Murray * All rights reserved. * Copyright (c) 2001 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define _BSD_SOURCE #include +#include #include #include #define PAM_SM_ACCOUNT #include #include #include +#include #include "pam_login_access.h" +#define OPT_ACCESSFILE "accessfile" +#define OPT_NOAUDIT "noaudit" +#define OPT_FIELDSEP "fieldsep" +#define OPT_LISTSEP "listsep" +#define OPT_NODEFGROUP "nodefgroup" + +#define _PATH_LOGACCESS "/etc/login.access" +#define _FIELD_SEPARATOR ":" +#define _LIST_SEPARATOR ", \t" + PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, int argc __unused, const char *argv[] __unused) { + struct pam_login_access_options login_access_opts; const void *rhost, *tty, *user; char hostname[MAXHOSTNAMELEN]; int pam_err; pam_err = pam_get_item(pamh, PAM_USER, &user); if (pam_err != PAM_SUCCESS) return (pam_err); if (user == NULL) return (PAM_SERVICE_ERR); PAM_LOG("Got user: %s", (const char *)user); pam_err = pam_get_item(pamh, PAM_RHOST, &rhost); if (pam_err != PAM_SUCCESS) return (pam_err); pam_err = pam_get_item(pamh, PAM_TTY, &tty); if (pam_err != PAM_SUCCESS) return (pam_err); gethostname(hostname, sizeof hostname); + login_access_opts.defgroup = openpam_get_option(pamh, OPT_NODEFGROUP) == NULL ? true : false; + login_access_opts.audit = openpam_get_option(pamh, OPT_NOAUDIT) == NULL ? true : false; + if ((login_access_opts.accessfile = openpam_get_option(pamh, OPT_ACCESSFILE)) == NULL) + login_access_opts.accessfile = _PATH_LOGACCESS; + if ((login_access_opts.fieldsep = openpam_get_option(pamh, OPT_FIELDSEP)) == NULL) + login_access_opts.fieldsep = _FIELD_SEPARATOR; + if ((login_access_opts.listsep = openpam_get_option(pamh, OPT_LISTSEP)) == NULL) + login_access_opts.listsep = _LIST_SEPARATOR; if (rhost != NULL && *(const char *)rhost != '\0') { PAM_LOG("Checking login.access for user %s from host %s", (const char *)user, (const char *)rhost); - if (login_access(user, rhost) != 0) + if (login_access(user, rhost, &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in from %s", (const char *)user, (const char *)rhost); } else if (tty != NULL && *(const char *)tty != '\0') { PAM_LOG("Checking login.access for user %s on tty %s", (const char *)user, (const char *)tty); - if (login_access(user, tty) != 0) + if (login_access(user, tty, &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in on %s", (const char *)user, (const char *)tty); } else { PAM_LOG("Checking login.access for user %s", (const char *)user); - if (login_access(user, "***unknown***") != 0) + if (login_access(user, "***unknown***", &login_access_opts) != 0) return (PAM_SUCCESS); PAM_VERBOSE_ERROR("%s is not allowed to log in", (const char *)user); } return (PAM_AUTH_ERR); } PAM_MODULE_ENTRY("pam_login_access"); Index: stable/12/lib/libpam/modules/pam_login_access/pam_login_access.h =================================================================== --- stable/12/lib/libpam/modules/pam_login_access/pam_login_access.h (revision 359116) +++ stable/12/lib/libpam/modules/pam_login_access/pam_login_access.h (revision 359117) @@ -1,41 +1,52 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2001 Mark R V Murray * All rights reserved. * Copyright (c) 2001 Networks Associates Technology, Inc. * All rights reserved. * * Portions of this software were developed for the FreeBSD Project by * ThinkSec AS and NAI Labs, the Security Research Division of Network * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 * ("CBOSS"), as part of the DARPA CHATS research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, 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. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ -extern int login_access(const char *, const char *); +#include + +struct pam_login_access_options { + bool defgroup; + bool audit; + const char *accessfile; + /* Delimiters for fields and for lists of users, ttys or hosts. */ + const char *fieldsep; /* field separator */ + const char *listsep; /* list-element separator */ +}; + +extern int login_access(const char *, const char *, struct pam_login_access_options *); Index: stable/12 =================================================================== --- stable/12 (revision 359116) +++ stable/12 (revision 359117) Property changes on: stable/12 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r358070