diff options
author | Tomas Mraz <tm@t8m.info> | 2007-03-29 20:33:07 +0000 |
---|---|---|
committer | Tomas Mraz <tm@t8m.info> | 2007-03-29 20:33:07 +0000 |
commit | f6b973b922818f189bdb70924de0c6691cf9ffe4 (patch) | |
tree | a2827d4f746f0c91a4ab740013b66ddc660bfb45 | |
parent | e2546c9b5832a738be84e5882c1804ff3b05c569 (diff) | |
download | pam-f6b973b922818f189bdb70924de0c6691cf9ffe4.tar.gz pam-f6b973b922818f189bdb70924de0c6691cf9ffe4.tar.bz2 pam-f6b973b922818f189bdb70924de0c6691cf9ffe4.zip |
Relevant BUGIDs:
Purpose of commit: new feature
Commit summary:
---------------
* modules/pam_limits/Makefile.am: Define limits.d dir and install it.
* modules/pam_limits/pam_limits.8.xml: Describe limits.d parsing.
* modules/pam_limits/pam_limits.c (pam_limit_s): Make conf_file ptr.
(pam_parse): conf_file is now ptr.
(pam_sm_open_session): Add parsing files from limits.d subdir using
glob, change pl to pointer.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | modules/pam_limits/Makefile.am | 4 | ||||
-rw-r--r-- | modules/pam_limits/pam_limits.8.xml | 10 | ||||
-rw-r--r-- | modules/pam_limits/pam_limits.c | 74 |
5 files changed, 81 insertions, 20 deletions
@@ -9,6 +9,13 @@ * modules/pam_unix/pam_unix_passwd.c (check_old_password, save_old_password): Likewise. + * modules/pam_limits/Makefile.am: Define limits.d dir and install it. + * modules/pam_limits/pam_limits.8.xml: Describe limits.d parsing. + * modules/pam_limits/pam_limits.c (pam_limit_s): Make conf_file ptr. + (pam_parse): conf_file is now ptr. + (pam_sm_open_session): Add parsing files from limits.d subdir using + glob, change pl to pointer. + 2007-03-12 Thorsten Kukuk <kukuk@thkukuk.de> * po/ar.po: New translation. @@ -3,9 +3,9 @@ Linux-PAM NEWS -- history of user-visible changes. Release X.XX.X.X -* Add translations for ar, ca, da, ru, sv and zu -* Update hungarian translation - +* Add translations for ar, ca, da, ru, sv and zu. +* Update hungarian translation. +* Add support for limits.d directory to pam_limits. Release 0.99.7.1 diff --git a/modules/pam_limits/Makefile.am b/modules/pam_limits/Makefile.am index be2852a9..60256a7c 100644 --- a/modules/pam_limits/Makefile.am +++ b/modules/pam_limits/Makefile.am @@ -13,8 +13,10 @@ TESTS = tst-pam_limits securelibdir = $(SECUREDIR) secureconfdir = $(SCONFIGDIR) +limits_conf_dir = $(SCONFIGDIR)/limits.d AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \ + -DLIMITS_FILE_DIR=\"$(limits_conf_dir)/*.conf\" \ -DLIMITS_FILE=\"$(SCONFIGDIR)/limits.conf\" AM_LDFLAGS = -no-undefined -avoid-version -module \ -L$(top_builddir)/libpam -lpam @@ -32,3 +34,5 @@ README: pam_limits.8.xml limits.conf.5.xml -include $(top_srcdir)/Make.xml.rules endif +install-data-local: + mkdir -p $(DESTDIR)$(limits_conf_dir) diff --git a/modules/pam_limits/pam_limits.8.xml b/modules/pam_limits/pam_limits.8.xml index 78060a20..9f13bb68 100644 --- a/modules/pam_limits/pam_limits.8.xml +++ b/modules/pam_limits/pam_limits.8.xml @@ -47,7 +47,15 @@ </para> <para> By default limits are taken from the <filename>/etc/security/limits.conf</filename> - config file. + config file. Then individual files from the <filename>/etc/security/limits.d/</filename> + directory are read. The files are parsed one after another in the order of "C" locale. + The effect of the individual files is the same as if all the files were + concatenated together in the order of parsing. + If a config file is explicitely specified with a module option then the + files in the above directory are not parsed. + </para> + <para> + The module must not be called by a multithreaded application. </para> </refsect1> diff --git a/modules/pam_limits/pam_limits.c b/modules/pam_limits/pam_limits.c index 20aa794a..f9a91164 100644 --- a/modules/pam_limits/pam_limits.c +++ b/modules/pam_limits/pam_limits.c @@ -31,7 +31,7 @@ #include <sys/stat.h> #include <sys/resource.h> #include <limits.h> - +#include <glob.h> #include <utmp.h> #ifndef UT_USER /* some systems have ut_name instead of ut_user */ #define UT_USER ut_user @@ -75,7 +75,7 @@ struct pam_limit_s { specific user or to count all logins */ int priority; /* the priority to run user process with */ struct user_limits_struct limits[RLIM_NLIMITS]; - char conf_file[BUFSIZ]; + const char *conf_file; int utmp_after_pam_call; char login_group[LINE_LENGTH]; }; @@ -101,6 +101,11 @@ struct pam_limit_s { #define PAM_DO_SETREUID 0x0002 #define PAM_UTMP_EARLY 0x0004 +/* Limits from globbed files. */ +#define LIMITS_CONF_GLOB LIMITS_FILE_DIR + +#define CONF_FILE (pl->conf_file != NULL)?pl->conf_file:LIMITS_FILE + static int _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, struct pam_limit_s *pl) @@ -115,7 +120,7 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, if (!strcmp(*argv,"debug")) { ctrl |= PAM_DEBUG_ARG; } else if (!strncmp(*argv,"conf=",5)) { - strncpy(pl->conf_file,*argv+5,sizeof(pl->conf_file)-1); + pl->conf_file = *argv+5; } else if (!strncmp(*argv,"change_uid",10)) { ctrl |= PAM_DO_SETREUID; } else if (!strcmp(*argv,"utmp_early")) { @@ -124,7 +129,6 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv, pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv); } } - pl->conf_file[sizeof(pl->conf_file) - 1] = '\0'; return ctrl; } @@ -434,7 +438,6 @@ static int parse_config_file(pam_handle_t *pamh, const char *uname, int ctrl, FILE *fil; char buf[LINE_LENGTH]; -#define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE /* check for the LIMITS_FILE */ if (ctrl & PAM_DEBUG_ARG) pam_syslog(pamh, LOG_DEBUG, "reading settings from '%s'", CONF_FILE); @@ -444,7 +447,6 @@ static int parse_config_file(pam_handle_t *pamh, const char *uname, int ctrl, "cannot read settings from %s: %m", CONF_FILE); return PAM_SERVICE_ERR; } -#undef CONF_FILE /* init things */ memset(buf, 0, sizeof(buf)); @@ -599,16 +601,22 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, int argc, const char **argv) { int retval; + int i; + int glob_rc; char *user_name; struct passwd *pwd; int ctrl; - struct pam_limit_s pl; + struct pam_limit_s plstruct; + struct pam_limit_s *pl = &plstruct; + glob_t globbuf; + const char *oldlocale; D(("called.")); - memset(&pl, 0, sizeof(pl)); + memset(pl, 0, sizeof(*pl)); + memset(&globbuf, 0, sizeof(globbuf)); - ctrl = _pam_parse(pamh, argc, argv, &pl); + ctrl = _pam_parse(pamh, argc, argv, pl); retval = pam_get_item( pamh, PAM_USER, (void*) &user_name ); if ( user_name == NULL || retval != PAM_SUCCESS ) { pam_syslog(pamh, LOG_CRIT, "open_session - error recovering username"); @@ -623,26 +631,60 @@ pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED, return PAM_USER_UNKNOWN; } - retval = init_limits(&pl); + retval = init_limits(pl); if (retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_WARNING, "cannot initialize"); return PAM_ABORT; } - retval = parse_config_file(pamh, pwd->pw_name, ctrl, &pl); + retval = parse_config_file(pamh, pwd->pw_name, ctrl, pl); if (retval == PAM_IGNORE) { - D(("the configuration file has an applicable '<domain> -' entry")); + D(("the configuration file ('%s') has an applicable '<domain> -' entry", CONF_FILE)); return PAM_SUCCESS; } - if (retval != PAM_SUCCESS) { - pam_syslog(pamh, LOG_WARNING, "error parsing the configuration file"); - return retval; + if (retval != PAM_SUCCESS || pl->conf_file != NULL) + /* skip reading limits.d if config file explicitely specified */ + goto out; + + /* Read subsequent *.conf files, if they exist. */ + + /* set the LC_COLLATE so the sorting order doesn't depend + on system locale */ + + oldlocale = setlocale(LC_COLLATE, "C"); + glob_rc = glob(LIMITS_CONF_GLOB, GLOB_ERR, NULL, &globbuf); + + if (oldlocale != NULL) + setlocale (LC_COLLATE, oldlocale); + + if (!glob_rc) { + /* 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); + if (retval == PAM_IGNORE) { + D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file)); + globfree(&globbuf); + return PAM_SUCCESS; + } + if (retval != PAM_SUCCESS) + goto out; + } + } + +out: + globfree(&globbuf); + if (retval != PAM_SUCCESS) + { + pam_syslog(pamh, LOG_WARNING, "error parsing the configuration file: '%s' ",CONF_FILE); + return retval; } if (ctrl & PAM_DO_SETREUID) { setreuid(pwd->pw_uid, -1); } - retval = setup_limits(pamh, pwd->pw_name, pwd->pw_uid, ctrl, &pl); + + retval = setup_limits(pamh, pwd->pw_name, pwd->pw_uid, ctrl, pl); if (retval & LOGIN_ERR) pam_error(pamh, _("Too many logins for '%s'."), pwd->pw_name); if (retval != LIMITED_OK) { |