Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into pac-verify
[sfrench/samba-autobuild/.git] / source4 / 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$");
36 #include "crypto-headers.h"
37 #include <rtbl.h>
38
39 /**
40  * @page page_cert The basic certificate
41  *
42  * The basic hx509 cerificate object in hx509 is hx509_cert. The
43  * hx509_cert object is representing one X509/PKIX certificate and
44  * associated attributes; like private key, friendly name, etc.
45  *
46  * A hx509_cert object is usully found via the keyset interfaces (@ref
47  * page_keyset), but its also possible to create a certificate
48  * directly from a parsed object with hx509_cert_init() and
49  * hx509_cert_init_data().
50  *
51  * See the library functions here: @ref hx509_cert
52  */
53
54 struct hx509_verify_ctx_data {
55     hx509_certs trust_anchors;
56     int flags;
57 #define HX509_VERIFY_CTX_F_TIME_SET                     1
58 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE      2
59 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280              4
60 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS          8
61 #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS           16
62     time_t time_now;
63     unsigned int max_depth;
64 #define HX509_VERIFY_MAX_DEPTH 30
65     hx509_revoke_ctx revoke_ctx;
66 };
67
68 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
69 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
70 #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
71
72 struct _hx509_cert_attrs {
73     size_t len;
74     hx509_cert_attribute *val;
75 };
76
77 struct hx509_cert_data {
78     unsigned int ref;
79     char *friendlyname;
80     Certificate *data;
81     hx509_private_key private_key;
82     struct _hx509_cert_attrs attrs;
83     hx509_name basename;
84     _hx509_cert_release_func release;
85     void *ctx;
86 };
87
88 typedef struct hx509_name_constraints {
89     NameConstraints *val;
90     size_t len;
91 } hx509_name_constraints;
92
93 #define GeneralSubtrees_SET(g,var) \
94         (g)->len = (var)->len, (g)->val = (var)->val;
95
96 /**
97  * Creates a hx509 context that most functions in the library
98  * uses. The context is only allowed to be used by one thread at each
99  * moment. Free the context with hx509_context_free().
100  *
101  * @param context Returns a pointer to new hx509 context.
102  *
103  * @return Returns an hx509 error code.
104  *
105  * @ingroup hx509
106  */
107
108 int
109 hx509_context_init(hx509_context *context)
110 {
111     *context = calloc(1, sizeof(**context));
112     if (*context == NULL)
113         return ENOMEM;
114
115     _hx509_ks_null_register(*context);
116     _hx509_ks_mem_register(*context);
117     _hx509_ks_file_register(*context);
118     _hx509_ks_pkcs12_register(*context);
119     _hx509_ks_pkcs11_register(*context);
120     _hx509_ks_dir_register(*context);
121     _hx509_ks_keychain_register(*context);
122
123     ENGINE_add_conf_module();
124     OpenSSL_add_all_algorithms();
125
126     (*context)->ocsp_time_diff = HX509_DEFAULT_OCSP_TIME_DIFF;
127
128     initialize_hx_error_table_r(&(*context)->et_list);
129     initialize_asn1_error_table_r(&(*context)->et_list);
130
131 #ifdef HX509_DEFAULT_ANCHORS
132     (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
133                            NULL, &(*context)->default_trust_anchors);
134 #endif
135
136     return 0;
137 }
138
139 /**
140  * Selects if the hx509_revoke_verify() function is going to require
141  * the existans of a revokation method (OCSP, CRL) or not. Note that
142  * hx509_verify_path(), hx509_cms_verify_signed(), and other function
143  * call hx509_revoke_verify().
144  * 
145  * @param context hx509 context to change the flag for.
146  * @param flag zero, revokation method required, non zero missing
147  * revokation method ok
148  *
149  * @ingroup hx509_verify
150  */
151
152 void
153 hx509_context_set_missing_revoke(hx509_context context, int flag)
154 {
155     if (flag)
156         context->flags |= HX509_CTX_VERIFY_MISSING_OK;
157     else
158         context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
159 }
160
161 /**
162  * Free the context allocated by hx509_context_init().
163  * 
164  * @param context context to be freed.
165  *
166  * @ingroup hx509
167  */
168
169 void
170 hx509_context_free(hx509_context *context)
171 {
172     hx509_clear_error_string(*context);
173     if ((*context)->ks_ops) {
174         free((*context)->ks_ops);
175         (*context)->ks_ops = NULL;
176     }
177     (*context)->ks_num_ops = 0;
178     free_error_table ((*context)->et_list);
179     if ((*context)->querystat)
180         free((*context)->querystat);
181     memset(*context, 0, sizeof(**context));
182     free(*context);
183     *context = NULL;
184 }
185
186 /*
187  *
188  */
189
190 Certificate *
191 _hx509_get_cert(hx509_cert cert)
192 {
193     return cert->data;
194 }
195
196 /*
197  *
198  */
199
200 int
201 _hx509_cert_get_version(const Certificate *t)
202 {
203     return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
204 }
205
206 /**
207  * Allocate and init an hx509 certificate object from the decoded
208  * certificate `c´.
209  *
210  * @param context A hx509 context.
211  * @param c
212  * @param cert
213  *
214  * @return Returns an hx509 error code.
215  *
216  * @ingroup hx509_cert
217  */
218
219 int
220 hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
221 {
222     int ret;
223
224     *cert = malloc(sizeof(**cert));
225     if (*cert == NULL)
226         return ENOMEM;
227     (*cert)->ref = 1;
228     (*cert)->friendlyname = NULL;
229     (*cert)->attrs.len = 0;
230     (*cert)->attrs.val = NULL;
231     (*cert)->private_key = NULL;
232     (*cert)->basename = NULL;
233     (*cert)->release = NULL;
234     (*cert)->ctx = NULL;
235
236     (*cert)->data = calloc(1, sizeof(*(*cert)->data));
237     if ((*cert)->data == NULL) {
238         free(*cert);
239         return ENOMEM;
240     }
241     ret = copy_Certificate(c, (*cert)->data);
242     if (ret) {
243         free((*cert)->data);
244         free(*cert);
245         *cert = NULL;
246     }
247     return ret;
248 }
249
250 /**
251  * Just like hx509_cert_init(), but instead of a decode certificate
252  * takes an pointer and length to a memory region that contains a
253  * DER/BER encoded certificate.
254  *
255  * If the memory region doesn't contain just the certificate and
256  * nothing more the function will fail with
257  * HX509_EXTRA_DATA_AFTER_STRUCTURE.
258  *
259  * @param context A hx509 context.
260  * @param ptr pointer to memory region containing encoded certificate.
261  * @param len length of memory region.
262  * @param cert a return pointer to a hx509 certificate object, will
263  * contain NULL on error.
264  *
265  * @return An hx509 error code, see hx509_get_error_string().
266  *
267  * @ingroup hx509_cert
268  */
269
270 int
271 hx509_cert_init_data(hx509_context context, 
272                      const void *ptr,
273                      size_t len,
274                      hx509_cert *cert)
275 {
276     Certificate t;
277     size_t size;
278     int ret;
279
280     ret = decode_Certificate(ptr, len, &t, &size);
281     if (ret) {
282         hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
283         return ret;
284     }
285     if (size != len) {
286         hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
287                                "Extra data after certificate");
288         return HX509_EXTRA_DATA_AFTER_STRUCTURE;
289     }
290
291     ret = hx509_cert_init(context, &t, cert);
292     free_Certificate(&t);
293     return ret;
294 }
295
296 void
297 _hx509_cert_set_release(hx509_cert cert, 
298                         _hx509_cert_release_func release,
299                         void *ctx)
300 {
301     cert->release = release;
302     cert->ctx = ctx;
303 }
304
305
306 /* Doesn't make a copy of `private_key'. */
307
308 int
309 _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
310 {
311     if (cert->private_key)
312         _hx509_private_key_free(&cert->private_key);
313     cert->private_key = _hx509_private_key_ref(private_key);
314     return 0;
315 }
316
317 /**
318  * Free reference to the hx509 certificate object, if the refcounter
319  * reaches 0, the object if freed. Its allowed to pass in NULL.
320  *
321  * @param cert the cert to free.
322  *
323  * @ingroup hx509_cert
324  */
325
326 void
327 hx509_cert_free(hx509_cert cert)
328 {
329     int i;
330
331     if (cert == NULL)
332         return;
333
334     if (cert->ref <= 0)
335         _hx509_abort("cert refcount <= 0 on free");
336     if (--cert->ref > 0)
337         return;
338
339     if (cert->release)
340         (cert->release)(cert, cert->ctx);
341
342     if (cert->private_key)
343         _hx509_private_key_free(&cert->private_key);
344
345     free_Certificate(cert->data);
346     free(cert->data);
347
348     for (i = 0; i < cert->attrs.len; i++) {
349         der_free_octet_string(&cert->attrs.val[i]->data);
350         der_free_oid(&cert->attrs.val[i]->oid);
351         free(cert->attrs.val[i]);
352     }
353     free(cert->attrs.val);
354     free(cert->friendlyname);
355     if (cert->basename)
356         hx509_name_free(&cert->basename);
357     memset(cert, 0, sizeof(cert));
358     free(cert);
359 }
360
361 /**
362  * Add a reference to a hx509 certificate object.
363  *
364  * @param cert a pointer to an hx509 certificate object.
365  *
366  * @return the same object as is passed in.
367  *
368  * @ingroup hx509_cert
369  */
370
371 hx509_cert
372 hx509_cert_ref(hx509_cert cert)
373 {
374     if (cert == NULL)
375         return NULL;
376     if (cert->ref <= 0)
377         _hx509_abort("cert refcount <= 0");
378     cert->ref++;
379     if (cert->ref == 0)
380         _hx509_abort("cert refcount == 0");
381     return cert;
382 }
383
384 /**
385  * Allocate an verification context that is used fo control the
386  * verification process. 
387  *
388  * @param context A hx509 context.
389  * @param ctx returns a pointer to a hx509_verify_ctx object.
390  *
391  * @return An hx509 error code, see hx509_get_error_string().
392  *
393  * @ingroup hx509_verify
394  */
395
396 int
397 hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
398 {
399     hx509_verify_ctx c;
400
401     c = calloc(1, sizeof(*c));
402     if (c == NULL)
403         return ENOMEM;
404
405     c->max_depth = HX509_VERIFY_MAX_DEPTH;
406
407     *ctx = c;
408     
409     return 0;
410 }
411
412 /**
413  * Free an hx509 verification context.
414  *
415  * @param ctx the context to be freed.
416  *
417  * @ingroup hx509_verify
418  */
419
420 void
421 hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
422 {
423     if (ctx) {
424         hx509_certs_free(&ctx->trust_anchors);
425         hx509_revoke_free(&ctx->revoke_ctx);
426         memset(ctx, 0, sizeof(*ctx));
427     }
428     free(ctx);
429 }
430
431 /**
432  * Set the trust anchors in the verification context, makes an
433  * reference to the keyset, so the consumer can free the keyset
434  * independent of the destruction of the verification context (ctx).
435  *
436  * @param ctx a verification context
437  * @param set a keyset containing the trust anchors.
438  *
439  * @ingroup hx509_verify
440  */
441
442 void
443 hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
444 {
445     ctx->trust_anchors = _hx509_certs_ref(set);
446 }
447
448 /**
449  * Attach an revocation context to the verfication context, , makes an
450  * reference to the revoke context, so the consumer can free the
451  * revoke context independent of the destruction of the verification
452  * context. If there is no revoke context, the verification process is
453  * NOT going to check any verification status.
454  *
455  * @param ctx a verification context.
456  * @param revoke_ctx a revoke context.
457  *
458  * @ingroup hx509_verify
459  */
460
461 void
462 hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
463 {
464     if (ctx->revoke_ctx)
465         hx509_revoke_free(&ctx->revoke_ctx);
466     ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
467 }
468
469 /**
470  * Set the clock time the the verification process is going to
471  * use. Used to check certificate in the past and future time. If not
472  * set the current time will be used.
473  *
474  * @param ctx a verification context.
475  * @param t the time the verifiation is using.
476  *
477  *
478  * @ingroup hx509_verify
479  */
480
481 void
482 hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
483 {
484     ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
485     ctx->time_now = t;
486 }
487
488 time_t
489 _hx509_verify_get_time(hx509_verify_ctx ctx)
490 {
491     return ctx->time_now;
492 }
493
494 /**
495  * Set the maximum depth of the certificate chain that the path
496  * builder is going to try.
497  *
498  * @param ctx a verification context
499  * @param max_depth maxium depth of the certificate chain, include
500  * trust anchor.
501  *
502  * @ingroup hx509_verify
503  */
504
505 void
506 hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
507 {
508     ctx->max_depth = max_depth;
509 }
510
511 /**
512  * Allow or deny the use of proxy certificates
513  *
514  * @param ctx a verification context
515  * @param boolean if non zero, allow proxy certificates.
516  *
517  * @ingroup hx509_verify
518  */
519
520 void
521 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
522 {
523     if (boolean)
524         ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
525     else
526         ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
527 }
528
529 /**
530  * Select strict RFC3280 verification of certificiates. This means
531  * checking key usage on CA certificates, this will make version 1
532  * certificiates unuseable.
533  *
534  * @param ctx a verification context
535  * @param boolean if non zero, use strict verification.
536  *
537  * @ingroup hx509_verify
538  */
539
540 void
541 hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
542 {
543     if (boolean)
544         ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
545     else
546         ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
547 }
548
549 /**
550  * Allow using the operating system builtin trust anchors if no other
551  * trust anchors are configured.
552  *
553  * @param ctx a verification context
554  * @param boolean if non zero, useing the operating systems builtin
555  * trust anchors.
556  *
557  *
558  * @return An hx509 error code, see hx509_get_error_string().
559  *
560  * @ingroup hx509_cert
561  */
562
563 void
564 hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
565 {
566     if (boolean)
567         ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
568     else
569         ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
570 }
571
572 static const Extension *
573 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
574 {
575     const TBSCertificate *c = &cert->tbsCertificate;
576
577     if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
578         return NULL;
579     
580     for (;*idx < c->extensions->len; (*idx)++) {
581         if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
582             return &c->extensions->val[(*idx)++];
583     }
584     return NULL;
585 }
586
587 static int
588 find_extension_auth_key_id(const Certificate *subject, 
589                            AuthorityKeyIdentifier *ai)
590 {
591     const Extension *e;
592     size_t size;
593     int i = 0;
594
595     memset(ai, 0, sizeof(*ai));
596
597     e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
598     if (e == NULL)
599         return HX509_EXTENSION_NOT_FOUND;
600     
601     return decode_AuthorityKeyIdentifier(e->extnValue.data, 
602                                          e->extnValue.length, 
603                                          ai, &size);
604 }
605
606 int
607 _hx509_find_extension_subject_key_id(const Certificate *issuer,
608                                      SubjectKeyIdentifier *si)
609 {
610     const Extension *e;
611     size_t size;
612     int i = 0;
613
614     memset(si, 0, sizeof(*si));
615
616     e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
617     if (e == NULL)
618         return HX509_EXTENSION_NOT_FOUND;
619     
620     return decode_SubjectKeyIdentifier(e->extnValue.data, 
621                                        e->extnValue.length,
622                                        si, &size);
623 }
624
625 static int
626 find_extension_name_constraints(const Certificate *subject, 
627                                 NameConstraints *nc)
628 {
629     const Extension *e;
630     size_t size;
631     int i = 0;
632
633     memset(nc, 0, sizeof(*nc));
634
635     e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
636     if (e == NULL)
637         return HX509_EXTENSION_NOT_FOUND;
638     
639     return decode_NameConstraints(e->extnValue.data, 
640                                   e->extnValue.length, 
641                                   nc, &size);
642 }
643
644 static int
645 find_extension_subject_alt_name(const Certificate *cert, int *i,
646                                 GeneralNames *sa)
647 {
648     const Extension *e;
649     size_t size;
650
651     memset(sa, 0, sizeof(*sa));
652
653     e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
654     if (e == NULL)
655         return HX509_EXTENSION_NOT_FOUND;
656     
657     return decode_GeneralNames(e->extnValue.data, 
658                                e->extnValue.length,
659                                sa, &size);
660 }
661
662 static int
663 find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
664 {
665     const Extension *e;
666     size_t size;
667     int i = 0;
668
669     memset(eku, 0, sizeof(*eku));
670
671     e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
672     if (e == NULL)
673         return HX509_EXTENSION_NOT_FOUND;
674     
675     return decode_ExtKeyUsage(e->extnValue.data, 
676                               e->extnValue.length,
677                               eku, &size);
678 }
679
680 static int
681 add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
682 {
683     void *p;
684     int ret;
685
686     p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
687     if (p == NULL)
688         return ENOMEM;
689     list->val = p;
690     ret = der_copy_octet_string(entry, &list->val[list->len]);
691     if (ret)
692         return ret;
693     list->len++;
694     return 0;
695 }
696
697 /**
698  * Free a list of octet strings returned by another hx509 library
699  * function.
700  *
701  * @param list list to be freed.
702  *
703  * @ingroup hx509_misc
704  */
705
706 void
707 hx509_free_octet_string_list(hx509_octet_string_list *list)
708 {
709     int i;
710     for (i = 0; i < list->len; i++)
711         der_free_octet_string(&list->val[i]);
712     free(list->val);
713     list->val = NULL;
714     list->len = 0;
715 }
716
717 /**
718  * Return a list of subjectAltNames specified by oid in the
719  * certificate. On error the 
720  *
721  * The returned list of octet string should be freed with
722  * hx509_free_octet_string_list().
723  *
724  * @param context A hx509 context.
725  * @param cert a hx509 certificate object.
726  * @param oid an oid to for SubjectAltName.
727  * @param list list of matching SubjectAltName.
728  *
729  * @return An hx509 error code, see hx509_get_error_string().
730  *
731  * @ingroup hx509_cert
732  */
733
734 int
735 hx509_cert_find_subjectAltName_otherName(hx509_context context,
736                                          hx509_cert cert,
737                                          const heim_oid *oid,
738                                          hx509_octet_string_list *list)
739 {
740     GeneralNames sa;
741     int ret, i, j;
742
743     list->val = NULL;
744     list->len = 0;
745
746     i = 0;
747     while (1) {
748         ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
749         i++;
750         if (ret == HX509_EXTENSION_NOT_FOUND) {
751             ret = 0;
752             break;
753         } else if (ret != 0) {
754             hx509_set_error_string(context, 0, ret, "Error searching for SAN");
755             hx509_free_octet_string_list(list);
756             return ret;
757         }
758
759         for (j = 0; j < sa.len; j++) {
760             if (sa.val[j].element == choice_GeneralName_otherName &&
761                 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0) 
762             {
763                 ret = add_to_list(list, &sa.val[j].u.otherName.value);
764                 if (ret) {
765                     hx509_set_error_string(context, 0, ret, 
766                                            "Error adding an exra SAN to "
767                                            "return list");
768                     hx509_free_octet_string_list(list);
769                     free_GeneralNames(&sa);
770                     return ret;
771                 }
772             }
773         }
774         free_GeneralNames(&sa);
775     }
776     return 0;
777 }
778
779
780 static int
781 check_key_usage(hx509_context context, const Certificate *cert, 
782                 unsigned flags, int req_present)
783 {
784     const Extension *e;
785     KeyUsage ku;
786     size_t size;
787     int ret, i = 0;
788     unsigned ku_flags;
789
790     if (_hx509_cert_get_version(cert) < 3)
791         return 0;
792
793     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
794     if (e == NULL) {
795         if (req_present) {
796             hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
797                                    "Required extension key "
798                                    "usage missing from certifiate");
799             return HX509_KU_CERT_MISSING;
800         }
801         return 0;
802     }
803     
804     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
805     if (ret)
806         return ret;
807     ku_flags = KeyUsage2int(ku);
808     if ((ku_flags & flags) != flags) {
809         unsigned missing = (~ku_flags) & flags;
810         char buf[256], *name;
811
812         unparse_flags(missing, asn1_KeyUsage_units(), buf, sizeof(buf));
813         _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
814         hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
815                                "Key usage %s required but missing "
816                                "from certifiate %s", buf, name);
817         free(name);
818         return HX509_KU_CERT_MISSING;
819     }
820     return 0;
821 }
822
823 /*
824  * Return 0 on matching key usage 'flags' for 'cert', otherwise return
825  * an error code. If 'req_present' the existance is required of the
826  * KeyUsage extension.
827  */
828
829 int
830 _hx509_check_key_usage(hx509_context context, hx509_cert cert, 
831                        unsigned flags, int req_present)
832 {
833     return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
834 }
835
836 enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
837
838 static int
839 check_basic_constraints(hx509_context context, const Certificate *cert, 
840                         enum certtype type, int depth)
841 {
842     BasicConstraints bc;
843     const Extension *e;
844     size_t size;
845     int ret, i = 0;
846
847     if (_hx509_cert_get_version(cert) < 3)
848         return 0;
849
850     e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
851     if (e == NULL) {
852         switch(type) {
853         case PROXY_CERT:
854         case EE_CERT:
855             return 0;
856         case CA_CERT: {
857             char *name;
858             ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
859             assert(ret == 0);
860             hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
861                                    "basicConstraints missing from "
862                                    "CA certifiacte %s", name);
863             free(name);
864             return HX509_EXTENSION_NOT_FOUND;
865         }
866         }
867     }
868     
869     ret = decode_BasicConstraints(e->extnValue.data, 
870                                   e->extnValue.length, &bc,
871                                   &size);
872     if (ret)
873         return ret;
874     switch(type) {
875     case PROXY_CERT:
876         if (bc.cA != NULL && *bc.cA)
877             ret = HX509_PARENT_IS_CA;
878         break;
879     case EE_CERT:
880         ret = 0;
881         break;
882     case CA_CERT:
883         if (bc.cA == NULL || !*bc.cA)
884             ret = HX509_PARENT_NOT_CA;
885         else if (bc.pathLenConstraint)
886             if (depth - 1 > *bc.pathLenConstraint)
887                 ret = HX509_CA_PATH_TOO_DEEP;
888         break;
889     }
890     free_BasicConstraints(&bc);
891     return ret;
892 }
893
894 int
895 _hx509_cert_is_parent_cmp(const Certificate *subject,
896                           const Certificate *issuer,
897                           int allow_self_signed)
898 {
899     int diff;
900     AuthorityKeyIdentifier ai;
901     SubjectKeyIdentifier si;
902     int ret_ai, ret_si, ret;
903
904     ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, 
905                           &subject->tbsCertificate.issuer,
906                           &diff);
907     if (ret)
908         return ret;
909     if (diff)
910         return diff;
911     
912     memset(&ai, 0, sizeof(ai));
913     memset(&si, 0, sizeof(si));
914
915     /*
916      * Try to find AuthorityKeyIdentifier, if it's not present in the
917      * subject certificate nor the parent.
918      */
919
920     ret_ai = find_extension_auth_key_id(subject, &ai);
921     if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
922         return 1;
923     ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
924     if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
925         return -1;
926
927     if (ret_si && ret_ai)
928         goto out;
929     if (ret_ai)
930         goto out;
931     if (ret_si) {
932         if (allow_self_signed) {
933             diff = 0;
934             goto out;
935         } else if (ai.keyIdentifier) {
936             diff = -1;
937             goto out;
938         }
939     }
940     
941     if (ai.keyIdentifier == NULL) {
942         Name name;
943
944         if (ai.authorityCertIssuer == NULL)
945             return -1;
946         if (ai.authorityCertSerialNumber == NULL)
947             return -1;
948
949         diff = der_heim_integer_cmp(ai.authorityCertSerialNumber, 
950                                     &issuer->tbsCertificate.serialNumber);
951         if (diff)
952             return diff;
953         if (ai.authorityCertIssuer->len != 1)
954             return -1;
955         if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
956             return -1;
957         
958         name.element = 
959             ai.authorityCertIssuer->val[0].u.directoryName.element;
960         name.u.rdnSequence = 
961             ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
962
963         ret = _hx509_name_cmp(&issuer->tbsCertificate.subject, 
964                               &name,
965                               &diff);
966         if (ret)
967             return ret;
968         if (diff)
969             return diff;
970         diff = 0;
971     } else
972         diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
973     if (diff)
974         goto out;
975
976  out:
977     free_AuthorityKeyIdentifier(&ai);
978     free_SubjectKeyIdentifier(&si);
979     return diff;
980 }
981
982 static int
983 certificate_is_anchor(hx509_context context,
984                       hx509_certs trust_anchors,
985                       const hx509_cert cert)
986 {
987     hx509_query q;
988     hx509_cert c;
989     int ret;
990
991     if (trust_anchors == NULL)
992         return 0;
993
994     _hx509_query_clear(&q);
995
996     q.match = HX509_QUERY_MATCH_CERTIFICATE;
997     q.certificate = _hx509_get_cert(cert);
998
999     ret = hx509_certs_find(context, trust_anchors, &q, &c);
1000     if (ret == 0)
1001         hx509_cert_free(c);
1002     return ret == 0;
1003 }
1004
1005 static int
1006 certificate_is_self_signed(hx509_context context,
1007                            const Certificate *cert,
1008                            int *self_signed)
1009 {
1010     int ret, diff;
1011     ret = _hx509_name_cmp(&cert->tbsCertificate.subject, 
1012                           &cert->tbsCertificate.issuer, &diff);
1013     *self_signed = (diff == 0);
1014     if (ret)
1015         hx509_set_error_string(context, 0, ret,
1016                                "Failed to check if self signed");
1017     return ret;
1018 }
1019
1020 /*
1021  * The subjectName is "null" when it's empty set of relative DBs.
1022  */
1023
1024 static int
1025 subject_null_p(const Certificate *c)
1026 {
1027     return c->tbsCertificate.subject.u.rdnSequence.len == 0;
1028 }
1029
1030
1031 static int
1032 find_parent(hx509_context context,
1033             time_t time_now,
1034             hx509_certs trust_anchors,
1035             hx509_path *path,
1036             hx509_certs pool, 
1037             hx509_cert current,
1038             hx509_cert *parent)
1039 {
1040     AuthorityKeyIdentifier ai;
1041     hx509_query q;
1042     int ret;
1043
1044     *parent = NULL;
1045     memset(&ai, 0, sizeof(ai));
1046     
1047     _hx509_query_clear(&q);
1048
1049     if (!subject_null_p(current->data)) {
1050         q.match |= HX509_QUERY_FIND_ISSUER_CERT;
1051         q.subject = _hx509_get_cert(current);
1052     } else {
1053         ret = find_extension_auth_key_id(current->data, &ai);
1054         if (ret) {
1055             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1056                                    "Subjectless certificate missing AuthKeyID");
1057             return HX509_CERTIFICATE_MALFORMED;
1058         }
1059
1060         if (ai.keyIdentifier == NULL) {
1061             free_AuthorityKeyIdentifier(&ai);
1062             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
1063                                    "Subjectless certificate missing keyIdentifier "
1064                                    "inside AuthKeyID");
1065             return HX509_CERTIFICATE_MALFORMED;
1066         }
1067
1068         q.subject_id = ai.keyIdentifier;
1069         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
1070     }
1071
1072     q.path = path;
1073     q.match |= HX509_QUERY_NO_MATCH_PATH;
1074
1075     if (pool) {
1076         q.timenow = time_now;
1077         q.match |= HX509_QUERY_MATCH_TIME;
1078
1079         ret = hx509_certs_find(context, pool, &q, parent);
1080         if (ret == 0) {
1081             free_AuthorityKeyIdentifier(&ai);
1082             return 0;
1083         }
1084         q.match &= ~HX509_QUERY_MATCH_TIME;
1085     }
1086
1087     if (trust_anchors) {
1088         ret = hx509_certs_find(context, trust_anchors, &q, parent);
1089         if (ret == 0) {
1090             free_AuthorityKeyIdentifier(&ai);
1091             return ret;
1092         }
1093     }
1094     free_AuthorityKeyIdentifier(&ai);
1095
1096     {
1097         hx509_name name;
1098         char *str;
1099
1100         ret = hx509_cert_get_subject(current, &name);
1101         if (ret) {
1102             hx509_clear_error_string(context);
1103             return HX509_ISSUER_NOT_FOUND;
1104         }
1105         ret = hx509_name_to_string(name, &str);
1106         hx509_name_free(&name);
1107         if (ret) {
1108             hx509_clear_error_string(context);
1109             return HX509_ISSUER_NOT_FOUND;
1110         }
1111         
1112         hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
1113                                "Failed to find issuer for "
1114                                "certificate with subject: '%s'", str);
1115         free(str);
1116     }
1117     return HX509_ISSUER_NOT_FOUND;
1118 }
1119
1120 /*
1121  *
1122  */
1123
1124 static int
1125 is_proxy_cert(hx509_context context, 
1126               const Certificate *cert, 
1127               ProxyCertInfo *rinfo)
1128 {
1129     ProxyCertInfo info;
1130     const Extension *e;
1131     size_t size;
1132     int ret, i = 0;
1133
1134     if (rinfo)
1135         memset(rinfo, 0, sizeof(*rinfo));
1136
1137     e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
1138     if (e == NULL) {
1139         hx509_clear_error_string(context);
1140         return HX509_EXTENSION_NOT_FOUND;
1141     }
1142
1143     ret = decode_ProxyCertInfo(e->extnValue.data, 
1144                                e->extnValue.length, 
1145                                &info,
1146                                &size);
1147     if (ret) {
1148         hx509_clear_error_string(context);
1149         return ret;
1150     }
1151     if (size != e->extnValue.length) {
1152         free_ProxyCertInfo(&info);
1153         hx509_clear_error_string(context);
1154         return HX509_EXTRA_DATA_AFTER_STRUCTURE; 
1155     }
1156     if (rinfo == NULL)
1157         free_ProxyCertInfo(&info);
1158     else
1159         *rinfo = info;
1160
1161     return 0;
1162 }
1163
1164 /*
1165  * Path operations are like MEMORY based keyset, but with exposed
1166  * internal so we can do easy searches.
1167  */
1168
1169 int
1170 _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
1171 {
1172     hx509_cert *val;
1173     val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
1174     if (val == NULL) {
1175         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
1176         return ENOMEM;
1177     }
1178
1179     path->val = val;
1180     path->val[path->len] = hx509_cert_ref(cert);
1181     path->len++;
1182
1183     return 0;
1184 }
1185
1186 void
1187 _hx509_path_free(hx509_path *path)
1188 {
1189     unsigned i;
1190     
1191     for (i = 0; i < path->len; i++)
1192         hx509_cert_free(path->val[i]);
1193     free(path->val);
1194     path->val = NULL;
1195     path->len = 0;
1196 }
1197
1198 /*
1199  * Find path by looking up issuer for the top certificate and continue
1200  * until an anchor certificate is found or max limit is found. A
1201  * certificate never included twice in the path.
1202  *
1203  * If the trust anchors are not given, calculate optimistic path, just
1204  * follow the chain upward until we no longer find a parent or we hit
1205  * the max path limit. In this case, a failure will always be returned
1206  * depending on what error condition is hit first.
1207  *
1208  * The path includes a path from the top certificate to the anchor
1209  * certificate.
1210  *
1211  * The caller needs to free `path´ both on successful built path and
1212  * failure.
1213  */
1214
1215 int
1216 _hx509_calculate_path(hx509_context context,
1217                       int flags,
1218                       time_t time_now,
1219                       hx509_certs anchors,
1220                       unsigned int max_depth,
1221                       hx509_cert cert,
1222                       hx509_certs pool,
1223                       hx509_path *path)
1224 {
1225     hx509_cert parent, current;
1226     int ret;
1227
1228     if (max_depth == 0)
1229         max_depth = HX509_VERIFY_MAX_DEPTH;
1230
1231     ret = _hx509_path_append(context, path, cert);
1232     if (ret)
1233         return ret;
1234
1235     current = hx509_cert_ref(cert);
1236
1237     while (!certificate_is_anchor(context, anchors, current)) {
1238
1239         ret = find_parent(context, time_now, anchors, path, 
1240                           pool, current, &parent);
1241         hx509_cert_free(current);
1242         if (ret)
1243             return ret;
1244
1245         ret = _hx509_path_append(context, path, parent);
1246         if (ret)
1247             return ret;
1248         current = parent;
1249
1250         if (path->len > max_depth) {
1251             hx509_cert_free(current);
1252             hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
1253                                    "Path too long while bulding "
1254                                    "certificate chain");
1255             return HX509_PATH_TOO_LONG;
1256         }
1257     }
1258
1259     if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) && 
1260         path->len > 0 && 
1261         certificate_is_anchor(context, anchors, path->val[path->len - 1]))
1262     {
1263         hx509_cert_free(path->val[path->len - 1]);
1264         path->len--;
1265     }
1266
1267     hx509_cert_free(current);
1268     return 0;
1269 }
1270
1271 int
1272 _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
1273                                const AlgorithmIdentifier *q)
1274 {
1275     int diff;
1276     diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
1277     if (diff)
1278         return diff;
1279     if (p->parameters) {
1280         if (q->parameters)
1281             return heim_any_cmp(p->parameters,
1282                                 q->parameters);
1283         else
1284             return 1;
1285     } else {
1286         if (q->parameters)
1287             return -1;
1288         else
1289             return 0;
1290     }
1291 }
1292
1293 int
1294 _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
1295 {
1296     int diff;
1297     diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
1298     if (diff)
1299         return diff;
1300     diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm, 
1301                                           &q->signatureAlgorithm);
1302     if (diff)
1303         return diff;
1304     diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
1305                                      &q->tbsCertificate._save);
1306     return diff;
1307 }
1308
1309 /**
1310  * Compare to hx509 certificate object, useful for sorting.
1311  *
1312  * @param p a hx509 certificate object.
1313  * @param q a hx509 certificate object.
1314  *
1315  * @return 0 the objects are the same, returns > 0 is p is "larger"
1316  * then q, < 0 if p is "smaller" then q.
1317  *
1318  * @ingroup hx509_cert
1319  */
1320
1321 int
1322 hx509_cert_cmp(hx509_cert p, hx509_cert q)
1323 {
1324     return _hx509_Certificate_cmp(p->data, q->data);
1325 }
1326
1327 /**
1328  * Return the name of the issuer of the hx509 certificate.
1329  *
1330  * @param p a hx509 certificate object.
1331  * @param name a pointer to a hx509 name, should be freed by
1332  * hx509_name_free().
1333  *
1334  * @return An hx509 error code, see hx509_get_error_string().
1335  *
1336  * @ingroup hx509_cert
1337  */
1338
1339 int
1340 hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
1341 {
1342     return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
1343 }
1344
1345 /**
1346  * Return the name of the subject of the hx509 certificate.
1347  *
1348  * @param p a hx509 certificate object.
1349  * @param name a pointer to a hx509 name, should be freed by
1350  * hx509_name_free(). See also hx509_cert_get_base_subject().
1351  *
1352  * @return An hx509 error code, see hx509_get_error_string().
1353  *
1354  * @ingroup hx509_cert
1355  */
1356
1357 int
1358 hx509_cert_get_subject(hx509_cert p, hx509_name *name)
1359 {
1360     return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
1361 }
1362
1363 /**
1364  * Return the name of the base subject of the hx509 certificate. If
1365  * the certiicate is a verified proxy certificate, the this function
1366  * return the base certificate (root of the proxy chain). If the proxy
1367  * certificate is not verified with the base certificate
1368  * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
1369  *
1370  * @param context a hx509 context.
1371  * @param c a hx509 certificate object.
1372  * @param name a pointer to a hx509 name, should be freed by
1373  * hx509_name_free(). See also hx509_cert_get_subject().
1374  *
1375  * @return An hx509 error code, see hx509_get_error_string().
1376  *
1377  * @ingroup hx509_cert
1378  */
1379
1380 int
1381 hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
1382                             hx509_name *name)
1383 {
1384     if (c->basename)
1385         return hx509_name_copy(context, c->basename, name);
1386     if (is_proxy_cert(context, c->data, NULL) == 0) {
1387         int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
1388         hx509_set_error_string(context, 0, ret,
1389                                "Proxy certificate have not been "
1390                                "canonicalize yet, no base name");
1391         return ret;
1392     }
1393     return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
1394 }
1395
1396 /**
1397  * Get serial number of the certificate.
1398  *
1399  * @param p a hx509 certificate object.
1400  * @param i serial number, should be freed ith der_free_heim_integer().
1401  *
1402  * @return An hx509 error code, see hx509_get_error_string().
1403  *
1404  * @ingroup hx509_cert
1405  */
1406
1407 int
1408 hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
1409 {
1410     return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
1411 }
1412
1413 /**
1414  * Get notBefore time of the certificate.
1415  *
1416  * @param p a hx509 certificate object.
1417  *
1418  * @return return not before time
1419  *
1420  * @ingroup hx509_cert
1421  */
1422
1423 time_t
1424 hx509_cert_get_notBefore(hx509_cert p)
1425 {
1426     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
1427 }
1428
1429 /**
1430  * Get notAfter time of the certificate.
1431  *
1432  * @param p a hx509 certificate object.
1433  *
1434  * @return return not after time.
1435  *
1436  * @ingroup hx509_cert
1437  */
1438
1439 time_t
1440 hx509_cert_get_notAfter(hx509_cert p)
1441 {
1442     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
1443 }
1444
1445 /**
1446  * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
1447  *
1448  * @param context a hx509 context.
1449  * @param p a hx509 certificate object.
1450  * @param spki SubjectPublicKeyInfo, should be freed with
1451  * free_SubjectPublicKeyInfo().
1452  *
1453  * @return An hx509 error code, see hx509_get_error_string().
1454  *
1455  * @ingroup hx509_cert
1456  */
1457
1458 int
1459 hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
1460 {
1461     int ret;
1462
1463     ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
1464     if (ret)
1465         hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
1466     return ret;
1467 }
1468
1469 /**
1470  * Get the AlgorithmIdentifier from the hx509 certificate.
1471  *
1472  * @param context a hx509 context.
1473  * @param p a hx509 certificate object.
1474  * @param alg AlgorithmIdentifier, should be freed with
1475  * free_AlgorithmIdentifier().
1476  *
1477  * @return An hx509 error code, see hx509_get_error_string().
1478  *
1479  * @ingroup hx509_cert
1480  */
1481
1482 int
1483 hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
1484                                         hx509_cert p, 
1485                                         AlgorithmIdentifier *alg)
1486 {
1487     int ret;
1488
1489     ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
1490     if (ret)
1491         hx509_set_error_string(context, 0, ret,
1492                                "Failed to copy SPKI AlgorithmIdentifier");
1493     return ret;
1494 }
1495
1496
1497 hx509_private_key
1498 _hx509_cert_private_key(hx509_cert p)
1499 {
1500     return p->private_key;
1501 }
1502
1503 int
1504 hx509_cert_have_private_key(hx509_cert p)
1505 {
1506     return p->private_key ? 1 : 0;
1507 }
1508
1509
1510 int
1511 _hx509_cert_private_key_exportable(hx509_cert p)
1512 {
1513     if (p->private_key == NULL)
1514         return 0;
1515     return _hx509_private_key_exportable(p->private_key);
1516 }
1517
1518 int
1519 _hx509_cert_private_decrypt(hx509_context context,
1520                             const heim_octet_string *ciphertext,
1521                             const heim_oid *encryption_oid,
1522                             hx509_cert p,
1523                             heim_octet_string *cleartext)
1524 {
1525     cleartext->data = NULL;
1526     cleartext->length = 0;
1527
1528     if (p->private_key == NULL) {
1529         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
1530                                "Private key missing");
1531         return HX509_PRIVATE_KEY_MISSING;
1532     }
1533
1534     return _hx509_private_key_private_decrypt(context,
1535                                               ciphertext,
1536                                               encryption_oid,
1537                                               p->private_key, 
1538                                               cleartext);
1539 }
1540
1541 int
1542 _hx509_cert_public_encrypt(hx509_context context,
1543                            const heim_octet_string *cleartext,
1544                            const hx509_cert p,
1545                            heim_oid *encryption_oid,
1546                            heim_octet_string *ciphertext)
1547 {
1548     return _hx509_public_encrypt(context,
1549                                  cleartext, p->data,
1550                                  encryption_oid, ciphertext);
1551 }
1552
1553 /*
1554  *
1555  */
1556
1557 time_t
1558 _hx509_Time2time_t(const Time *t)
1559 {
1560     switch(t->element) {
1561     case choice_Time_utcTime:
1562         return t->u.utcTime;
1563     case choice_Time_generalTime:
1564         return t->u.generalTime;
1565     }
1566     return 0;
1567 }
1568
1569 /*
1570  *
1571  */
1572
1573 static int
1574 init_name_constraints(hx509_name_constraints *nc)
1575 {
1576     memset(nc, 0, sizeof(*nc));
1577     return 0;
1578 }
1579
1580 static int
1581 add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
1582                      hx509_name_constraints *nc)
1583 {
1584     NameConstraints tnc;
1585     int ret;
1586
1587     ret = find_extension_name_constraints(c, &tnc);
1588     if (ret == HX509_EXTENSION_NOT_FOUND)
1589         return 0;
1590     else if (ret) {
1591         hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
1592         return ret;
1593     } else if (not_ca) {
1594         ret = HX509_VERIFY_CONSTRAINTS;
1595         hx509_set_error_string(context, 0, ret, "Not a CA and "
1596                                "have NameConstraints");
1597     } else {
1598         NameConstraints *val;
1599         val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
1600         if (val == NULL) {
1601             hx509_clear_error_string(context);
1602             ret = ENOMEM;
1603             goto out;
1604         }
1605         nc->val = val;
1606         ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
1607         if (ret) {
1608             hx509_clear_error_string(context);
1609             goto out;
1610         }
1611         nc->len += 1;
1612     }
1613 out:
1614     free_NameConstraints(&tnc);
1615     return ret;
1616 }
1617
1618 static int
1619 match_RDN(const RelativeDistinguishedName *c,
1620           const RelativeDistinguishedName *n)
1621 {
1622     int i;
1623
1624     if (c->len != n->len)
1625         return HX509_NAME_CONSTRAINT_ERROR;
1626     
1627     for (i = 0; i < n->len; i++) {
1628         int diff, ret;
1629
1630         if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
1631             return HX509_NAME_CONSTRAINT_ERROR;
1632         ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
1633         if (ret)
1634             return ret;
1635         if (diff != 0)
1636             return HX509_NAME_CONSTRAINT_ERROR;
1637     }
1638     return 0;
1639 }
1640
1641 static int
1642 match_X501Name(const Name *c, const Name *n)
1643 {
1644     int i, ret;
1645
1646     if (c->element != choice_Name_rdnSequence
1647         || n->element != choice_Name_rdnSequence)
1648         return 0;
1649     if (c->u.rdnSequence.len > n->u.rdnSequence.len)
1650         return HX509_NAME_CONSTRAINT_ERROR;
1651     for (i = 0; i < c->u.rdnSequence.len; i++) {
1652         ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
1653         if (ret)
1654             return ret;
1655     }
1656     return 0;
1657
1658
1659
1660 static int
1661 match_general_name(const GeneralName *c, const GeneralName *n, int *match)
1662 {
1663     /* 
1664      * Name constraints only apply to the same name type, see RFC3280,
1665      * 4.2.1.11.
1666      */
1667     assert(c->element == n->element);
1668
1669     switch(c->element) {
1670     case choice_GeneralName_otherName:
1671         if (der_heim_oid_cmp(&c->u.otherName.type_id,
1672                          &n->u.otherName.type_id) != 0)
1673             return HX509_NAME_CONSTRAINT_ERROR;
1674         if (heim_any_cmp(&c->u.otherName.value,
1675                          &n->u.otherName.value) != 0)
1676             return HX509_NAME_CONSTRAINT_ERROR;
1677         *match = 1;
1678         return 0;
1679     case choice_GeneralName_rfc822Name: {
1680         const char *s;
1681         size_t len1, len2;
1682         s = strchr(c->u.rfc822Name, '@');
1683         if (s) {
1684             if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
1685                 return HX509_NAME_CONSTRAINT_ERROR;
1686         } else {
1687             s = strchr(n->u.rfc822Name, '@');
1688             if (s == NULL)
1689                 return HX509_NAME_CONSTRAINT_ERROR;
1690             len1 = strlen(c->u.rfc822Name);
1691             len2 = strlen(s + 1);
1692             if (len1 > len2)
1693                 return HX509_NAME_CONSTRAINT_ERROR;
1694             if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
1695                 return HX509_NAME_CONSTRAINT_ERROR;
1696             if (len1 < len2 && s[len2 - len1 + 1] != '.')
1697                 return HX509_NAME_CONSTRAINT_ERROR;
1698         }
1699         *match = 1;
1700         return 0;
1701     }
1702     case choice_GeneralName_dNSName: {
1703         size_t lenc, lenn;
1704
1705         lenc = strlen(c->u.dNSName);
1706         lenn = strlen(n->u.dNSName);
1707         if (lenc > lenn)
1708             return HX509_NAME_CONSTRAINT_ERROR;
1709         if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
1710             return HX509_NAME_CONSTRAINT_ERROR;
1711         if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
1712             return HX509_NAME_CONSTRAINT_ERROR;
1713         *match = 1;
1714         return 0;
1715     }
1716     case choice_GeneralName_directoryName: {
1717         Name c_name, n_name;
1718         int ret;
1719
1720         c_name._save.data = NULL;
1721         c_name._save.length = 0;
1722         c_name.element = c->u.directoryName.element;
1723         c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
1724
1725         n_name._save.data = NULL;
1726         n_name._save.length = 0;
1727         n_name.element = n->u.directoryName.element;
1728         n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
1729
1730         ret = match_X501Name(&c_name, &n_name);
1731         if (ret == 0)
1732             *match = 1;
1733         return ret;
1734     }
1735     case choice_GeneralName_uniformResourceIdentifier:
1736     case choice_GeneralName_iPAddress:
1737     case choice_GeneralName_registeredID:
1738     default:
1739         return HX509_NAME_CONSTRAINT_ERROR;
1740     }
1741 }
1742
1743 static int
1744 match_alt_name(const GeneralName *n, const Certificate *c, 
1745                int *same, int *match)
1746 {
1747     GeneralNames sa;
1748     int ret, i, j;
1749
1750     i = 0;
1751     do {
1752         ret = find_extension_subject_alt_name(c, &i, &sa);
1753         if (ret == HX509_EXTENSION_NOT_FOUND) {
1754             ret = 0;
1755             break;
1756         } else if (ret != 0)
1757             break;
1758
1759         for (j = 0; j < sa.len; j++) {
1760             if (n->element == sa.val[j].element) {
1761                 *same = 1;
1762                 ret = match_general_name(n, &sa.val[j], match);
1763             }
1764         }
1765         free_GeneralNames(&sa);
1766     } while (1);
1767     return ret;
1768 }
1769
1770
1771 static int
1772 match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
1773 {
1774     int name, alt_name, same;
1775     unsigned int i;
1776     int ret = 0;
1777
1778     name = alt_name = same = *match = 0;
1779     for (i = 0; i < t->len; i++) {
1780         if (t->val[i].minimum && t->val[i].maximum)
1781             return HX509_RANGE;
1782
1783         /*
1784          * If the constraint apply to directoryNames, test is with
1785          * subjectName of the certificate if the certificate have a
1786          * non-null (empty) subjectName.
1787          */
1788
1789         if (t->val[i].base.element == choice_GeneralName_directoryName
1790             && !subject_null_p(c))
1791         {
1792             GeneralName certname;
1793             
1794             memset(&certname, 0, sizeof(certname));
1795             certname.element = choice_GeneralName_directoryName;
1796             certname.u.directoryName.element = 
1797                 c->tbsCertificate.subject.element;
1798             certname.u.directoryName.u.rdnSequence = 
1799                 c->tbsCertificate.subject.u.rdnSequence;
1800     
1801             ret = match_general_name(&t->val[i].base, &certname, &name);
1802         }
1803
1804         /* Handle subjectAltNames, this is icky since they
1805          * restrictions only apply if the subjectAltName is of the
1806          * same type. So if there have been a match of type, require
1807          * altname to be set.
1808          */
1809         ret = match_alt_name(&t->val[i].base, c, &same, &alt_name);
1810     }
1811     if (name && (!same || alt_name))
1812         *match = 1;
1813     return ret;
1814 }
1815
1816 static int
1817 check_name_constraints(hx509_context context, 
1818                        const hx509_name_constraints *nc,
1819                        const Certificate *c)
1820 {
1821     int match, ret;
1822     int i;
1823
1824     for (i = 0 ; i < nc->len; i++) {
1825         GeneralSubtrees gs;
1826
1827         if (nc->val[i].permittedSubtrees) {
1828             GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
1829             ret = match_tree(&gs, c, &match);
1830             if (ret) {
1831                 hx509_clear_error_string(context);
1832                 return ret;
1833             }
1834             /* allow null subjectNames, they wont matches anything */
1835             if (match == 0 && !subject_null_p(c)) {
1836                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1837                                        "Error verify constraints, "
1838                                        "certificate didn't match any "
1839                                        "permitted subtree");
1840                 return HX509_VERIFY_CONSTRAINTS;
1841             }
1842         }
1843         if (nc->val[i].excludedSubtrees) {
1844             GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
1845             ret = match_tree(&gs, c, &match);
1846             if (ret) {
1847                 hx509_clear_error_string(context);
1848                 return ret;
1849             }
1850             if (match) {
1851                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
1852                                        "Error verify constraints, "
1853                                        "certificate included in excluded "
1854                                        "subtree");
1855                 return HX509_VERIFY_CONSTRAINTS;
1856             }
1857         }
1858     }
1859     return 0;
1860 }
1861
1862 static void
1863 free_name_constraints(hx509_name_constraints *nc)
1864 {
1865     int i;
1866
1867     for (i = 0 ; i < nc->len; i++)
1868         free_NameConstraints(&nc->val[i]);
1869     free(nc->val);
1870 }
1871
1872 /**
1873  * Build and verify the path for the certificate to the trust anchor
1874  * specified in the verify context. The path is constructed from the
1875  * certificate, the pool and the trust anchors.
1876  *
1877  * @param context A hx509 context.
1878  * @param ctx A hx509 verification context.
1879  * @param cert the certificate to build the path from.
1880  * @param pool A keyset of certificates to build the chain from.
1881  *
1882  * @return An hx509 error code, see hx509_get_error_string().
1883  *
1884  * @ingroup hx509_verify
1885  */
1886
1887 int
1888 hx509_verify_path(hx509_context context,
1889                   hx509_verify_ctx ctx,
1890                   hx509_cert cert,
1891                   hx509_certs pool)
1892 {
1893     hx509_name_constraints nc;
1894     hx509_path path;
1895     int ret, i, proxy_cert_depth, selfsigned_depth, diff;
1896     enum certtype type;
1897     Name proxy_issuer;
1898     hx509_certs anchors = NULL;
1899
1900     memset(&proxy_issuer, 0, sizeof(proxy_issuer));
1901
1902     ret = init_name_constraints(&nc);
1903     if (ret)    
1904         return ret;
1905
1906     path.val = NULL;
1907     path.len = 0;
1908
1909     if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
1910         ctx->time_now = time(NULL);
1911
1912     /*
1913      *
1914      */
1915     if (ctx->trust_anchors)
1916         anchors = _hx509_certs_ref(ctx->trust_anchors);
1917     else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
1918         anchors = _hx509_certs_ref(context->default_trust_anchors);
1919     else {
1920         ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
1921         if (ret)
1922             goto out;
1923     }
1924
1925     /*
1926      * Calculate the path from the certificate user presented to the
1927      * to an anchor.
1928      */
1929     ret = _hx509_calculate_path(context, 0, ctx->time_now,
1930                                 anchors, ctx->max_depth,
1931                                 cert, pool, &path);
1932     if (ret)
1933         goto out;
1934
1935     /*
1936      * Check CA and proxy certificate chain from the top of the
1937      * certificate chain. Also check certificate is valid with respect
1938      * to the current time.
1939      *
1940      */
1941
1942     proxy_cert_depth = 0;
1943     selfsigned_depth = 0;
1944
1945     if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
1946         type = PROXY_CERT;
1947     else
1948         type = EE_CERT;
1949
1950     for (i = 0; i < path.len; i++) {
1951         Certificate *c;
1952         time_t t;
1953
1954         c = _hx509_get_cert(path.val[i]);
1955         
1956         /*
1957          * Lets do some basic check on issuer like
1958          * keyUsage.keyCertSign and basicConstraints.cA bit depending
1959          * on what type of certificate this is.
1960          */
1961
1962         switch (type) {
1963         case CA_CERT:
1964
1965             /* XXX make constants for keyusage */
1966             ret = check_key_usage(context, c, 1 << 5,
1967                                   REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
1968             if (ret) {
1969                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
1970                                        "Key usage missing from CA certificate");
1971                 goto out;
1972             }
1973
1974             /* self signed cert doesn't add to path length */
1975             if (i + 1 != path.len) {
1976                 int selfsigned;
1977
1978                 ret = certificate_is_self_signed(context, c, &selfsigned);
1979                 if (ret)
1980                     goto out;
1981                 if (selfsigned) 
1982                     selfsigned_depth++;
1983             }
1984
1985             break;
1986         case PROXY_CERT: {
1987             ProxyCertInfo info;     
1988
1989             if (is_proxy_cert(context, c, &info) == 0) {
1990                 int j;
1991
1992                 if (info.pCPathLenConstraint != NULL &&
1993                     *info.pCPathLenConstraint < i)
1994                 {
1995                     free_ProxyCertInfo(&info);
1996                     ret = HX509_PATH_TOO_LONG;
1997                     hx509_set_error_string(context, 0, ret,
1998                                            "Proxy certificate chain "
1999                                            "longer then allowed");
2000                     goto out;
2001                 }
2002                 /* XXX MUST check info.proxyPolicy */
2003                 free_ProxyCertInfo(&info);
2004                 
2005                 j = 0;
2006                 if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
2007                     ret = HX509_PROXY_CERT_INVALID;
2008                     hx509_set_error_string(context, 0, ret, 
2009                                            "Proxy certificate have explicity "
2010                                            "forbidden subjectAltName");
2011                     goto out;
2012                 }
2013
2014                 j = 0;
2015                 if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
2016                     ret = HX509_PROXY_CERT_INVALID;
2017                     hx509_set_error_string(context, 0, ret, 
2018                                            "Proxy certificate have explicity "
2019                                            "forbidden issuerAltName");
2020                     goto out;
2021                 }
2022                         
2023                 /* 
2024                  * The subject name of the proxy certificate should be
2025                  * CN=XXX,<proxy issuer>, prune of CN and check if its
2026                  * the same over the whole chain of proxy certs and
2027                  * then check with the EE cert when we get to it.
2028                  */
2029
2030                 if (proxy_cert_depth) {
2031                     ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
2032                     if (ret) {
2033                         hx509_set_error_string(context, 0, ret, "Out of memory");
2034                         goto out;
2035                     }
2036                     if (diff) {
2037                         ret = HX509_PROXY_CERT_NAME_WRONG;
2038                         hx509_set_error_string(context, 0, ret,
2039                                                "Base proxy name not right");
2040                         goto out;
2041                     }
2042                 }
2043
2044                 free_Name(&proxy_issuer);
2045
2046                 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
2047                 if (ret) {
2048                     hx509_clear_error_string(context);
2049                     goto out;
2050                 }
2051
2052                 j = proxy_issuer.u.rdnSequence.len;
2053                 if (proxy_issuer.u.rdnSequence.len < 2 
2054                     || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
2055                     || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
2056                                         oid_id_at_commonName()))
2057                 {
2058                     ret = HX509_PROXY_CERT_NAME_WRONG;
2059                     hx509_set_error_string(context, 0, ret,
2060                                            "Proxy name too short or "
2061                                            "does not have Common name "
2062                                            "at the top");
2063                     goto out;
2064                 }
2065
2066                 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
2067                 proxy_issuer.u.rdnSequence.len -= 1;
2068
2069                 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
2070                 if (ret) {
2071                     hx509_set_error_string(context, 0, ret, "Out of memory");
2072                     goto out;
2073                 }
2074                 if (diff != 0) {
2075                     ret = HX509_PROXY_CERT_NAME_WRONG;
2076                     hx509_set_error_string(context, 0, ret,
2077                                            "Proxy issuer name not as expected");
2078                     goto out;
2079                 }
2080
2081                 break;
2082             } else {
2083                 /* 
2084                  * Now we are done with the proxy certificates, this
2085                  * cert was an EE cert and we we will fall though to
2086                  * EE checking below.
2087                  */
2088                 type = EE_CERT;
2089                 /* FALLTHOUGH */
2090             }
2091         }
2092         case EE_CERT:
2093             /*
2094              * If there where any proxy certificates in the chain
2095              * (proxy_cert_depth > 0), check that the proxy issuer
2096              * matched proxy certificates "base" subject.
2097              */
2098             if (proxy_cert_depth) {
2099
2100                 ret = _hx509_name_cmp(&proxy_issuer, 
2101                                       &c->tbsCertificate.subject, &diff);
2102                 if (ret) {
2103                     hx509_set_error_string(context, 0, ret, "out of memory");
2104                     goto out;
2105                 }
2106                 if (diff) {
2107                     ret = HX509_PROXY_CERT_NAME_WRONG;
2108                     hx509_clear_error_string(context);
2109                     goto out;
2110                 }
2111                 if (cert->basename)
2112                     hx509_name_free(&cert->basename);
2113                 
2114                 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
2115                 if (ret) {
2116                     hx509_clear_error_string(context);
2117                     goto out;
2118                 }
2119             }
2120
2121             break;
2122         }
2123
2124         ret = check_basic_constraints(context, c, type, 
2125                                       i - proxy_cert_depth - selfsigned_depth);
2126         if (ret)
2127             goto out;
2128             
2129         /*
2130          * Don't check the trust anchors expiration time since they
2131          * are transported out of band, from RFC3820.
2132          */
2133         if (i + 1 != path.len || CHECK_TA(ctx)) {
2134
2135             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2136             if (t > ctx->time_now) {
2137                 ret = HX509_CERT_USED_BEFORE_TIME;
2138                 hx509_clear_error_string(context);
2139                 goto out;
2140             }
2141             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2142             if (t < ctx->time_now) {
2143                 ret = HX509_CERT_USED_AFTER_TIME;
2144                 hx509_clear_error_string(context);
2145                 goto out;
2146             }
2147         }
2148
2149         if (type == EE_CERT)
2150             type = CA_CERT;
2151         else if (type == PROXY_CERT)
2152             proxy_cert_depth++;
2153     }
2154
2155     /*
2156      * Verify constraints, do this backward so path constraints are
2157      * checked in the right order.
2158      */
2159
2160     for (ret = 0, i = path.len - 1; i >= 0; i--) {
2161         Certificate *c;
2162         int selfsigned;
2163
2164         c = _hx509_get_cert(path.val[i]);
2165
2166         ret = certificate_is_self_signed(context, c, &selfsigned);
2167         if (ret)
2168             goto out;
2169
2170         /* verify name constraints, not for selfsigned and anchor */
2171         if (!selfsigned || i + 1 != path.len) {
2172             ret = check_name_constraints(context, &nc, c);
2173             if (ret) {
2174                 goto out;
2175             }
2176         }
2177         ret = add_name_constraints(context, c, i == 0, &nc);
2178         if (ret)
2179             goto out;
2180
2181         /* XXX verify all other silly constraints */
2182
2183     }
2184
2185     /*
2186      * Verify that no certificates has been revoked.
2187      */
2188
2189     if (ctx->revoke_ctx) {
2190         hx509_certs certs;
2191
2192         ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
2193                                NULL, &certs);
2194         if (ret)
2195             goto out;
2196
2197         for (i = 0; i < path.len; i++) {
2198             ret = hx509_certs_add(context, certs, path.val[i]);
2199             if (ret) {
2200                 hx509_certs_free(&certs);
2201                 goto out;
2202             }
2203         }
2204         ret = hx509_certs_merge(context, certs, pool);
2205         if (ret) {
2206             hx509_certs_free(&certs);
2207             goto out;
2208         }
2209
2210         for (i = 0; i < path.len - 1; i++) {
2211             int parent = (i < path.len - 1) ? i + 1 : i;
2212
2213             ret = hx509_revoke_verify(context,
2214                                       ctx->revoke_ctx, 
2215                                       certs,
2216                                       ctx->time_now,
2217                                       path.val[i],
2218                                       path.val[parent]);
2219             if (ret) {
2220                 hx509_certs_free(&certs);
2221                 goto out;
2222             }
2223         }
2224         hx509_certs_free(&certs);
2225     }
2226
2227     /*
2228      * Verify signatures, do this backward so public key working
2229      * parameter is passed up from the anchor up though the chain.
2230      */
2231
2232     for (i = path.len - 1; i >= 0; i--) {
2233         Certificate *signer, *c;
2234
2235         c = _hx509_get_cert(path.val[i]);
2236
2237         /* is last in chain (trust anchor) */
2238         if (i + 1 == path.len) {
2239             int selfsigned;
2240
2241             signer = path.val[i]->data;
2242
2243             ret = certificate_is_self_signed(context, signer, &selfsigned);
2244             if (ret)
2245                 goto out;
2246
2247             /* if trust anchor is not self signed, don't check sig */
2248             if (!selfsigned)
2249                 continue;
2250         } else {
2251             /* take next certificate in chain */
2252             signer = path.val[i + 1]->data;
2253         }
2254
2255         /* verify signatureValue */
2256         ret = _hx509_verify_signature_bitstring(context,
2257                                                 signer,
2258                                                 &c->signatureAlgorithm,
2259                                                 &c->tbsCertificate._save,
2260                                                 &c->signatureValue);
2261         if (ret) {
2262             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
2263                                    "Failed to verify signature of certificate");
2264             goto out;
2265         }
2266     }
2267
2268 out:
2269     hx509_certs_free(&anchors);
2270     free_Name(&proxy_issuer);
2271     free_name_constraints(&nc);
2272     _hx509_path_free(&path);
2273
2274     return ret;
2275 }
2276
2277 /**
2278  * Verify a signature made using the private key of an certificate.
2279  *
2280  * @param context A hx509 context.
2281  * @param signer the certificate that made the signature.
2282  * @param alg algorthm that was used to sign the data.
2283  * @param data the data that was signed.
2284  * @param sig the sigature to verify.
2285  *
2286  * @return An hx509 error code, see hx509_get_error_string().
2287  *
2288  * @ingroup hx509_crypto
2289  */
2290
2291 int
2292 hx509_verify_signature(hx509_context context,
2293                        const hx509_cert signer,
2294                        const AlgorithmIdentifier *alg,
2295                        const heim_octet_string *data,
2296                        const heim_octet_string *sig)
2297 {
2298     return _hx509_verify_signature(context, signer->data, alg, data, sig);
2299 }
2300
2301
2302 /**
2303  * Verify that the certificate is allowed to be used for the hostname
2304  * and address.
2305  *
2306  * @param context A hx509 context.
2307  * @param cert the certificate to match with
2308  * @param flags Flags to modify the behavior:
2309  * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
2310  * @param type type of hostname:
2311  * - HX509_HN_HOSTNAME for plain hostname.
2312  * - HX509_HN_DNSSRV for DNS SRV names.
2313  * @param hostname the hostname to check
2314  * @param sa address of the host
2315  * @param sa_size length of address
2316  *
2317  * @return An hx509 error code, see hx509_get_error_string().
2318  *
2319  * @ingroup hx509_cert
2320  */
2321
2322 int
2323 hx509_verify_hostname(hx509_context context,
2324                       const hx509_cert cert,
2325                       int flags,
2326                       hx509_hostname_type type,
2327                       const char *hostname,
2328                       const struct sockaddr *sa,
2329                       /* XXX krb5_socklen_t */ int sa_size) 
2330 {
2331     GeneralNames san;
2332     int ret, i, j;
2333
2334     if (sa && sa_size <= 0)
2335         return EINVAL;
2336
2337     memset(&san, 0, sizeof(san));
2338
2339     i = 0;
2340     do {
2341         ret = find_extension_subject_alt_name(cert->data, &i, &san);
2342         if (ret == HX509_EXTENSION_NOT_FOUND) {
2343             ret = 0;
2344             break;
2345         } else if (ret != 0)
2346             break;
2347
2348         for (j = 0; j < san.len; j++) {
2349             switch (san.val[j].element) {
2350             case choice_GeneralName_dNSName:
2351                 if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
2352                     free_GeneralNames(&san);
2353                     return 0;
2354                 }
2355                 break;
2356             default:
2357                 break;
2358             }
2359         }
2360         free_GeneralNames(&san);
2361     } while (1);
2362
2363     {
2364         const Name *name = &cert->data->tbsCertificate.subject;
2365
2366         /* match if first component is a CN= */
2367         if (name->u.rdnSequence.len > 0
2368             && name->u.rdnSequence.val[0].len == 1
2369             && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
2370                                 oid_id_at_commonName()) == 0)
2371         {
2372             DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
2373
2374             switch (ds->element) {
2375             case choice_DirectoryString_printableString:
2376                 if (strcasecmp(ds->u.printableString, hostname) == 0)
2377                     return 0;
2378                 break;
2379             case choice_DirectoryString_ia5String:
2380                 if (strcasecmp(ds->u.ia5String, hostname) == 0)
2381                     return 0;
2382                 break;
2383             case choice_DirectoryString_utf8String:
2384                 if (strcasecmp(ds->u.utf8String, hostname) == 0)
2385                     return 0;
2386             default:
2387                 break;
2388             }
2389         }
2390     }
2391
2392     if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
2393         ret = HX509_NAME_CONSTRAINT_ERROR;
2394
2395     return ret;
2396 }
2397
2398 int
2399 _hx509_set_cert_attribute(hx509_context context,
2400                           hx509_cert cert, 
2401                           const heim_oid *oid, 
2402                           const heim_octet_string *attr)
2403 {
2404     hx509_cert_attribute a;
2405     void *d;
2406
2407     if (hx509_cert_get_attribute(cert, oid) != NULL)
2408         return 0;
2409
2410     d = realloc(cert->attrs.val, 
2411                 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
2412     if (d == NULL) {
2413         hx509_clear_error_string(context);
2414         return ENOMEM;
2415     }
2416     cert->attrs.val = d;
2417
2418     a = malloc(sizeof(*a));
2419     if (a == NULL)
2420         return ENOMEM;
2421
2422     der_copy_octet_string(attr, &a->data);
2423     der_copy_oid(oid, &a->oid);
2424     
2425     cert->attrs.val[cert->attrs.len] = a;
2426     cert->attrs.len++;
2427
2428     return 0;
2429 }
2430
2431 /**
2432  * Get an external attribute for the certificate, examples are
2433  * friendly name and id.
2434  *
2435  * @param cert hx509 certificate object to search
2436  * @param oid an oid to search for.
2437  *
2438  * @return an hx509_cert_attribute, only valid as long as the
2439  * certificate is referenced.
2440  *
2441  * @ingroup hx509_cert
2442  */
2443
2444 hx509_cert_attribute
2445 hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
2446 {
2447     int i;
2448     for (i = 0; i < cert->attrs.len; i++)
2449         if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
2450             return cert->attrs.val[i];
2451     return NULL;
2452 }
2453
2454 /**
2455  * Set the friendly name on the certificate.
2456  *
2457  * @param cert The certificate to set the friendly name on
2458  * @param name Friendly name.
2459  *
2460  * @return An hx509 error code, see hx509_get_error_string().
2461  *
2462  * @ingroup hx509_cert
2463  */
2464
2465 int
2466 hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
2467 {
2468     if (cert->friendlyname)
2469         free(cert->friendlyname);
2470     cert->friendlyname = strdup(name);
2471     if (cert->friendlyname == NULL)
2472         return ENOMEM;
2473     return 0;
2474 }
2475
2476 /**
2477  * Get friendly name of the certificate.
2478  *
2479  * @param cert cert to get the friendly name from.
2480  *
2481  * @return an friendly name or NULL if there is. The friendly name is
2482  * only valid as long as the certificate is referenced.
2483  *
2484  * @ingroup hx509_cert
2485  */
2486
2487 const char *
2488 hx509_cert_get_friendly_name(hx509_cert cert)
2489 {
2490     hx509_cert_attribute a;
2491     PKCS9_friendlyName n;
2492     size_t sz;
2493     int ret, i;
2494
2495     if (cert->friendlyname)
2496         return cert->friendlyname;
2497
2498     a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
2499     if (a == NULL) {
2500         hx509_name name;
2501
2502         ret = hx509_cert_get_subject(cert, &name);
2503         if (ret)
2504             return NULL;
2505         ret = hx509_name_to_string(name, &cert->friendlyname);
2506         hx509_name_free(&name);
2507         if (ret)
2508             return NULL;
2509         return cert->friendlyname;
2510     }
2511
2512     ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
2513     if (ret)
2514         return NULL;
2515         
2516     if (n.len != 1) {
2517         free_PKCS9_friendlyName(&n);
2518         return NULL;
2519     }
2520     
2521     cert->friendlyname = malloc(n.val[0].length + 1);
2522     if (cert->friendlyname == NULL) {
2523         free_PKCS9_friendlyName(&n);
2524         return NULL;
2525     }
2526     
2527     for (i = 0; i < n.val[0].length; i++) {
2528         if (n.val[0].data[i] <= 0xff)
2529             cert->friendlyname[i] = n.val[0].data[i] & 0xff;
2530         else
2531             cert->friendlyname[i] = 'X';
2532     }
2533     cert->friendlyname[i] = '\0';
2534     free_PKCS9_friendlyName(&n);
2535
2536     return cert->friendlyname;
2537 }
2538
2539 void
2540 _hx509_query_clear(hx509_query *q)
2541 {
2542     memset(q, 0, sizeof(*q));
2543 }
2544
2545 /**
2546  * Allocate an query controller. Free using hx509_query_free().
2547  *
2548  * @param context A hx509 context.
2549  * @param q return pointer to a hx509_query.
2550  *
2551  * @return An hx509 error code, see hx509_get_error_string().
2552  *
2553  * @ingroup hx509_cert
2554  */
2555
2556 int
2557 hx509_query_alloc(hx509_context context, hx509_query **q)
2558 {
2559     *q = calloc(1, sizeof(**q));
2560     if (*q == NULL)
2561         return ENOMEM;
2562     return 0;
2563 }
2564
2565
2566 /**
2567  * Set match options for the hx509 query controller.
2568  *
2569  * @param q query controller.
2570  * @param option options to control the query controller.
2571  *
2572  * @return An hx509 error code, see hx509_get_error_string().
2573  *
2574  * @ingroup hx509_cert
2575  */
2576
2577 void
2578 hx509_query_match_option(hx509_query *q, hx509_query_option option)
2579 {
2580     switch(option) {
2581     case HX509_QUERY_OPTION_PRIVATE_KEY:
2582         q->match |= HX509_QUERY_PRIVATE_KEY;
2583         break;
2584     case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
2585         q->match |= HX509_QUERY_KU_ENCIPHERMENT;
2586         break;
2587     case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
2588         q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
2589         break;
2590     case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
2591         q->match |= HX509_QUERY_KU_KEYCERTSIGN;
2592         break;
2593     case HX509_QUERY_OPTION_END:
2594     default:
2595         break;
2596     }
2597 }
2598
2599 /**
2600  * Set the issuer and serial number of match in the query
2601  * controller. The function make copies of the isser and serial number.
2602  *
2603  * @param q a hx509 query controller
2604  * @param issuer issuer to search for
2605  * @param serialNumber the serialNumber of the issuer.
2606  *
2607  * @return An hx509 error code, see hx509_get_error_string().
2608  *
2609  * @ingroup hx509_cert
2610  */
2611
2612 int
2613 hx509_query_match_issuer_serial(hx509_query *q,
2614                                 const Name *issuer, 
2615                                 const heim_integer *serialNumber)
2616 {
2617     int ret;
2618     if (q->serial) {
2619         der_free_heim_integer(q->serial);
2620         free(q->serial);
2621     }
2622     q->serial = malloc(sizeof(*q->serial));
2623     if (q->serial == NULL)
2624         return ENOMEM;
2625     ret = der_copy_heim_integer(serialNumber, q->serial);
2626     if (ret) {
2627         free(q->serial);
2628         q->serial = NULL;
2629         return ret;
2630     }
2631     if (q->issuer_name) {
2632         free_Name(q->issuer_name);
2633         free(q->issuer_name);
2634     }
2635     q->issuer_name = malloc(sizeof(*q->issuer_name));
2636     if (q->issuer_name == NULL)
2637         return ENOMEM;
2638     ret = copy_Name(issuer, q->issuer_name);
2639     if (ret) {
2640         free(q->issuer_name);
2641         q->issuer_name = NULL;
2642         return ret;
2643     }
2644     q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
2645     return 0;
2646 }
2647
2648 /**
2649  * Set the query controller to match on a friendly name
2650  *
2651  * @param q a hx509 query controller.
2652  * @param name a friendly name to match on
2653  *
2654  * @return An hx509 error code, see hx509_get_error_string().
2655  *
2656  * @ingroup hx509_cert
2657  */
2658
2659 int
2660 hx509_query_match_friendly_name(hx509_query *q, const char *name)
2661 {
2662     if (q->friendlyname)
2663         free(q->friendlyname);
2664     q->friendlyname = strdup(name);
2665     if (q->friendlyname == NULL)
2666         return ENOMEM;
2667     q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
2668     return 0;
2669 }
2670
2671 /**
2672  * Set the query controller to require an one specific EKU (extended
2673  * key usage). Any previous EKU matching is overwitten. If NULL is
2674  * passed in as the eku, the EKU requirement is reset.
2675  *
2676  * @param q a hx509 query controller.
2677  * @param eku an EKU to match on.
2678  *
2679  * @return An hx509 error code, see hx509_get_error_string().
2680  *
2681  * @ingroup hx509_cert
2682  */
2683
2684 int
2685 hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
2686 {
2687     int ret;
2688
2689     if (eku == NULL) {
2690         if (q->eku) {
2691             der_free_oid(q->eku);
2692             free(q->eku);
2693             q->eku = NULL;
2694         }
2695         q->match &= ~HX509_QUERY_MATCH_EKU;
2696     } else {
2697         if (q->eku) {
2698             der_free_oid(q->eku);
2699         } else {
2700             q->eku = calloc(1, sizeof(*q->eku));
2701             if (q->eku == NULL)
2702                 return ENOMEM;
2703         }
2704         ret = der_copy_oid(eku, q->eku);
2705         if (ret) {
2706             free(q->eku);
2707             q->eku = NULL;
2708             return ret;
2709         }
2710         q->match |= HX509_QUERY_MATCH_EKU;
2711     }
2712     return 0;
2713 }
2714
2715 int
2716 hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
2717 {
2718     if (q->expr) {
2719         _hx509_expr_free(q->expr);
2720         q->expr = NULL;
2721     }
2722
2723     if (expr == NULL) {
2724         q->match &= ~HX509_QUERY_MATCH_EXPR;
2725     } else {
2726         q->expr = _hx509_expr_parse(expr);
2727         if (q->expr)
2728             q->match |= HX509_QUERY_MATCH_EXPR;
2729     }
2730
2731     return 0;
2732 }
2733
2734 /**
2735  * Set the query controller to match using a specific match function.
2736  *
2737  * @param q a hx509 query controller.
2738  * @param func function to use for matching, if the argument is NULL,
2739  * the match function is removed.
2740  * @param ctx context passed to the function.
2741  *
2742  * @return An hx509 error code, see hx509_get_error_string().
2743  *
2744  * @ingroup hx509_cert
2745  */
2746
2747 int
2748 hx509_query_match_cmp_func(hx509_query *q,
2749                            int (*func)(void *, hx509_cert),
2750                            void *ctx)
2751 {
2752     if (func)
2753         q->match |= HX509_QUERY_MATCH_FUNCTION;
2754     else
2755         q->match &= ~HX509_QUERY_MATCH_FUNCTION;
2756     q->cmp_func = func;
2757     q->cmp_func_ctx = ctx;
2758     return 0;
2759 }
2760
2761 /**
2762  * Free the query controller.
2763  *
2764  * @param context A hx509 context.
2765  * @param q a pointer to the query controller.
2766  *
2767  * @ingroup hx509_cert
2768  */
2769
2770 void
2771 hx509_query_free(hx509_context context, hx509_query *q)
2772 {
2773     if (q == NULL)
2774         return;
2775
2776     if (q->serial) {
2777         der_free_heim_integer(q->serial);
2778         free(q->serial);
2779     }
2780     if (q->issuer_name) {
2781         free_Name(q->issuer_name);
2782         free(q->issuer_name);
2783     }
2784     if (q->eku) {
2785         der_free_oid(q->eku);
2786         free(q->eku);
2787     }
2788     if (q->friendlyname)
2789         free(q->friendlyname);
2790     if (q->expr)
2791         _hx509_expr_free(q->expr);
2792
2793     memset(q, 0, sizeof(*q));
2794     free(q);
2795 }
2796
2797 int
2798 _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
2799 {
2800     Certificate *c = _hx509_get_cert(cert);
2801     int ret, diff;
2802
2803     _hx509_query_statistic(context, 1, q);
2804
2805     if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
2806         _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
2807         return 0;
2808
2809     if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
2810         _hx509_Certificate_cmp(q->certificate, c) != 0)
2811         return 0;
2812
2813     if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
2814         && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
2815         return 0;
2816
2817     if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
2818         ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
2819         if (ret || diff)
2820             return 0;
2821     }
2822
2823     if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
2824         ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
2825         if (ret || diff)
2826             return 0;
2827     }
2828
2829     if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
2830         SubjectKeyIdentifier si;
2831
2832         ret = _hx509_find_extension_subject_key_id(c, &si);
2833         if (ret == 0) {
2834             if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
2835                 ret = 1;
2836             free_SubjectKeyIdentifier(&si);
2837         }
2838         if (ret)
2839             return 0;
2840     }
2841     if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
2842         return 0;
2843     if ((q->match & HX509_QUERY_PRIVATE_KEY) && 
2844         _hx509_cert_private_key(cert) == NULL)
2845         return 0;
2846
2847     {
2848         unsigned ku = 0;
2849         if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
2850             ku |= (1 << 0);
2851         if (q->match & HX509_QUERY_KU_NONREPUDIATION)
2852             ku |= (1 << 1);
2853         if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
2854             ku |= (1 << 2);
2855         if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
2856             ku |= (1 << 3);
2857         if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
2858             ku |= (1 << 4);
2859         if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
2860             ku |= (1 << 5);
2861         if (q->match & HX509_QUERY_KU_CRLSIGN)
2862             ku |= (1 << 6);
2863         if (ku && check_key_usage(context, c, ku, TRUE))
2864             return 0;
2865     }
2866     if ((q->match & HX509_QUERY_ANCHOR))
2867         return 0;
2868
2869     if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
2870         hx509_cert_attribute a;
2871
2872         a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
2873         if (a == NULL)
2874             return 0;
2875         if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
2876             return 0;
2877     }
2878
2879     if (q->match & HX509_QUERY_NO_MATCH_PATH) {
2880         size_t i;
2881
2882         for (i = 0; i < q->path->len; i++)
2883             if (hx509_cert_cmp(q->path->val[i], cert) == 0)
2884                 return 0;
2885     }
2886     if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
2887         const char *name = hx509_cert_get_friendly_name(cert);
2888         if (name == NULL)
2889             return 0;
2890         if (strcasecmp(q->friendlyname, name) != 0)
2891             return 0;
2892     }
2893     if (q->match & HX509_QUERY_MATCH_FUNCTION) {
2894         ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
2895         if (ret != 0)
2896             return 0;
2897     }
2898
2899     if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
2900         heim_octet_string os;
2901
2902         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
2903         os.length = 
2904             c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
2905
2906         ret = _hx509_verify_signature(context,
2907                                       NULL,
2908                                       hx509_signature_sha1(),
2909                                       &os,
2910                                       q->keyhash_sha1);
2911         if (ret != 0)
2912             return 0;
2913     }
2914
2915     if (q->match & HX509_QUERY_MATCH_TIME) {
2916         time_t t;
2917         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
2918         if (t > q->timenow)
2919             return 0;
2920         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
2921         if (t < q->timenow)
2922             return 0;
2923     }
2924
2925     /* If an EKU is required, check the cert for it. */
2926     if ((q->match & HX509_QUERY_MATCH_EKU) &&
2927         hx509_cert_check_eku(context, cert, q->eku, 0))
2928         return 0;
2929
2930     if ((q->match & HX509_QUERY_MATCH_EXPR)) {
2931         hx509_env env = NULL;
2932
2933         ret = _hx509_cert_to_env(context, cert, &env);
2934         if (ret)
2935             return 0;
2936
2937         ret = _hx509_expr_eval(context, env, q->expr);
2938         hx509_env_free(&env);
2939         if (ret == 0)
2940             return 0;
2941     }
2942
2943     if (q->match & ~HX509_QUERY_MASK)
2944         return 0;
2945
2946     return 1;
2947 }
2948
2949 /**
2950  * Set a statistic file for the query statistics.
2951  *
2952  * @param context A hx509 context.
2953  * @param fn statistics file name
2954  *
2955  * @ingroup hx509_cert
2956  */
2957
2958 void
2959 hx509_query_statistic_file(hx509_context context, const char *fn)
2960 {
2961     if (context->querystat)
2962         free(context->querystat);
2963     context->querystat = strdup(fn);
2964 }
2965
2966 void
2967 _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
2968 {
2969     FILE *f;
2970     if (context->querystat == NULL)
2971         return;
2972     f = fopen(context->querystat, "a");
2973     if (f == NULL)
2974         return;
2975     rk_cloexec_file(f);
2976     fprintf(f, "%d %d\n", type, q->match);
2977     fclose(f);
2978 }
2979
2980 static const char *statname[] = {
2981     "find issuer cert",
2982     "match serialnumber",
2983     "match issuer name",
2984     "match subject name",
2985     "match subject key id",
2986     "match issuer id",
2987     "private key",
2988     "ku encipherment",
2989     "ku digitalsignature",
2990     "ku keycertsign",
2991     "ku crlsign",
2992     "ku nonrepudiation",
2993     "ku keyagreement",
2994     "ku dataencipherment",
2995     "anchor",
2996     "match certificate",
2997     "match local key id",
2998     "no match path",
2999     "match friendly name",
3000     "match function",
3001     "match key hash sha1",
3002     "match time"
3003 };
3004
3005 struct stat_el {
3006     unsigned long stats;
3007     unsigned int index;
3008 };
3009
3010
3011 static int
3012 stat_sort(const void *a, const void *b)
3013 {
3014     const struct stat_el *ae = a;
3015     const struct stat_el *be = b;
3016     return be->stats - ae->stats;
3017 }
3018
3019 /**
3020  * Unparse the statistics file and print the result on a FILE descriptor.
3021  *
3022  * @param context A hx509 context.
3023  * @param printtype tyep to print
3024  * @param out the FILE to write the data on.
3025  *
3026  * @ingroup hx509_cert
3027  */
3028
3029 void
3030 hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
3031 {
3032     rtbl_t t;
3033     FILE *f;
3034     int type, mask, i, num;
3035     unsigned long multiqueries = 0, totalqueries = 0;
3036     struct stat_el stats[32];
3037
3038     if (context->querystat == NULL)
3039         return;
3040     f = fopen(context->querystat, "r");
3041     if (f == NULL) {
3042         fprintf(out, "No statistic file %s: %s.\n", 
3043                 context->querystat, strerror(errno));
3044         return;
3045     }
3046     rk_cloexec_file(f);
3047     
3048     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3049         stats[i].index = i;
3050         stats[i].stats = 0;
3051     }
3052
3053     while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
3054         if (type != printtype)
3055             continue;
3056         num = i = 0;
3057         while (mask && i < sizeof(stats)/sizeof(stats[0])) {
3058             if (mask & 1) {
3059                 stats[i].stats++;
3060                 num++;
3061             }
3062             mask = mask >>1 ;
3063             i++;
3064         }
3065         if (num > 1)
3066             multiqueries++;
3067         totalqueries++;
3068     }
3069     fclose(f);
3070
3071     qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
3072
3073     t = rtbl_create();
3074     if (t == NULL)
3075         errx(1, "out of memory");
3076
3077     rtbl_set_separator (t, "  ");
3078     
3079     rtbl_add_column_by_id (t, 0, "Name", 0);
3080     rtbl_add_column_by_id (t, 1, "Counter", 0);
3081
3082
3083     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
3084         char str[10];
3085
3086         if (stats[i].index < sizeof(statname)/sizeof(statname[0])) 
3087             rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
3088         else {
3089             snprintf(str, sizeof(str), "%d", stats[i].index);
3090             rtbl_add_column_entry_by_id (t, 0, str);
3091         }
3092         snprintf(str, sizeof(str), "%lu", stats[i].stats);
3093         rtbl_add_column_entry_by_id (t, 1, str);
3094     }
3095
3096     rtbl_format(t, out);
3097     rtbl_destroy(t);
3098
3099     fprintf(out, "\nQueries: multi %lu total %lu\n", 
3100             multiqueries, totalqueries);
3101 }
3102
3103 /**
3104  * Check the extended key usage on the hx509 certificate.
3105  *
3106  * @param context A hx509 context.
3107  * @param cert A hx509 context.
3108  * @param eku the EKU to check for
3109  * @param allow_any_eku if the any EKU is set, allow that to be a
3110  * substitute.
3111  *
3112  * @return An hx509 error code, see hx509_get_error_string().
3113  *
3114  * @ingroup hx509_cert
3115  */
3116
3117 int
3118 hx509_cert_check_eku(hx509_context context, hx509_cert cert,
3119                      const heim_oid *eku, int allow_any_eku)
3120 {
3121     ExtKeyUsage e;
3122     int ret, i;
3123
3124     ret = find_extension_eku(_hx509_get_cert(cert), &e);
3125     if (ret) {
3126         hx509_clear_error_string(context);
3127         return ret;
3128     }
3129
3130     for (i = 0; i < e.len; i++) {
3131         if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
3132             free_ExtKeyUsage(&e);
3133             return 0;
3134         }
3135         if (allow_any_eku) {
3136 #if 0
3137             if (der_heim_oid_cmp(id_any_eku, &e.val[i]) == 0) {
3138                 free_ExtKeyUsage(&e);
3139                 return 0;
3140             }
3141 #endif
3142         }
3143     }
3144     free_ExtKeyUsage(&e);
3145     hx509_clear_error_string(context);
3146     return HX509_CERTIFICATE_MISSING_EKU;
3147 }
3148
3149 int
3150 _hx509_cert_get_keyusage(hx509_context context,
3151                          hx509_cert c,
3152                          KeyUsage *ku)
3153 {
3154     Certificate *cert;
3155     const Extension *e;
3156     size_t size;
3157     int ret, i = 0;
3158
3159     memset(ku, 0, sizeof(*ku));
3160
3161     cert = _hx509_get_cert(c);
3162
3163     if (_hx509_cert_get_version(cert) < 3)
3164         return 0;
3165
3166     e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
3167     if (e == NULL)
3168         return HX509_KU_CERT_MISSING;
3169     
3170     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
3171     if (ret)
3172         return ret;
3173     return 0;
3174 }
3175
3176 int
3177 _hx509_cert_get_eku(hx509_context context,
3178                     hx509_cert cert,
3179                     ExtKeyUsage *e)
3180 {
3181     int ret;
3182
3183     memset(e, 0, sizeof(*e));
3184
3185     ret = find_extension_eku(_hx509_get_cert(cert), e);
3186     if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
3187         hx509_clear_error_string(context);
3188         return ret;
3189     }
3190     return 0;
3191 }
3192
3193 /**
3194  * Encodes the hx509 certificate as a DER encode binary.
3195  *
3196  * @param context A hx509 context.
3197  * @param c the certificate to encode.
3198  * @param os the encode certificate, set to NULL, 0 on case of
3199  * error. Free the returned structure with hx509_xfree().
3200  *
3201  * @return An hx509 error code, see hx509_get_error_string().
3202  *
3203  * @ingroup hx509_cert
3204  */
3205
3206 int
3207 hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
3208 {
3209     size_t size;
3210     int ret;
3211
3212     os->data = NULL;
3213     os->length = 0;
3214
3215     ASN1_MALLOC_ENCODE(Certificate, os->data, os->length, 
3216                        _hx509_get_cert(c), &size, ret);
3217     if (ret) {
3218         os->data = NULL;
3219         os->length = 0;
3220         return ret;
3221     }
3222     if (os->length != size)
3223         _hx509_abort("internal ASN.1 encoder error");
3224
3225     return ret;
3226 }
3227
3228 /*
3229  * Last to avoid lost __attribute__s due to #undef.
3230  */
3231
3232 #undef __attribute__
3233 #define __attribute__(X)
3234
3235 void
3236 _hx509_abort(const char *fmt, ...)
3237      __attribute__ ((noreturn, format (printf, 1, 2)))
3238 {
3239     va_list ap;
3240     va_start(ap, fmt);
3241     vprintf(fmt, ap);
3242     va_end(ap);
3243     printf("\n");
3244     fflush(stdout);
3245     abort();
3246 }
3247
3248 /**
3249  * Free a data element allocated in the library.
3250  *
3251  * @param ptr data to be freed.
3252  *
3253  * @ingroup hx509_misc
3254  */
3255
3256 void
3257 hx509_xfree(void *ptr)
3258 {
3259     free(ptr);
3260 }
3261
3262 /**
3263  *
3264  */
3265
3266 int
3267 _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
3268 {
3269     ExtKeyUsage eku;
3270     hx509_name name;
3271     char *buf;
3272     int ret;
3273     hx509_env envcert = NULL;
3274
3275     *env = NULL;
3276
3277     /* version */
3278     asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
3279     ret = hx509_env_add(context, &envcert, "version", buf);
3280     free(buf);
3281     if (ret)
3282         goto out;
3283
3284     /* subject */
3285     ret = hx509_cert_get_subject(cert, &name);
3286     if (ret)
3287         goto out;
3288
3289     ret = hx509_name_to_string(name, &buf);
3290     if (ret) {
3291         hx509_name_free(&name);
3292         goto out;
3293     }
3294
3295     ret = hx509_env_add(context, &envcert, "subject", buf);
3296     hx509_name_free(&name);
3297     if (ret)
3298         goto out;
3299
3300     /* issuer */
3301     ret = hx509_cert_get_issuer(cert, &name);
3302     if (ret)
3303         goto out;
3304
3305     ret = hx509_name_to_string(name, &buf);
3306     hx509_name_free(&name);
3307     if (ret)
3308         goto out;
3309
3310     ret = hx509_env_add(context, &envcert, "issuer", buf);
3311     hx509_xfree(buf);
3312     if (ret)
3313         goto out;
3314
3315     /* eku */
3316
3317     ret = _hx509_cert_get_eku(context, cert, &eku);
3318     if (ret == HX509_EXTENSION_NOT_FOUND)
3319         ;
3320     else if (ret != 0)
3321         goto out;
3322     else {
3323         int i;
3324         hx509_env enveku = NULL;
3325
3326         for (i = 0; i < eku.len; i++) {
3327
3328             ret = der_print_heim_oid(&eku.val[i], '.', &buf);
3329             if (ret) {
3330                 free_ExtKeyUsage(&eku);
3331                 hx509_env_free(&enveku);
3332                 goto out;
3333             }
3334             ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
3335             free(buf);
3336             if (ret) {
3337                 free_ExtKeyUsage(&eku);
3338                 hx509_env_free(&enveku);
3339                 goto out;
3340             }
3341         }
3342         free_ExtKeyUsage(&eku);
3343
3344         ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
3345         if (ret) {
3346             hx509_env_free(&enveku);
3347             goto out;
3348         }
3349     }
3350
3351     ret = hx509_env_add_binding(context, env, "certificate", envcert);
3352     if (ret)
3353         goto out;
3354
3355     return 0;
3356
3357 out:
3358     hx509_env_free(&envcert);
3359     return ret;
3360 }