root/source4/heimdal/lib/hx509/file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _hx509_map_file_os
  2. _hx509_unmap_file_os
  3. _hx509_write_file
  4. header
  5. hx509_pem_write
  6. hx509_pem_add_header
  7. hx509_pem_free_header
  8. hx509_pem_find_header
  9. hx509_pem_read

   1 /*
   2  * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  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.
  16  *
  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.
  20  *
  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.
  32  */
  33 
  34 #include "hx_locl.h"
  35 RCSID("$ID$");
  36 
  37 int
  38 _hx509_map_file_os(const char *fn, heim_octet_string *os)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40     size_t length;
  41     void *data;
  42     int ret;
  43 
  44     ret = rk_undumpdata(fn, &data, &length);
  45 
  46     os->data = data;
  47     os->length = length;
  48 
  49     return ret;
  50 }
  51 
  52 void
  53 _hx509_unmap_file_os(heim_octet_string *os)
     /* [<][>][^][v][top][bottom][index][help] */
  54 {
  55     rk_xfree(os->data);
  56 }
  57 
  58 int
  59 _hx509_write_file(const char *fn, const void *data, size_t length)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61     rk_dumpdata(fn, data, length);
  62     return 0;
  63 }
  64 
  65 /*
  66  *
  67  */
  68 
  69 static void
  70 header(FILE *f, const char *type, const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72     fprintf(f, "-----%s %s-----\n", type, str);
  73 }
  74 
  75 int
  76 hx509_pem_write(hx509_context context, const char *type,
     /* [<][>][^][v][top][bottom][index][help] */
  77                 hx509_pem_header *headers, FILE *f,
  78                 const void *data, size_t size)
  79 {
  80     const char *p = data;
  81     size_t length;
  82     char *line;
  83 
  84 #define ENCODE_LINE_LENGTH      54
  85 
  86     header(f, "BEGIN", type);
  87 
  88     while (headers) {
  89         fprintf(f, "%s: %s\n%s",
  90                 headers->header, headers->value,
  91                 headers->next ? "" : "\n");
  92         headers = headers->next;
  93     }
  94 
  95     while (size > 0) {
  96         ssize_t l;
  97         
  98         length = size;
  99         if (length > ENCODE_LINE_LENGTH)
 100             length = ENCODE_LINE_LENGTH;
 101         
 102         l = base64_encode(p, length, &line);
 103         if (l < 0) {
 104             hx509_set_error_string(context, 0, ENOMEM,
 105                                    "malloc - out of memory");
 106             return ENOMEM;
 107         }
 108         size -= length;
 109         fprintf(f, "%s\n", line);
 110         p += length;
 111         free(line);
 112     }
 113 
 114     header(f, "END", type);
 115 
 116     return 0;
 117 }
 118 
 119 /*
 120  *
 121  */
 122 
 123 int
 124 hx509_pem_add_header(hx509_pem_header **headers,
     /* [<][>][^][v][top][bottom][index][help] */
 125                      const char *header, const char *value)
 126 {
 127     hx509_pem_header *h;
 128 
 129     h = calloc(1, sizeof(*h));
 130     if (h == NULL)
 131         return ENOMEM;
 132     h->header = strdup(header);
 133     if (h->header == NULL) {
 134         free(h);
 135         return ENOMEM;
 136     }
 137     h->value = strdup(value);
 138     if (h->value == NULL) {
 139         free(h->header);
 140         free(h);
 141         return ENOMEM;
 142     }
 143 
 144     h->next = *headers;
 145     *headers = h;
 146 
 147     return 0;
 148 }
 149 
 150 void
 151 hx509_pem_free_header(hx509_pem_header *headers)
     /* [<][>][^][v][top][bottom][index][help] */
 152 {
 153     hx509_pem_header *h;
 154     while (headers) {
 155         h = headers;
 156         headers = headers->next;
 157         free(h->header);
 158         free(h->value);
 159         free(h);
 160     }
 161 }
 162 
 163 /*
 164  *
 165  */
 166 
 167 const char *
 168 hx509_pem_find_header(const hx509_pem_header *h, const char *header)
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170     while(h) {
 171         if (strcmp(header, h->header) == 0)
 172             return h->value;
 173         h = h->next;
 174     }
 175     return NULL;
 176 }
 177 
 178 
 179 /*
 180  *
 181  */
 182 
 183 int
 184 hx509_pem_read(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 185                FILE *f,
 186                hx509_pem_read_func func,
 187                void *ctx)
 188 {
 189     hx509_pem_header *headers = NULL;
 190     char *type = NULL;
 191     void *data = NULL;
 192     size_t len = 0;
 193     char buf[1024];
 194     int ret = HX509_PARSING_KEY_FAILED;
 195 
 196     enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
 197 
 198     where = BEFORE;
 199 
 200     while (fgets(buf, sizeof(buf), f) != NULL) {
 201         char *p;
 202         int i;
 203 
 204         i = strcspn(buf, "\n");
 205         if (buf[i] == '\n') {
 206             buf[i] = '\0';
 207             if (i > 0)
 208                 i--;
 209         }
 210         if (buf[i] == '\r') {
 211             buf[i] = '\0';
 212             if (i > 0)
 213                 i--;
 214         }
 215         
 216         switch (where) {
 217         case BEFORE:
 218             if (strncmp("-----BEGIN ", buf, 11) == 0) {
 219                 type = strdup(buf + 11);
 220                 if (type == NULL)
 221                     break;
 222                 p = strchr(type, '-');
 223                 if (p)
 224                     *p = '\0';
 225                 where = SEARCHHEADER;
 226             }
 227             break;
 228         case SEARCHHEADER:
 229             p = strchr(buf, ':');
 230             if (p == NULL) {
 231                 where = INDATA;
 232                 goto indata;
 233             }
 234             /* FALLTHOUGH */
 235         case INHEADER:
 236             if (buf[0] == '\0') {
 237                 where = INDATA;
 238                 break;
 239             }
 240             p = strchr(buf, ':');
 241             if (p) {
 242                 *p++ = '\0';
 243                 while (isspace((int)*p))
 244                     p++;
 245                 ret = hx509_pem_add_header(&headers, buf, p);
 246                 if (ret)
 247                     abort();
 248             }
 249             break;
 250         case INDATA:
 251         indata:
 252 
 253             if (strncmp("-----END ", buf, 9) == 0) {
 254                 where = DONE;
 255                 break;
 256             }
 257 
 258             p = emalloc(i);
 259             i = base64_decode(buf, p);
 260             if (i < 0) {
 261                 free(p);
 262                 goto out;
 263             }
 264         
 265             data = erealloc(data, len + i);
 266             memcpy(((char *)data) + len, p, i);
 267             free(p);
 268             len += i;
 269             break;
 270         case DONE:
 271             abort();
 272         }
 273 
 274         if (where == DONE) {
 275             ret = (*func)(context, type, headers, data, len, ctx);
 276         out:
 277             free(data);
 278             data = NULL;
 279             len = 0;
 280             free(type);
 281             type = NULL;
 282             where = BEFORE;
 283             hx509_pem_free_header(headers);
 284             headers = NULL;
 285             if (ret)
 286                 break;
 287         }
 288     }
 289 
 290     if (where != BEFORE) {
 291         hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
 292                                "File ends before end of PEM end tag");
 293         ret = HX509_PARSING_KEY_FAILED;
 294     }
 295     if (data)
 296         free(data);
 297     if (type)
 298         free(type);
 299     if (headers)
 300         hx509_pem_free_header(headers);
 301 
 302     return ret;
 303 }

/* [<][>][^][v][top][bottom][index][help] */