Use DES_set_key_unchecked().
[heimdal.git] / lib / hx509 / file.c
blobb076b74f44df661485ba84c065e572b54f357729
1 /*
2 * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "hx_locl.h"
35 RCSID("$ID$");
37 int
38 _hx509_map_file_os(const char *fn, heim_octet_string *os, struct stat *rsb)
40 size_t length;
41 void *data;
42 int ret;
44 ret = _hx509_map_file(fn, &data, &length, rsb);
46 os->data = data;
47 os->length = length;
49 return ret;
52 void
53 _hx509_unmap_file_os(heim_octet_string *os)
55 _hx509_unmap_file(os->data, os->length);
58 int
59 _hx509_map_file(const char *fn, void **data, size_t *length, struct stat *rsb)
61 struct stat sb;
62 size_t len;
63 ssize_t l;
64 int ret;
65 void *d;
66 int fd;
68 *data = NULL;
69 *length = 0;
71 fd = open(fn, O_RDONLY);
72 if (fd < 0)
73 return errno;
75 if (fstat(fd, &sb) < 0) {
76 ret = errno;
77 close(fd);
78 return ret;
81 len = sb.st_size;
83 d = malloc(len);
84 if (d == NULL) {
85 close(fd);
86 return ENOMEM;
89 l = read(fd, d, len);
90 close(fd);
91 if (l < 0 || l != len) {
92 free(d);
93 return EINVAL;
96 if (rsb)
97 *rsb = sb;
98 *data = d;
99 *length = len;
100 return 0;
103 void
104 _hx509_unmap_file(void *data, size_t len)
106 free(data);
110 _hx509_write_file(const char *fn, const void *data, size_t length)
112 ssize_t sz;
113 const unsigned char *p = data;
114 int fd;
116 fd = open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644);
117 if (fd < 0)
118 return errno;
120 do {
121 sz = write(fd, p, length);
122 if (sz < 0) {
123 int saved_errno = errno;
124 close(fd);
125 return saved_errno;
127 if (sz == 0)
128 break;
129 length -= sz;
130 } while (length > 0);
132 if (close(fd) == -1)
133 return errno;
135 return 0;
142 static void
143 header(FILE *f, const char *type, const char *str)
145 fprintf(f, "-----%s %s-----\n", type, str);
149 hx509_pem_write(hx509_context context, const char *type,
150 hx509_pem_header *headers, FILE *f,
151 const void *data, size_t size)
153 const char *p = data;
154 size_t length;
155 char *line;
157 #define ENCODE_LINE_LENGTH 54
159 header(f, "BEGIN", type);
161 while (headers) {
162 fprintf(f, "%s: %s\n%s",
163 headers->header, headers->value,
164 headers->next ? "" : "\n");
165 headers = headers->next;
168 while (size > 0) {
169 ssize_t l;
171 length = size;
172 if (length > ENCODE_LINE_LENGTH)
173 length = ENCODE_LINE_LENGTH;
175 l = base64_encode(p, length, &line);
176 if (l < 0) {
177 hx509_set_error_string(context, 0, ENOMEM,
178 "malloc - out of memory");
179 return ENOMEM;
181 size -= length;
182 fprintf(f, "%s\n", line);
183 p += length;
184 free(line);
187 header(f, "END", type);
189 return 0;
197 hx509_pem_add_header(hx509_pem_header **headers,
198 const char *header, const char *value)
200 hx509_pem_header *h;
202 h = calloc(1, sizeof(*h));
203 if (h == NULL)
204 return ENOMEM;
205 h->header = strdup(header);
206 if (h->header == NULL) {
207 free(h);
208 return ENOMEM;
210 h->value = strdup(value);
211 if (h->value == NULL) {
212 free(h->header);
213 free(h);
214 return ENOMEM;
217 h->next = *headers;
218 *headers = h;
220 return 0;
223 void
224 hx509_pem_free_header(hx509_pem_header *headers)
226 hx509_pem_header *h;
227 while (headers) {
228 h = headers;
229 headers = headers->next;
230 free(h->header);
231 free(h->value);
232 free(h);
240 const char *
241 hx509_pem_find_header(const hx509_pem_header *h, const char *header)
243 while(h) {
244 if (strcmp(header, h->header) == 0)
245 return h->value;
246 h = h->next;
248 return NULL;
257 hx509_pem_read(hx509_context context,
258 FILE *f,
259 hx509_pem_read_func func,
260 void *ctx)
262 hx509_pem_header *headers = NULL;
263 char *type = NULL;
264 void *data = NULL;
265 size_t len = 0;
266 char buf[1024];
267 int ret = HX509_PARSING_KEY_FAILED;
269 enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
271 where = BEFORE;
273 while (fgets(buf, sizeof(buf), f) != NULL) {
274 char *p;
275 int i;
277 i = strcspn(buf, "\n");
278 if (buf[i] == '\n') {
279 buf[i] = '\0';
280 if (i > 0)
281 i--;
283 if (buf[i] == '\r') {
284 buf[i] = '\0';
285 if (i > 0)
286 i--;
289 switch (where) {
290 case BEFORE:
291 if (strncmp("-----BEGIN ", buf, 11) == 0) {
292 type = strdup(buf + 11);
293 if (type == NULL)
294 break;
295 p = strchr(type, '-');
296 if (p)
297 *p = '\0';
298 where = SEARCHHEADER;
300 break;
301 case SEARCHHEADER:
302 p = strchr(buf, ':');
303 if (p == NULL) {
304 where = INDATA;
305 goto indata;
307 /* FALLTHOUGH */
308 case INHEADER:
309 if (buf[0] == '\0') {
310 where = INDATA;
311 break;
313 p = strchr(buf, ':');
314 if (p) {
315 *p++ = '\0';
316 while (isspace((int)*p))
317 p++;
318 ret = hx509_pem_add_header(&headers, buf, p);
319 if (ret)
320 abort();
322 break;
323 case INDATA:
324 indata:
326 if (strncmp("-----END ", buf, 9) == 0) {
327 where = DONE;
328 break;
331 p = emalloc(i);
332 i = base64_decode(buf, p);
333 if (i < 0) {
334 free(p);
335 goto out;
338 data = erealloc(data, len + i);
339 memcpy(((char *)data) + len, p, i);
340 free(p);
341 len += i;
342 break;
343 case DONE:
344 abort();
347 if (where == DONE) {
348 ret = (*func)(context, type, headers, data, len, ctx);
349 out:
350 free(data);
351 data = NULL;
352 len = 0;
353 free(type);
354 type = NULL;
355 where = BEFORE;
356 hx509_pem_free_header(headers);
357 headers = NULL;
358 if (ret)
359 break;
363 if (where != BEFORE) {
364 hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
365 "File ends before end of PEM end tag");
366 ret = HX509_PARSING_KEY_FAILED;
368 if (data)
369 free(data);
370 if (type)
371 free(type);
372 if (headers)
373 hx509_pem_free_header(headers);
375 return ret;