2010-12-14 11:02:26 +00:00
|
|
|
Index: modules/pam_limits/limits.conf.5.xml
|
|
|
|
===================================================================
|
|
|
|
RCS file: /cvsroot/pam/Linux-PAM/modules/pam_limits/limits.conf.5.xml,v
|
2010-12-14 11:35:57 +00:00
|
|
|
retrieving revision 1.9
|
2010-12-14 11:02:26 +00:00
|
|
|
retrieving revision 1.11
|
2010-12-14 11:35:57 +00:00
|
|
|
diff -u -p -r1.9 -r1.11
|
|
|
|
--- modules/pam_limits/limits.conf.5.xml 20 Feb 2009 13:27:14 -0000 1.9
|
2010-12-14 11:02:26 +00:00
|
|
|
+++ modules/pam_limits/limits.conf.5.xml 14 Dec 2010 08:40:40 -0000 1.11
|
2010-12-14 11:35:57 +00:00
|
|
|
@@ -53,7 +53,38 @@
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
the wildcard <emphasis remap='B'>%</emphasis>, for maxlogins limit only,
|
|
|
|
- can also be used with <emphasis remap='b'>%group</emphasis> syntax.
|
|
|
|
+ can also be used with <emphasis remap='B'>%group</emphasis> syntax. If the
|
|
|
|
+ <emphasis remap='B'>%</emphasis> wildcard is used alone it is identical
|
|
|
|
+ to using <emphasis remap='B'>*</emphasis> with maxsyslogins limit. With
|
|
|
|
+ a group specified after <emphasis remap='B'>%</emphasis> it limits the total
|
|
|
|
+ number of logins of all users that are member of the group.
|
|
|
|
+ </para>
|
|
|
|
+ </listitem>
|
2010-12-14 11:02:26 +00:00
|
|
|
+ <listitem>
|
|
|
|
+ <para>
|
|
|
|
+ an uid range specified as <replaceable><min_uid></replaceable><emphasis
|
|
|
|
+ remap='B'>:</emphasis><replaceable><max_uid></replaceable>. If min_uid
|
|
|
|
+ is omitted, the match is exact for the max_uid. If max_uid is omitted, all
|
|
|
|
+ uids greater than or equal min_uid match.
|
|
|
|
+ </para>
|
|
|
|
+ </listitem>
|
|
|
|
+ <listitem>
|
|
|
|
+ <para>
|
|
|
|
+ a gid range specified as <emphasis
|
|
|
|
+ remap='B'>@</emphasis><replaceable><min_gid></replaceable><emphasis
|
|
|
|
+ remap='B'>:</emphasis><replaceable><max_gid></replaceable>. If min_gid
|
|
|
|
+ is omitted, the match is exact for the max_gid. If max_gid is omitted, all
|
|
|
|
+ gids greater than or equal min_gid match. For the exact match all groups including
|
|
|
|
+ the user's supplementary groups are examined. For the range matches only
|
|
|
|
+ the user's primary group is examined.
|
|
|
|
+ </para>
|
|
|
|
+ </listitem>
|
|
|
|
+ <listitem>
|
|
|
|
+ <para>
|
|
|
|
+ a gid specified as <emphasis
|
|
|
|
+ remap='B'>%:</emphasis><replaceable><gid></replaceable> applicable
|
|
|
|
+ to maxlogins limit only. It limits the total number of logins of all users
|
|
|
|
+ that are member of the group with the specified gid.
|
2010-12-14 11:35:57 +00:00
|
|
|
</para>
|
|
|
|
</listitem>
|
2010-12-14 11:02:26 +00:00
|
|
|
</itemizedlist>
|
2010-12-14 11:35:57 +00:00
|
|
|
@@ -182,7 +213,7 @@
|
|
|
|
<varlistentry>
|
|
|
|
<term><option>maxsyslogins</option></term>
|
|
|
|
<listitem>
|
|
|
|
- <para>maximum number of logins on system</para>
|
|
|
|
+ <para>maximum number of all logins on system</para>
|
|
|
|
</listitem>
|
|
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
|
|
@@ -272,12 +303,15 @@
|
2010-12-14 11:02:26 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
* soft core 0
|
|
|
|
-* hard rss 10000
|
|
|
|
+* hard nofile 512
|
|
|
|
@student hard nproc 20
|
|
|
|
@faculty soft nproc 20
|
|
|
|
@faculty hard nproc 50
|
|
|
|
ftp hard nproc 0
|
|
|
|
@student - maxlogins 4
|
|
|
|
+:123 hard cpu 5000
|
|
|
|
+@500: soft cpu 10000
|
|
|
|
+600:700 hard locks 10
|
|
|
|
</programlisting>
|
|
|
|
</refsect1>
|
|
|
|
|
|
|
|
Index: modules/pam_limits/pam_limits.c
|
|
|
|
===================================================================
|
|
|
|
RCS file: /cvsroot/pam/Linux-PAM/modules/pam_limits/pam_limits.c,v
|
|
|
|
retrieving revision 1.48
|
|
|
|
retrieving revision 1.49
|
|
|
|
diff -u -p -r1.48 -r1.49
|
|
|
|
--- modules/pam_limits/pam_limits.c 18 Nov 2010 09:37:32 -0000 1.48
|
|
|
|
+++ modules/pam_limits/pam_limits.c 14 Dec 2010 08:40:40 -0000 1.49
|
|
|
|
@@ -55,6 +55,12 @@
|
|
|
|
#define LIMITS_DEF_DEFAULT 4 /* limit was set by an default entry */
|
|
|
|
#define LIMITS_DEF_NONE 5 /* this limit was not set yet */
|
|
|
|
|
|
|
|
+#define LIMIT_RANGE_ERR -1 /* error in specified uid/gid range */
|
|
|
|
+#define LIMIT_RANGE_NONE 0 /* no range specified */
|
|
|
|
+#define LIMIT_RANGE_ONE 1 /* exact uid/gid specified (:max_uid)*/
|
|
|
|
+#define LIMIT_RANGE_MIN 2 /* only minimum uid/gid specified (min_uid:) */
|
|
|
|
+#define LIMIT_RANGE_MM 3 /* both min and max uid/gid specified (min_uid:max_uid) */
|
|
|
|
+
|
|
|
|
static const char *limits_def_names[] = {
|
|
|
|
"USER",
|
|
|
|
"GROUP",
|
|
|
|
@@ -520,8 +526,57 @@ process_limit (const pam_handle_t *pamh,
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static int parse_config_file(pam_handle_t *pamh, const char *uname, int ctrl,
|
|
|
|
- struct pam_limit_s *pl)
|
|
|
|
+static int
|
|
|
|
+parse_uid_range(pam_handle_t *pamh, const char *domain,
|
|
|
|
+ uid_t *min_uid, uid_t *max_uid)
|
|
|
|
+{
|
|
|
|
+ const char *range = domain;
|
|
|
|
+ char *pmax;
|
|
|
|
+ char *endptr;
|
|
|
|
+ int rv = LIMIT_RANGE_MM;
|
|
|
|
+
|
|
|
|
+ if ((pmax=strchr(range, ':')) == NULL)
|
|
|
|
+ return LIMIT_RANGE_NONE;
|
|
|
|
+ ++pmax;
|
|
|
|
+
|
|
|
|
+ if (range[0] == '@' || range[0] == '%')
|
|
|
|
+ ++range;
|
|
|
|
+
|
|
|
|
+ if (range[0] == ':')
|
|
|
|
+ rv = LIMIT_RANGE_ONE;
|
|
|
|
+ else {
|
|
|
|
+ errno = 0;
|
|
|
|
+ *min_uid = strtoul (range, &endptr, 10);
|
|
|
|
+ if (errno != 0 || (range == endptr) || *endptr != ':') {
|
|
|
|
+ pam_syslog(pamh, LOG_DEBUG,
|
|
|
|
+ "wrong min_uid/gid value in '%s'", domain);
|
|
|
|
+ return LIMIT_RANGE_ERR;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (*pmax == '\0') {
|
|
|
|
+ if (rv == LIMIT_RANGE_ONE)
|
|
|
|
+ return LIMIT_RANGE_ERR;
|
|
|
|
+ else
|
|
|
|
+ return LIMIT_RANGE_MIN;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ errno = 0;
|
|
|
|
+ *max_uid = strtoul (pmax, &endptr, 10);
|
|
|
|
+ if (errno != 0 || (pmax == endptr) || *endptr != '\0') {
|
|
|
|
+ pam_syslog(pamh, LOG_DEBUG,
|
|
|
|
+ "wrong max_uid/gid value in '%s'", domain);
|
|
|
|
+ return LIMIT_RANGE_ERR;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (rv == LIMIT_RANGE_ONE)
|
|
|
|
+ *min_uid = *max_uid;
|
|
|
|
+ return rv;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+parse_config_file(pam_handle_t *pamh, const char *uname, uid_t uid, gid_t gid,
|
|
|
|
+ int ctrl, struct pam_limit_s *pl)
|
|
|
|
{
|
|
|
|
FILE *fil;
|
|
|
|
char buf[LINE_LENGTH];
|
|
|
|
@@ -543,8 +598,10 @@ static int parse_config_file(pam_handle_
|
|
|
|
char item[LINE_LENGTH];
|
|
|
|
char value[LINE_LENGTH];
|
|
|
|
int i;
|
|
|
|
+ int rngtype;
|
|
|
|
size_t j;
|
|
|
|
char *tptr,*line;
|
|
|
|
+ uid_t min_uid = (uid_t)-1, max_uid = (uid_t)-1;
|
|
|
|
|
|
|
|
line = buf;
|
|
|
|
/* skip the leading white space */
|
|
|
|
@@ -572,6 +629,11 @@ static int parse_config_file(pam_handle_
|
|
|
|
for(j=0; j < strlen(ltype); j++)
|
|
|
|
ltype[j]=tolower(ltype[j]);
|
|
|
|
|
|
|
|
+ if ((rngtype=parse_uid_range(pamh, domain, &min_uid, &max_uid)) < 0) {
|
|
|
|
+ pam_syslog(pamh, LOG_WARNING, "invalid uid range '%s' - skipped", domain);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
if (i == 4) { /* a complete line */
|
|
|
|
for(j=0; j < strlen(item); j++)
|
|
|
|
item[j]=tolower(item[j]);
|
|
|
|
@@ -581,47 +643,133 @@ static int parse_config_file(pam_handle_
|
|
|
|
if (strcmp(uname, domain) == 0) /* this user have a limit */
|
|
|
|
process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
|
|
|
|
else if (domain[0]=='@') {
|
|
|
|
- if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
+ if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
pam_syslog(pamh, LOG_DEBUG,
|
|
|
|
"checking if %s is in group %s",
|
|
|
|
uname, domain + 1);
|
|
|
|
- }
|
|
|
|
- if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1))
|
|
|
|
- process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
|
|
|
|
+ }
|
|
|
|
+ switch(rngtype) {
|
|
|
|
+ case LIMIT_RANGE_NONE:
|
|
|
|
+ if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1))
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_ONE:
|
|
|
|
+ if (pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid))
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
|
|
|
|
pl);
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_MM:
|
|
|
|
+ if (gid > (gid_t)max_uid)
|
|
|
|
+ break;
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ case LIMIT_RANGE_MIN:
|
|
|
|
+ if (gid >= (gid_t)min_uid)
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_GROUP, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ }
|
|
|
|
} else if (domain[0]=='%') {
|
|
|
|
- if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
+ if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
pam_syslog(pamh, LOG_DEBUG,
|
|
|
|
"checking if %s is in group %s",
|
|
|
|
uname, domain + 1);
|
|
|
|
- }
|
|
|
|
- if (strcmp(domain,"%") == 0)
|
|
|
|
- process_limit(pamh, LIMITS_DEF_ALL, ltype, item, value, ctrl,
|
|
|
|
- pl);
|
|
|
|
- else if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
|
|
|
|
- strcpy(pl->login_group, domain+1);
|
|
|
|
- process_limit(pamh, LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
|
|
|
|
- pl);
|
|
|
|
}
|
|
|
|
- } else if (strcmp(domain, "*") == 0)
|
|
|
|
- process_limit(pamh, LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
|
|
|
|
- pl);
|
|
|
|
+ switch(rngtype) {
|
|
|
|
+ case LIMIT_RANGE_NONE:
|
|
|
|
+ if (strcmp(domain,"%") == 0)
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_ALL, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ else if (pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
|
|
|
|
+ strcpy(pl->login_group, domain+1);
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_ONE:
|
|
|
|
+ if (pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid)) {
|
|
|
|
+ struct group *grp;
|
|
|
|
+ grp = pam_modutil_getgrgid(pamh, (gid_t)max_uid);
|
|
|
|
+ strncpy(pl->login_group, grp->gr_name, sizeof(pl->login_group));
|
|
|
|
+ pl->login_group[sizeof(pl->login_group)-1] = '\0';
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_MIN:
|
|
|
|
+ case LIMIT_RANGE_MM:
|
|
|
|
+ pam_syslog(pamh, LOG_WARNING, "range unsupported for %%group matching - ignored");
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ switch(rngtype) {
|
|
|
|
+ case LIMIT_RANGE_NONE:
|
|
|
|
+ if (strcmp(domain, "*") == 0)
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
|
|
|
|
+ pl);
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_ONE:
|
|
|
|
+ if (uid != max_uid)
|
|
|
|
+ break;
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ case LIMIT_RANGE_MM:
|
|
|
|
+ if (uid > max_uid)
|
|
|
|
+ break;
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ case LIMIT_RANGE_MIN:
|
|
|
|
+ if (uid >= min_uid)
|
|
|
|
+ process_limit(pamh, LIMITS_DEF_USER, ltype, item, value, ctrl, pl);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
} else if (i == 2 && ltype[0] == '-') { /* Probably a no-limit line */
|
|
|
|
if (strcmp(uname, domain) == 0) {
|
|
|
|
if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
pam_syslog(pamh, LOG_DEBUG, "no limits for '%s'", uname);
|
|
|
|
}
|
|
|
|
- fclose(fil);
|
|
|
|
- return PAM_IGNORE;
|
|
|
|
- } else if (domain[0] == '@' && pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
|
|
|
|
+ } else if (domain[0] == '@') {
|
|
|
|
+ switch(rngtype) {
|
|
|
|
+ case LIMIT_RANGE_NONE:
|
|
|
|
+ if (!pam_modutil_user_in_group_nam_nam(pamh, uname, domain+1))
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_ONE:
|
|
|
|
+ if (!pam_modutil_user_in_group_nam_gid(pamh, uname, (gid_t)max_uid))
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_MM:
|
|
|
|
+ if (gid > (gid_t)max_uid)
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ case LIMIT_RANGE_MIN:
|
|
|
|
+ if (gid < (gid_t)min_uid)
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ }
|
|
|
|
if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
pam_syslog(pamh, LOG_DEBUG,
|
|
|
|
"no limits for '%s' in group '%s'",
|
|
|
|
uname, domain+1);
|
|
|
|
}
|
|
|
|
- fclose(fil);
|
|
|
|
- return PAM_IGNORE;
|
|
|
|
+ } else {
|
|
|
|
+ switch(rngtype) {
|
|
|
|
+ case LIMIT_RANGE_NONE:
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ case LIMIT_RANGE_ONE:
|
|
|
|
+ if (uid != max_uid)
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ break;
|
|
|
|
+ case LIMIT_RANGE_MM:
|
|
|
|
+ if (uid > max_uid)
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ /* fallthrough */
|
|
|
|
+ case LIMIT_RANGE_MIN:
|
|
|
|
+ if (uid >= min_uid)
|
|
|
|
+ break;
|
|
|
|
+ continue; /* next line */
|
|
|
|
+ }
|
|
|
|
+ if (ctrl & PAM_DEBUG_ARG) {
|
|
|
|
+ pam_syslog(pamh, LOG_DEBUG, "no limits for '%s'", uname);
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
+ fclose(fil);
|
|
|
|
+ return PAM_IGNORE;
|
|
|
|
} else {
|
|
|
|
pam_syslog(pamh, LOG_WARNING, "invalid line '%s' - skipped", line);
|
|
|
|
}
|
|
|
|
@@ -731,7 +879,7 @@ pam_sm_open_session (pam_handle_t *pamh,
|
|
|
|
return PAM_ABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
- retval = parse_config_file(pamh, pwd->pw_name, ctrl, pl);
|
|
|
|
+ retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
|
|
|
|
if (retval == PAM_IGNORE) {
|
|
|
|
D(("the configuration file ('%s') has an applicable '<domain> -' entry", CONF_FILE));
|
|
|
|
return PAM_SUCCESS;
|
|
|
|
@@ -755,7 +903,7 @@ pam_sm_open_session (pam_handle_t *pamh,
|
|
|
|
/* Parse the *.conf files. */
|
|
|
|
for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
|
|
|
|
pl->conf_file = globbuf.gl_pathv[i];
|
|
|
|
- retval = parse_config_file(pamh, pwd->pw_name, ctrl, pl);
|
|
|
|
+ retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
|
|
|
|
if (retval == PAM_IGNORE) {
|
|
|
|
D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file));
|
|
|
|
globfree(&globbuf);
|