diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-08-15 22:22:31 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-08-15 22:22:31 +0300 |
commit | 7a40b7873bd666809183cdd952d6e2a8f1870981 (patch) | |
tree | 0ae71532dc78f597b717152b564d6681d1ad832a /lib/transform.c | |
parent | 988b8e27f5df26d7e9f6fd7984677873ca1c40cb (diff) | |
download | pam-modules-7a40b7873bd666809183cdd952d6e2a8f1870981.tar.gz pam-modules-7a40b7873bd666809183cdd952d6e2a8f1870981.tar.bz2 |
Major cleanup
* lib/graypam.h (gray_pam_init)
(gray_raise,gray_malloc,gray_zalloc,gray_calloc)
(gray_realloc,gray_strdup): Remove.
(gray_slist_err,gray_slist_clrerr): New functions.
(gray_slist_append,gray_slist_append_char): Return ssize_t.
(gray_slist_coalesce): Likewise.
(gray_slist_grow_backslash_num)
(gray_slist_grow_backslash): Return int.
(errno_to_pam): New function.
(gray_set_transform_expr): Return int.
* lib/mem.c (gray_raise,gray_malloc,gray_zalloc,gray_calloc)
(gray_realloc,gray_strdup): Remove.
(gray_2nrealloc): Rewrite.
* lib/base64.c: Check return from gray_slist_append_char
* lib/env.c: Check return values from gray_slist functions
* lib/ldappass.c: Likewise.
* lib/slist.c (gray_slist_bucket) <ec>: New member.
(gray_slist_err,gray_slist_clrerr): New functions.
(gray_slist_append,gray_slist_append_char): Return ssize_t.
(gray_slist_coalesce): Likewise.
(gray_slist_grow_backslash_num)
(gray_slist_grow_backslash): Return int.
* lib/transform.c: Use standard memory allocation functions.
* pam_ldaphome/pam_ldaphome.c: Likewise.
* pam_innetgr/pam_innetgr.c: Likewise.
* pam_log/pam_log.c: Likewise.
* pam_regex/pam_regex.c: Likewise.
* pam_sql/pam_mysql.c: Likewise.
* pam_sql/pam_pgsql.c: Likewise.
Diffstat (limited to 'lib/transform.c')
-rw-r--r-- | lib/transform.c | 244 |
1 files changed, 185 insertions, 59 deletions
diff --git a/lib/transform.c b/lib/transform.c index 36972f0..c8ed54d 100644 --- a/lib/transform.c +++ b/lib/transform.c @@ -63,23 +63,42 @@ struct transform unsigned match_number; regex_t regex; int has_regex; + int error; /* Compiled replacement expression */ struct replace_segm *repl_head, *repl_tail; size_t segm_count; /* Number of elements in the above list */ }; +static inline int +transform_err(struct transform *tf) +{ + return tf->error; +} + +static void +transform_seterr (struct transform *tf, int ec) +{ + errno_to_pam (errno); + tf->error = ec; +} + static struct transform *transform_head, *transform_tail; +static char *case_ctl_buffer; +static size_t case_ctl_bufsize; static struct transform * -new_transform () +new_transform (void) { - struct transform *p = gray_zalloc (sizeof *p); - if (transform_tail) - transform_tail->next = p; - else - transform_head = p; - transform_tail = p; + struct transform *p = calloc (1, sizeof *p); + if (p) + { + if (transform_tail) + transform_tail->next = p; + else + transform_head = p; + transform_tail = p; + } return p; } @@ -102,14 +121,19 @@ free_transform (struct transform *tr) static struct replace_segm * add_segment (struct transform *tf) { - struct replace_segm *segm = gray_malloc (sizeof *segm); - segm->next = NULL; - if (tf->repl_tail) - tf->repl_tail->next = segm; + struct replace_segm *segm = malloc (sizeof *segm); + if (segm) + { + segm->next = NULL; + if (tf->repl_tail) + tf->repl_tail->next = segm; + else + tf->repl_head = segm; + tf->repl_tail = segm; + tf->segm_count++; + } else - tf->repl_head = segm; - tf->repl_tail = segm; - tf->segm_count++; + transform_seterr (tf, errno_to_pam (errno)); return segm; } @@ -122,17 +146,25 @@ free_segment (struct replace_segm *segm) } static void -add_literal_segment (struct transform *tf, char *str, char *end) +add_literal_segment (struct transform *tf, char const *str, char const *end) { size_t len = end - str; if (len) { struct replace_segm *segm = add_segment (tf); - segm->type = segm_literal; - segm->v.literal.ptr = gray_malloc (len + 1); - memcpy (segm->v.literal.ptr, str, len); - segm->v.literal.ptr[len] = 0; - segm->v.literal.size = len; + if (segm) + { + segm->type = segm_literal; + segm->v.literal.ptr = malloc (len + 1); + if (segm->v.literal.ptr) + { + memcpy (segm->v.literal.ptr, str, len); + segm->v.literal.ptr[len] = 0; + segm->v.literal.size = len; + } + else + transform_seterr (tf, errno_to_pam (errno)); + } } } @@ -140,41 +172,61 @@ static void add_char_segment (struct transform *tf, int chr) { struct replace_segm *segm = add_segment (tf); - segm->type = segm_literal; - segm->v.literal.ptr = gray_malloc (2); - segm->v.literal.ptr[0] = chr; - segm->v.literal.ptr[1] = 0; - segm->v.literal.size = 1; + if (segm) + { + segm->type = segm_literal; + segm->v.literal.ptr = malloc (2); + if (segm->v.literal.ptr) + { + segm->v.literal.ptr[0] = chr; + segm->v.literal.ptr[1] = 0; + segm->v.literal.size = 1; + } + else + transform_seterr (tf, errno_to_pam (errno)); + } } static void add_backref_segment (struct transform *tf, size_t ref) { struct replace_segm *segm = add_segment (tf); - segm->type = segm_backref; - segm->v.ref = ref; + if (segm) + { + segm->type = segm_backref; + segm->v.ref = ref; + } } static void add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl) { struct replace_segm *segm = add_segment (tf); - segm->type = segm_case_ctl; - segm->v.ctl = ctl; + if (segm) + { + segm->type = segm_case_ctl; + segm->v.ctl = ctl; + } } -static const char * -parse_transform_expr (const char *expr) +static int +parse_transform_expr (const char *expr, const char **endp) { int delim; int i, j, rc; - char *str, *beg, *cur; + char *str; + const char *beg; + const char *cur; const char *p; int cflags = 0; struct transform *tf = new_transform (); if (expr[0] != 's') - gray_raise ("Invalid transform expression"); + { + _pam_log(LOG_ERR, "invalid transform expression"); + *endp = expr; + return PAM_SERVICE_ERR; + } delim = expr[1]; @@ -184,7 +236,11 @@ parse_transform_expr (const char *expr) i++; if (expr[i] != delim) - gray_raise ("Invalid transform expression"); + { + _pam_log(LOG_ERR, "invalid transform expression"); + *endp = expr + i; + return PAM_SERVICE_ERR; + } /* Scan replacement expression */ for (j = i + 1; expr[j] && expr[j] != delim; j++) @@ -192,7 +248,11 @@ parse_transform_expr (const char *expr) j++; if (expr[j] != delim) - gray_raise ("Invalid transform expression"); + { + _pam_log(LOG_ERR, "invalid transform expression"); + *endp = expr + j; + return PAM_SERVICE_ERR; + } /* Check flags */ tf->transform_type = transform_first; @@ -218,14 +278,21 @@ parse_transform_expr (const char *expr) break; default: - gray_raise("Unknown flag in transform expression: %c", *p); + _pam_log(LOG_ERR, "unknown flag in transform expression: %c", *p); + *endp = p; + return PAM_SERVICE_ERR; } if (*p == ';') p++; /* Extract and compile regex */ - str = gray_malloc (i - 1); + str = malloc (i - 1); + if (!str) + { + *endp = p; + return errno_to_pam (errno); + } memcpy (str, expr + 2, i - 2); str[i - 2] = 0; @@ -235,7 +302,10 @@ parse_transform_expr (const char *expr) { char errbuf[512]; regerror (rc, &tf->regex, errbuf, sizeof (errbuf)); - gray_raise("Invalid transform expression: %s", errbuf); + _pam_log(LOG_ERR, "invalid transform expression: %s", errbuf); + free (str); + *endp = p; + return PAM_SERVICE_ERR; } tf->has_regex = 1; if (str[0] == '^' || str[strlen (str) - 1] == '$') @@ -245,12 +315,25 @@ parse_transform_expr (const char *expr) /* Extract and compile replacement expr */ i++; - str = gray_malloc (j - i + 1); + str = malloc (j - i + 1); + if (!str) + { + *endp = p; + return errno_to_pam (errno); + } + memcpy (str, expr + i, j - i); str[j - i] = 0; for (cur = beg = str; *cur;) { + if (transform_err (tf)) + { + *endp = expr + i + (beg - str); + free (str); + return transform_err (tf); + } + if (*cur == '\\') { size_t n; @@ -260,11 +343,16 @@ parse_transform_expr (const char *expr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - n = strtoul (cur, &cur, 10); + n = strtoul (cur, (char**)&cur, 10); if (n > tf->regex.re_nsub) - gray_raise ("Invalid transform replacement: " - "back reference out of range"); - add_backref_segment (tf, n); + { + _pam_log(LOG_ERR, + "invalid transform replacement: " + "back reference out of range"); + transform_seterr (tf, PAM_SERVICE_ERR); + } + else + add_backref_segment (tf, n); break; case '\\': @@ -367,19 +455,33 @@ parse_transform_expr (const char *expr) cur++; } add_literal_segment (tf, beg, cur); - - return p; + if (transform_err (tf)) + { + *endp = expr + i + (beg - str); + free (str); + return transform_err (tf); + } + *endp = p; + return 0; } -void +int gray_set_transform_expr (const char *expr) { while (*expr) - expr = parse_transform_expr (expr); + { + int rc = parse_transform_expr (expr, &expr); + if (rc != PAM_SUCCESS) + { + gray_free_transform_expr (); + return rc; + } + } + return PAM_SUCCESS; } void -gray_free_transform_expr () +gray_free_transform_expr (void) { while (transform_head) { @@ -388,6 +490,9 @@ gray_free_transform_expr () transform_head = next; } transform_tail = NULL; + free (case_ctl_buffer); + case_ctl_buffer = NULL; + case_ctl_bufsize = 0; } /* Run case conversion specified by CASE_CTL on array PTR of SIZE @@ -395,14 +500,15 @@ gray_free_transform_expr () static char * run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size) { - static char *case_ctl_buffer; - static size_t case_ctl_bufsize; char *p; if (case_ctl_bufsize < size) { + p = realloc (case_ctl_buffer, size); + if (!p) + return NULL; + case_ctl_buffer = p; case_ctl_bufsize = size; - case_ctl_buffer = gray_realloc (case_ctl_buffer, case_ctl_bufsize); } memcpy (case_ctl_buffer, ptr, size); switch (case_ctl) @@ -432,7 +538,7 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size) } -void +static int _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist, char *input) { @@ -450,8 +556,9 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist, save_ctl = ctl_stop; \ } - rmp = gray_malloc ((tf->regex.re_nsub + 1) * sizeof (*rmp)); - + rmp = malloc ((tf->regex.re_nsub + 1) * sizeof (*rmp)); + if (!rmp) + return errno; while (*input) { size_t disp; @@ -488,6 +595,8 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist, ptr = run_case_conv (case_ctl, segm->v.literal.ptr, segm->v.literal.size); + if (!ptr) + return errno; CASE_CTL_RESET(); } gray_slist_append (slist, ptr, segm->v.literal.size); @@ -503,6 +612,8 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist, if (case_ctl != ctl_stop) { ptr = run_case_conv (case_ctl, ptr, size); + if (!ptr) + return errno; CASE_CTL_RESET(); } @@ -551,20 +662,35 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist, gray_slist_append_char (slist, 0); free (rmp); + return gray_slist_err (slist); } int gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output) { - struct transform *tf; - - for (tf = transform_head; tf; tf = tf->next) + if (transform_head) + { + struct transform *tf; + for (tf = transform_head; tf; tf = tf->next) + { + int rc = _single_transform_name_to_slist (tf, slist, input); + if (rc) + return errno_to_pam(rc); + input = gray_slist_finish (slist); + if (!input) + return errno_to_pam(errno); + } + } + else { - _single_transform_name_to_slist (tf, slist, input); + gray_slist_append(slist, input, strlen(input) + 1); input = gray_slist_finish (slist); + if (!input) + return errno_to_pam(errno); } *output = input; - return transform_head != NULL; + + return PAM_SUCCESS; } |