diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/base64.c | 20 | ||||
-rw-r--r-- | lib/env.c | 66 | ||||
-rw-r--r-- | lib/graypam.h | 50 | ||||
-rw-r--r-- | lib/ldappass.c | 107 | ||||
-rw-r--r-- | lib/mem.c | 81 | ||||
-rw-r--r-- | lib/slist.c | 127 | ||||
-rw-r--r-- | lib/transform.c | 244 |
7 files changed, 456 insertions, 239 deletions
diff --git a/lib/base64.c b/lib/base64.c index 85b974a..9d0191e 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -54,15 +54,21 @@ gray_base64_decode(gray_slist_t slist, const char *iptr, size_t isize) /* I have a entire block of data 32 bits get the output data. */ if (i == 4) { - gray_slist_append_char(slist, - (data[0] << 2) | ((data[1] & 0x30) >> 4)); - gray_slist_append_char(slist, - ((data[1] & 0xf) << 4) | ((data[2] & 0x3c) >> 2)); - gray_slist_append_char(slist, - ((data[2] & 0x3) << 6) | data[3]); + if (gray_slist_append_char(slist, + (data[0] << 2) | ((data[1] & 0x30) >> 4)) != 1) + return -1; + if (gray_slist_append_char(slist, + ((data[1] & 0xf) << 4) | ((data[2] & 0x3c) >> 2)) + != 1) + return -1; + if (gray_slist_append_char(slist, + ((data[2] & 0x3) << 6) | data[3]) != 1) + return -1; nbytes += 3 - pad; - } else + } else { + errno = EILSEQ; return -1; + } i = 0; } return nbytes; @@ -94,7 +94,7 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap) return 1; } - while (p = fgets(buf, sizeof buf, fp)) { + while ((p = fgets(buf, sizeof buf, fp))) { int len; struct gray_env *env; @@ -105,17 +105,28 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap) if (len == 0) continue; if (p[len-1] != '\n') { - if (!slist) + if (!slist) { slist = gray_slist_create(); - gray_slist_append(slist, p, len); - while (p = fgets(buf, sizeof buf, fp)) { + if (!slist) { + rc = errno; + break; + } + } + if (gray_slist_append(slist, p, len) != len) { + rc = errno; + break; + } + while ((p = fgets(buf, sizeof buf, fp))) { len = strlen(p); gray_slist_append(slist, p, len); if (p[len - 1] == '\n') break; } - gray_slist_append_char(slist, 0); - p = gray_slist_finish(slist); + if (gray_slist_append_char(slist, 0) != 1 + || (p = gray_slist_finish(slist)) == NULL) { + rc = errno; + break; + } len = strlen(p); } @@ -129,10 +140,19 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap) int err = 0; /* Collect continuation lines */ - if (!slist) + if (!slist) { slist = gray_slist_create(); + if (!slist) { + rc = errno; + break; + } + } do { - gray_slist_append(slist, p, len - 1); + if (gray_slist_append(slist, p, len - 1) + != len - 1) { + rc = errno; + break; + } p = fgets (buf, sizeof buf, fp); if (!p) break; @@ -150,26 +170,33 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap) p[len-1] = 0; len = gray_trim_ws(p); } while (p[len-1] == '\\'); - if (len) - gray_slist_append(slist, p, len); - gray_slist_append_char(slist, 0); - p = gray_slist_finish(slist); + if (rc) + break; + if (len) { + if (gray_slist_append(slist, p, len) != len) { + rc = errno; + break; + } + } + if (gray_slist_append_char(slist, 0) != 1 + || (p = gray_slist_finish(slist)) == NULL) { + rc = errno; + break; + } if (err) continue; } env = malloc(sizeof *env); if (!env) { - _pam_log(LOG_EMERG, "not enough memory"); - rc = 1; + rc = errno; break; } env->name = strdup(p); if (!env->name) { - _pam_log(LOG_EMERG, "not enough memory"); + rc = errno; free(env); - rc = 1; break; } @@ -195,7 +222,12 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap) gray_slist_free(&slist); fclose(fp); - *penv = config_env; + if (rc) { + _pam_log(LOG_EMERG, "%s", strerror(rc)); + gray_env_free(config_env); + } else { + *penv = config_env; + } return rc; } diff --git a/lib/graypam.h b/lib/graypam.h index 76dcd68..69c4909 100644 --- a/lib/graypam.h +++ b/lib/graypam.h @@ -84,40 +84,30 @@ extern jmp_buf gray_pam_jmp; -#define gray_pam_init(retval) \ - if (setjmp(gray_pam_jmp)) \ - return retval; \ - -void gray_raise(const char *fmt, ...); - -void *gray_malloc(size_t size); -void *gray_zalloc(size_t size); -void *gray_calloc(size_t count, size_t size); -void *gray_realloc(void *ptr, size_t size); void *gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz); -char *gray_strdup(const char *str); void gray_pam_delete(char *x); void gray_cleanup_string(pam_handle_t *pamh, void *x, int error_status); void gray_cleanup_regex(pam_handle_t *pamh, void *x, int error_status); void gray_make_str(pam_handle_t *pamh, const char *str, const char *name, char **ret); - typedef struct gray_slist *gray_slist_t; -gray_slist_t gray_slist_create(); +gray_slist_t gray_slist_create(void); +int gray_slist_err(gray_slist_t slist); +void gray_slist_clrerr(gray_slist_t slist); void gray_slist_clear(gray_slist_t slist); void gray_slist_free(gray_slist_t *slist); -void gray_slist_append(gray_slist_t slist, const char *str, size_t n); -void gray_slist_append_char(gray_slist_t slist, char c); +ssize_t gray_slist_append(gray_slist_t slist, const char *str, size_t n); +ssize_t gray_slist_append_char(gray_slist_t slist, char c); size_t gray_slist_size(gray_slist_t slist); -size_t gray_slist_coalesce(gray_slist_t slist); +ssize_t gray_slist_coalesce(gray_slist_t slist); void *gray_slist_head(gray_slist_t slist, size_t *psize); void *gray_slist_finish(gray_slist_t slist); -void gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend, - int len, int base); -void gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp); +int gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend, + int len, int base); +int gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp); void gray_log_init(int dont_open, const char *tag, int f); @@ -129,10 +119,28 @@ void gray_wait_debug(size_t interval, const char *file, size_t line); #define _pam_vlog gray_pam_vlog #define _pam_log gray_pam_log #define _pam_debug gray_pam_debug - + +static inline int +errno_to_pam(int ec) +{ + switch (ec) { + case EILSEQ: + _pam_log(LOG_ERR, "malformed password hash"); + return PAM_SERVICE_ERR; + + case ENOMEM: + _pam_log(LOG_ERR, "%s", strerror(errno)); + return PAM_BUF_ERR; + + default: + break; + } + _pam_log(LOG_ERR, "%s", strerror(errno)); + return PAM_SERVICE_ERR; +} int gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output); -void gray_set_transform_expr (const char *expr); +int gray_set_transform_expr (const char *expr); void gray_free_transform_expr (void); diff --git a/lib/ldappass.c b/lib/ldappass.c index 968078c..247cf16 100644 --- a/lib/ldappass.c +++ b/lib/ldappass.c @@ -48,10 +48,14 @@ chk_md5 (const char *db_pass, const char *pass) { unsigned char md5digest[16]; struct gpam_md5_ctx md5context; - gray_slist_t slist = gray_slist_create (); + gray_slist_t slist; ssize_t size; char *p; int rc; + + slist = gray_slist_create (); + if (!slist) + return errno_to_pam(errno); gpam_md5_init_ctx (&md5context); gpam_md5_process_bytes (pass, strlen (pass), &md5context); @@ -60,12 +64,21 @@ chk_md5 (const char *db_pass, const char *pass) size = gray_base64_decode(slist, db_pass, strlen (db_pass)); if (size != 16) { + rc = errno_to_pam(errno); gray_slist_free(&slist); - return PAM_AUTH_ERR; + return rc; } p = gray_slist_finish(slist); - rc = memcmp (md5digest, p, sizeof md5digest) == 0 ? - PAM_SUCCESS : PAM_AUTH_ERR; + if (p) + { + rc = memcmp (md5digest, p, sizeof md5digest) == 0 + ? PAM_SUCCESS + : PAM_AUTH_ERR; + } + else + { + rc = errno_to_pam(errno); + } gray_slist_free(&slist); return rc; } @@ -77,26 +90,38 @@ chk_smd5 (const char *db_pass, const char *pass) unsigned char md5digest[16]; unsigned char *d1; struct gpam_md5_ctx md5context; - gray_slist_t slist = gray_slist_create(); + gray_slist_t slist; ssize_t size; + slist = gray_slist_create(); + if (!slist) + return errno_to_pam(errno); + size = gray_base64_decode(slist, db_pass, strlen (db_pass)); if (size <= 16) { - _pam_log(LOG_ERR, "malformed SMD5 password: %s", db_pass); + rc = errno_to_pam(errno); gray_slist_free(&slist); - return PAM_AUTH_ERR; + return rc; } d1 = gray_slist_finish(slist); - - gpam_md5_init_ctx (&md5context); - gpam_md5_process_bytes (pass, strlen (pass), &md5context); - gpam_md5_process_bytes (d1 + 16, size - 16, &md5context); - gpam_md5_finish_ctx (&md5context, md5digest); + if (d1) + { + gpam_md5_init_ctx (&md5context); + gpam_md5_process_bytes (pass, strlen (pass), &md5context); + gpam_md5_process_bytes (d1 + 16, size - 16, &md5context); + gpam_md5_finish_ctx (&md5context, md5digest); - rc = memcmp (md5digest, d1, sizeof md5digest) == 0 ? - PAM_SUCCESS : PAM_AUTH_ERR; + rc = memcmp (md5digest, d1, sizeof md5digest) == 0 + ? PAM_SUCCESS + : PAM_AUTH_ERR; + } + else + { + rc = errno_to_pam(gray_slist_err(slist)); + } + gray_slist_free(&slist); return rc; } @@ -108,9 +133,13 @@ chk_sha (const char *db_pass, const char *pass) unsigned char sha1digest[20]; unsigned char *d1; struct gpam_sha1_ctx sha1context; - gray_slist_t slist = gray_slist_create(); + gray_slist_t slist; ssize_t size; - + + slist = gray_slist_create(); + if (!slist) + return errno_to_pam(errno); + gpam_sha1_init_ctx (&sha1context); gpam_sha1_process_bytes (pass, strlen (pass), &sha1context); gpam_sha1_finish_ctx (&sha1context, sha1digest); @@ -118,13 +147,22 @@ chk_sha (const char *db_pass, const char *pass) size = gray_base64_decode(slist, db_pass, strlen (db_pass)); if (size != 20) { + rc = errno_to_pam(errno); gray_slist_free(&slist); - return 1; + return rc; } d1 = gray_slist_finish(slist); - rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ? - PAM_SUCCESS : PAM_AUTH_ERR; + if (d1) + { + rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 + ? PAM_SUCCESS + : PAM_AUTH_ERR; + } + else + { + rc = errno_to_pam(errno); + } gray_slist_free(&slist); return rc; } @@ -136,25 +174,36 @@ chk_ssha (const char *db_pass, const char *pass) unsigned char sha1digest[20]; unsigned char *d1; struct gpam_sha1_ctx sha1context; - gray_slist_t slist = gray_slist_create(); + gray_slist_t slist; ssize_t size; + slist = gray_slist_create(); + if (!slist) + return errno_to_pam(errno); + size = gray_base64_decode(slist, db_pass, strlen (db_pass)); if (size <= 16) { - _pam_log (LOG_ERR, "malformed SSHA1 password: %s", db_pass); + rc = errno_to_pam(errno); gray_slist_free(&slist); - return 1; + return rc; } d1 = gray_slist_finish(slist); - - gpam_sha1_init_ctx (&sha1context); - gpam_sha1_process_bytes (pass, strlen (pass), &sha1context); - gpam_sha1_process_bytes (d1 + 20, size - 20, &sha1context); - gpam_sha1_finish_ctx (&sha1context, sha1digest); + if (d1) + { + gpam_sha1_init_ctx (&sha1context); + gpam_sha1_process_bytes (pass, strlen (pass), &sha1context); + gpam_sha1_process_bytes (d1 + 20, size - 20, &sha1context); + gpam_sha1_finish_ctx (&sha1context, sha1digest); - rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ? - PAM_SUCCESS : PAM_AUTH_ERR; + rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 + ? PAM_SUCCESS + : PAM_AUTH_ERR; + } + else + { + rc = errno_to_pam(errno); + } gray_slist_free(&slist); return rc; } @@ -16,81 +16,28 @@ #include <graypam.h> -jmp_buf gray_pam_jmp; - -void -gray_raise(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - _pam_vlog(LOG_ERR, fmt, ap); - va_end(ap); - longjmp(gray_pam_jmp, 1); -} - -void * -gray_malloc(size_t size) -{ - void *p = malloc(size); - if (!p) - gray_raise("Not enough memory"); - return p; -} - -void * -gray_zalloc(size_t size) -{ - void *p = malloc(size); - if (!p) - gray_raise("Not enough memory"); - memset(p, 0, size); - return p; -} - -void * -gray_calloc(size_t count, size_t size) -{ - return gray_zalloc(count * size); -} - -void * -gray_realloc(void *ptr, size_t size) -{ - ptr = realloc(ptr, size); - if (!ptr) - gray_raise("Not enough memory"); - return ptr; -} - void * gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz) { size_t count = *pcount; if (!ptr) { - if (!count) - count = *pcount = 16; - return gray_calloc(count, elsiz); + if (!count) { + count = 64 / elsiz; + count += !count; + } + } else { + if ((size_t)-1 / 2 / elsiz <= count) { + errno = ENOMEM; + return NULL; + } + count += (count + 1) / 2; } - if ((size_t)-1 / 2 / elsiz <= count) - gray_raise("Not enough memory"); - count *= 2; - *pcount = count; - return gray_realloc(ptr, count * elsiz); -} - - -char * -gray_strdup(const char *str) -{ - char *p; - - if (!str) - return NULL; - p = gray_malloc(strlen(str) + 1); - return strcpy(p, str); + ptr = realloc(ptr, count * elsiz); + if (ptr) + *pcount = count; + return ptr; } - void gray_pam_delete(char *x) diff --git a/lib/slist.c b/lib/slist.c index b110350..46e516e 100644 --- a/lib/slist.c +++ b/lib/slist.c @@ -28,38 +28,47 @@ struct gray_slist_bucket { struct gray_slist { struct gray_slist_bucket *head, *tail; struct gray_slist_bucket *free; + int ec; /* error code */ }; static struct gray_slist_bucket * alloc_bucket(size_t size) { - struct gray_slist_bucket *p = gray_malloc(sizeof(*p) + size); - p->buf = (char*)(p + 1); - p->level = 0; - p->size = size; - p->next = NULL; + struct gray_slist_bucket *p = malloc(sizeof(*p) + size); + if (p) { + p->buf = (char*)(p + 1); + p->level = 0; + p->size = size; + p->next = NULL; + } return p; } -static void +static int alloc_pool(gray_slist_t slist, size_t size) { struct gray_slist_bucket *p = alloc_bucket(GRAY_SLIST_BUCKET_SIZE); + if (!p) { + slist->ec = errno; + return 1; + } if (slist->tail) slist->tail->next = p; else slist->head = p; slist->tail = p; + return 0; } -static size_t +static ssize_t copy_chars(gray_slist_t slist, const char *str, size_t n) { size_t rest; - - if (!slist->head || slist->tail->level == slist->tail->size) - alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE); + if (!slist->head || slist->tail->level == slist->tail->size) { + if (alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE)) + return -1; + } rest = slist->tail->size - slist->tail->level; if (n > rest) n = rest; @@ -69,13 +78,28 @@ copy_chars(gray_slist_t slist, const char *str, size_t n) } gray_slist_t -gray_slist_create() +gray_slist_create(void) { - gray_slist_t slist = gray_malloc(sizeof(*slist)); - slist->head = slist->tail = slist->free = 0; + gray_slist_t slist = malloc(sizeof(*slist)); + if (slist) { + slist->head = slist->tail = slist->free = 0; + slist->ec = 0; + } return slist; } +int +gray_slist_err(gray_slist_t slist) +{ + return slist->ec; +} + +void +gray_slist_clerr(gray_slist_t slist) +{ + slist->ec = 0; +} + void gray_slist_clear(gray_slist_t slist) { @@ -84,14 +108,15 @@ gray_slist_clear(gray_slist_t slist) slist->free = slist->head; slist->head = slist->tail = NULL; } + gray_slist_clerr(slist); } void gray_slist_free(gray_slist_t *slist) { - struct gray_slist_bucket *p; if (*slist) { + struct gray_slist_bucket *p; gray_slist_clear(*slist); for (p = (*slist)->free; p; ) { struct gray_slist_bucket *next = p->next; @@ -103,21 +128,27 @@ gray_slist_free(gray_slist_t *slist) *slist = NULL; } -void +ssize_t gray_slist_append(gray_slist_t slist, const char *str, size_t n) { - const char *ptr = str; - while (n) { - size_t s = copy_chars(slist, ptr, n); - ptr += s; - n -= s; + ssize_t total; + + if (slist->ec) + return -1; + total = 0; + while (total < n) { + ssize_t s = copy_chars(slist, str + total, n - total); + if (s == -1) + return -1; + total += s; } + return total; } -void +ssize_t gray_slist_append_char(gray_slist_t slist, char c) { - gray_slist_append(slist, &c, 1); + return gray_slist_append(slist, &c, 1); } size_t @@ -130,17 +161,22 @@ gray_slist_size(gray_slist_t slist) return size; } -size_t +ssize_t gray_slist_coalesce(gray_slist_t slist) { size_t size; - if (slist->head && slist->head->next == NULL) + if (slist->ec) + return -1; + else if (slist->head && slist->head->next == NULL) size = slist->head->level; else { size = gray_slist_size(slist); - struct gray_slist_bucket *bucket = alloc_bucket(size); - struct gray_slist_bucket *p; + struct gray_slist_bucket *bucket, *p; + + bucket = alloc_bucket(size); + if (!bucket) + return -1; for (p = slist->head; p; ) { struct gray_slist_bucket *next = p->next; @@ -165,7 +201,10 @@ gray_slist_head(gray_slist_t slist, size_t *psize) void * gray_slist_finish(gray_slist_t slist) { - gray_slist_coalesce(slist); + if (slist->ec) + return NULL; + if (gray_slist_coalesce(slist) == -1) + return NULL; gray_slist_clear(slist); return slist->free->buf; } @@ -174,14 +213,16 @@ gray_slist_finish(gray_slist_t slist) #define to_num(c) \ (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 )) -void +int gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend, int len, int base) { int i; int val = 0; char *start = text; - + + if (slist->ec) + return -1; if (text[0] == '\\') { text++; if (base == 16) @@ -196,14 +237,17 @@ gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend, } if (i == 0) { - gray_slist_append(slist, start, 1); + if (gray_slist_append(slist, start, 1) != 1) + return -1; if (pend) *pend = start + 1; } else { - gray_slist_append_char(slist, val); + if (gray_slist_append_char(slist, val) != 1) + return -1; if (pend) *pend = text + i; } + return 0; } int @@ -219,22 +263,27 @@ gray_decode_backslash(int c) return c; } -void +int gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp) { if (text[1] == '\\' || (unsigned char)text[1] > 127) { - gray_slist_append_char(slist, text[1]); + if (gray_slist_append_char(slist, text[1]) != 1) + return -1; text += 2; - } else if (isdigit(text[1])) - gray_slist_grow_backslash_num(slist, text, &text, 3, 8); - else if (text[1] == 'x' || text[1] == 'X') - gray_slist_grow_backslash_num(slist, text, &text, 2, 16); - else { + } else if (isdigit(text[1])) { + if (gray_slist_grow_backslash_num(slist, text, &text, 3, 8)) + return -1; + } else if (text[1] == 'x' || text[1] == 'X') { + if (gray_slist_grow_backslash_num(slist, text, &text, 2, 16)) + return -1; + } else { int c = gray_decode_backslash(text[1]); - gray_slist_append_char(slist, c); + if (gray_slist_append_char(slist, c) != 1) + return -1; text += 2; } *endp = text; + return 0; } 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_s |