Hello all,
I've been looking for a way to dynamically add groups to users
belonging to a certain user-group.
For example, I would like to dynamically add to the group 'plugdev',
all users belonging to the 'Domain Users' group.
From a quick look at the pam_group module I see that it supports
netgroups but not regular user groups (the kind you get from
/etc/groups).
To this end, I'm attaching a short patch that enables group-based access
in pam_group. Since the '@' sign is reserved for specifying netgroups,
I'm using the '%' sign to specify user-groups in the config file, like
this:
xsh; tty* ; %users ; Al0000-2400 ; disk
Also, some tweaking has been done on the code that parses the config
file. To be able to specify user-groups containing spaces, but still
retain backwards compatibility with space-delimited lists, I've
introduced the escaped space '\ ' sequence, which is used like this:
gdm ; * ; %Domain\ Users ; Al0000-2400 ; plugdev
Documentation files, along with the sample config file have been
updated to reflect these changes.
A few words regarding the implementation:
To be able to retain '\ ' as a space ' ' I'm scanning the input
data for consecutive spaces, comma's etc. just once. In the CVS
version of the code the whole buffer was (redundantly) scanned
multiple times, each time new data was read from the config file
(see modules/pam_group/pam_group.c:128).
The patch also includes a few indentation fixes and a new
macro ( IS_TOKEN(c) ) for simplifying the task of parsing
the tokens of logical expressions.
I'm not sure if this was needed, but I've added a short
entry in the ChangeLog file with an overview of the changes
made.
So, have a look at the patch and let me know what you think :-)
Best Regards,
Dimitris Glynos
diff -urN Linux-PAM/ChangeLog Linux-PAMb/ChangeLog
--- Linux-PAM/ChangeLog 2009-11-19 12:43:23.000000000 +0200
+++ Linux-PAMb/ChangeLog 2009-12-07 20:50:32.000000000 +0200
@@ -1,3 +1,14 @@
+2009-12-07 Dimitris Glynos <dimitris@xxxxxxxxxxxxxxx>
+ * modules/pam_group/pam_group.c:
+ - Support the dynamic "subscription" to groups for members of
+ regular user groups (i.e. not just netgroups).
+ - Support (escaped) space characters in group names.
+ - Perform buffer contraction, comment deletion and
+ multiple space substitution, in one pass, on the
+ config file data
+ - Use the macro IS_TOKEN(c) for detecting characters of
+ a token belonging to a logical expression.
+
2009-11-19 Tomas Mraz <t8m@xxxxxxxxxx>
* modules/pam_sepermit/pam_sepermit.c(sepermit_match): Return
diff -urN Linux-PAM/modules/pam_group/group.conf Linux-PAMb/modules/pam_group/group.conf
--- Linux-PAM/modules/pam_group/group.conf 2007-09-01 05:10:32.000000000 +0300
+++ Linux-PAMb/modules/pam_group/group.conf 2009-12-07 20:53:31.000000000 +0200
@@ -95,5 +95,12 @@
#xsh; tty* ;*;Al0900-1800;floppy
#
+# and another example: any member of the group 'Domain Users' running
+# 'xsh' on tty*, is granted access (at any time) to the group 'plugdev'
+#
+
+#xsh; tty* ; %Domain\ Users ; Al0000-2400 ; plugdev
+
+#
# End of group.conf file
#
diff -urN Linux-PAM/modules/pam_group/group.conf.5.xml Linux-PAMb/modules/pam_group/group.conf.5.xml
--- Linux-PAM/modules/pam_group/group.conf.5.xml 2006-06-22 22:44:30.000000000 +0300
+++ Linux-PAMb/modules/pam_group/group.conf.5.xml 2009-12-07 20:53:31.000000000 +0200
@@ -28,7 +28,9 @@
For this module to function correctly there must be a correctly
formatted <filename>/etc/security/group.conf</filename> file present.
White spaces are ignored and lines maybe extended with '\' (escaped
- newlines). Text following a '#' is ignored to the end of the line.
+ newlines). Space characters that are part of group names may be
+ specified using the escaped form '\ '. Text following a '#' is ignored
+ to the end of the line.
</para>
<para>
@@ -52,13 +54,14 @@
<para>
The third field, the <replaceable>users</replaceable>
- field, is a logic list of users or a netgroup of users to whom this
- rule applies.
+ field, is a logic list of users, or a group of users, or a netgroup of
+ users to whom this rule applies. Group names are preceded by a '%'
+ symbol, while netgroup names are preceded by a '@' symbol.
</para>
<para>
For these items the simple wildcard '*' may be used only once.
- With netgroups no wildcards or logic operators are allowed.
+ With groups or netgroups no wildcards or logic operators are allowed.
</para>
<para>
@@ -109,7 +112,14 @@
</para>
<programlisting>
xsh; tty* ;sword;!Wk0900-1800;games, sound
-xsh; tty* ;*;Al0900-1800;floppy
+xsh; tty* ;*;Al0900-1800;floppy</programlisting>
+
+ <para>
+ Any member of the group 'Domain Users' running 'xsh' on tty*,
+ is granted access (at any time) to the group 'plugdev'
+ </para>
+ <programlisting>
+xsh; tty* ; %Domain\ Users ; Al0000-2400 ; plugdev
</programlisting>
</refsect1>
diff -urN Linux-PAM/modules/pam_group/pam_group.c Linux-PAMb/modules/pam_group/pam_group.c
--- Linux-PAM/modules/pam_group/pam_group.c 2008-12-01 13:26:59.000000000 +0200
+++ Linux-PAMb/modules/pam_group/pam_group.c 2009-12-07 20:53:31.000000000 +0200
@@ -24,6 +24,10 @@
#define PAM_GROUP_BUFLEN 1000
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
+#define IS_TOKEN(c) ( isalpha(c) || (c) == '*' || isdigit(c) \
+ || (c) == '_' || (c) == '-' \
+ || (c) == '.' || (c) == '/' \
+ || (c) == ':' || (c) == ' ' )
#ifndef TRUE
# define TRUE 1
@@ -105,7 +109,7 @@
(*buf)[*to] = '\0';
while (fd >= 0 && *to < PAM_GROUP_BUFLEN) {
- int i;
+ int i, last_read_pos;
/* now try to fill the remainder of the buffer */
@@ -117,15 +121,18 @@
} else if (!i) {
close(fd);
fd = -1; /* end of file reached */
- } else
+ last_read_pos = *to;
+ } else {
+ last_read_pos = *to;
*to += i;
+ }
/*
* contract the buffer. Delete any comments, and replace all
* multiple spaces with single commas
*/
- i = 0;
+ i = last_read_pos;
#ifdef DEBUG_DUMP
D(("buffer=<%s>",*buf));
#endif
@@ -162,8 +169,12 @@
if ((*buf)[i+1] == '\n') {
shift_bytes(i + *buf, 2, *to - (i+2));
*to -= 2;
+ } else if ((*buf)[i+1] == ' ') {
+ shift_bytes(i + *buf, 1, *to - (i+1));
+ *to -= 1;
+ ++i;
} else {
- ++i; /* we don't escape non-newline characters */
+ ++i; /* we escape only space and newline characters */
}
break;
case '!':
@@ -198,8 +209,8 @@
return fd;
case FIELD_SEPARATOR: /* end of the field */
(*buf)[i] = '\0';
- *from = ++i;
- return fd;
+ *from = ++i;
+ return fd;
}
}
*from = i;
@@ -242,8 +253,7 @@
break;
default:
- if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
- || c == '-' || c == '.' || c == '/' || c == ':') {
+ if (IS_TOKEN(c)) {
token = 1;
} else if (token) {
--to;
@@ -276,8 +286,7 @@
if (next == VAL) {
if (c == '!')
not = !not;
- else if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
- || c == '-' || c == '.' || c == '/' || c == ':') {
+ else if (IS_TOKEN(c)) {
right = not ^ agrees(pamh, me, x+at, l, rule);
if (oper == AND)
left &= right;
@@ -506,8 +515,7 @@
break;
default:
- if (isalpha(c) || isdigit(c) || c == '_' || c == '*'
- || c == '-') {
+ if (IS_TOKEN(c)) {
token = 1;
} else if (token) {
--to;
@@ -578,6 +586,28 @@
return len;
}
+static int
+grp_exists(pam_handle_t *pamh, const char *grpnam, gid_t *grps, int no_grps)
+{
+ struct group *grp;
+ gid_t grp_id;
+ int i;
+
+ if (!(grp = pam_modutil_getgrnam(pamh, grpnam))) {
+ D(("unknown group name: %s\n", grpnam));
+ return 0;
+ }
+
+ grp_id = grp->gr_gid;
+
+ for (i=0; i<no_grps; i++) {
+ if (grps[i] == grp_id) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
static int check_account(pam_handle_t *pamh, const char *service,
const char *tty, const char *user)
@@ -657,9 +687,15 @@
"%s: no user entry #%d", PAM_GROUP_CONF, count);
continue;
}
+
/* If buffer starts with @, we are using netgroups */
if (buffer[0] == '@')
good &= innetgr (&buffer[1], NULL, user, NULL);
+
+ /* if buffer starts with %, we are using user groups */
+ else if (buffer[0] == '%')
+ good &= grp_exists(pamh, &buffer[1], grps, no_grps);
+
else
good &= logic_field(pamh,user, buffer, count, is_same);
D(("with user: %s", good ? "passes":"fails" ));
_______________________________________________
Pam-list mailing list
Pam-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/pam-list