diff options
Diffstat (limited to 'pam_ldaphome/pam_ldaphome.c')
-rw-r--r-- | pam_ldaphome/pam_ldaphome.c | 262 |
1 files changed, 169 insertions, 93 deletions
diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c index dd3f9e3..0b492dd 100644 --- a/pam_ldaphome/pam_ldaphome.c +++ b/pam_ldaphome/pam_ldaphome.c @@ -179,3 +179,3 @@ get_intval(struct gray_env *env, const char *name, int base, unsigned long *pv) -char * +static char * parse_ldap_uri(const char *uri) @@ -724,9 +724,17 @@ check_groups(int gc, char **gv, const char *username, gid_t gid) char *pgname; + int rc = 1; gp = getgrgid(gid); - pgname = gp ? gray_strdup(gp->gr_name) : NULL; - for (i = 0; i < gc; i++) { + if (gp) { + pgname = strdup(gp->gr_name); + if (!pgname) { + errno_to_pam(errno); + return -1; + } + } else + gp = NULL; + for (i = 0; rc && i < gc; i++) { if (strcmp(gv[i], pgname) == 0) { - free(pgname); - return 0; + rc = 0; + break; } @@ -735,6 +743,6 @@ check_groups(int gc, char **gv, const char *username, gid_t gid) char **p; - for (p = gp->gr_mem; *p; p++) + for (p = gp->gr_mem; *p; p++) { if (strcmp(username, *p) == 0) { - free(pgname); - return 0; + rc = 0; + break; } @@ -742,3 +750,5 @@ check_groups(int gc, char **gv, const char *username, gid_t gid) } - return 1; + } + free(pgname); + return rc; } @@ -858,32 +868,20 @@ copy_file(pam_handle_t *pamh, const char *src, const char *dst, -#define INITIAL_READLINK_SIZE 128 - -int -read_link_name(const char *name, char **pbuf, size_t *psize, size_t *plen) +static int +read_link_name(const char *name, char **pbuf) { int rc = 0; - char *buf = *pbuf; - size_t size = *psize; - ssize_t linklen; + char *buf = NULL; + size_t size = 0; + ssize_t linklen = 0; while (1) { - if (!buf) { - size = INITIAL_READLINK_SIZE; - buf = malloc(size); - } else { - char *p; - size_t newsize = size << 1; - if (newsize < size) { - rc = ENAMETOOLONG; + if (linklen == size) { + char *p = gray_2nrealloc(&buf, &size, 1); + if (!p) { + errno_to_pam(errno); + rc = 1; break; } - size = newsize; - p = realloc(buf, size); - if (!p) - free(buf); buf = p; - } - if (!buf) { - rc = 1; - break; + linklen = size; } @@ -896,3 +894,3 @@ read_link_name(const char *name, char **pbuf, size_t *psize, size_t *plen) - if ((size_t) linklen < size) { + if (linklen < size) { buf[linklen++] = '\0'; @@ -908,8 +906,4 @@ read_link_name(const char *name, char **pbuf, size_t *psize, size_t *plen) } - size = 0; } *pbuf = buf; - *psize = size; - if (plen) - *plen = linklen; return rc; @@ -922,7 +916,6 @@ copy_link(pam_handle_t *pamh, const char *src, const char *dst, { - char *lnkname = NULL; - size_t lnklen = 0; + char *lnkname; int rc; - if (read_link_name(src, &lnkname, &lnklen, NULL)) { + if (read_link_name(src, &lnkname)) { _pam_log(LOG_ERR, "error reading link %s: %s", @@ -1001,3 +994,7 @@ create_interdir(const char *path, struct passwd *pw) len = p - path; - dir = gray_malloc(len + 1); + dir = malloc(len + 1); + if (!dir) { + errno_to_pam(errno); + return -1; + } memcpy(dir, path, len); @@ -1270,2 +1267,17 @@ struct pubkeyfile { +/* Close the public key file */ +static void +pubkeyfile_close(struct pubkeyfile *pkb) +{ + close(pkb->fd); + free(pkb->file_name); + free(pkb->base); + free(pkb->lnv); + + pkb->fd = -1; + pkb->file_name = NULL; + pkb->base = NULL; + pkb->lnv = NULL; +} + /* Open public key file NAME. Return 0 on success. On error, issue a @@ -1282,3 +1294,9 @@ pubkeyfile_open(struct pubkeyfile *pkb, char *name) } - pkb->file_name = gray_strdup(name); + pkb->file_name = strdup(name); + if (!pkb->file_name) { + int rc = errno_to_pam(errno); + close(pkb->fd); + pkb->fd = -1; + return rc; + } return 0; @@ -1300,3 +1318,7 @@ pubkeyfile_read(struct pubkeyfile *pkb) pkb->size = st.st_size; - pkb->base = gray_malloc(st.st_size + 1); + pkb->base = malloc(st.st_size + 1); + if (!pkb->base) { + errno_to_pam(errno); + return -1; + } if (full_read(pkb->fd, pkb->file_name, pkb->base, pkb->size)) { @@ -1312,4 +1334,7 @@ pubkeyfile_read(struct pubkeyfile *pkb) pkb->lnm = pkb->lnc + 1; - pkb->lnv = gray_calloc(pkb->lnm, sizeof(pkb->lnv[0])); - + pkb->lnv = calloc(pkb->lnm, sizeof(pkb->lnv[0])); + if (pkb->lnv) { + errno_to_pam(errno); + return -1; + } i = 0; @@ -1331,3 +1356,6 @@ pubkeyfile_init(struct pubkeyfile *pkb, char *name) return -1; - return pubkeyfile_read(pkb); + if (pubkeyfile_read(pkb) == 0) + return 0; + pubkeyfile_close(pkb); + return -1; } @@ -1390,3 +1418,3 @@ pubkeyfile_remove_lines(struct pubkeyfile *pkb, int pos, int count) the existing data. */ -static void +static int pubkeyfile_alloc_lines(struct pubkeyfile *pkb, size_t pos, size_t count) @@ -1396,8 +1424,12 @@ pubkeyfile_alloc_lines(struct pubkeyfile *pkb, size_t pos, size_t count) __FILE__, __LINE__); - abort(); + return PAM_SERVICE_ERR; } if (pkb->lnc + count + 1 > pkb->lnm) { - pkb->lnm += count; - pkb->lnv = gray_realloc(pkb->lnv, - pkb->lnm * sizeof(pkb->lnv[0])); + char **p; + size_t lnm = pkb->lnm + count; + p = realloc(pkb->lnv, lnm * sizeof(pkb->lnv[0])); + if (!p) + return errno_to_pam(errno); + pkb->lnv = p; + pkb->lnm = lnm; } @@ -1406,2 +1438,3 @@ pubkeyfile_alloc_lines(struct pubkeyfile *pkb, size_t pos, size_t count) pkb->lnc += count; + return PAM_SUCCESS; } @@ -1410,3 +1443,3 @@ pubkeyfile_alloc_lines(struct pubkeyfile *pkb, size_t pos, size_t count) existing lines as necessary. */ -void +static int pubkeyfile_insert_lines(struct pubkeyfile *pkb, size_t pos, char **lv) @@ -1415,2 +1448,3 @@ pubkeyfile_insert_lines(struct pubkeyfile *pkb, size_t pos, char **lv) size_t lc; + int rc; @@ -1419,4 +1453,4 @@ pubkeyfile_insert_lines(struct pubkeyfile *pkb, size_t pos, char **lv) - pubkeyfile_alloc_lines(pkb, pos, lc); - + rc = pubkeyfile_alloc_lines(pkb, pos, lc); + if (rc == 0) { for (i = 0; i < lc; i++) @@ -1424,14 +1458,5 @@ pubkeyfile_insert_lines(struct pubkeyfile *pkb, size_t pos, char **lv) } - -/* Close the public key file */ -void -pubkeyfile_close(struct pubkeyfile *pkb) -{ - close(pkb->fd); - free(pkb->file_name); - free(pkb->base); - free(pkb->lnv); + return rc; } - static int @@ -1453,3 +1478,5 @@ store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env) len++; - file_name = gray_malloc(len + 1); + file_name = malloc(len + 1); + if (!file_name) + return errno_to_pam(errno); memcpy(file_name, pw->pw_dir, homelen); @@ -1522,5 +1549,7 @@ store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env) pubkeyfile_remove_lines(&pkf, 0, i); - pubkeyfile_insert_lines(&pkf, 0, keys); + retval = pubkeyfile_insert_lines(&pkf, 0, keys); + if (retval == PAM_SUCCESS) { pubkeyfile_write(&pkf); retval = PAM_TRY_AGAIN; + } } else @@ -1562,5 +1591,7 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) gray_slist_t slist; - char **keys; slist = gray_slist_create(); + if (!slist) + retval = errno_to_pam(errno); + else { gray_expand_string(pamh, filter_pat, slist); @@ -1568,5 +1599,5 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) filter = gray_slist_finish(slist); - - keys = get_pubkeys(ld, base, filter, attr); - gray_slist_free(&slist); + if (filter) { + char **keys = get_pubkeys(ld, base, filter, + attr); if (keys) { @@ -1576,2 +1607,7 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) retval = PAM_SUCCESS; + } else { + retval = errno_to_pam(gray_slist_err(slist)); + } + gray_slist_free(&slist); + } } @@ -1696,2 +1732,8 @@ locate_unset(char **env, const char *name) +/* Concatenate NAMELEN bytes from NAME, "=", A, and B. Allocate the + result using malloc. + + On ENOMEM, log a diagnostic message and exit with code 127. This function + should be used from child process only. +*/ static char * @@ -1703,5 +1745,7 @@ env_concat(char *name, size_t namelen, char *a, char *b) if (a && b) { - res = gray_malloc(namelen + 1 + strlen(a) + strlen(b) + 1); + res = malloc(namelen + 1 + strlen(a) + strlen(b) + 1); + if (res) { strcpy(res + namelen + 1, a); strcat(res, b); + } } else if (a) { @@ -1710,5 +1754,7 @@ env_concat(char *name, size_t namelen, char *a, char *b) len--; - res = gray_malloc(namelen + 1 + len + 1); + res = malloc(namelen + 1 + len + 1); + if (res) { memcpy(res + namelen + 1, a, len); res[namelen + 1 + len] = 0; + } } else /* if (a == NULL) */ { @@ -1717,7 +1763,13 @@ env_concat(char *name, size_t namelen, char *a, char *b) len = strlen(b); - res = gray_malloc(namelen + 1 + len + 1); + res = malloc(namelen + 1 + len + 1); + if (res) strcpy(res + namelen + 1, b); } + if (res) { memcpy(res, name, namelen); res[namelen] = '='; + } else { + errno_to_pam(errno); + _exit(127); + } return res; @@ -1742,2 +1794,10 @@ parsenv(char *str) +# define ASSERT_NOTNULL(p) do { \ + if (!(p)) { \ + errno_to_pam(errno); \ + _exit(127); \ + } \ + } while (0) + + if (!str) @@ -1793,7 +1853,4 @@ parsenv(char *str) if (wi == wc) { - if (wc == 0) - wc = 4; - else - wc *= 2; - wv = gray_realloc(wv, wc * sizeof(wv[0])); + wv = gray_2nrealloc(wv, &wc, sizeof(wv[0])); + ASSERT_NOTNULL(wv); } @@ -1803,3 +1860,4 @@ parsenv(char *str) len -= 2; - wv[wi] = gray_malloc(len + 1); + wv[wi] = malloc(len + 1); + ASSERT_NOTNULL(wv[wi]); for (q = wv[wi]; *kw; ) { @@ -1814,3 +1872,4 @@ parsenv(char *str) len -= 2; - wv[wi] = gray_malloc(len + 1); + wv[wi] = malloc(len + 1); + ASSERT_NOTNULL(wv[wi]); q = wv[wi]; @@ -1829,3 +1888,4 @@ parsenv(char *str) default: - wv[wi] = gray_malloc(len + 1); + wv[wi] = malloc(len + 1); + ASSERT_NOTNULL(wv[wi]); memcpy(wv[wi], kw, len); @@ -1840,10 +1900,14 @@ parsenv(char *str) if (wc == wi) { - ++wc; - wv = gray_realloc(wv, (wc + 1) * sizeof(wv[0])); + wv = gray_2nrealloc(wv, &wc, sizeof(wv[0])); + ASSERT_NOTNULL(wv); } - wv[wi++] = gray_strdup(kw); + wv[wi] = strdup(kw); + ASSERT_NOTNULL(wv[wi]); + ++wi; } - if (wc == wi) - wv = gray_realloc(wv, (wc + 1) * sizeof(wv[0])); + if (wc == wi) { + wv = gray_2nrealloc(wv, &wc, sizeof(wv[0])); + ASSERT_NOTNULL(wv); + } wv[wi] = NULL; @@ -1853,2 +1917,5 @@ parsenv(char *str) +/* Setup environment for exec* family call. On ENOMEM, exit with code 127. + This function should be called from a child process. +*/ static char ** @@ -1881,4 +1948,7 @@ env_setup(char *envstr) /* Allocate the new environment. */ - new_env = gray_calloc(count + 1, sizeof new_env[0]); - + new_env = calloc(count + 1, sizeof new_env[0]); + if (!new_env) { + errno_to_pam(errno); + _exit(127); + } /* Populate the environment. */ @@ -1940,5 +2010,12 @@ runas(struct passwd *pw) if (strcmp (*p, pw->pw_name) == 0) { - if (sgc == sgm) - sgv = gray_2nrealloc(sgv, &sgm, + if (sgc == sgm) { + gid_t *p; + p = gray_2nrealloc(sgv, &sgm, sizeof(sgv[0])); + if (!p) { + errno_to_pam(errno); + return 1; //FIXME: proper error code + } + sgv = p; + } sgv[sgc++] = gr->gr_gid; @@ -2145,3 +2222,2 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv, DEBUG(90,("enter %s", func)); - gray_pam_init(PAM_AUTHINFO_UNAVAIL); if (gray_env_read(config_file_name, &env) == 0) { @@ -2150,3 +2226,3 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv, - if (val = gray_env_get(env, "ldap-config")) { + if ((val = gray_env_get(env, "ldap-config"))) { if (strcmp(val, "none") == 0) @@ -2164,3 +2240,3 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv, - if (val = gray_env_get(env, "authorized_keys")) + if ((val = gray_env_get(env, "authorized_keys"))) authorized_keys_file = val; |