Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Nov 2005 21:43:53 +0100 (CET)
From:      Oliver Fromme <olli@secnetix.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        Oliver Fromme <olli@secnetix.de>
Subject:   bin/89327: [PATCH] Add pattern matching to login.access(5)
Message-ID:  <200511202043.jAKKhrx7079623@lurza.secnetix.de>
Resent-Message-ID: <200511202050.jAKKoPhc059425@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         89327
>Category:       bin
>Synopsis:       [PATCH] Add pattern matching to login.access(5)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Nov 20 20:50:25 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Oliver Fromme
>Release:        FreeBSD 6.0-STABLE i386
>Organization:
secnetix GmbH & Co. KG, Munich, Germany 
		http://www.secnetix.de/bsd
>Environment:
System: FreeBSD epia.fromme.com 6.0-STABLE FreeBSD 6.0-STABLE #0: Fri Nov  4 21:35:33 CET 2005     olli@epia.fromme.com:/usr/src/sys/i386/compile/EPIA  i386

>Description:

The file login.access(5) can be used to restrict access
for users coming from certain remote hosts, or on certain
local terminals.  For example, we have some users who are
allowed to log in from virtual terminals only.  However,
it is tedious and error-prone to list all of the terminal
devices in the file.  The entry has to look like this:

+:foo bar:ttyv0 ttyv1 ttyv2 ttyv3 ttyv4 ttyv5 ttyv6 ttyv7
+:foo bar:ttyv8 ttyv9 ttyva ttyvb ttyvc ttyvd ttyve ttyvf

Th patch presented in this PR allows to use patterns like
those used by the bourne shell (using wildcards "*", "?"
and "[").  The above entry is now much easier:

+:foo bar:ttyv?

Similarly, "ttyd?" can be used to restrict all of the
serial dial-in lines.

The patch is quite simple.  Basically I just replaced the
strcasecmp(3) function with fnmatch(3).  Normally, the
special wildcard characters ("*", "?", "[") don't appear
in terminal device names, and they're also forbidden in
host names, so there shouldn't be any regression cases.

The login.access(5) file is used at three different places
in the FreeBSD source tree:  in src/usr.bin/login, in
src/lib/libpam/modules/pam_login_access, and in src/cryp-
to/heimdal/appl/login.  The latter is third-party software,
so I'm not sure if it's appropriate to patch it in the
FreeBSD source tree.  However, for consistency, I patched
it in the same way and include the patch below for your
consideration.

The patch set also includes updates to the manual pages
which describe the feature, and also a clarification that
all matches are performed in a case-insensitive way.
(The latter is even true without my patch, but that
behaviour was undocumented.)

>How-To-Repeat:

n/a

>Fix:

--- src/usr.bin/login/login_access.c.orig	Fri Mar 22 02:22:49 2002
+++ src/usr.bin/login/login_access.c	Sun Nov 20 21:16:13 2005
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 #include <ctype.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <grp.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -175,7 +176,7 @@
 	return (YES);
     } else if ((group = getgrnam(tok)) != NULL) {/* try group membership */
 	for (i = 0; group->gr_mem[i]; i++)
-	    if (strcasecmp(string, group->gr_mem[i]) == 0)
+	    if (fnmatch(string, group->gr_mem[i], FNM_CASEFOLD) == 0)
 		return (YES);
     }
     return (NO);
@@ -205,7 +206,7 @@
 	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)
+	    && fnmatch(tok, string + str_len - tok_len, FNM_CASEFOLD) == 0)
 	    return (YES);
     } else if (strcasecmp(tok, "LOCAL") == 0) {	/* local: no dots */
 	if (strchr(string, '.') == 0)
@@ -231,7 +232,7 @@
 
     if (strcasecmp(tok, "ALL") == 0) {		/* all: always matches */
 	return (YES);
-    } else if (strcasecmp(tok, string) == 0) {	/* try exact match */
+    } else if (fnmatch(tok, string, FNM_CASEFOLD) == 0) { /* try exact match */
 	return (YES);
     }
     return (NO);
--- src/usr.bin/login/login.access.5.orig	Sat Jul  3 00:22:27 2004
+++ src/usr.bin/login/login.access.5	Sun Nov 20 21:21:17 2005
@@ -45,6 +45,15 @@
 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.
+.Pp
+In names of users, groups, ttys, hosts and domains,
+the special wildcard characters "*", "?" and "[" can be used,
+matching patterns according to the rules used by the shell.
+This is most useful for tty names:
+The pattern "ttyv?" in the third field matches all virtual
+terminals, and "ttyd?" matches all serial dial-in lines.
+.Pp
+All matches are case-insensitive.
 .Sh FILES
 .Bl -tag -width /etc/login.access -compact
 .It Pa /etc/login.access
--- src/lib/libpam/modules/pam_login_access/login_access.c.orig	Fri Mar  5 09:10:18 2004
+++ src/lib/libpam/modules/pam_login_access/login_access.c	Sun Nov 20 21:17:41 2005
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <ctype.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <grp.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -170,7 +171,7 @@
 	return (YES);
     } else if ((group = getgrnam(tok)) != NULL) {/* try group membership */
 	for (i = 0; group->gr_mem[i]; i++)
-	    if (strcasecmp(string, group->gr_mem[i]) == 0)
+	    if (fnmatch(string, group->gr_mem[i], FNM_CASEFOLD) == 0)
 		return (YES);
     }
     return (NO);
