From ec0035c9b8e0690f3bc21f3de089c39eae660916 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 3 Jul 2007 08:00:08 +0000 Subject: r23678: Update to current lorikeet-heimdal (-r 767), which should fix the panics on hosts without /dev/random. Andrew Bartlett (This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f) --- source4/heimdal/lib/hx509/file.c | 240 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) (limited to 'source4/heimdal/lib/hx509/file.c') diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c index 1152af2423..b076b74f44 100644 --- a/source4/heimdal/lib/hx509/file.c +++ b/source4/heimdal/lib/hx509/file.c @@ -134,3 +134,243 @@ _hx509_write_file(const char *fn, const void *data, size_t length) return 0; } + +/* + * + */ + +static void +header(FILE *f, const char *type, const char *str) +{ + fprintf(f, "-----%s %s-----\n", type, str); +} + +int +hx509_pem_write(hx509_context context, const char *type, + hx509_pem_header *headers, FILE *f, + const void *data, size_t size) +{ + const char *p = data; + size_t length; + char *line; + +#define ENCODE_LINE_LENGTH 54 + + header(f, "BEGIN", type); + + while (headers) { + fprintf(f, "%s: %s\n%s", + headers->header, headers->value, + headers->next ? "" : "\n"); + headers = headers->next; + } + + while (size > 0) { + ssize_t l; + + length = size; + if (length > ENCODE_LINE_LENGTH) + length = ENCODE_LINE_LENGTH; + + l = base64_encode(p, length, &line); + if (l < 0) { + hx509_set_error_string(context, 0, ENOMEM, + "malloc - out of memory"); + return ENOMEM; + } + size -= length; + fprintf(f, "%s\n", line); + p += length; + free(line); + } + + header(f, "END", type); + + return 0; +} + +/* + * + */ + +int +hx509_pem_add_header(hx509_pem_header **headers, + const char *header, const char *value) +{ + hx509_pem_header *h; + + h = calloc(1, sizeof(*h)); + if (h == NULL) + return ENOMEM; + h->header = strdup(header); + if (h->header == NULL) { + free(h); + return ENOMEM; + } + h->value = strdup(value); + if (h->value == NULL) { + free(h->header); + free(h); + return ENOMEM; + } + + h->next = *headers; + *headers = h; + + return 0; +} + +void +hx509_pem_free_header(hx509_pem_header *headers) +{ + hx509_pem_header *h; + while (headers) { + h = headers; + headers = headers->next; + free(h->header); + free(h->value); + free(h); + } +} + +/* + * + */ + +const char * +hx509_pem_find_header(const hx509_pem_header *h, const char *header) +{ + while(h) { + if (strcmp(header, h->header) == 0) + return h->value; + h = h->next; + } + return NULL; +} + + +/* + * + */ + +int +hx509_pem_read(hx509_context context, + FILE *f, + hx509_pem_read_func func, + void *ctx) +{ + hx509_pem_header *headers = NULL; + char *type = NULL; + void *data = NULL; + size_t len = 0; + char buf[1024]; + int ret = HX509_PARSING_KEY_FAILED; + + enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where; + + where = BEFORE; + + while (fgets(buf, sizeof(buf), f) != NULL) { + char *p; + int i; + + i = strcspn(buf, "\n"); + if (buf[i] == '\n') { + buf[i] = '\0'; + if (i > 0) + i--; + } + if (buf[i] == '\r') { + buf[i] = '\0'; + if (i > 0) + i--; + } + + switch (where) { + case BEFORE: + if (strncmp("-----BEGIN ", buf, 11) == 0) { + type = strdup(buf + 11); + if (type == NULL) + break; + p = strchr(type, '-'); + if (p) + *p = '\0'; + where = SEARCHHEADER; + } + break; + case SEARCHHEADER: + p = strchr(buf, ':'); + if (p == NULL) { + where = INDATA; + goto indata; + } + /* FALLTHOUGH */ + case INHEADER: + if (buf[0] == '\0') { + where = INDATA; + break; + } + p = strchr(buf, ':'); + if (p) { + *p++ = '\0'; + while (isspace((int)*p)) + p++; + ret = hx509_pem_add_header(&headers, buf, p); + if (ret) + abort(); + } + break; + case INDATA: + indata: + + if (strncmp("-----END ", buf, 9) == 0) { + where = DONE; + break; + } + + p = emalloc(i); + i = base64_decode(buf, p); + if (i < 0) { + free(p); + goto out; + } + + data = erealloc(data, len + i); + memcpy(((char *)data) + len, p, i); + free(p); + len += i; + break; + case DONE: + abort(); + } + + if (where == DONE) { + ret = (*func)(context, type, headers, data, len, ctx); + out: + free(data); + data = NULL; + len = 0; + free(type); + type = NULL; + where = BEFORE; + hx509_pem_free_header(headers); + headers = NULL; + if (ret) + break; + } + } + + if (where != BEFORE) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "File ends before end of PEM end tag"); + ret = HX509_PARSING_KEY_FAILED; + } + if (data) + free(data); + if (type) + free(type); + if (headers) + hx509_pem_free_header(headers); + + return ret; +} -- cgit