diff options
Diffstat (limited to 'modules/pam_unix')
-rw-r--r-- | modules/pam_unix/support.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/modules/pam_unix/support.c b/modules/pam_unix/support.c index 336742a1..5dd3b946 100644 --- a/modules/pam_unix/support.c +++ b/modules/pam_unix/support.c @@ -347,19 +347,20 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, int files, int nis, struct passwd **ret) { FILE *passwd; - char buf[16384]; + char *buf = NULL; int matched = 0; char *slogin, *spasswd, *suid, *sgid, *sgecos, *shome, *sshell, *p; size_t retlen, userlen; - memset(buf, 0, sizeof(buf)); - userlen = strlen(name); - if (!matched && files && userlen < sizeof(buf) && strchr(name, ':') == NULL) { + if (!matched && files && strchr(name, ':') == NULL) { passwd = fopen("/etc/passwd", "r"); if (passwd != NULL) { - while (fgets(buf, sizeof(buf), passwd) != NULL) { - if ((buf[userlen] == ':') && + size_t n = 0; + ssize_t r; + + while ((r = getline(&buf, &n, passwd)) != -1) { + if ((size_t)r > userlen && (buf[userlen] == ':') && (strncmp(name, buf, userlen) == 0)) { p = buf + strlen(buf) - 1; while (isspace((unsigned char)*p) && (p >= buf)) { @@ -369,6 +370,9 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, break; } } + if (!matched) { + _pam_drop(buf); + } fclose(passwd); } } @@ -385,9 +389,7 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, i = yp_match(domain, "passwd.byname", name, strlen(name), &userinfo, &len); yp_unbind(domain); - if ((i == YPERR_SUCCESS) && ((size_t)len < sizeof(buf))) { - strncpy(buf, userinfo, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; + if (i == YPERR_SUCCESS && (buf = strdup(userinfo)) != NULL) { matched = 1; } } @@ -470,7 +472,11 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, p += strlen(p) + 1; (*ret)->pw_shell = strcpy(p, sshell); - snprintf(buf, sizeof(buf), "_pam_unix_getpwnam_%s", name); + _pam_drop(buf); + if (asprintf(&buf, "_pam_unix_getpwnam_%s", name) < 0) { + buf = NULL; + goto fail; + } if (pam_set_data(pamh, buf, *ret, _unix_cleanup) != PAM_SUCCESS) { @@ -480,8 +486,8 @@ int _unix_getpwnam(pam_handle_t *pamh, const char *name, return matched; fail: - free(*ret); - *ret = NULL; + _pam_drop(buf); + _pam_drop(*ret); return matched; } |