here's my patch. sorry it's large because i think that per-user umask should be optional, so i've done most of the work to make that happen... now you have to specify "user" as an argument to pam_umask.so... as it happens it has to be the first argument, because arguments are processed left-to-right.
in theory i really think it should be user=~/.pam_umask or somethign like that (so that different pam configurations can use different umasks) but really i think this is total feeping creaturism. personally i'd do without the per-user stuff entirely... but at least this patch makes it stop segfaulting. -dean diff -ru pam-umask-0.02/README pam-umask-0.02.dg1/README --- pam-umask-0.02/README 2005-07-17 06:26:31.000000000 -0700 +++ pam-umask-0.02.dg1/README 2005-07-18 16:02:36.214696259 -0700 @@ -12,14 +12,22 @@ session optional pam_umask.so umask=002 -to the services where you want to set the umask to 002 +to the services where you want to set the umask to 002. (For example +in /etc/pam.d/common-session.) Note that using "optional" instead of "required" will allow users to login even if pam_umask fails to parse the umask line. Using "required" will deny login if an error occurs while setting the umask, which is clearly a non-desireable situation. -The module also supports per-user umasks. If a user has a .pam_umask -in his home directory, the contents will be used to set the umask. -Note that strtol is used for parsing, so making sure to have a leading -zero (like 022 or 002) is recommended. +The module also supports per-user umasks. To enable per-user umasks +use a line like so: + +session optional pam_umask.so user umask=002 + +In this case, if a user has a .pam_umask in his home directory, the +contents will be used to set the umask. Note that strtol is used +for parsing, so making sure to have a leading zero (like 022 or 002) +is recommended. Otherwise the "umask=002" argument will be used. + +(Note that the ordering of arguments is important.) diff -ru pam-umask-0.02/pam_umask.c pam-umask-0.02.dg1/pam_umask.c --- pam-umask-0.02/pam_umask.c 2005-07-17 06:34:53.000000000 -0700 +++ pam-umask-0.02.dg1/pam_umask.c 2005-07-18 15:56:04.955805118 -0700 @@ -48,54 +48,17 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) { - const char **user; - int ret; - struct passwd *puser; - FILE *umask_file; - char *umask_file_path, *user_umask; mode_t um; + int i; - ret = pam_get_item(pamh, PAM_USER, user); - if (ret != PAM_SUCCESS) { - _log_err(LOG_ERR, "Can't get user"); + if (argc == 0) { + _log_err(LOG_ERR, "at least one of \"umask=NNN\" or \"user\" must be supplied"); return PAM_SESSION_ERR; } - puser = getpwnam(*user); - if (!puser) { - _log_err(LOG_ERR, "User %s not found using getpwent", *user); - return PAM_SESSION_ERR; - } - _log_err(LOG_ERR, "User is %s", *user); - - umask_file_path = xmalloc(strlen(puser->pw_dir) + - strlen(PAM_UMASK_FILE_NAME) + - 1); - sprintf(umask_file_path, "%s/%s", puser->pw_dir, PAM_UMASK_FILE_NAME); - - umask_file = fopen(umask_file_path, "r"); - - if (umask_file != NULL) { - user_umask = freadline(umask_file); - um = strtol(user_umask, NULL, 0); - if (um == LONG_MIN || um == LONG_MAX) { - _log_err(LOG_ERR, "illegal umask specified for user: %s", puser->pw_name); - return PAM_SESSION_ERR; - } - fclose(umask_file); - umask(um); - return PAM_SUCCESS; - } - - _log_err(LOG_ERR, ".pam file not found", *user); - - - /* Ok, either no file, unreadable or something else. Ignore and go on with - the system umask. */ - - if (argc-- > 0) { - if (strncmp(argv[argc], "umask=", 6) == 0) { - um = strtol((argv[argc])+6, NULL, 0); + for (i = 0; i < argc; ++i) { + if (strncmp(argv[i], "umask=", 6) == 0) { + um = strtol((argv[i])+6, NULL, 0); if (um == LONG_MIN || um == LONG_MAX) { _log_err(LOG_ERR, "illegal umask specified"); return PAM_SESSION_ERR; @@ -103,8 +66,57 @@ umask(um); return PAM_SUCCESS; } + // TODO: this really should be user=~/.pam_umask ... so that different + // pam config files could specify different per-user umask files... but + // damn this is really feeping creaturism. + else if (strcmp(argv[i], "user") == 0) { + const void *v_user; + const char *user; + int ret; + struct passwd *puser; + FILE *umask_file; + char *umask_file_path, *user_umask; + + ret = pam_get_item(pamh, PAM_USER, &v_user); + if (ret != PAM_SUCCESS) { + _log_err(LOG_ERR, "Can't get user"); + return PAM_SESSION_ERR; + } + user = v_user; + + puser = getpwnam(user); + if (!puser) { + _log_err(LOG_ERR, "User %s not found using getpwent", user); + return PAM_SESSION_ERR; + } + + umask_file_path = xmalloc(strlen(puser->pw_dir) + + strlen(PAM_UMASK_FILE_NAME) + + 2); + sprintf(umask_file_path, "%s/%s", puser->pw_dir, PAM_UMASK_FILE_NAME); + umask_file = fopen(umask_file_path, "r"); + if (umask_file != NULL) { + user_umask = freadline(umask_file); + um = strtol(user_umask, NULL, 0); + if (um == LONG_MIN || um == LONG_MAX) { + _log_err(LOG_ERR, "illegal umask specified for user: %s", puser->pw_name); + return PAM_SESSION_ERR; + } + fclose(umask_file); + umask(um); + return PAM_SUCCESS; + } + if (errno != ENOENT) { + /* we'll log these errors, but we won't fail when they occur */ + _log_err(LOG_ERR, "error opening '%s' for reading: %s", umask_file_path, strerror(errno)); + } + } + else { + _log_err(LOG_ERR, "unrecognized argument"); + return PAM_SESSION_ERR; + } } - return PAM_SESSION_ERR; + return PAM_SUCCESS; } -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]