summaryrefslogtreecommitdiff
path: root/extra/source/pam/patches/pam-1.1.3-limits-range.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extra/source/pam/patches/pam-1.1.3-limits-range.patch')
-rw-r--r--extra/source/pam/patches/pam-1.1.3-limits-range.patch351
1 files changed, 351 insertions, 0 deletions
diff --git a/extra/source/pam/patches/pam-1.1.3-limits-range.patch b/extra/source/pam/patches/pam-1.1.3-limits-range.patch
new file mode 100644
index 00000000..c357eb28
--- /dev/null
+++ b/extra/source/pam/patches/pam-1.1.3-limits-range.patch
@@ -0,0 +1,351 @@
+Index: modules/pam_limits/limits.conf.5.xml
+===================================================================
+RCS file: /cvsroot/pam/Linux-PAM/modules/pam_limits/limits.conf.5.xml,v
+retrieving revision 1.9
+retrieving revision 1.11
+diff -u -p -r1.9 -r1.11
+--- modules/pam_limits/limits.conf.5.xml 20 Feb 2009 13:27:14 -0000 1.9
++++ modules/pam_limits/limits.conf.5.xml 14 Dec 2010 08:40:40 -0000 1.11
+@@ -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>
++ <listitem>
++ <para>
++ an uid range specified as <replaceable>&lt;min_uid&gt;</replaceable><emphasis
++ remap='B'>:</emphasis><replaceable>&lt;max_uid&gt;</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>&lt;min_gid&gt;</replaceable><emphasis
++ remap='B'>:</emphasis><replaceable>&lt;max_gid&gt;</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>&lt;gid&gt;</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.
+ </para>
+ </listitem>
+ </itemizedlist>
+@@ -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 @@
+ </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);