From f6b973b922818f189bdb70924de0c6691cf9ffe4 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 29 Mar 2007 20:33:07 +0000 Subject: 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. --- modules/pam_limits/pam_limits.c | 74 ++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 16 deletions(-) (limited to 'modules/pam_limits/pam_limits.c') 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 #include #include - +#include #include #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 ' -' entry")); + D(("the configuration file ('%s') has an applicable ' -' 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 ' -' 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) { -- cgit v1.2.3