@@ -199,7 +200,7 @@
 	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)
+	    && fnmatch(tok, string + str_len - tok_len, FNM_CASEFOLD) == 0)
 	    return (YES);
     } else if (strcasecmp(tok, "LOCAL") == 0) {	/* local: no dots */
 	if (strchr(string, '.') == 0)
@@ -224,7 +225,7 @@
 
     if (strcasecmp(tok, "ALL") == 0) {		/* all: always matches */
 	return (YES);
-    } else if (strcasecmp(tok, string) == 0) {	/* try exact match */
+    } else if (fnmatch(tok, string, FNM_CASEFOLD) == 0) { /* try exact match */
 	return (YES);
     }
     return (NO);
--- src/lib/libpam/modules/pam_login_access/login.access.5.orig	Sat Jul  3 01:52:17 2004
+++ src/lib/libpam/modules/pam_login_access/login.access.5	Sun Nov 20 21:21:18 2005
@@ -46,6 +46,15 @@
 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.
+.Pp
+In names of users, groups, ttys, hosts and domains,
+the special wildcard characters "*", "?" and "[" can be used,
+matching patterns according to the rules used by the shell.
+This is most useful for tty names:
+The pattern "ttyv?" in the third field matches all virtual
+terminals, and "ttyd?" matches all serial dial-in lines.
+.Pp
+All matches are case-insensitive.
 .Sh FILES
 .Bl -tag -width /etc/login.access -compact
 .It Pa /etc/login.access
--- src/crypto/heimdal/appl/login/login_access.c.orig	Tue Feb 19 16:46:04 2002
+++ src/crypto/heimdal/appl/login/login_access.c	Sun Nov 20 21:17:39 2005
@@ -24,6 +24,7 @@
   */
 
 #include "login_locl.h"
+#include <fnmatch.h>
 
 RCSID("$Id: login_access.c,v 1.2 2001/06/04 14:09:45 assar Exp $");
 
@@ -217,7 +218,7 @@
 	if (item->user->pw_gid == group->gr_gid)
 	    return (YES);
 	for (i = 0; group->gr_mem[i]; i++)
-	    if (strcasecmp(string, group->gr_mem[i]) == 0)
+	    if (fnmatch(string, group->gr_mem[i], FNM_CASEFOLD) == 0)
 		return (YES);
     }
     return (NO);
@@ -246,7 +247,7 @@
 	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)
+	    && fnmatch(tok, string + str_len - tok_len, FNM_CASEFOLD) == 0)
 	    return (YES);
     } else if (strcasecmp(tok, "LOCAL") == 0) {	/* local: no dots */
 	if (strchr(string, '.') == 0)
@@ -270,7 +271,7 @@
 
     if (strcasecmp(tok, "ALL") == 0) {		/* all: always matches */
 	return (YES);
-    } else if (strcasecmp(tok, string) == 0) {	/* try exact match */
+    } else if (fnmatch(tok, string, FNM_CASEFOLD) == 0) { /* try exact match */
 	return (YES);
     }
     return (NO);
--- src/crypto/heimdal/appl/login/login.access.5.orig	Thu Oct  9 21:36:19 2003
+++ src/crypto/heimdal/appl/login/login.access.5	Sun Nov 20 21:21:15 2005
@@ -44,6 +44,15 @@
 .Pp
 If the string EXCEPT is found in either the user or from list, the
 rest of the list are exceptions to the list before EXCEPT.
+.Pp
+In names of users, groups, ttys, hosts and domains,
+the special wildcard characters "*", "?" and "[" can be used,
+matching patterns according to the rules used by the shell.
+This is most useful for tty names:
+The pattern "ttyv?" in the third field matches all virtual
+terminals, and "ttyd?" matches all serial dial-in lines.
+.Pp
+All matches are case-insensitive.
 .Sh BUGS
 If there's a user and a group with the same name, there is no way to
 make the group match if the user also matches.
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200511202043.jAKKhrx7079623>