r23456: Update Samba4 to current lorikeet-heimdal.
[sfrench/samba-autobuild/.git] / source / heimdal / lib / hx509 / cert.c
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: cert.c 20915 2007-06-05 03:58:56Z lha $");
36 #include "crypto-headers.h"
37 #include <rtbl.h>
38
39 struct hx509_verify_ctx_data {
40     hx509_certs trust_anchors;
41     int flags;
42 #define HX509_VERIFY_CTX_F_TIME_SET                     1
43 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE      2
44 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280              4
45 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS          8
46     time_t time_now;
47     unsigned int max_depth;
48 #define HX509_VERIFY_MAX_DEPTH 30
49     hx509_revoke_ctx revoke_ctx;
50 };
51
52 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
53 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
54
55 struct _hx509_cert_attrs {
56     size_t len;
57     hx509_cert_attribute *val;
58 };
59
60 struct hx509_cert_data {
61     unsigned int ref;
62     char *friendlyname;
63     Certificate *data;
64     hx509_private_key private_key;
65     struct _hx509_cert_attrs attrs;
66     hx509_name basename;
67     _hx509_cert_release_func release;
68     void *ctx;
69 };
70
71 typedef struct hx509_name_constraints {
72     NameConstraints *val;
73     size_t len;
74 } hx509_name_constraints;
75
76 #define GeneralSubtrees_SET(g,var) \
77         (g)->len = (var)->len, (g)->val = (var)->val;
78
79 /*
80  *
81  */
82
83 void
84 _hx509_abort(const char *fmt, ...)
85 {
86     va_list ap;
87     va_start(ap, fmt);
88     vprintf(fmt, ap);
89     va_end(ap);
90     printf("\n");
91     fflush(stdout);
92     abort();
93 }
94
95 /*
96  *
97  */
98
99 int
100 hx509_context_init(hx509_context *context)
101 {
102     *context = calloc(1, sizeof(**context));
103     if (*context == NULL)
104         return ENOMEM;
105
106     _hx509_ks_null_register(*context);
107     _hx509_ks_mem_register(*context);
108     _hx509_ks_file_register(*context);
109     _hx509_ks_pkcs12_register(*context);
110     _hx509_ks_pkcs11_register(*context);
111     _hx509_ks_dir_register(*context);
112     _hx509_ks_keychain_register(*context);
113
114     ENGINE_add_conf_module();
115     OpenSSL_add_all_algorithms();
116
117     (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
118
119     initialize_hx_error_table_r(&(*context)->et_list);
120     initialize_asn1_error_table_r(&(*context)->et_list);
121
122 #ifdef HX509_DEFAULT_ANCHORS
123     (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
124                            NULL, &(*context)->default_trust_anchors);
125 #endif
126
127     return 0;
128 }
129
130 void
131 hx509_context_set_missing_revoke(hx509_context context, int flag)
132 {
133     if (flag)
134         context->flags |= HX509_CTX_VERIFY_MISSING_OK;
135     else
136         context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
137 }
138
139 void
140 hx509_context_free(hx509_context *context)
141 {
142     hx509_clear_error_string(*context);
143     if ((*context)->ks_ops) {
144         free((*context)->ks_ops);
145         (*context)->ks_ops = NULL;
146     }
147     (*context)->ks_num_ops = 0;
148     free_error_table ((*context)->et_list);
149     if ((*context)->querystat)
150         free((*context)->querystat);
151     memset(*context, 0, sizeof(**context));
152     free(*context);
153     *context = NULL;
154 }
155
156
157 /*
158  *
159  */
160
161 Certificate *
162 _hx509_get_cert(hx509_cert cert)
163 {
164     return cert->data;
165 }
166
167 /*
168  *
169  */
170
171 #if 0
172 void
173 _hx509_print_cert_subject(hx509_cert cert)
174 {
175     char *subject_name;
176     hx509_name name;
177     int ret;
178
179     ret = hx509_cert_get_subject(cert, &name);
180     if (ret)
181         abort();
182         
183     ret = hx509_name_to_string(name, &subject_name);
184     hx509_name_free(&name);
185     if (ret)
186         abort();
187
188     printf("name: %s\n", subject_name);
189
190     free(subject_name);
191 }
192 #endif
193
194 /*
195  *
196  */
197
198 int
199 _hx509_cert_get_version(const Certificate *t)
200 {
201     return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
202 }
203
204 int
205 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
206 {
207     int ret;
208
209     *cert = malloc(sizeof(**cert));
210     if (*cert == NULL)
211         return ENOMEM;
212     (*cert)->ref = 1;
213     (*cert)->friendlyname = NULL;
214     (*cert)->attrs.len = 0;
215     (*cert)->attrs.val = NULL;
216     (*cert)->private_key = NULL;
217     (*cert)->basename = NULL;
218     (*cert)->release = NULL;
219     (*cert)->ctx = NULL;
220
221     (*cert)->data = calloc(1, sizeof(*(*cert)->data));
222     if ((*cert)->data == NULL) {
223         free(*cert);
224         return ENOMEM;
225     }
226     ret = copy_Certificate(c, (*cert)->data);
227     if (ret) {
228         free((*cert)->data);
229         free(*cert);
230     }
231     return ret;
232 }
233
234 void
235 _hx509_cert_set_release(hx509_cert cert, 
236                         _hx509_cert_release_func release,
237                         void *ctx)
238 {
239     cert->release = release;
240     cert->ctx = ctx;
241 }
242
243
244 /* Doesn't make a copy of `private_key'. */
245
246 int
247 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
248 {
249     if (cert->private_key)
250         _hx509_private_key_free(&cert->private_key);
251     cert->private_key = _hx509_private_key_ref(private_key);
252     return 0;
253 }
254
255 void
256 hx509_cert_free(hx509_cert cert)
257 {
258     int i;
259
260     if (cert == NULL)
261         return;
262
263     if (cert->ref <= 0)
264         _hx509_abort("refcount <= 0");
265     if (--cert->ref > 0)
266         return;
267
268     if (cert->release)
269         (cert->release)(cert, cert->ctx);
270
271     if (cert->private_key)
272         _hx509_private_key_free(&cert->private_key);
273
274     free_Certificate(cert->data);
275     free(cert->data);
276
277     for (i = 0; i < cert->attrs.len; i++) {
278         der_free_octet_string(&cert->attrs.val[i]->data);
279         der_free_oid(&cert->attrs.val[i]->oid);
280         free(cert->attrs.val[i]);
281     }
282     free(cert->attrs.val);
283     free(cert->friendlyname);
284     if (cert->basename)
285         hx509_name_free(&cert->basename);
286     memset(cert, 0, sizeof(cert));
287     free(cert);
288 }
289
290 hx509_cert
291 hx509_cert_ref(hx509_cert cert)
292 {
293     if (cert->ref <= 0)
294         _hx509_abort("refcount <= 0");
295     cert->ref++;
296     if (cert->ref == 0)
297         _hx509_abort("refcount == 0");
298     return cert;
299 }
300
301 int
302 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
303 {
304     hx509_verify_ctx c;
305
306     c = calloc(1, sizeof(*c));
307     if (c == NULL)
308         return ENOMEM;
309
310     c->max_depth = HX509_VERIFY_MAX_DEPTH;
311
312     *ctx = c;
313     
314     return 0;
315 }
316
317 void
318 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
319 {
320     if (ctx)
321         memset(ctx, 0, sizeof(*ctx));
322     free(ctx);
323 }
324
325 void
326 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
327 {
328     ctx->trust_anchors = set;
329 }
330
331 void
332 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
333 {
334     ctx->revoke_ctx = revoke_ctx;
335 }
336
337 void
338 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
339 {
340     ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
341     ctx->time_now = t;
342 }
343
344 void
345 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
346 {
347     if (boolean)
348         ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
349     else
350         ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
351 }
352
353 void
354 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
355 {
356     if (boolean)
357         ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
358     else
359         ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
360 }
361
362 static const Extension *
363 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
364 {
365     const TBSCertificate *c = &cert->tbsCertificate;
366
367     if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
368         return NULL;
369     
370     for (;*idx < c->extensions->len; (*idx)++) {
371         if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
372             return &c->extensions->val[(*idx)++];
373     }
374     return NULL;
375 }
376
377 static int
378 find_extension_auth_key_id(const Certificate *subject, 
379                            AuthorityKeyIdentifier *ai)
380 {
381     const Extension *e;
382     size_t size;
383     int i = 0;
384
385     memset(ai, 0, sizeof(*ai));
386
387     e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
388     if (e == NULL)
389         return HX509_EXTENSION_NOT_FOUND;
390     
391     return decode_AuthorityKeyIdentifier(e->extnValue.data, 
392                                          e->extnValue.length, 
393                                          ai, &size);
394 }
395
396 int
397 _hx509_find_extension_subject_key_id(const Certificate *issuer,
398                                      SubjectKeyIdentifier *si)
399 {
400     const Extension *e;
401     size_t size;
402     int i = 0;
403
404     memset(si, 0, sizeof(*si));
405
406     e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
407     if (e == NULL)
408         return HX509_EXTENSION_NOT_FOUND;
409     
410     return decode_SubjectKeyIdentifier(e->extnValue.data, 
411                                        e->extnValue.length,
412                                        si, &size);
413 }
414
415 static int
416 find_extension_name_constraints(const Certificate *subject, 
417                                 NameConstraints *nc)
418 {
419     const Extension *e;
420     size_t size;
421     int i = 0;
422
423     memset(nc, 0, sizeof(*nc));
424
425     e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
426     if (e == NULL)
427         return HX509_EXTENSION_NOT_FOUND;
428     
429     return decode_NameConstraints(e->extnValue.data, 
430                                   e->extnValue.length, 
431                                   nc, &size);
432 }
433
434 static int
435 find_extension_subject_alt_name(const Certificate *cert, int *i,
436                                 GeneralNames *sa)
437 {
438     const Extension *e;
439     size_t size;
440
441     memset(sa, 0, sizeof(*sa));
442
443     e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
444     if (e == NULL)
445         return HX509_EXTENSION_NOT_FOUND;
446     
447     return decode_GeneralNames(e->extnValue.data, 
448                                e->extnValue.length,
449                                sa, &size);
450 }
451
452 static int
453 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
454 {
455     const Extension *e;
456     size_t size;
457     int i = 0;
458
459     memset(eku, 0, sizeof(*eku));
460
461     e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
462     if (e == NULL)
463         return HX509_EXTENSION_NOT_FOUND;
464     
465     return decode_ExtKeyUsage(e->extnValue.data, 
466                               e->extnValue.length,
467                               eku, &size);
468 }
469
470 static int
471 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
472 {
473     void *p;
474     int ret;
475
476     p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
477     if (p == NULL)
478         return ENOMEM;
479     list->val = p;
480     ret = der_copy_octet_string(entry, &list->val[list->len]);
481     if (ret)
482         return ret;
483     list->len++;
484     return 0;
485 }
486
487 void
488 hx509_free_octet_string_list(hx509_octet_string_list *list)
489 {
490     int i;
491     for (i = 0; i < list->len; i++)
492         der_free_octet_string(&list->val[i]);
493     free(list->val);
494     list->val = NULL;
495     list->len = 0;
496 }
497
498 int
499 hx509_cert_find_subjectAltName_otherName(hx509_cert cert,
500                                          const heim_oid *oid,
501                                          hx509_octet_string_list *list)
502 {
503     GeneralNames sa;
504     int ret, i, j;
505
506     list->val = NULL;
507     list->len = 0;
508
509     i = 0;
510     while (1) {
511         ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
512         i++;
513         if (ret == HX509_EXTENSION_NOT_FOUND) {
514             ret = 0;
515             break;
516         } else if (ret != 0)
517             break;
518
519
520         for (j = 0; j < sa.len; j++) {
521             if (sa.val[j].element == choice_GeneralName_otherName &&
522                 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0) 
523             {
524                 ret = add_to_list(list, &sa.val[j].u.otherName.value);
525                 if (ret) {
526                     free_GeneralNames(&sa);
527                     return ret;
528                 }
529             }
530         }
531         free_GeneralNames(&sa);
532     }
533     return ret;
534 }
535
536
537 static int
538 check_key_usage(hx509_context context, const Certificate *cert, 
539                 unsigned flags, int req_present)
540 {
541     const Extension *e;
542     KeyUsage ku;
543     size_t size;
544     int ret, i = 0;
545     unsigned ku_flags;
546
547     if (_hx509_cert_get_version(cert) < 3)
548         return 0;
549
550     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
551     if (e == NULL) {
552         if (req_present) {
553             hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
554                                    "Required extension key "
555                                    "usage missing from certifiate");
556             return HX509_KU_CERT_MISSING;
557         }
558         return 0;
559     }
560     
561     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
562     if (ret)
563         return ret;
564     ku_flags = KeyUsage2int(ku);
565     if ((ku_flags & flags) != flags) {
566         unsigned missing = (~ku_flags) & flags;
567         char buf[256], *name;
568
569         unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
570         _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
571         hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
572                                "Key usage %s required but missing "
573                                "from certifiate %s", buf, name);
574         free(name);
575         return HX509_KU_CERT_MISSING;
576     }
577     return 0;
578 }
579
580 int
581 _hx509_check_key_usage(hx509_context context, hx509_cert cert, 
582                        unsigned flags, int req_present)
583 {
584     return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
585 }
586
587 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
588
589 static int
590 check_basic_constraints(hx509_context context, const Certificate *cert, 
591                         enum certtype type, int depth)
592 {
593     BasicConstraints bc;
594     const Extension *e;
595     size_t size;
596     int ret, i = 0;
597
598     if (_hx509_cert_get_version(cert) < 3)
599         return 0;
600
601     e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
602     if (e == NULL) {
603         switch(type) {
604         case PROXY_CERT:
605         case EE_CERT:
606             return 0;
607         case CA_CERT: {
608             char *name;
609             ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
610             assert(ret == 0);
611             hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
612                                    "basicConstraints missing from "
613                                    "CA certifiacte %s", name);
614             free(name);
615             return HX509_EXTENSION_NOT_FOUND;
616         }
617         }
618     }
619     
620     ret = decode_BasicConstraints(e->extnValue.data, 
621                                   e->extnValue.length, &bc,
622                                   &size);
623     if (ret)
624         return ret;
625     switch(type) {
626     case PROXY_CERT:
627         if (bc.cA != NULL && *bc.cA)
628             ret = HX509_PARENT_IS_CA;
629         break;
630     case EE_CERT:
631         ret = 0;
632         break;
633     case CA_CERT:
634         if (bc.cA == NULL || !*bc.cA)
635             ret = HX509_PARENT_NOT_CA;
636         else if (bc.pathLenConstraint)
637             if (depth - 1 > *bc.pathLenConstraint)
638                 ret = HX509_CA_PATH_TOO_DEEP;
639         break;
640     }
641     free_BasicConstraints(&bc);
642     return ret;
643 }
644
645 int
646 _hx509_cert_is_parent_cmp(const Certificate *subject,
647                           const Certificate *issuer,
648                           int allow_self_signed)
649 {
650     int diff;
651     AuthorityKeyIdentifier ai;
652     SubjectKeyIdentifier si;
653     int ret_ai, ret_si;
654
655     diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, 
656                            &subject->tbsCertificate.issuer);
657     if (diff)
658         return diff;
659     
660     memset(&ai, 0, sizeof(ai));
661     memset(&si, 0, sizeof(si));
662
663     /*
664      * Try to find AuthorityKeyIdentifier, if its not present in the
665      * subject certificate nor the parent.
666      */
667
668     ret_ai = find_extension_auth_key_id(subject, &ai);
669     if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
670         return 1;
671     ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
672     if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
673         return -1;
674
675     if (ret_si && ret_ai)
676         goto out;
677     if (ret_ai)
678         goto out;
679     if (ret_si) {
680         if (allow_self_signed) {
681             diff = 0;
682             goto out;
683         } else if (ai.keyIdentifier) {
684             diff = -1;
685             goto out;
686         }
687     }
688     
689     if (ai.keyIdentifier == NULL) {
690         Name name;
691
692         if (ai.authorityCertIssuer == NULL)
693             return -1;
694         if (ai.authorityCertSerialNumber == NULL)
695             return -1;
696
697         diff = der_heim_integer_cmp(ai.authorityCertSerialNumber, 
698                                     &issuer->tbsCertificate.serialNumber);
699         if (diff)
700             return diff;
701         if (ai.authorityCertIssuer->len != 1)
702             return -1;
703         if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
704             return -1;
705         
706         name.element = 
707             ai.authorityCertIssuer->val[0].u.directoryName.element;
708         name.u.rdnSequence = 
709             ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
710
711         diff = _hx509_name_cmp(&issuer->tbsCertificate.subject, 
712                                &name);
713         if (diff)
714             return diff;
715         diff = 0;
716     } else
717         diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
718     if (diff)
719         goto out;
720
721  out:
722     free_AuthorityKeyIdentifier(&ai);
723     free_SubjectKeyIdentifier(&si);
724     return diff;
725 }
726
727 static int
728 certificate_is_anchor(hx509_context context,
729                       hx509_certs trust_anchors,
730                       const hx509_cert cert)
731 {
732     hx509_query q;
733     hx509_cert c;
734     int ret;
735
736     if (trust_anchors == NULL)
737         return 0;
738
739     _hx509_query_clear(&q);
740
741     q.match = HX509_QUERY_MATCH_CERTIFICATE;
742     q.certificate = _hx509_get_cert(cert);
743
744     ret = hx509_certs_find(context, trust_anchors, &q, &c);
745     if (ret == 0)
746         hx509_cert_free(c);
747     return ret == 0;
748 }
749
750 static int
751 certificate_is_self_signed(const Certificate *cert)
752 {
753     return _hx509_cert_is_parent_cmp(cert, cert, 1) == 0;
754 }
755
756 /*
757  * The subjectName is "null" when its empty set of relative DBs.
758  */
759
760 static int
761 subject_null_p(const Certificate *c)
762 {
763     return c->tbsCertificate.subject.u.rdnSequence.len == 0;
764 }
765
766
767 static int
768 find_parent(hx509_context context,
769             time_t time_now,
770             hx509_certs trust_anchors,
771             hx509_path *path,
772             hx509_certs pool, 
773             hx509_cert current,
774             hx509_cert *parent)
775 {
776     AuthorityKeyIdentifier ai;
777     hx509_query q;
778     int ret;
779
780     *parent = NULL;
781     memset(&ai, 0, sizeof(ai));
782     
783     _hx509_query_clear(&q);
784
785     if (!subject_null_p(current->data)) {
786         q.match |= HX509_QUERY_FIND_ISSUER_CERT;
787         q.subject = _hx509_get_cert(current);
788     } else {
789         ret = find_extension_auth_key_id(current->data, &ai);
790         if (ret) {
791             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
792                                    "Subjectless certificate missing AuthKeyID");
793             return HX509_CERTIFICATE_MALFORMED;
794         }
795
796         if (ai.keyIdentifier == NULL) {
797             free_AuthorityKeyIdentifier(&ai);
798             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
799                                    "Subjectless certificate missing keyIdentifier "
800                                    "inside AuthKeyID");
801             return HX509_CERTIFICATE_MALFORMED;
802         }
803
804         q.subject_id = ai.keyIdentifier;
805         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
806     }
807
808     q.path = path;
809     q.match |= HX509_QUERY_NO_MATCH_PATH;
810
811     if (pool) {
812         q.timenow = time_now;
813         q.match |= HX509_QUERY_MATCH_TIME;
814
815         ret = hx509_certs_find(context, pool, &q, parent);
816         if (ret == 0) {
817             free_AuthorityKeyIdentifier(&ai);
818             return 0;
819         }
820         q.match &= ~HX509_QUERY_MATCH_TIME;
821     }
822
823     if (trust_anchors) {
824         ret = hx509_certs_find(context, trust_anchors, &q, parent);
825         if (ret == 0) {
826             free_AuthorityKeyIdentifier(&ai);
827             return ret;
828         }
829     }
830     free_AuthorityKeyIdentifier(&ai);
831
832     {
833         hx509_name name;
834         char *str;
835
836         ret = hx509_cert_get_subject(current, &name);
837         if (ret) {
838             hx509_clear_error_string(context);
839             return HX509_ISSUER_NOT_FOUND;
840         }
841         ret = hx509_name_to_string(name, &str);
842         hx509_name_free(&name);
843         if (ret) {
844             hx509_clear_error_string(context);
845             return HX509_ISSUER_NOT_FOUND;
846         }
847         
848         hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
849                                "Failed to find issuer for "
850                                "certificate with subject: '%s'", str);
851         free(str);
852     }
853     return HX509_ISSUER_NOT_FOUND;
854 }
855
856 /*
857  *
858  */
859
860 static int
861 is_proxy_cert(hx509_context context, 
862               const Certificate *cert, 
863               ProxyCertInfo *rinfo)
864 {
865     ProxyCertInfo info;
866     const Extension *e;
867     size_t size;
868     int ret, i = 0;
869
870     if (rinfo)
871         memset(rinfo, 0, sizeof(*rinfo));
872
873     e = find_extension(cert, oid_id_pe_proxyCertInfo(), &i);
874     if (e == NULL) {
875         hx509_clear_error_string(context);
876         return HX509_EXTENSION_NOT_FOUND;
877     }
878
879     ret = decode_ProxyCertInfo(e->extnValue.data, 
880                                e->extnValue.length, 
881                                &info,
882                                &size);
883     if (ret) {
884         hx509_clear_error_string(context);
885         return ret;
886     }
887     if (size != e->extnValue.length) {
888         free_ProxyCertInfo(&info);
889         hx509_clear_error_string(context);
890         return HX509_EXTRA_DATA_AFTER_STRUCTURE; 
891     }
892     if (rinfo == NULL)
893         free_ProxyCertInfo(&info);
894     else
895         *rinfo = info;
896
897     return 0;
898 }
899
900 /*
901  * Path operations are like MEMORY based keyset, but with exposed
902  * internal so we can do easy searches.
903  */
904
905 int
906 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
907 {
908     hx509_cert *val;
909     val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
910     if (val == NULL) {
911         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
912         return ENOMEM;
913     }
914
915     path->val = val;
916     path->val[path->len] = hx509_cert_ref(cert);
917     path->len++;
918
919     return 0;
920 }
921
922 void
923 _hx509_path_free(hx509_path *path)
924 {
925     unsigned i;
926     
927     for (i = 0; i < path->len; i++)
928         hx509_cert_free(path->val[i]);
929     free(path->val);
930     path->val = NULL;
931     path->len = 0;
932 }
933
934 /*
935  * Find path by looking up issuer for the top certificate and continue
936  * until an anchor certificate is found or max limit is found. A
937  * certificate never included twice in the path.
938  *
939  * If the trust anchors are not given, calculate optimistic path, just
940  * follow the chain upward until we no longer find a parent or we hit
941  * the max path limit. In this case, a failure will always be returned
942  * depending on what error condition is hit first.
943  *
944  * The path includes a path from the top certificate to the anchor
945  * certificate.
946  *
947  * The caller needs to free `path´ both on successful built path and
948  * failure.
949  */
950
951 int
952 _hx509_calculate_path(hx509_context context,
953                       int flags,
954                       time_t time_now,
955                       hx509_certs anchors,
956                       unsigned int max_depth,
957                       hx509_cert cert,
958                       hx509_certs pool,
959                       hx509_path *path)
960 {
961     hx509_cert parent, current;
962     int ret;
963
964     if (max_depth == 0)
965         max_depth = HX509_VERIFY_MAX_DEPTH;
966
967     ret = _hx509_path_append(context, path, cert);
968     if (ret)
969         return ret;
970
971     current = hx509_cert_ref(cert);
972
973     while (!certificate_is_anchor(context, anchors, current)) {
974
975         ret = find_parent(context, time_now, anchors, path, 
976                           pool, current, &parent);
977         hx509_cert_free(current);
978         if (ret)
979             return ret;
980
981         ret = _hx509_path_append(context, path, parent);
982         if (ret)
983             return ret;
984         current = parent;
985
986         if (path->len > max_depth) {
987             hx509_cert_free(current);
988             hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
989                                    "Path too long while bulding "
990                                    "certificate chain");
991             return HX509_PATH_TOO_LONG;
992         }
993     }
994
995     if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) && 
996         path->len > 0 && 
997         certificate_is_anchor(context, anchors, path->val[path->len - 1]))
998     {
999         hx509_cert_free(path->val[path->len - 1]);
1000         path->len--;
1001     }
1002
1003     hx509_cert_free(current);
1004     return 0;
1005 }
1006
1007 static int
1008 AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1009                         const AlgorithmIdentifier *q)
1010 {
1011     int diff;
1012     diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1013     if (diff)
1014         return diff;
1015     if (p->parameters) {
1016         if (q->parameters)
1017             return heim_any_cmp(p->parameters,
1018                                 q->parameters);
1019         else
1020             return 1;
1021     } else {
1022         if (q->parameters)
1023             return -1;
1024         else
1025             return 0;
1026     }
1027 }
1028
1029 int
1030 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1031 {
1032     int diff;
1033     diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1034     if (diff)
1035         return diff;
1036     diff = AlgorithmIdentifier_cmp(&p->signatureAlgorithm, 
1037                                    &q->signatureAlgorithm);
1038     if (diff)
1039         return diff;
1040     diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1041                                      &q->tbsCertificate._save);
1042     return diff;
1043 }
1044
1045 int
1046 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1047 {
1048     return _hx509_Certificate_cmp(p->data, q->data);
1049 }
1050
1051 int
1052 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1053 {
1054     return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1055 }
1056
1057 int
1058 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1059 {
1060     return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1061 }
1062
1063 int
1064 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1065                             hx509_name *name)
1066 {
1067     if (c->basename)
1068         return hx509_name_copy(context, c->basename, name);
1069     if (is_proxy_cert(context, c->data, NULL) == 0) {
1070         int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1071         hx509_set_error_string(context, 0, ret,
1072                                "Proxy certificate have not been "
1073                                "canonicalize yet, no base name");
1074         return ret;
1075     }
1076     return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1077 }
1078
1079 int
1080 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1081 {
1082     return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1083 }
1084
1085 time_t
1086 hx509_cert_get_notBefore(hx509_cert p)
1087 {
1088     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1089 }
1090
1091 time_t
1092 hx509_cert_get_notAfter(hx509_cert p)
1093 {
1094     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1095 }
1096
1097 int
1098 hx509_cert_get_SPKI(hx509_cert p, SubjectPublicKeyInfo *spki)
1099 {
1100     return copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo,
1101                                      spki);
1102 }
1103
1104 hx509_private_key
1105 _hx509_cert_private_key(hx509_cert p)
1106 {
1107     return p->private_key;
1108 }
1109
1110 int
1111 _hx509_cert_private_key_exportable(hx509_cert p)
1112 {
1113     if (p->private_key == NULL)
1114         return 0;
1115     return _hx509_private_key_exportable(p->private_key);
1116 }
1117
1118 int
1119 _hx509_cert_private_decrypt(hx509_context context,
1120                             const heim_octet_string *ciphertext,
1121                             const heim_oid *encryption_oid,
1122                             hx509_cert p,
1123                             heim_octet_string *cleartext)
1124 {
1125     cleartext->data = NULL;
1126     cleartext->length = 0;
1127
1128     if (p->private_key == NULL) {
1129         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1130                                "Private key missing");
1131         return HX509_PRIVATE_KEY_MISSING;
1132     }
1133
1134     return _hx509_private_key_private_decrypt(context,
1135                                               ciphertext,
1136                                               encryption_oid,
1137                                               p->private_key, 
1138                                               cleartext);
1139 }
1140
1141 int
1142 _hx509_cert_public_encrypt(hx509_context context,
1143                            const heim_octet_string *cleartext,
1144                            const hx509_cert p,
1145                            heim_oid *encryption_oid,
1146                            heim_octet_string *ciphertext)
1147 {
1148     return _hx509_public_encrypt(context,
1149                                  cleartext, p->data,
1150                                  encryption_oid, ciphertext);
1151 }
1152
1153 /*
1154  *
1155  */
1156
1157 time_t
1158 _hx509_Time2time_t(const Time *t)
1159 {
1160     switch(t->element) {
1161     case choice_Time_utcTime:
1162         return t->u.utcTime;
1163     case choice_Time_generalTime:
1164         return t->u.generalTime;
1165     }
1166     return 0;
1167 }
1168
1169 /*
1170  *
1171  */
1172
1173 static int
1174 init_name_constraints(hx509_name_constraints *nc)
1175 {
1176     memset(nc, 0, sizeof(*nc));
1177     return 0;
1178 }
1179
1180 static int
1181 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1182                      hx509_name_constraints *nc)
1183 {
1184     NameConstraints tnc;
1185     int ret;
1186
1187     ret = find_extension_name_constraints(c, &tnc);
1188     if (ret == HX509_EXTENSION_NOT_FOUND)
1189         return 0;
1190     else if (ret) {
1191         hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1192         return ret;
1193     } else if (not_ca) {
1194         ret = HX509_VERIFY_CONSTRAINTS;
1195         hx509_set_error_string(context, 0, ret, "Not a CA and "
1196                                "have NameConstraints");
1197     } else {
1198         NameConstraints *val;
1199         val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1200         if (val == NULL) {
1201             hx509_clear_error_string(context);
1202             ret = ENOMEM;
1203             goto out;
1204         }
1205         nc->val = val;
1206         ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1207         if (ret) {
1208             hx509_clear_error_string(context);
1209             goto out;
1210         }
1211         nc->len += 1;
1212     }
1213 out:
1214     free_NameConstraints(&tnc);
1215     return ret;
1216 }
1217
1218 static int
1219 match_RDN(const RelativeDistinguishedName *c,
1220           const RelativeDistinguishedName *n)
1221 {
1222     int i;
1223
1224     if (c->len != n->len)
1225         return HX509_NAME_CONSTRAINT_ERROR;
1226     
1227     for (i = 0; i < n->len; i++) {
1228         if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1229             return HX509_NAME_CONSTRAINT_ERROR;
1230         if (_hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value) != 0)
1231             return HX509_NAME_CONSTRAINT_ERROR;
1232     }
1233     return 0;
1234 }
1235
1236 static int
1237 match_X501Name(const Name *c, const Name *n)
1238 {
1239     int i, ret;
1240
1241     if (c->element != choice_Name_rdnSequence
1242         || n->element != choice_Name_rdnSequence)
1243         return 0;
1244     if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1245         return HX509_NAME_CONSTRAINT_ERROR;
1246     for (i = 0; i < c->u.rdnSequence.len; i++) {
1247         ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1248         if (ret)
1249             return ret;
1250     }
1251     return 0;
1252
1253
1254
1255 static int
1256 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1257 {
1258     /* 
1259      * Name constraints only apply to the same name type, see RFC3280,
1260      * 4.2.1.11.
1261      */
1262     assert(c->element == n->element);
1263
1264     switch(c->element) {
1265     case choice_GeneralName_otherName:
1266         if (der_heim_oid_cmp(&c->u.otherName.type_id,
1267                          &n->u.otherName.type_id) != 0)
1268             return HX509_NAME_CONSTRAINT_ERROR;
1269         if (heim_any_cmp(&c->u.otherName.value,
1270                          &n->u.otherName.value) != 0)
1271             return HX509_NAME_CONSTRAINT_ERROR;
1272         *match = 1;
1273         return 0;
1274     case choice_GeneralName_rfc822Name: {
1275         const char *s;
1276         size_t len1, len2;
1277         s = strchr(c->u.rfc822Name, '@');
1278         if (s) {
1279             if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1280                 return HX509_NAME_CONSTRAINT_ERROR;
1281         } else {
1282             s = strchr(n->u.rfc822Name, '@');
1283             if (s == NULL)
1284                 return HX509_NAME_CONSTRAINT_ERROR;
1285             len1 = strlen(c->u.rfc822Name);
1286             len2 = strlen(s + 1);
1287             if (len1 > len2)
1288                 return HX509_NAME_CONSTRAINT_ERROR;
1289             if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1290                 return HX509_NAME_CONSTRAINT_ERROR;
1291             if (len1 < len2 && s[len2 - len1] != '.')
1292                 return HX509_NAME_CONSTRAINT_ERROR;
1293         }
1294         *match = 1;
1295         return 0;
1296     }
1297     case choice_GeneralName_dNSName: {
1298         size_t len1, len2;
1299
1300         len1 = strlen(c->u.dNSName);
1301         len2 = strlen(n->u.dNSName);
1302         if (len1 > len2)
1303             return HX509_NAME_CONSTRAINT_ERROR;
1304         if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0)
1305             return HX509_NAME_CONSTRAINT_ERROR;
1306         *match = 1;
1307         return 0;
1308     }
1309     case choice_GeneralName_directoryName: {
1310         Name c_name, n_name;
1311         int ret;
1312
1313         c_name._save.data = NULL;
1314         c_name._save.length = 0;
1315         c_name.element = c->u.directoryName.element;
1316         c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1317
1318         n_name._save.data = NULL;
1319         n_name._save.length = 0;
1320         n_name.element = n->u.directoryName.element;
1321         n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1322
1323         ret = match_X501Name(&c_name, &n_name);
1324         if (ret == 0)
1325             *match = 1;
1326         return ret;
1327     }
1328     case choice_GeneralName_uniformResourceIdentifier:
1329     case choice_GeneralName_iPAddress:
1330     case choice_GeneralName_registeredID:
1331     default:
1332         return HX509_NAME_CONSTRAINT_ERROR;
1333     }
1334 }
1335
1336 static int
1337 match_alt_name(const GeneralName *n, const Certificate *c, 
1338                int *same, int *match)
1339 {
1340     GeneralNames sa;
1341     int ret, i, j;
1342
1343     i = 0;
1344     do {
1345         ret = find_extension_subject_alt_name(c, &i, &sa);
1346         if (ret == HX509_EXTENSION_NOT_FOUND) {
1347             ret = 0;
1348             break;
1349         } else if (ret != 0)
1350             break;
1351
1352         for (j = 0; j < sa.len; j++) {
1353             if (n->element == sa.val[j].element) {
1354                 *same = 1;
1355                 ret = match_general_name(n, &sa.val[j], match);
1356             }
1357         }
1358         free_GeneralNames(&sa);
1359     } while (1);
1360
1361     return ret;
1362 }
1363
1364
1365 static int
1366 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1367 {
1368     int name, alt_name, same;
1369     unsigned int i;
1370     int ret = 0;
1371
1372     name = alt_name = same = *match = 0;
1373     for (i = 0; i < t->len; i++) {
1374         if (t->val[i].minimum && t->val[i].maximum)
1375             return HX509_RANGE;
1376
1377         /*
1378          * If the constraint apply to directoryNames, test is with
1379          * subjectName of the certificate if the certificate have a
1380          * non-null (empty) subjectName.
1381          */
1382
1383         if (t->val[i].base.element == choice_GeneralName_directoryName
1384             && !subject_null_p(c))
1385         {
1386             GeneralName certname;
1387             
1388             memset(&certname, 0, sizeof(certname));
1389             certname.element = choice_GeneralName_directoryName;
1390             certname.u.directoryName.element = 
1391                 c->tbsCertificate.subject.element;
1392             certname.u.directoryName.u.rdnSequence = 
1393                 c->tbsCertificate.subject.u.rdnSequence;
1394     
1395             ret = match_general_name(&t->val[i].base, &certname, &name);
1396         }
1397
1398         /* Handle subjectAltNames, this is icky since they
1399          * restrictions only apply if the subjectAltName is of the
1400          * same type. So if there have been a match of type, require
1401          * altname to be set.
1402          */
1403         ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1404     }
1405     if (name && (!same || alt_name))
1406         *match = 1;
1407     return ret;
1408 }
1409
1410 static int
1411 check_name_constraints(hx509_context context, 
1412                        const hx509_name_constraints *nc,
1413                        const Certificate *c)
1414 {
1415     int match, ret;
1416     int i;
1417
1418     for (i = 0 ; i < nc->len; i++) {
1419         GeneralSubtrees gs;
1420
1421         if (nc->val[i].permittedSubtrees) {
1422             GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1423             ret = match_tree(&gs, c, &match);
1424             if (ret) {
1425                 hx509_clear_error_string(context);
1426                 return ret;
1427             }
1428             /* allow null subjectNames, they wont matches anything */
1429             if (match == 0 && !subject_null_p(c)) {
1430                 hx509_clear_error_string(context);
1431                 return HX509_VERIFY_CONSTRAINTS;
1432             }
1433         }
1434         if (nc->val[i].excludedSubtrees) {
1435             GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1436             ret = match_tree(&gs, c, &match);
1437             if (ret) {
1438                 hx509_clear_error_string(context);
1439                 return ret;
1440             }
1441             if (match) {
1442                 hx509_clear_error_string(context);
1443                 return HX509_VERIFY_CONSTRAINTS;
1444             }
1445         }
1446     }
1447     return 0;
1448 }
1449
1450 static void
1451 free_name_constraints(hx509_name_constraints *nc)
1452 {
1453     int i;
1454
1455     for (i = 0 ; i < nc->len; i++)
1456         free_NameConstraints(&nc->val[i]);
1457     free(nc->val);
1458 }
1459
1460 int
1461 hx509_verify_path(hx509_context context,
1462                   hx509_verify_ctx ctx,
1463                   hx509_cert cert,
1464                   hx509_certs pool)
1465 {
1466     hx509_name_constraints nc;
1467     hx509_path path;
1468 #if 0
1469     const AlgorithmIdentifier *alg_id;
1470 #endif
1471     int ret, i, proxy_cert_depth;
1472     enum certtype type;
1473     Name proxy_issuer;
1474     hx509_certs anchors = NULL;
1475
1476     memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1477
1478     ret = init_name_constraints(&nc);
1479     if (ret)    
1480         return ret;
1481
1482     path.val = NULL;
1483     path.len = 0;
1484
1485     if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1486         ctx->time_now = time(NULL);
1487
1488     /*
1489      *
1490      */
1491     ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors);
1492     if (ret)
1493         goto out;
1494     ret = hx509_certs_merge(context, anchors, ctx->trust_anchors);
1495     if (ret)
1496         goto out;
1497     ret = hx509_certs_merge(context, anchors, context->default_trust_anchors);
1498     if (ret)
1499         goto out;
1500
1501     /*
1502      * Calculate the path from the certificate user presented to the
1503      * to an anchor.
1504      */
1505     ret = _hx509_calculate_path(context, 0, ctx->time_now,
1506                                 anchors, ctx->max_depth,
1507                                 cert, pool, &path);
1508     if (ret)
1509         goto out;
1510
1511 #if 0
1512     alg_id = path.val[path->len - 1]->data->tbsCertificate.signature;
1513 #endif
1514
1515     /*
1516      * Check CA and proxy certificate chain from the top of the
1517      * certificate chain. Also check certificate is valid with respect
1518      * to the current time.
1519      *
1520      */
1521
1522     proxy_cert_depth = 0;
1523
1524     if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1525         type = PROXY_CERT;
1526     else
1527         type = EE_CERT;
1528
1529     for (i = 0; i < path.len; i++) {
1530         Certificate *c;
1531         time_t t;
1532
1533         c = _hx509_get_cert(path.val[i]);
1534         
1535         /*
1536          * Lets do some basic check on issuer like
1537          * keyUsage.keyCertSign and basicConstraints.cA bit depending
1538          * on what type of certificate this is.
1539          */
1540
1541         switch (type) {
1542         case CA_CERT:
1543             /* XXX make constants for keyusage */
1544             ret = check_key_usage(context, c, 1 << 5,
1545                                   REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1546             if (ret) {
1547                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1548                                        "Key usage missing from CA certificate");
1549                 goto out;
1550             }
1551             break;
1552         case PROXY_CERT: {
1553             ProxyCertInfo info;     
1554
1555             if (is_proxy_cert(context, c, &info) == 0) {
1556                 int j;
1557
1558                 if (info.pCPathLenConstraint != NULL &&
1559                     *info.pCPathLenConstraint < i)
1560                 {
1561                     free_ProxyCertInfo(&info);
1562                     ret = HX509_PATH_TOO_LONG;
1563                     hx509_set_error_string(context, 0, ret,
1564                                            "Proxy certificate chain "
1565                                            "longer then allowed");
1566                     goto out;
1567                 }
1568                 /* XXX MUST check info.proxyPolicy */
1569                 free_ProxyCertInfo(&info);
1570                 
1571                 j = 0;
1572                 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
1573                     ret = HX509_PROXY_CERT_INVALID;
1574                     hx509_set_error_string(context, 0, ret, 
1575                                            "Proxy certificate have explicity "
1576                                            "forbidden subjectAltName");
1577                     goto out;
1578                 }
1579
1580                 j = 0;
1581                 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
1582                     ret = HX509_PROXY_CERT_INVALID;
1583                     hx509_set_error_string(context, 0, ret, 
1584                                            "Proxy certificate have explicity "
1585                                            "forbidden issuerAltName");
1586                     goto out;
1587                 }
1588                         
1589                 /* 
1590                  * The subject name of the proxy certificate should be
1591                  * CN=XXX,<proxy issuer>, prune of CN and check if its
1592                  * the same over the whole chain of proxy certs and
1593                  * then check with the EE cert when we get to it.
1594                  */
1595
1596                 if (proxy_cert_depth) {
1597                     ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject);
1598                     if (ret) {
1599                         ret = HX509_PROXY_CERT_NAME_WRONG;
1600                         hx509_set_error_string(context, 0, ret,
1601                                                "Base proxy name not right");
1602                         goto out;
1603                     }
1604                 }
1605
1606                 free_Name(&proxy_issuer);
1607
1608                 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
1609                 if (ret) {
1610                     hx509_clear_error_string(context);
1611                     goto out;
1612                 }
1613
1614                 j = proxy_issuer.u.rdnSequence.len;
1615                 if (proxy_issuer.u.rdnSequence.len < 2 
1616                     || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
1617                     || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
1618                                         oid_id_at_commonName()))
1619                 {
1620                     ret = HX509_PROXY_CERT_NAME_WRONG;
1621                     hx509_set_error_string(context, 0, ret,
1622                                            "Proxy name too short or "
1623                                            "does not have Common name "
1624                                            "at the top");
1625                     goto out;
1626                 }
1627
1628                 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
1629                 proxy_issuer.u.rdnSequence.len -= 1;
1630
1631                 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer);
1632                 if (ret != 0) {
1633                     ret = HX509_PROXY_CERT_NAME_WRONG;
1634                     hx509_set_error_string(context, 0, ret,
1635                                            "Proxy issuer name not as expected");
1636                     goto out;
1637                 }
1638
1639                 break;
1640             } else {
1641                 /* 
1642                  * Now we are done with the proxy certificates, this
1643                  * cert was an EE cert and we we will fall though to
1644                  * EE checking below.
1645                  */
1646                 type = EE_CERT;
1647                 /* FALLTHOUGH */
1648             }
1649         }
1650         case EE_CERT:
1651             /*
1652              * If there where any proxy certificates in the chain
1653              * (proxy_cert_depth > 0), check that the proxy issuer
1654              * matched proxy certificates "base" subject.
1655              */
1656             if (proxy_cert_depth) {
1657
1658                 ret = _hx509_name_cmp(&proxy_issuer,
1659                                       &c->tbsCertificate.subject);
1660                 if (ret) {
1661                     ret = HX509_PROXY_CERT_NAME_WRONG;
1662                     hx509_clear_error_string(context);
1663                     goto out;
1664                 }
1665                 if (cert->basename)
1666                     hx509_name_free(&cert->basename);
1667                 
1668                 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
1669                 if (ret) {
1670                     hx509_clear_error_string(context);
1671                     goto out;
1672                 }
1673             }
1674
1675             break;
1676         }
1677
1678         ret = check_basic_constraints(context, c, type, i - proxy_cert_depth);
1679         if (ret)
1680             goto out;
1681             
1682         /*
1683          * Don't check the trust anchors expiration time since they
1684          * are transported out of band, from RFC3820.
1685          */
1686         if (i + 1 != path.len || CHECK_TA(ctx)) {
1687
1688             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
1689             if (t > ctx->time_now) {
1690                 ret = HX509_CERT_USED_BEFORE_TIME;
1691                 hx509_clear_error_string(context);
1692                 goto out;
1693             }
1694             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
1695             if (t < ctx->time_now) {
1696                 ret = HX509_CERT_USED_AFTER_TIME;
1697                 hx509_clear_error_string(context);
1698                 goto out;
1699             }
1700         }
1701
1702         if (type == EE_CERT)
1703             type = CA_CERT;
1704         else if (type == PROXY_CERT)
1705             proxy_cert_depth++;
1706     }
1707
1708     /*
1709      * Verify constraints, do this backward so path constraints are
1710      * checked in the right order.
1711      */
1712
1713     for (ret = 0, i = path.len - 1; i >= 0; i--) {
1714         Certificate *c;
1715
1716         c = _hx509_get_cert(path.val[i]);
1717
1718 #if 0
1719         /* check that algorithm and parameters is the same */
1720         /* XXX this is wrong */
1721         ret = alg_cmp(&c->tbsCertificate.signature, alg_id);
1722         if (ret) {
1723             hx509_clear_error_string(context);
1724             ret = HX509_PATH_ALGORITHM_CHANGED;
1725             goto out;
1726         }
1727 #endif
1728
1729         /* verify name constraints, not for selfsigned and anchor */
1730         if (!certificate_is_self_signed(c) || i == path.len - 1) {
1731             ret = check_name_constraints(context, &nc, c);
1732             if (ret) {
1733                 goto out;
1734             }
1735         }
1736         ret = add_name_constraints(context, c, i == 0, &nc);
1737         if (ret)
1738             goto out;
1739
1740         /* XXX verify all other silly constraints */
1741
1742     }
1743
1744     /*
1745      * Verify that no certificates has been revoked.
1746      */
1747
1748     if (ctx->revoke_ctx) {
1749         hx509_certs certs;
1750
1751         ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
1752                                NULL, &certs);
1753         if (ret)
1754             goto out;
1755
1756         for (i = 0; i < path.len; i++) {
1757             ret = hx509_certs_add(context, certs, path.val[i]);
1758             if (ret) {
1759                 hx509_certs_free(&certs);
1760                 goto out;
1761             }
1762         }
1763         ret = hx509_certs_merge(context, certs, pool);
1764         if (ret) {
1765             hx509_certs_free(&certs);
1766             goto out;
1767         }
1768
1769         for (i = 0; i < path.len - 1; i++) {
1770             int parent = (i < path.len - 1) ? i + 1 : i;
1771
1772             ret = hx509_revoke_verify(context,
1773                                       ctx->revoke_ctx, 
1774                                       certs,
1775                                       ctx->time_now,
1776                                       path.val[i],
1777                                       path.val[parent]);
1778             if (ret) {
1779                 hx509_certs_free(&certs);
1780                 goto out;
1781             }
1782         }
1783         hx509_certs_free(&certs);
1784     }
1785
1786 #if 0
1787     for (i = path.len - 1; i >= 0; i--) {
1788         _hx509_print_cert_subject(path.val[i]);
1789     }
1790 #endif
1791
1792     /*
1793      * Verify signatures, do this backward so public key working
1794      * parameter is passed up from the anchor up though the chain.
1795      */
1796
1797     for (i = path.len - 1; i >= 0; i--) {
1798         Certificate *signer, *c;
1799
1800         c = _hx509_get_cert(path.val[i]);
1801
1802         /* is last in chain (trust anchor) */
1803         if (i == path.len - 1) {
1804             signer = path.val[i]->data;
1805
1806             /* if trust anchor is not self signed, don't check sig */
1807             if (!certificate_is_self_signed(signer))
1808                 continue;
1809         } else {
1810             /* take next certificate in chain */
1811             signer = path.val[i + 1]->data;
1812         }
1813
1814         /* verify signatureValue */
1815         ret = _hx509_verify_signature_bitstring(context,
1816                                                 signer,
1817                                                 &c->signatureAlgorithm,
1818                                                 &c->tbsCertificate._save,
1819                                                 &c->signatureValue);
1820         if (ret) {
1821             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1822                                    "Failed to verify signature of certificate");
1823             goto out;
1824         }
1825     }
1826
1827 out:
1828     hx509_certs_free(&anchors);
1829     free_Name(&proxy_issuer);
1830     free_name_constraints(&nc);
1831     _hx509_path_free(&path);
1832
1833     return ret;
1834 }
1835
1836 int
1837 hx509_verify_signature(hx509_context context,
1838                        const hx509_cert signer,
1839                        const AlgorithmIdentifier *alg,
1840                        const heim_octet_string *data,
1841                        const heim_octet_string *sig)
1842 {
1843     return _hx509_verify_signature(context, signer->data, alg, data, sig);
1844 }
1845
1846 int
1847 hx509_verify_hostname(hx509_context context,
1848                       const hx509_cert cert,
1849                       int require_match,
1850                       const char *hostname,
1851                       const struct sockaddr *sa,
1852                       /* XXX krb5_socklen_t */ int sa_size) 
1853 {
1854     if (sa && sa_size <= 0)
1855         return EINVAL;
1856     return 0;
1857 }
1858
1859 int
1860 _hx509_set_cert_attribute(hx509_context context,
1861                           hx509_cert cert, 
1862                           const heim_oid *oid, 
1863                           const heim_octet_string *attr)
1864 {
1865     hx509_cert_attribute a;
1866     void *d;
1867
1868     if (hx509_cert_get_attribute(cert, oid) != NULL)
1869         return 0;
1870
1871     d = realloc(cert->attrs.val, 
1872                 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
1873     if (d == NULL) {
1874         hx509_clear_error_string(context);
1875         return ENOMEM;
1876     }
1877     cert->attrs.val = d;
1878
1879     a = malloc(sizeof(*a));
1880     if (a == NULL)
1881         return ENOMEM;
1882
1883     der_copy_octet_string(attr, &a->data);
1884     der_copy_oid(oid, &a->oid);
1885     
1886     cert->attrs.val[cert->attrs.len] = a;
1887     cert->attrs.len++;
1888
1889     return 0;
1890 }
1891
1892 hx509_cert_attribute
1893 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
1894 {
1895     int i;
1896     for (i = 0; i < cert->attrs.len; i++)
1897         if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
1898             return cert->attrs.val[i];
1899     return NULL;
1900 }
1901
1902 int
1903 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
1904 {
1905     if (cert->friendlyname)
1906         free(cert->friendlyname);
1907     cert->friendlyname = strdup(name);
1908     if (cert->friendlyname == NULL)
1909         return ENOMEM;
1910     return 0;
1911 }
1912
1913
1914 const char *
1915 hx509_cert_get_friendly_name(hx509_cert cert)
1916 {
1917     hx509_cert_attribute a;
1918     PKCS9_friendlyName n;
1919     size_t sz;
1920     int ret, i;
1921
1922     if (cert->friendlyname)
1923         return cert->friendlyname;
1924
1925     a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
1926     if (a == NULL) {
1927         /* XXX use subject name ? */
1928         return NULL; 
1929     }
1930
1931     ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
1932     if (ret)
1933         return NULL;
1934         
1935     if (n.len != 1) {
1936         free_PKCS9_friendlyName(&n);
1937         return NULL;
1938     }
1939     
1940     cert->friendlyname = malloc(n.val[0].length + 1);
1941     if (cert->friendlyname == NULL) {
1942         free_PKCS9_friendlyName(&n);
1943         return NULL;
1944     }
1945     
1946     for (i = 0; i < n.val[0].length; i++) {
1947         if (n.val[0].data[i] <= 0xff)
1948             cert->friendlyname[i] = n.val[0].data[i] & 0xff;
1949         else
1950             cert->friendlyname[i] = 'X';
1951     }
1952     cert->friendlyname[i] = '\0';
1953     free_PKCS9_friendlyName(&n);
1954
1955     return cert->friendlyname;
1956 }
1957
1958 void
1959 _hx509_query_clear(hx509_query *q)
1960 {
1961     memset(q, 0, sizeof(*q));
1962 }
1963
1964 int
1965 hx509_query_alloc(hx509_context context, hx509_query **q)
1966 {
1967     *q = calloc(1, sizeof(**q));
1968     if (*q == NULL)
1969         return ENOMEM;
1970     return 0;
1971 }
1972
1973 void
1974 hx509_query_match_option(hx509_query *q, hx509_query_option option)
1975 {
1976     switch(option) {
1977     case HX509_QUERY_OPTION_PRIVATE_KEY:
1978         q->match |= HX509_QUERY_PRIVATE_KEY;
1979         break;
1980     case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
1981         q->match |= HX509_QUERY_KU_ENCIPHERMENT;
1982         break;
1983     case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
1984         q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
1985         break;
1986     case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
1987         q->match |= HX509_QUERY_KU_KEYCERTSIGN;
1988         break;
1989     case HX509_QUERY_OPTION_END:
1990     default:
1991         break;
1992     }
1993 }
1994
1995 int
1996 hx509_query_match_issuer_serial(hx509_query *q,
1997                                 const Name *issuer, 
1998                                 const heim_integer *serialNumber)
1999 {
2000     int ret;
2001     if (q->serial) {
2002         der_free_heim_integer(q->serial);
2003         free(q->serial);
2004     }
2005     q->serial = malloc(sizeof(*q->serial));
2006     if (q->serial == NULL)
2007         return ENOMEM;
2008     ret = der_copy_heim_integer(serialNumber, q->serial);
2009     if (ret) {
2010         free(q->serial);
2011         q->serial = NULL;
2012         return ret;
2013     }
2014     if (q->issuer_name) {
2015         free_Name(q->issuer_name);
2016         free(q->issuer_name);
2017     }
2018     q->issuer_name = malloc(sizeof(*q->issuer_name));
2019     if (q->issuer_name == NULL)
2020         return ENOMEM;
2021     ret = copy_Name(issuer, q->issuer_name);
2022     if (ret) {
2023         free(q->issuer_name);
2024         q->issuer_name = NULL;
2025         return ret;
2026     }
2027     q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2028     return 0;
2029 }
2030
2031
2032 int
2033 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2034 {
2035     if (q->friendlyname)
2036         free(q->friendlyname);
2037     q->friendlyname = strdup(name);
2038     if (q->friendlyname == NULL)
2039         return ENOMEM;
2040     q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2041     return 0;
2042 }
2043
2044 int
2045 hx509_query_match_cmp_func(hx509_query *q,
2046                            int (*func)(void *, hx509_cert),
2047                            void *ctx)
2048 {
2049     if (func)
2050         q->match |= HX509_QUERY_MATCH_FUNCTION;
2051     else
2052         q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2053     q->cmp_func = func;
2054     q->cmp_func_ctx = ctx;
2055     return 0;
2056 }
2057
2058
2059 void
2060 hx509_query_free(hx509_context context, hx509_query *q)
2061 {
2062     if (q->serial) {
2063         der_free_heim_integer(q->serial);
2064         free(q->serial);
2065         q->serial = NULL;
2066     }
2067     if (q->issuer_name) {
2068         free_Name(q->issuer_name);
2069         free(q->issuer_name);
2070         q->issuer_name = NULL;
2071     }
2072     if (q) {
2073         free(q->friendlyname);
2074         memset(q, 0, sizeof(*q));
2075     }
2076     free(q);
2077 }
2078
2079 int
2080 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2081 {
2082     Certificate *c = _hx509_get_cert(cert);
2083
2084     _hx509_query_statistic(context, 1, q);
2085
2086     if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2087         _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2088         return 0;
2089
2090     if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2091         _hx509_Certificate_cmp(q->certificate, c) != 0)
2092         return 0;
2093
2094     if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2095         && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2096         return 0;
2097
2098     if ((q->match & HX509_QUERY_MATCH_ISSUER_NAME)
2099         && _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name) != 0)
2100         return 0;
2101
2102     if ((q->match & HX509_QUERY_MATCH_SUBJECT_NAME)
2103         && _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name) != 0)
2104         return 0;
2105
2106     if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2107         SubjectKeyIdentifier si;
2108         int ret;
2109
2110         ret = _hx509_find_extension_subject_key_id(c, &si);
2111         if (ret == 0) {
2112             if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2113                 ret = 1;
2114             free_SubjectKeyIdentifier(&si);
2115         }
2116         if (ret)
2117             return 0;
2118     }
2119     if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2120         return 0;
2121     if ((q->match & HX509_QUERY_PRIVATE_KEY) && 
2122         _hx509_cert_private_key(cert) == NULL)
2123         return 0;
2124
2125     {
2126         unsigned ku = 0;
2127         if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2128             ku |= (1 << 0);
2129         if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2130             ku |= (1 << 1);
2131         if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2132             ku |= (1 << 2);
2133         if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2134             ku |= (1 << 3);
2135         if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2136             ku |= (1 << 4);
2137         if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2138             ku |= (1 << 5);
2139         if (q->match & HX509_QUERY_KU_CRLSIGN)
2140             ku |= (1 << 6);
2141         if (ku && check_key_usage(context, c, ku, TRUE))
2142             return 0;
2143     }
2144     if ((q->match & HX509_QUERY_ANCHOR))
2145         return 0;
2146
2147     if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2148         hx509_cert_attribute a;
2149
2150         a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2151         if (a == NULL)
2152             return 0;
2153         if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2154             return 0;
2155     }
2156
2157     if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2158         size_t i;
2159
2160         for (i = 0; i < q->path->len; i++)
2161             if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2162                 return 0;
2163     }
2164     if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2165         const char *name = hx509_cert_get_friendly_name(cert);
2166         if (name == NULL)
2167             return 0;
2168         if (strcasecmp(q->friendlyname, name) != 0)
2169             return 0;
2170     }
2171     if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2172         int ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
2173         if (ret != 0)
2174             return 0;
2175     }
2176
2177     if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2178         heim_octet_string os;
2179         int ret;
2180
2181         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2182         os.length = 
2183             c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2184
2185         ret = _hx509_verify_signature(context,
2186                                       NULL,
2187                                       hx509_signature_sha1(),
2188                                       &os,
2189                                       q->keyhash_sha1);
2190         if (ret != 0)
2191             return 0;
2192     }
2193
2194     if (q->match & HX509_QUERY_MATCH_TIME) {
2195         time_t t;
2196         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2197         if (t > q->timenow)
2198             return 0;
2199         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2200         if (t < q->timenow)
2201             return 0;
2202     }
2203
2204     if (q->match & ~HX509_QUERY_MASK)
2205         return 0;
2206
2207     return 1;
2208 }
2209
2210 void
2211 hx509_query_statistic_file(hx509_context context, const char *fn)
2212 {
2213     if (context->querystat)
2214         free(context->querystat);
2215     context->querystat = strdup(fn);
2216 }
2217
2218 void
2219 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
2220 {
2221     FILE *f;
2222     if (context->querystat == NULL)
2223         return;
2224     f = fopen(context->querystat, "a");
2225     if (f == NULL)
2226         return;
2227     fprintf(f, "%d %d\n", type, q->match);
2228     fclose(f);
2229 }
2230
2231 static const char *statname[] = {
2232     "find issuer cert",
2233     "match serialnumber",
2234     "match issuer name",
2235     "match subject name",
2236     "match subject key id",
2237     "match issuer id",
2238     "private key",
2239     "ku encipherment",
2240     "ku digitalsignature",
2241     "ku keycertsign",
2242     "ku crlsign",
2243     "ku nonrepudiation",
2244     "ku keyagreement",
2245     "ku dataencipherment",
2246     "anchor",
2247     "match certificate",
2248     "match local key id",
2249     "no match path",
2250     "match friendly name",
2251     "match function",
2252     "match key hash sha1",
2253     "match time"
2254 };
2255
2256 struct stat_el {
2257     unsigned long stats;
2258     unsigned int index;
2259 };
2260
2261
2262 static int
2263 stat_sort(const void *a, const void *b)
2264 {
2265     const struct stat_el *ae = a;
2266     const struct stat_el *be = b;
2267     return be->stats - ae->stats;
2268 }
2269
2270 void
2271 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
2272 {
2273     rtbl_t t;
2274     FILE *f;
2275     int type, mask, i, num;
2276     unsigned long multiqueries = 0, totalqueries = 0;
2277     struct stat_el stats[32];
2278
2279     if (context->querystat == NULL)
2280         return;
2281     f = fopen(context->querystat, "r");
2282     if (f == NULL) {
2283         fprintf(out, "No statistic file %s: %s.\n", 
2284                 context->querystat, strerror(errno));
2285         return;
2286     }
2287     
2288     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
2289         stats[i].index = i;
2290         stats[i].stats = 0;
2291     }
2292
2293     while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
2294         if (type != printtype)
2295             continue;
2296         num = i = 0;
2297         while (mask && i < sizeof(stats)/sizeof(stats[0])) {
2298             if (mask & 1) {
2299                 stats[i].stats++;
2300                 num++;
2301             }
2302             mask = mask >>1 ;
2303             i++;
2304         }
2305         if (num > 1)
2306             multiqueries++;
2307         totalqueries++;
2308     }
2309     fclose(f);
2310
2311     qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
2312
2313     t = rtbl_create();
2314     if (t == NULL)
2315         errx(1, "out of memory");
2316
2317     rtbl_set_separator (t, "  ");
2318     
2319     rtbl_add_column_by_id (t, 0, "Name", 0);
2320     rtbl_add_column_by_id (t, 1, "Counter", 0);
2321
2322
2323     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
2324         char str[10];
2325
2326         if (stats[i].index < sizeof(statname)/sizeof(statname[0])) 
2327             rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
2328         else {
2329             snprintf(str, sizeof(str), "%d", stats[i].index);
2330             rtbl_add_column_entry_by_id (t, 0, str);
2331         }
2332         snprintf(str, sizeof(str), "%lu", stats[i].stats);
2333         rtbl_add_column_entry_by_id (t, 1, str);
2334     }
2335
2336     rtbl_format(t, out);
2337     rtbl_destroy(t);
2338
2339     fprintf(out, "\nQueries: multi %lu total %lu\n", 
2340             multiqueries, totalqueries);
2341 }
2342
2343 int
2344 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
2345                      const heim_oid *eku, int allow_any_eku)
2346 {
2347     ExtKeyUsage e;
2348     int ret, i;
2349
2350     ret = find_extension_eku(_hx509_get_cert(cert), &e);
2351     if (ret) {
2352         hx509_clear_error_string(context);
2353         return ret;
2354     }
2355
2356     for (i = 0; i < e.len; i++) {
2357         if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
2358             free_ExtKeyUsage(&e);
2359             return 0;
2360         }
2361         if (allow_any_eku) {
2362 #if 0
2363             if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
2364                 free_ExtKeyUsage(&e);
2365                 return 0;
2366             }
2367 #endif
2368         }
2369     }
2370     free_ExtKeyUsage(&e);
2371     hx509_clear_error_string(context);
2372     return HX509_CERTIFICATE_MISSING_EKU;
2373 }
2374
2375 int
2376 _hx509_cert_get_keyusage(hx509_context context,
2377                          hx509_cert c,
2378                          KeyUsage *ku)
2379 {
2380     Certificate *cert;
2381     const Extension *e;
2382     size_t size;
2383     int ret, i = 0;
2384
2385     memset(ku, 0, sizeof(*ku));
2386
2387     cert = _hx509_get_cert(c);
2388
2389     if (_hx509_cert_get_version(cert) < 3)
2390         return 0;
2391
2392     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
2393     if (e == NULL)
2394         return HX509_KU_CERT_MISSING;
2395     
2396     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
2397     if (ret)
2398         return ret;
2399     return 0;
2400 }
2401
2402 int
2403 _hx509_cert_get_eku(hx509_context context,
2404                     hx509_cert cert,
2405                     ExtKeyUsage *e)
2406 {
2407     int ret;
2408
2409     memset(e, 0, sizeof(*e));
2410
2411     ret = find_extension_eku(_hx509_get_cert(cert), e);
2412     if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
2413         hx509_clear_error_string(context);
2414         return ret;
2415     }
2416     return 0;
2417 }
2418
2419 int
2420 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
2421 {
2422     size_t size;
2423     int ret;
2424
2425     os->data = NULL;
2426     os->length = 0;
2427
2428     ASN1_MALLOC_ENCODE(Certificate, os->data, os->length, 
2429                        _hx509_get_cert(c), &size, ret);
2430     if (ret)
2431         return ret;
2432     if (os->length != size)
2433         _hx509_abort("internal ASN.1 encoder error");
2434
2435     return ret;
2436 }