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

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

DEFINITIONS

This source file includes following definitions.
  1. _hx509_collector_alloc
  2. _hx509_collector_get_lock
  3. _hx509_collector_certs_add
  4. free_private_key
  5. _hx509_collector_private_key_add
  6. match_localkeyid
  7. match_keys
  8. _hx509_collector_collect_certs
  9. _hx509_collector_collect_private_keys
  10. _hx509_collector_free

   1 /*
   2  * Copyright (c) 2004 - 2007 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 struct private_key {
  38     AlgorithmIdentifier alg;
  39     hx509_private_key private_key;
  40     heim_octet_string localKeyId;
  41 };
  42 
  43 struct hx509_collector {
  44     hx509_lock lock;
  45     hx509_certs unenvelop_certs;
  46     hx509_certs certs;
  47     struct {
  48         struct private_key **data;
  49         size_t len;
  50     } val;
  51 };
  52 
  53 
  54 int
  55 _hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector)
     /* [<][>][^][v][top][bottom][index][help] */
  56 {
  57     struct hx509_collector *c;
  58     int ret;
  59 
  60     *collector = NULL;
  61 
  62     c = calloc(1, sizeof(*c));
  63     if (c == NULL) {
  64         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
  65         return ENOMEM;
  66     }
  67     c->lock = lock;
  68 
  69     ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert",
  70                            0,NULL, &c->unenvelop_certs);
  71     if (ret) {
  72         free(c);
  73         return ret;
  74     }
  75     c->val.data = NULL;
  76     c->val.len = 0;
  77     ret = hx509_certs_init(context, "MEMORY:collector-tmp-store",
  78                            0, NULL, &c->certs);
  79     if (ret) {
  80         hx509_certs_free(&c->unenvelop_certs);
  81         free(c);
  82         return ret;
  83     }
  84 
  85     *collector = c;
  86     return 0;
  87 }
  88 
  89 hx509_lock
  90 _hx509_collector_get_lock(struct hx509_collector *c)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92     return c->lock;
  93 }
  94 
  95 
  96 int
  97 _hx509_collector_certs_add(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
  98                            struct hx509_collector *c,
  99                            hx509_cert cert)
 100 {
 101     return hx509_certs_add(context, c->certs, cert);
 102 }
 103 
 104 static void
 105 free_private_key(struct private_key *key)
     /* [<][>][^][v][top][bottom][index][help] */
 106 {
 107     free_AlgorithmIdentifier(&key->alg);
 108     if (key->private_key)
 109         _hx509_private_key_free(&key->private_key);
 110     der_free_octet_string(&key->localKeyId);
 111     free(key);
 112 }
 113 
 114 int
 115 _hx509_collector_private_key_add(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 116                                  struct hx509_collector *c,
 117                                  const AlgorithmIdentifier *alg,
 118                                  hx509_private_key private_key,
 119                                  const heim_octet_string *key_data,
 120                                  const heim_octet_string *localKeyId)
 121 {
 122     struct private_key *key;
 123     void *d;
 124     int ret;
 125 
 126     key = calloc(1, sizeof(*key));
 127     if (key == NULL)
 128         return ENOMEM;
 129 
 130     d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0]));
 131     if (d == NULL) {
 132         free(key);
 133         hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
 134         return ENOMEM;
 135     }
 136     c->val.data = d;
 137         
 138     ret = copy_AlgorithmIdentifier(alg, &key->alg);
 139     if (ret) {
 140         hx509_set_error_string(context, 0, ret, "Failed to copy "
 141                                "AlgorithmIdentifier");
 142         goto out;
 143     }
 144     if (private_key) {
 145         key->private_key = private_key;
 146     } else {
 147         ret = _hx509_parse_private_key(context, &alg->algorithm,
 148                                        key_data->data, key_data->length,
 149                                        &key->private_key);
 150         if (ret)
 151             goto out;
 152     }
 153     if (localKeyId) {
 154         ret = der_copy_octet_string(localKeyId, &key->localKeyId);
 155         if (ret) {
 156             hx509_set_error_string(context, 0, ret,
 157                                    "Failed to copy localKeyId");
 158             goto out;
 159         }
 160     } else
 161         memset(&key->localKeyId, 0, sizeof(key->localKeyId));
 162 
 163     c->val.data[c->val.len] = key;
 164     c->val.len++;
 165 
 166 out:
 167     if (ret)
 168         free_private_key(key);
 169 
 170     return ret;
 171 }
 172 
 173 static int
 174 match_localkeyid(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 175                  struct private_key *value,
 176                  hx509_certs certs)
 177 {
 178     hx509_cert cert;
 179     hx509_query q;
 180     int ret;
 181 
 182     if (value->localKeyId.length == 0) {
 183         hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING,
 184                                "No local key attribute on private key");
 185         return HX509_LOCAL_ATTRIBUTE_MISSING;
 186     }
 187 
 188     _hx509_query_clear(&q);
 189     q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID;
 190 
 191     q.local_key_id = &value->localKeyId;
 192 
 193     ret = hx509_certs_find(context, certs, &q, &cert);
 194     if (ret == 0) {
 195         
 196         if (value->private_key)
 197             _hx509_cert_assign_key(cert, value->private_key);
 198         hx509_cert_free(cert);
 199     }
 200     return ret;
 201 }
 202 
 203 static int
 204 match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
     /* [<][>][^][v][top][bottom][index][help] */
 205 {
 206     hx509_cursor cursor;
 207     hx509_cert c;
 208     int ret, found = HX509_CERT_NOT_FOUND;
 209 
 210     if (value->private_key == NULL) {
 211         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
 212                                "No private key to compare with");
 213         return HX509_PRIVATE_KEY_MISSING;
 214     }
 215 
 216     ret = hx509_certs_start_seq(context, certs, &cursor);
 217     if (ret)
 218         return ret;
 219 
 220     c = NULL;
 221     while (1) {
 222         ret = hx509_certs_next_cert(context, certs, cursor, &c);
 223         if (ret)
 224             break;
 225         if (c == NULL)
 226             break;
 227         if (_hx509_cert_private_key(c)) {
 228             hx509_cert_free(c);
 229             continue;
 230         }
 231 
 232         ret = _hx509_match_keys(c, value->private_key);
 233         if (ret) {
 234             _hx509_cert_assign_key(c, value->private_key);
 235             hx509_cert_free(c);
 236             found = 0;
 237             break;
 238         }
 239         hx509_cert_free(c);
 240     }
 241 
 242     hx509_certs_end_seq(context, certs, cursor);
 243 
 244     if (found)
 245         hx509_clear_error_string(context);
 246 
 247     return found;
 248 }
 249 
 250 int
 251 _hx509_collector_collect_certs(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 252                                struct hx509_collector *c,
 253                                hx509_certs *ret_certs)
 254 {
 255     hx509_certs certs;
 256     int ret, i;
 257 
 258     *ret_certs = NULL;
 259 
 260     ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs);
 261     if (ret)
 262         return ret;
 263 
 264     ret = hx509_certs_merge(context, certs, c->certs);
 265     if (ret) {
 266         hx509_certs_free(&certs);
 267         return ret;
 268     }
 269 
 270     for (i = 0; i < c->val.len; i++) {
 271         ret = match_localkeyid(context, c->val.data[i], certs);
 272         if (ret == 0)
 273             continue;
 274         ret = match_keys(context, c->val.data[i], certs);
 275         if (ret == 0)
 276             continue;
 277     }
 278 
 279     *ret_certs = certs;
 280 
 281     return 0;
 282 }
 283 
 284 int
 285 _hx509_collector_collect_private_keys(hx509_context context,
     /* [<][>][^][v][top][bottom][index][help] */
 286                                       struct hx509_collector *c,
 287                                       hx509_private_key **keys)
 288 {
 289     int i, nkeys;
 290 
 291     *keys = NULL;
 292 
 293     for (i = 0, nkeys = 0; i < c->val.len; i++)
 294         if (c->val.data[i]->private_key)
 295             nkeys++;
 296 
 297     *keys = calloc(nkeys + 1, sizeof(**keys));
 298     if (*keys == NULL) {
 299         hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
 300         return ENOMEM;
 301     }
 302 
 303     for (i = 0, nkeys = 0; i < c->val.len; i++) {
 304         if (c->val.data[i]->private_key) {
 305             (*keys)[nkeys++] = c->val.data[i]->private_key;
 306             c->val.data[i]->private_key = NULL;
 307         }
 308     }
 309     (*keys)[nkeys++] = NULL;
 310 
 311     return 0;
 312 }
 313 
 314 
 315 void
 316 _hx509_collector_free(struct hx509_collector *c)
     /* [<][>][^][v][top][bottom][index][help] */
 317 {
 318     int i;
 319 
 320     if (c->unenvelop_certs)
 321         hx509_certs_free(&c->unenvelop_certs);
 322     if (c->certs)
 323         hx509_certs_free(&c->certs);
 324     for (i = 0; i < c->val.len; i++)
 325         free_private_key(c->val.data[i]);
 326     if (c->val.data)
 327         free(c->val.data);
 328     free(c);
 329 }

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