diff options
author | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 15:43:05 -0800 |
---|---|---|
committer | Steve Langasek <steve.langasek@ubuntu.com> | 2019-01-03 15:44:43 -0800 |
commit | 9a4298687784e7812c8aeef6e0e97830febbf393 (patch) | |
tree | 45942549c91c2ae3cb6b58aa5df40b9e121f908a /Linux-PAM/modules/pam_limits/pam_limits.c | |
parent | d5b06b67bbeeed7c05c0eb2e05d6a972ad050d1c (diff) | |
parent | 9bc383eeb9d9f5976645cb4c4850a8d36b2bd7da (diff) | |
download | pam-9a4298687784e7812c8aeef6e0e97830febbf393.tar.gz pam-9a4298687784e7812c8aeef6e0e97830febbf393.tar.bz2 pam-9a4298687784e7812c8aeef6e0e97830febbf393.zip |
New upstream version 0.99.8.1
Diffstat (limited to 'Linux-PAM/modules/pam_limits/pam_limits.c')
-rw-r--r-- | Linux-PAM/modules/pam_limits/pam_limits.c | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/Linux-PAM/modules/pam_limits/pam_limits.c b/Linux-PAM/modules/pam_limits/pam_limits.c index 20aa794a..a4bc727f 100644 --- a/Linux-PAM/modules/pam_limits/pam_limits.c +++ b/Linux-PAM/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 @@ -39,6 +39,7 @@ #include <grp.h> #include <pwd.h> +#include <locale.h> /* Module defines */ #define LINE_LENGTH 1024 @@ -75,7 +76,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 +102,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 +121,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 +130,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; } @@ -370,8 +375,13 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, switch(limit_item) { case RLIMIT_CPU: - if (rlimit_value != RLIM_INFINITY) - rlimit_value *= 60; + if (rlimit_value != RLIM_INFINITY) + { + if (rlimit_value >= RLIM_INFINITY/60) + rlimit_value = RLIM_INFINITY; + else + rlimit_value *= 60; + } break; case RLIMIT_FSIZE: case RLIMIT_DATA: @@ -381,13 +391,20 @@ process_limit (const pam_handle_t *pamh, int source, const char *lim_type, case RLIMIT_MEMLOCK: case RLIMIT_AS: if (rlimit_value != RLIM_INFINITY) - rlimit_value *= 1024; + { + if (rlimit_value >= RLIM_INFINITY/1024) + rlimit_value = RLIM_INFINITY; + else + rlimit_value *= 1024; + } break; #ifdef RLIMIT_NICE case RLIMIT_NICE: if (int_value > 19) int_value = 19; - rlimit_value = 19 - int_value; + if (int_value < -20) + int_value = -20; + rlimit_value = 20 - int_value; #endif break; } @@ -434,7 +451,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 +460,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 +614,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 +644,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) { |