s4:heimdal: import lorikeet-heimdal-202201172009 (commit 5a0b45cd723628b3690ea848548b...
[samba.git] / source4 / heimdal / lib / hx509 / ca.c
1 /*
2  * Copyright (c) 2006 - 2010 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
36 /**
37  * @page page_ca Hx509 CA functions
38  *
39  * See the library functions here: @ref hx509_ca
40  */
41
42 struct hx509_ca_tbs {
43     hx509_name subject;
44     SubjectPublicKeyInfo spki;
45     KeyUsage ku;
46     ExtKeyUsage eku;
47     GeneralNames san;
48     CertificatePolicies cps;
49     PolicyMappings pms;
50     heim_integer serial;
51     struct {
52         unsigned int proxy:1;
53         unsigned int ca:1;
54         unsigned int key:1;
55         unsigned int serial:1;
56         unsigned int domaincontroller:1;
57         unsigned int xUniqueID:1;
58     } flags;
59     time_t notBefore;
60     time_t notAfter;
61     HeimPkinitPrincMaxLifeSecs pkinitTicketMaxLife;
62     int pathLenConstraint; /* both for CA and Proxy */
63     CRLDistributionPoints crldp;
64     heim_bit_string subjectUniqueID;
65     heim_bit_string issuerUniqueID;
66     AlgorithmIdentifier *sigalg;
67 };
68
69 /**
70  * Allocate an to-be-signed certificate object that will be converted
71  * into an certificate.
72  *
73  * @param context A hx509 context.
74  * @param tbs returned to-be-signed certicate object, free with
75  * hx509_ca_tbs_free().
76  *
77  * @return An hx509 error code, see hx509_get_error_string().
78  *
79  * @ingroup hx509_ca
80  */
81
82 HX509_LIB_FUNCTION int HX509_LIB_CALL
83 hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84 {
85     *tbs = calloc(1, sizeof(**tbs));
86     if (*tbs == NULL)
87         return ENOMEM;
88
89     return 0;
90 }
91
92 /**
93  * Free an To Be Signed object.
94  *
95  * @param tbs object to free.
96  *
97  * @ingroup hx509_ca
98  */
99
100 HX509_LIB_FUNCTION void HX509_LIB_CALL
101 hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102 {
103     if (tbs == NULL || *tbs == NULL)
104         return;
105
106     free_SubjectPublicKeyInfo(&(*tbs)->spki);
107     free_CertificatePolicies(&(*tbs)->cps);
108     free_PolicyMappings(&(*tbs)->pms);
109     free_GeneralNames(&(*tbs)->san);
110     free_ExtKeyUsage(&(*tbs)->eku);
111     der_free_heim_integer(&(*tbs)->serial);
112     free_CRLDistributionPoints(&(*tbs)->crldp);
113     der_free_bit_string(&(*tbs)->subjectUniqueID);
114     der_free_bit_string(&(*tbs)->issuerUniqueID);
115     if ((*tbs)->subject)
116         hx509_name_free(&(*tbs)->subject);
117     if ((*tbs)->sigalg) {
118         free_AlgorithmIdentifier((*tbs)->sigalg);
119         free((*tbs)->sigalg);
120     }
121
122     memset(*tbs, 0, sizeof(**tbs));
123     free(*tbs);
124     *tbs = NULL;
125 }
126
127 /**
128  * Set the absolute time when the certificate is valid from. If not
129  * set the current time will be used.
130  *
131  * @param context A hx509 context.
132  * @param tbs object to be signed.
133  * @param t time the certificated will start to be valid
134  *
135  * @return An hx509 error code, see hx509_get_error_string().
136  *
137  * @ingroup hx509_ca
138  */
139
140 HX509_LIB_FUNCTION int HX509_LIB_CALL
141 hx509_ca_tbs_set_notBefore(hx509_context context,
142                            hx509_ca_tbs tbs,
143                            time_t t)
144 {
145     tbs->notBefore = t;
146     return 0;
147 }
148
149 /**
150  * Set the absolute time when the certificate is valid to.
151  *
152  * @param context A hx509 context.
153  * @param tbs object to be signed.
154  * @param t time when the certificate will expire
155  *
156  * @return An hx509 error code, see hx509_get_error_string().
157  *
158  * @ingroup hx509_ca
159  */
160
161 HX509_LIB_FUNCTION int HX509_LIB_CALL
162 hx509_ca_tbs_set_notAfter(hx509_context context,
163                            hx509_ca_tbs tbs,
164                            time_t t)
165 {
166     tbs->notAfter = t;
167     return 0;
168 }
169
170 /**
171  * Set the relative time when the certificiate is going to expire.
172  *
173  * @param context A hx509 context.
174  * @param tbs object to be signed.
175  * @param delta seconds to the certificate is going to expire.
176  *
177  * @return An hx509 error code, see hx509_get_error_string().
178  *
179  * @ingroup hx509_ca
180  */
181
182 HX509_LIB_FUNCTION int HX509_LIB_CALL
183 hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
184                                    hx509_ca_tbs tbs,
185                                    time_t delta)
186 {
187     return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
188 }
189
190 HX509_LIB_FUNCTION int HX509_LIB_CALL
191 hx509_ca_tbs_set_pkinit_max_life(hx509_context context,
192                                  hx509_ca_tbs tbs,
193                                  time_t max_life)
194 {
195     tbs->pkinitTicketMaxLife = max_life;
196     return 0;
197 }
198
199 static const struct units templatebits[] = {
200     { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
201     { "KeyUsage", HX509_CA_TEMPLATE_KU },
202     { "SPKI", HX509_CA_TEMPLATE_SPKI },
203     { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
204     { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
205     { "serial", HX509_CA_TEMPLATE_SERIAL },
206     { "subject", HX509_CA_TEMPLATE_SUBJECT },
207     { "pkinitMaxLife", HX509_CA_TEMPLATE_PKINIT_MAX_LIFE },
208     { NULL, 0 }
209 };
210
211 /**
212  * Make of template units, use to build flags argument to
213  * hx509_ca_tbs_set_template() with parse_units().
214  *
215  * @return an units structure.
216  *
217  * @ingroup hx509_ca
218  */
219
220 HX509_LIB_FUNCTION const struct units * HX509_LIB_CALL
221 hx509_ca_tbs_template_units(void)
222 {
223     return templatebits;
224 }
225
226 /**
227  * Initialize the to-be-signed certificate object from a template certificate.
228  *
229  * @param context A hx509 context.
230  * @param tbs object to be signed.
231  * @param flags bit field selecting what to copy from the template
232  * certificate.
233  * @param cert template certificate.
234  *
235  * @return An hx509 error code, see hx509_get_error_string().
236  *
237  * @ingroup hx509_ca
238  */
239
240 HX509_LIB_FUNCTION int HX509_LIB_CALL
241 hx509_ca_tbs_set_template(hx509_context context,
242                           hx509_ca_tbs tbs,
243                           int flags,
244                           hx509_cert cert)
245 {
246     int ret;
247
248     if (flags & HX509_CA_TEMPLATE_SUBJECT) {
249         if (tbs->subject)
250             hx509_name_free(&tbs->subject);
251         ret = hx509_cert_get_subject(cert, &tbs->subject);
252         if (ret) {
253             hx509_set_error_string(context, 0, ret,
254                                    "Failed to get subject from template");
255             return ret;
256         }
257     }
258     if (flags & HX509_CA_TEMPLATE_SERIAL) {
259         der_free_heim_integer(&tbs->serial);
260         ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
261         tbs->flags.serial = !ret;
262         if (ret) {
263             hx509_set_error_string(context, 0, ret,
264                                    "Failed to copy serial number");
265             return ret;
266         }
267     }
268     if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
269         tbs->notBefore = hx509_cert_get_notBefore(cert);
270     if (flags & HX509_CA_TEMPLATE_NOTAFTER)
271         tbs->notAfter = hx509_cert_get_notAfter(cert);
272     if (flags & HX509_CA_TEMPLATE_SPKI) {
273         free_SubjectPublicKeyInfo(&tbs->spki);
274         ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
275         tbs->flags.key = !ret;
276         if (ret)
277             return ret;
278     }
279     if (flags & HX509_CA_TEMPLATE_KU) {
280         ret = _hx509_cert_get_keyusage(context, cert, &tbs->ku);
281         if (ret)
282             return ret;
283     }
284     if (flags & HX509_CA_TEMPLATE_EKU) {
285         ExtKeyUsage eku;
286         size_t i;
287         ret = _hx509_cert_get_eku(context, cert, &eku);
288         if (ret)
289             return ret;
290         for (i = 0; i < eku.len; i++) {
291             ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
292             if (ret) {
293                 free_ExtKeyUsage(&eku);
294                 return ret;
295             }
296         }
297         free_ExtKeyUsage(&eku);
298     }
299     if (flags & HX509_CA_TEMPLATE_PKINIT_MAX_LIFE) {
300         time_t max_life;
301
302         if ((max_life = hx509_cert_get_pkinit_max_life(context, cert, 0)) > 0)
303             hx509_ca_tbs_set_pkinit_max_life(context, tbs, max_life);
304     }
305     return 0;
306 }
307
308 /**
309  * Make the to-be-signed certificate object a CA certificate. If the
310  * pathLenConstraint is negative path length constraint is used.
311  *
312  * @param context A hx509 context.
313  * @param tbs object to be signed.
314  * @param pathLenConstraint path length constraint, negative, no
315  * constraint.
316  *
317  * @return An hx509 error code, see hx509_get_error_string().
318  *
319  * @ingroup hx509_ca
320  */
321
322 HX509_LIB_FUNCTION int HX509_LIB_CALL
323 hx509_ca_tbs_set_ca(hx509_context context,
324                     hx509_ca_tbs tbs,
325                     int pathLenConstraint)
326 {
327     tbs->flags.ca = 1;
328     tbs->pathLenConstraint = pathLenConstraint;
329     return 0;
330 }
331
332 /**
333  * Make the to-be-signed certificate object a proxy certificate. If the
334  * pathLenConstraint is negative path length constraint is used.
335  *
336  * @param context A hx509 context.
337  * @param tbs object to be signed.
338  * @param pathLenConstraint path length constraint, negative, no
339  * constraint.
340  *
341  * @return An hx509 error code, see hx509_get_error_string().
342  *
343  * @ingroup hx509_ca
344  */
345
346 HX509_LIB_FUNCTION int HX509_LIB_CALL
347 hx509_ca_tbs_set_proxy(hx509_context context,
348                        hx509_ca_tbs tbs,
349                        int pathLenConstraint)
350 {
351     tbs->flags.proxy = 1;
352     tbs->pathLenConstraint = pathLenConstraint;
353     return 0;
354 }
355
356
357 /**
358  * Make the to-be-signed certificate object a windows domain controller certificate.
359  *
360  * @param context A hx509 context.
361  * @param tbs object to be signed.
362  *
363  * @return An hx509 error code, see hx509_get_error_string().
364  *
365  * @ingroup hx509_ca
366  */
367
368 HX509_LIB_FUNCTION int HX509_LIB_CALL
369 hx509_ca_tbs_set_domaincontroller(hx509_context context,
370                                   hx509_ca_tbs tbs)
371 {
372     tbs->flags.domaincontroller = 1;
373     return 0;
374 }
375
376 /**
377  * Set the subject public key info (SPKI) in the to-be-signed certificate
378  * object. SPKI is the public key and key related parameters in the
379  * certificate.
380  *
381  * @param context A hx509 context.
382  * @param tbs object to be signed.
383  * @param spki subject public key info to use for the to-be-signed certificate object.
384  *
385  * @return An hx509 error code, see hx509_get_error_string().
386  *
387  * @ingroup hx509_ca
388  */
389
390 HX509_LIB_FUNCTION int HX509_LIB_CALL
391 hx509_ca_tbs_set_spki(hx509_context context,
392                       hx509_ca_tbs tbs,
393                       const SubjectPublicKeyInfo *spki)
394 {
395     int ret;
396     free_SubjectPublicKeyInfo(&tbs->spki);
397     ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
398     tbs->flags.key = !ret;
399     return ret;
400 }
401
402 /**
403  * Set the serial number to use for to-be-signed certificate object.
404  *
405  * @param context A hx509 context.
406  * @param tbs object to be signed.
407  * @param serialNumber serial number to use for the to-be-signed
408  * certificate object.
409  *
410  * @return An hx509 error code, see hx509_get_error_string().
411  *
412  * @ingroup hx509_ca
413  */
414
415 HX509_LIB_FUNCTION int HX509_LIB_CALL
416 hx509_ca_tbs_set_serialnumber(hx509_context context,
417                               hx509_ca_tbs tbs,
418                               const heim_integer *serialNumber)
419 {
420     int ret;
421     der_free_heim_integer(&tbs->serial);
422     ret = der_copy_heim_integer(serialNumber, &tbs->serial);
423     tbs->flags.serial = !ret;
424     return ret;
425 }
426
427 /**
428  * Copy elements of a CSR into a TBS, but only if all of them are authorized.
429  *
430  * @param context A hx509 context.
431  * @param tbs object to be signed.
432  * @param req CSR
433  *
434  * @return An hx509 error code, see hx509_get_error_string().
435  *
436  * @ingroup hx509_ca
437  */
438
439 HX509_LIB_FUNCTION int HX509_LIB_CALL
440 hx509_ca_tbs_set_from_csr(hx509_context context,
441                           hx509_ca_tbs tbs,
442                           hx509_request req)
443 {
444     hx509_san_type san_type;
445     heim_oid oid = { 0, 0 };
446     KeyUsage ku;
447     size_t i;
448     char *s = NULL;
449     int ret;
450
451     if (hx509_request_count_unauthorized(req)) {
452         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
453         return EACCES;
454     }
455
456     ret = hx509_request_get_ku(context, req, &ku);
457     if (ret == 0 && KeyUsage2int(ku))
458         ret = hx509_ca_tbs_add_ku(context, tbs, ku);
459
460     for (i = 0; ret == 0; i++) {
461         free(s); s = NULL;
462         der_free_oid(&oid);
463         ret = hx509_request_get_eku(req, i, &s);
464         if (ret == 0)
465             ret = der_parse_heim_oid(s, ".", &oid);
466         if (ret == 0)
467             ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
468     }
469     if (ret == HX509_NO_ITEM)
470         ret = 0;
471
472     for (i = 0; ret == 0; i++) {
473         free(s); s = NULL;
474         ret = hx509_request_get_san(req, i, &san_type, &s);
475         if (ret == 0)
476             ret = hx509_ca_tbs_add_san(context, tbs, san_type, s);
477     }
478     if (ret == HX509_NO_ITEM)
479         ret = 0;
480
481     der_free_oid(&oid);
482     free(s);
483     return ret;
484 }
485
486 /**
487  * An an extended key usage to the to-be-signed certificate object.
488  * Duplicates will detected and not added.
489  *
490  * @param context A hx509 context.
491  * @param tbs object to be signed.
492  * @param oid extended key usage to add.
493  *
494  * @return An hx509 error code, see hx509_get_error_string().
495  *
496  * @ingroup hx509_ca
497  */
498
499 HX509_LIB_FUNCTION int HX509_LIB_CALL
500 hx509_ca_tbs_add_ku(hx509_context context,
501                     hx509_ca_tbs tbs,
502                     KeyUsage ku)
503 {
504     tbs->ku = ku;
505     return 0;
506 }
507
508 /**
509  * An an extended key usage to the to-be-signed certificate object.
510  * Duplicates will detected and not added.
511  *
512  * @param context A hx509 context.
513  * @param tbs object to be signed.
514  * @param oid extended key usage to add.
515  *
516  * @return An hx509 error code, see hx509_get_error_string().
517  *
518  * @ingroup hx509_ca
519  */
520
521 HX509_LIB_FUNCTION int HX509_LIB_CALL
522 hx509_ca_tbs_add_eku(hx509_context context,
523                      hx509_ca_tbs tbs,
524                      const heim_oid *oid)
525 {
526     void *ptr;
527     int ret;
528     unsigned i;
529
530     /* search for duplicates */
531     for (i = 0; i < tbs->eku.len; i++) {
532         if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
533             return 0;
534     }
535
536     ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
537     if (ptr == NULL) {
538         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
539         return ENOMEM;
540     }
541     tbs->eku.val = ptr;
542     ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
543     if (ret) {
544         hx509_set_error_string(context, 0, ret, "out of memory");
545         return ret;
546     }
547     tbs->eku.len += 1;
548     return 0;
549 }
550
551 /**
552  * Add a certificate policy to the to-be-signed certificate object.  Duplicates
553  * will detected and not added.
554  *
555  * @param context A hx509 context.
556  * @param tbs object to be signed.
557  * @param oid policy OID.
558  * @param cps_uri CPS URI to qualify policy with.
559  * @param user_notice user notice display text to qualify policy with.
560  *
561  * @return An hx509 error code, see hx509_get_error_string().
562  *
563  * @ingroup hx509_ca
564  */
565
566 HX509_LIB_FUNCTION int HX509_LIB_CALL
567 hx509_ca_tbs_add_pol(hx509_context context,
568                      hx509_ca_tbs tbs,
569                      const heim_oid *oid,
570                      const char *cps_uri,
571                      const char *user_notice)
572 {
573     PolicyQualifierInfos pqis;
574     PolicyQualifierInfo pqi;
575     PolicyInformation pi;
576     size_t i, size;
577     int ret = 0;
578
579     /* search for duplicates */
580     for (i = 0; i < tbs->cps.len; i++) {
581         if (der_heim_oid_cmp(oid, &tbs->cps.val[i].policyIdentifier) == 0)
582             return 0;
583     }
584
585     memset(&pi, 0, sizeof(pi));
586     memset(&pqi, 0, sizeof(pqi));
587     memset(&pqis, 0, sizeof(pqis));
588
589     pi.policyIdentifier = *oid;
590     if (cps_uri) {
591         CPSuri uri;
592
593         uri.length = strlen(cps_uri);
594         uri.data = (void *)(uintptr_t)cps_uri;
595         pqi.policyQualifierId = asn1_oid_id_pkix_qt_cps;
596
597         ASN1_MALLOC_ENCODE(CPSuri,
598                            pqi.qualifier.data,
599                            pqi.qualifier.length,
600                            &uri, &size, ret);
601         if (ret == 0) {
602             ret = add_PolicyQualifierInfos(&pqis, &pqi);
603             free_heim_any(&pqi.qualifier);
604         }
605     }
606     if (ret == 0 && user_notice) {
607         DisplayText dt;
608         UserNotice un;
609
610         dt.element = choice_DisplayText_utf8String;
611         dt.u.utf8String = (void *)(uintptr_t)user_notice;
612         un.explicitText = &dt;
613         un.noticeRef = 0;
614
615         pqi.policyQualifierId = asn1_oid_id_pkix_qt_unotice;
616         ASN1_MALLOC_ENCODE(UserNotice,
617                            pqi.qualifier.data,
618                            pqi.qualifier.length,
619                            &un, &size, ret);
620         if (ret == 0) {
621             ret = add_PolicyQualifierInfos(&pqis, &pqi);
622             free_heim_any(&pqi.qualifier);
623         }
624     }
625
626     pi.policyQualifiers = pqis.len ? &pqis : 0;
627
628     if (ret == 0)
629         ret = add_CertificatePolicies(&tbs->cps, &pi);
630
631     free_PolicyQualifierInfos(&pqis);
632     return ret;
633 }
634
635 /**
636  * Add a certificate policy mapping to the to-be-signed certificate object.
637  * Duplicates will detected and not added.
638  *
639  * @param context A hx509 context.
640  * @param tbs object to be signed.
641  * @param issuer issuerDomainPolicy policy OID.
642  * @param subject subjectDomainPolicy policy OID.
643  *
644  * @return An hx509 error code, see hx509_get_error_string().
645  *
646  * @ingroup hx509_ca
647  */
648
649 HX509_LIB_FUNCTION int HX509_LIB_CALL
650 hx509_ca_tbs_add_pol_mapping(hx509_context context,
651                              hx509_ca_tbs tbs,
652                              const heim_oid *issuer,
653                              const heim_oid *subject)
654 {
655     PolicyMapping pm;
656     size_t i;
657
658     /* search for duplicates */
659     for (i = 0; i < tbs->pms.len; i++) {
660         PolicyMapping *pmp = &tbs->pms.val[i];
661         if (der_heim_oid_cmp(issuer, &pmp->issuerDomainPolicy) == 0 &&
662             der_heim_oid_cmp(subject, &pmp->subjectDomainPolicy) == 0)
663             return 0;
664     }
665
666     memset(&pm, 0, sizeof(pm));
667     pm.issuerDomainPolicy = *issuer;
668     pm.subjectDomainPolicy = *subject;
669     return add_PolicyMappings(&tbs->pms, &pm);
670 }
671
672 /**
673  * Add CRL distribution point URI to the to-be-signed certificate
674  * object.
675  *
676  * @param context A hx509 context.
677  * @param tbs object to be signed.
678  * @param uri uri to the CRL.
679  * @param issuername name of the issuer.
680  *
681  * @return An hx509 error code, see hx509_get_error_string().
682  *
683  * @ingroup hx509_ca
684  */
685
686 HX509_LIB_FUNCTION int HX509_LIB_CALL
687 hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
688                             hx509_ca_tbs tbs,
689                             const char *uri,
690                             hx509_name issuername)
691 {
692     DistributionPointName dpn;
693     DistributionPoint dp;
694     GeneralNames crlissuer;
695     GeneralName gn, ign;
696     Name in;
697     int ret;
698
699     memset(&dp, 0, sizeof(dp));
700     memset(&gn, 0, sizeof(gn));
701     memset(&ign, 0, sizeof(ign));
702     memset(&in, 0, sizeof(in));
703     gn.element = choice_GeneralName_uniformResourceIdentifier;
704     gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
705     gn.u.uniformResourceIdentifier.length = strlen(uri);
706     dpn.element = choice_DistributionPointName_fullName;
707     dpn.u.fullName.len = 1;
708     dpn.u.fullName.val = &gn;
709     dp.distributionPoint = &dpn;
710
711     if (issuername) {
712         ign.element = choice_GeneralName_directoryName;
713         ret = hx509_name_to_Name(issuername, &ign.u.directoryName);
714         if (ret) {
715             hx509_set_error_string(context, 0, ret, "out of memory");
716             return ret;
717         }
718         crlissuer.len = 1;
719         crlissuer.val = &ign;
720         dp.cRLIssuer = &crlissuer;
721     }
722
723     ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
724     if (issuername)
725         free_Name(&ign.u.directoryName);
726
727     if (ret)
728         hx509_set_error_string(context, 0, ret, "out of memory");
729     return ret;
730 }
731
732 /**
733  * Add Subject Alternative Name otherName to the to-be-signed
734  * certificate object.
735  *
736  * @param context A hx509 context.
737  * @param tbs object to be signed.
738  * @param oid the oid of the OtherName.
739  * @param os data in the other name.
740  *
741  * @return An hx509 error code, see hx509_get_error_string().
742  *
743  * @ingroup hx509_ca
744  */
745
746 HX509_LIB_FUNCTION int HX509_LIB_CALL
747 hx509_ca_tbs_add_san_otherName(hx509_context context,
748                                hx509_ca_tbs tbs,
749                                const heim_oid *oid,
750                                const heim_octet_string *os)
751 {
752     GeneralName gn;
753
754     memset(&gn, 0, sizeof(gn));
755     gn.element = choice_GeneralName_otherName;
756     gn.u.otherName.type_id = *oid;
757     gn.u.otherName.value = *os;
758
759     return add_GeneralNames(&tbs->san, &gn);
760 }
761
762 static
763 int
764 dequote_strndup(hx509_context context, const char *in, size_t len, char **out)
765 {
766     size_t i, k;
767     char *s;
768
769     *out = NULL;
770     if ((s = malloc(len + 1)) == NULL) {
771         hx509_set_error_string(context, 0, ENOMEM, "malloc: out of memory");
772         return ENOMEM;
773     }
774
775     for (k = i = 0; i < len; i++) {
776         if (in[i] == '\\') {
777             switch (in[++i]) {
778             case 't': s[k++] = '\t'; break;
779             case 'b': s[k++] = '\b'; break;
780             case 'n': s[k++] = '\n'; break;
781             case '0':
782                 for (i++; i < len; i++) {
783                     if (in[i] == '\0')
784                         break;
785                     if (in[i++] == '\\' && in[i] == '0')
786                         continue;
787                     hx509_set_error_string(context, 0,
788                                            HX509_PARSING_NAME_FAILED,
789                                            "embedded NULs not supported in "
790                                            "PKINIT SANs");
791                     free(s);
792                     return HX509_PARSING_NAME_FAILED;
793                 }
794                 break;
795             case '\0':
796                 hx509_set_error_string(context, 0,
797                                        HX509_PARSING_NAME_FAILED,
798                                        "trailing unquoted backslashes not "
799                                        "allowed in PKINIT SANs");
800                 free(s);
801                 return HX509_PARSING_NAME_FAILED;
802             default:  s[k++] = in[i]; break;
803             }
804         } else {
805             s[k++] = in[i];
806         }
807     }
808     s[k] = '\0';
809
810     *out = s;
811     return 0;
812 }
813
814 int
815 _hx509_make_pkinit_san(hx509_context context,
816                        const char *principal,
817                        heim_octet_string *os)
818 {
819     KRB5PrincipalName p;
820     size_t size;
821     int ret;
822
823     os->data = NULL;
824     os->length = 0;
825     memset(&p, 0, sizeof(p));
826
827     /* Parse principal */
828     {
829         const char *str, *str_start;
830         size_t n, i;
831
832         /* Count number of components */
833         n = 1;
834         for (str = principal; *str != '\0' && *str != '@'; str++) {
835             if (*str == '\\') {
836                 if (str[1] == '\0') {
837                     ret = HX509_PARSING_NAME_FAILED;
838                     hx509_set_error_string(context, 0, ret,
839                                            "trailing \\ in principal name");
840                     goto out;
841                 }
842                 str++;
843             } else if(*str == '/') {
844                 n++;
845             } else if(*str == '@') {
846                 break;
847             }
848         }
849         if (*str != '@') {
850             /* Note that we allow the realm to be empty */
851             ret = HX509_PARSING_NAME_FAILED;
852             hx509_set_error_string(context, 0, ret, "Missing @ in principal");
853             goto out;
854         };
855
856         p.principalName.name_string.val =
857             calloc(n, sizeof(*p.principalName.name_string.val));
858         if (p.principalName.name_string.val == NULL) {
859             ret = ENOMEM;
860             hx509_set_error_string(context, 0, ret, "malloc: out of memory");
861             goto out;
862         }
863         p.principalName.name_string.len = n;
864         p.principalName.name_type = KRB5_NT_PRINCIPAL;
865
866         for (i = 0, str_start = str = principal; *str != '\0'; str++) {
867             if (*str=='\\') {
868                 str++;
869             } else if(*str == '/') {
870                 /* Note that we allow components to be empty */
871                 ret = dequote_strndup(context, str_start, str - str_start,
872                                       &p.principalName.name_string.val[i++]);
873                 if (ret)
874                     goto out;
875                 str_start = str + 1;
876             } else if(*str == '@') {
877                 ret = dequote_strndup(context, str_start, str - str_start,
878                                       &p.principalName.name_string.val[i++]);
879                 if (ret == 0)
880                     ret = dequote_strndup(context, str + 1, strlen(str + 1), &p.realm);
881                 if (ret)
882                     goto out;
883                 break;
884             }
885         }
886     }
887
888     ASN1_MALLOC_ENCODE(KRB5PrincipalName, os->data, os->length, &p, &size, ret);
889     if (ret) {
890         hx509_set_error_string(context, 0, ret, "Out of memory");
891         goto out;
892     }
893     if (size != os->length)
894         _hx509_abort("internal ASN.1 encoder error");
895
896 out:
897     free_KRB5PrincipalName(&p);
898     return ret;
899 }
900
901 static int
902 add_ia5string_san(hx509_context context,
903                   hx509_ca_tbs tbs,
904                   const heim_oid *oid,
905                   const char *string)
906 {
907     SRVName ustring;
908     heim_octet_string os;
909     size_t size;
910     int ret;
911
912     ustring.data = (void *)(uintptr_t)string;
913     ustring.length = strlen(string);
914
915     os.length = 0;
916     os.data = NULL;
917
918     ASN1_MALLOC_ENCODE(SRVName, os.data, os.length, &ustring, &size, ret);
919     if (ret) {
920         hx509_set_error_string(context, 0, ret, "Out of memory");
921         return ret;
922     }
923     if (size != os.length)
924         _hx509_abort("internal ASN.1 encoder error");
925
926     ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
927     free(os.data);
928     return ret;
929 }
930
931 /**
932  * Add DNSSRV Subject Alternative Name to the to-be-signed certificate object.
933  *
934  * @param context A hx509 context.
935  * @param tbs object to be signed.
936  * @param dnssrv An ASCII string of the for _Service.Name.
937  *
938  * @return An hx509 error code, see hx509_get_error_string().
939  *
940  * @ingroup hx509_ca
941  */
942
943 HX509_LIB_FUNCTION int HX509_LIB_CALL
944 hx509_ca_tbs_add_san_dnssrv(hx509_context context,
945                             hx509_ca_tbs tbs,
946                             const char *dnssrv)
947 {
948     size_t i, len;
949
950     /* Minimal DNSSRV input validation */
951     if (dnssrv == 0 || dnssrv[0] != '_') {
952         hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
953         return EINVAL;
954     }
955     for (i = 1, len = strlen(dnssrv); i < len; i++) {
956         if (dnssrv[i] == '.' && dnssrv[i + 1] != '\0')
957             break;
958     }
959     if (i == len) {
960         hx509_set_error_string(context, 0, EINVAL, "Invalid DNSSRV name");
961         return EINVAL;
962     }
963
964     return add_ia5string_san(context, tbs,
965                              &asn1_oid_id_pkix_on_dnsSRV, dnssrv);
966 }
967
968 /**
969  * Add Kerberos Subject Alternative Name to the to-be-signed
970  * certificate object. The principal string is a UTF8 string.
971  *
972  * @param context A hx509 context.
973  * @param tbs object to be signed.
974  * @param principal Kerberos principal to add to the certificate.
975  *
976  * @return An hx509 error code, see hx509_get_error_string().
977  *
978  * @ingroup hx509_ca
979  */
980
981 HX509_LIB_FUNCTION int HX509_LIB_CALL
982 hx509_ca_tbs_add_san_pkinit(hx509_context context,
983                             hx509_ca_tbs tbs,
984                             const char *principal)
985 {
986     heim_octet_string os;
987     int ret;
988
989     ret = _hx509_make_pkinit_san(context, principal, &os);
990     if (ret == 0)
991         ret = hx509_ca_tbs_add_san_otherName(context, tbs,
992                                              &asn1_oid_id_pkinit_san, &os);
993     free(os.data);
994     return ret;
995 }
996
997 /*
998  *
999  */
1000
1001 static int
1002 add_utf8_san(hx509_context context,
1003              hx509_ca_tbs tbs,
1004              const heim_oid *oid,
1005              const char *string)
1006 {
1007     const PKIXXmppAddr ustring = (const PKIXXmppAddr)(uintptr_t)string;
1008     heim_octet_string os;
1009     size_t size;
1010     int ret;
1011
1012     os.length = 0;
1013     os.data = NULL;
1014
1015     ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
1016     if (ret) {
1017         hx509_set_error_string(context, 0, ret, "Out of memory");
1018         return ret;
1019     }
1020     if (size != os.length)
1021         _hx509_abort("internal ASN.1 encoder error");
1022
1023     ret = hx509_ca_tbs_add_san_otherName(context, tbs, oid, &os);
1024     free(os.data);
1025     return ret;
1026 }
1027
1028 /**
1029  * Add Microsoft UPN Subject Alternative Name to the to-be-signed
1030  * certificate object. The principal string is a UTF8 string.
1031  *
1032  * @param context A hx509 context.
1033  * @param tbs object to be signed.
1034  * @param principal Microsoft UPN string.
1035  *
1036  * @return An hx509 error code, see hx509_get_error_string().
1037  *
1038  * @ingroup hx509_ca
1039  */
1040
1041 HX509_LIB_FUNCTION int HX509_LIB_CALL
1042 hx509_ca_tbs_add_san_ms_upn(hx509_context context,
1043                             hx509_ca_tbs tbs,
1044                             const char *principal)
1045 {
1046     return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
1047 }
1048
1049 /**
1050  * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
1051  * certificate object. The jid is an UTF8 string.
1052  *
1053  * @param context A hx509 context.
1054  * @param tbs object to be signed.
1055  * @param jid string of an a jabber id in UTF8.
1056  *
1057  * @return An hx509 error code, see hx509_get_error_string().
1058  *
1059  * @ingroup hx509_ca
1060  */
1061
1062 HX509_LIB_FUNCTION int HX509_LIB_CALL
1063 hx509_ca_tbs_add_san_jid(hx509_context context,
1064                          hx509_ca_tbs tbs,
1065                          const char *jid)
1066 {
1067     return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
1068 }
1069
1070
1071 /**
1072  * Add a Subject Alternative Name hostname to to-be-signed certificate
1073  * object. A domain match starts with ., an exact match does not.
1074  *
1075  * Example of a an domain match: .domain.se matches the hostname
1076  * host.domain.se.
1077  *
1078  * @param context A hx509 context.
1079  * @param tbs object to be signed.
1080  * @param dnsname a hostame.
1081  *
1082  * @return An hx509 error code, see hx509_get_error_string().
1083  *
1084  * @ingroup hx509_ca
1085  */
1086
1087 HX509_LIB_FUNCTION int HX509_LIB_CALL
1088 hx509_ca_tbs_add_san_hostname(hx509_context context,
1089                               hx509_ca_tbs tbs,
1090                               const char *dnsname)
1091 {
1092     GeneralName gn;
1093
1094     memset(&gn, 0, sizeof(gn));
1095     gn.element = choice_GeneralName_dNSName;
1096     gn.u.dNSName.data = rk_UNCONST(dnsname);
1097     gn.u.dNSName.length = strlen(dnsname);
1098
1099     return add_GeneralNames(&tbs->san, &gn);
1100 }
1101
1102 /**
1103  * Add a Subject Alternative Name rfc822 (email address) to
1104  * to-be-signed certificate object.
1105  *
1106  * @param context A hx509 context.
1107  * @param tbs object to be signed.
1108  * @param rfc822Name a string to a email address.
1109  *
1110  * @return An hx509 error code, see hx509_get_error_string().
1111  *
1112  * @ingroup hx509_ca
1113  */
1114
1115 HX509_LIB_FUNCTION int HX509_LIB_CALL
1116 hx509_ca_tbs_add_san_rfc822name(hx509_context context,
1117                                 hx509_ca_tbs tbs,
1118                                 const char *rfc822Name)
1119 {
1120     GeneralName gn;
1121
1122     memset(&gn, 0, sizeof(gn));
1123     gn.element = choice_GeneralName_rfc822Name;
1124     gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
1125     gn.u.rfc822Name.length = strlen(rfc822Name);
1126
1127     return add_GeneralNames(&tbs->san, &gn);
1128 }
1129
1130 /*
1131  * PermanentIdentifier is one SAN for naming devices with TPMs after their
1132  * endorsement keys or EK certificates.  See TPM 2.0 Keys for Device Identity
1133  * and Attestation, Version 1.00, Revision 2, 9/17/2020 (DRAFT).
1134  *
1135  * The text on the form of permanent identifiers for TPM endorsement keys sans
1136  * certificates is clearly problematic, saying: "When the TPM does not have an
1137  * EK certificate, the identifierValue is a digest of a concatenation of the
1138  * UTF8 string “EkPubkey” (terminating NULL not included) with the binary EK
1139  * public key", but since arbitrary binary is not necessarily valid UTF-8...
1140  * and since NULs embedded in UTF-8 might be OK in some contexts but really
1141  * isn't in C (and Heimdal's ASN.1 compiler does not allow NULs in the
1142  * middle of strings)...  That just cannot be correct.  Since elsewhere the TCG
1143  * specs use the hex encoding of the SHA-256 digest of the DER encoding of
1144  * public keys, that's what we should support in Heimdal, and maybe send in a
1145  * comment.
1146  *
1147  * Also, even where one should use hex encoding of the SHA-256 digest of the
1148  * DER encoding of public keys, how should the public keys be represented?
1149  * Presumably as SPKIs, with all the required parameters and no more.
1150  */
1151
1152 /**
1153  * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1154  * certificate object.  The permanent identifier form for TPM endorsement key
1155  * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1156  * of the certificate.  The permanent identifier form for TPM endorsement keys
1157  * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1158  * not well specified at this point.  It is the caller's responsibility to
1159  * format the identifierValue.
1160  *
1161  * @param context A hx509 context.
1162  * @param tbs object to be signed.
1163  * @param str permanent identifier name in the form "[<assigner-oid>]:[<id>]".
1164  * @param assigner The OID of an assigner.
1165  *
1166  * @return An hx509 error code, see hx509_get_error_string().
1167  *
1168  * @ingroup hx509_ca
1169  */
1170
1171 HX509_LIB_FUNCTION int HX509_LIB_CALL
1172 hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context,
1173                                                 hx509_ca_tbs tbs,
1174                                                 const char *str)
1175 {
1176     const heim_oid *found = NULL;
1177     heim_oid oid;
1178     const char *oidstr, *id;
1179     char *freeme, *p;
1180     int ret;
1181
1182     if ((freeme = strdup(str)) == NULL)
1183         return hx509_enomem(context);
1184
1185     oidstr = freeme;
1186     p = strchr(freeme, ':');
1187     if (!p) {
1188         hx509_set_error_string(context, 0, EINVAL,
1189                                "Invalid PermanentIdentifier string (should be \"[<oid>]:[<id>]\")",
1190                                oidstr);
1191         free(freeme);
1192         return EINVAL;
1193     }
1194     if (p) {
1195         *(p++) = '\0';
1196         id = p;
1197     }
1198     if (oidstr[0] != '\0') {
1199         ret = der_find_heim_oid_by_name(oidstr, &found);
1200         if (ret) {
1201             ret = der_parse_heim_oid(oidstr, " .", &oid);
1202             if (ret == 0)
1203                 found = &oid;
1204         }
1205     }
1206     ret = hx509_ca_tbs_add_san_permanentIdentifier(context, tbs, id, found);
1207     if (found == &oid)
1208         der_free_oid(&oid);
1209     free(freeme);
1210     return ret;
1211 }
1212
1213 /**
1214  * Add a Subject Alternative Name of PermanentIdentifier type to a to-be-signed
1215  * certificate object.  The permanent identifier form for TPM endorsement key
1216  * certificates is the hex encoding of the SHA-256 digest of the DER encoding
1217  * of the certificate.  The permanent identifier form for TPM endorsement keys
1218  * are of the form "EkPubkey<public-key>", where the form of <public-key> is
1219  * not well specified at this point.  It is the caller's responsibility to
1220  * format the identifierValue.
1221  *
1222  * @param context A hx509 context.
1223  * @param tbs object to be signed.
1224  * @param identifierValue The permanent identifier name.
1225  * @param assigner The OID of an assigner.
1226  *
1227  * @return An hx509 error code, see hx509_get_error_string().
1228  *
1229  * @ingroup hx509_ca
1230  */
1231
1232 HX509_LIB_FUNCTION int HX509_LIB_CALL
1233 hx509_ca_tbs_add_san_permanentIdentifier(hx509_context context,
1234                                          hx509_ca_tbs tbs,
1235                                          const char *identifierValue,
1236                                          const heim_oid *assigner)
1237 {
1238     PermanentIdentifier pi;
1239     heim_utf8_string s = (void *)(uintptr_t)identifierValue;
1240     heim_octet_string os;
1241     size_t size;
1242     int ret;
1243
1244     pi.identifierValue = &s;
1245     pi.assigner = (heim_oid*)(uintptr_t)assigner;
1246     os.length = 0;
1247     os.data = NULL;
1248
1249     ASN1_MALLOC_ENCODE(PermanentIdentifier, os.data, os.length, &pi, &size,
1250                        ret);
1251     if (ret) {
1252         hx509_set_error_string(context, 0, ret, "Out of memory");
1253         return ret;
1254     }
1255     if (size != os.length)
1256         _hx509_abort("internal ASN.1 encoder error");
1257
1258     ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1259                                          &asn1_oid_id_pkix_on_permanentIdentifier,
1260                                          &os);
1261     free(os.data);
1262     return ret;
1263 }
1264
1265 /**
1266  * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1267  * certificate object.
1268  *
1269  * @param context A hx509 context.
1270  * @param tbs object to be signed.
1271  * @param str a string of the form "<oid>:<serial>".
1272  * @param hwserial The serial number.
1273  *
1274  * @return An hx509 error code, see hx509_get_error_string().
1275  *
1276  * @ingroup hx509_ca
1277  */
1278
1279 HX509_LIB_FUNCTION int HX509_LIB_CALL
1280 hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context,
1281                                                hx509_ca_tbs tbs,
1282                                                const char *str)
1283 {
1284     const heim_oid *found = NULL;
1285     heim_oid oid;
1286     const char *oidstr, *sno;
1287     char *freeme, *p;
1288     int ret;
1289
1290     if ((freeme = strdup(str)) == NULL)
1291         return hx509_enomem(context);
1292
1293     oidstr = freeme;
1294     p = strchr(freeme, ':');
1295     if (!p) {
1296         hx509_set_error_string(context, 0, EINVAL,
1297                                "Invalid HardwareModuleName string (should be "
1298                                "\"<oid>:<serial>\")",
1299                                oidstr);
1300         free(freeme);
1301         return EINVAL;
1302     }
1303     if (p) {
1304         *(p++) = '\0';
1305         sno = p;
1306     }
1307     if (oidstr[0] == '\0') {
1308         found = &asn1_oid_tcg_tpm20;
1309     } else {
1310         ret = der_find_heim_oid_by_name(oidstr, &found);
1311         if (ret) {
1312             ret = der_parse_heim_oid(oidstr, " .", &oid);
1313             if (ret == 0)
1314                 found = &oid;
1315         }
1316     }
1317     if (!found) {
1318         hx509_set_error_string(context, 0, EINVAL,
1319                                "Could not resolve or parse OID \"%s\"",
1320                                oidstr);
1321         free(freeme);
1322         return EINVAL;
1323     }
1324     ret = hx509_ca_tbs_add_san_hardwareModuleName(context, tbs, found, sno);
1325     if (found == &oid)
1326         der_free_oid(&oid);
1327     free(freeme);
1328     return ret;
1329 }
1330
1331 /**
1332  * Add a Subject Alternative Name of HardwareModuleName type to a to-be-signed
1333  * certificate object.
1334  *
1335  * @param context A hx509 context.
1336  * @param tbs object to be signed.
1337  * @param hwtype The hardwar module type (e.g., `&asn1_oid_tcg_tpm20').
1338  * @param hwserial The serial number.
1339  *
1340  * @return An hx509 error code, see hx509_get_error_string().
1341  *
1342  * @ingroup hx509_ca
1343  */
1344
1345 HX509_LIB_FUNCTION int HX509_LIB_CALL
1346 hx509_ca_tbs_add_san_hardwareModuleName(hx509_context context,
1347                                         hx509_ca_tbs tbs,
1348                                         const heim_oid *hwtype,
1349                                         const char *hwserial)
1350 {
1351     HardwareModuleName hm;
1352     heim_octet_string os;
1353     size_t size;
1354     int ret;
1355
1356     hm.hwType = *hwtype;
1357     hm.hwSerialNum.data = (void *)(uintptr_t)hwserial;
1358     hm.hwSerialNum.length = strlen(hwserial);
1359     os.length = 0;
1360     os.data = NULL;
1361
1362     ASN1_MALLOC_ENCODE(HardwareModuleName, os.data, os.length, &hm, &size,
1363                        ret);
1364     if (ret) {
1365         hx509_set_error_string(context, 0, ret, "Out of memory");
1366         return ret;
1367     }
1368     if (size != os.length)
1369         _hx509_abort("internal ASN.1 encoder error");
1370
1371     ret = hx509_ca_tbs_add_san_otherName(context, tbs,
1372                                          &asn1_oid_id_on_hardwareModuleName,
1373                                          &os);
1374     free(os.data);
1375     return ret;
1376 }
1377
1378 /**
1379  * Add a Subject Alternative Name of the given type to the
1380  * to-be-signed certificate object.
1381  *
1382  * @param context A hx509 context.
1383  * @param tbs object to be signed.
1384  * @param rfc822Name a string to a email address.
1385  *
1386  * @return An hx509 error code, see hx509_get_error_string().
1387  *
1388  * @ingroup hx509_ca
1389  */
1390
1391 HX509_LIB_FUNCTION int HX509_LIB_CALL
1392 hx509_ca_tbs_add_san(hx509_context context,
1393                      hx509_ca_tbs tbs,
1394                      hx509_san_type type,
1395                      const char *s)
1396 {
1397     switch (type) {
1398     case HX509_SAN_TYPE_EMAIL:
1399         return hx509_ca_tbs_add_san_rfc822name(context, tbs, s);
1400     case HX509_SAN_TYPE_DNSNAME:
1401         return hx509_ca_tbs_add_san_hostname(context, tbs, s);
1402     case HX509_SAN_TYPE_DN:
1403         return ENOTSUP;
1404     case HX509_SAN_TYPE_REGISTERED_ID:
1405         return ENOTSUP;
1406     case HX509_SAN_TYPE_XMPP:
1407         return hx509_ca_tbs_add_san_jid(context, tbs, s);
1408     case HX509_SAN_TYPE_PKINIT:
1409         return hx509_ca_tbs_add_san_pkinit(context, tbs, s);
1410     case HX509_SAN_TYPE_MS_UPN:
1411         return hx509_ca_tbs_add_san_ms_upn(context, tbs, s);
1412     default:
1413         return ENOTSUP;
1414     }
1415 }
1416
1417 /**
1418  * Set the subject name of a to-be-signed certificate object.
1419  *
1420  * @param context A hx509 context.
1421  * @param tbs object to be signed.
1422  * @param subject the name to set a subject.
1423  *
1424  * @return An hx509 error code, see hx509_get_error_string().
1425  *
1426  * @ingroup hx509_ca
1427  */
1428
1429 HX509_LIB_FUNCTION int HX509_LIB_CALL
1430 hx509_ca_tbs_set_subject(hx509_context context,
1431                          hx509_ca_tbs tbs,
1432                          hx509_name subject)
1433 {
1434     if (tbs->subject)
1435         hx509_name_free(&tbs->subject);
1436     return hx509_name_copy(context, subject, &tbs->subject);
1437 }
1438
1439 /**
1440  * Set the issuerUniqueID and subjectUniqueID
1441  *
1442  * These are only supposed to be used considered with version 2
1443  * certificates, replaced by the two extensions SubjectKeyIdentifier
1444  * and IssuerKeyIdentifier. This function is to allow application
1445  * using legacy protocol to issue them.
1446  *
1447  * @param context A hx509 context.
1448  * @param tbs object to be signed.
1449  * @param issuerUniqueID to be set
1450  * @param subjectUniqueID to be set
1451  *
1452  * @return An hx509 error code, see hx509_get_error_string().
1453  *
1454  * @ingroup hx509_ca
1455  */
1456
1457 HX509_LIB_FUNCTION int HX509_LIB_CALL
1458 hx509_ca_tbs_set_unique(hx509_context context,
1459                         hx509_ca_tbs tbs,
1460                         const heim_bit_string *subjectUniqueID,
1461                         const heim_bit_string *issuerUniqueID)
1462 {
1463     int ret;
1464
1465     der_free_bit_string(&tbs->subjectUniqueID);
1466     der_free_bit_string(&tbs->issuerUniqueID);
1467
1468     if (subjectUniqueID) {
1469         ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
1470         if (ret)
1471             return ret;
1472     }
1473
1474     if (issuerUniqueID) {
1475         ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
1476         if (ret)
1477             return ret;
1478     }
1479
1480     return 0;
1481 }
1482
1483 /**
1484  * Expand the the subject name in the to-be-signed certificate object
1485  * using hx509_name_expand().
1486  *
1487  * @param context A hx509 context.
1488  * @param tbs object to be signed.
1489  * @param env environment variable to expand variables in the subject
1490  * name, see hx509_env_init().
1491  *
1492  * @return An hx509 error code, see hx509_get_error_string().
1493  *
1494  * @ingroup hx509_ca
1495  */
1496
1497 HX509_LIB_FUNCTION int HX509_LIB_CALL
1498 hx509_ca_tbs_subject_expand(hx509_context context,
1499                             hx509_ca_tbs tbs,
1500                             hx509_env env)
1501 {
1502     return hx509_name_expand(context, tbs->subject, env);
1503 }
1504
1505 /**
1506  * Get the name of a to-be-signed certificate object.
1507  *
1508  * @param context A hx509 context.
1509  * @param tbs object to be signed.
1510  *
1511  * @return An hx509 name.
1512  *
1513  * @ingroup hx509_ca
1514  */
1515
1516 HX509_LIB_FUNCTION hx509_name HX509_LIB_CALL
1517 hx509_ca_tbs_get_name(hx509_ca_tbs tbs)
1518 {
1519     return tbs->subject;
1520 }
1521
1522 /**
1523  * Set signature algorithm on the to be signed certificate
1524  *
1525  * @param context A hx509 context.
1526  * @param tbs object to be signed.
1527  * @param sigalg signature algorithm to use
1528  *
1529  * @return An hx509 error code, see hx509_get_error_string().
1530  *
1531  * @ingroup hx509_ca
1532  */
1533
1534 HX509_LIB_FUNCTION int HX509_LIB_CALL
1535 hx509_ca_tbs_set_signature_algorithm(hx509_context context,
1536                                      hx509_ca_tbs tbs,
1537                                      const AlgorithmIdentifier *sigalg)
1538 {
1539     int ret;
1540
1541     tbs->sigalg = calloc(1, sizeof(*tbs->sigalg));
1542     if (tbs->sigalg == NULL) {
1543         hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
1544         return ENOMEM;
1545     }
1546     ret = copy_AlgorithmIdentifier(sigalg, tbs->sigalg);
1547     if (ret) {
1548         free(tbs->sigalg);
1549         tbs->sigalg = NULL;
1550         return ret;
1551     }
1552     return 0;
1553 }
1554
1555 /*
1556  *
1557  */
1558
1559 static int
1560 add_extension(hx509_context context,
1561               TBSCertificate *tbsc,
1562               int critical_flag,
1563               const heim_oid *oid,
1564               const heim_octet_string *data)
1565 {
1566     Extension ext;
1567     int ret;
1568
1569     memset(&ext, 0, sizeof(ext));
1570
1571     ext.critical = critical_flag;
1572     ret = der_copy_oid(oid, &ext.extnID);
1573     if (ret) {
1574         hx509_set_error_string(context, 0, ret, "Out of memory");
1575         goto out;
1576     }
1577     ret = der_copy_octet_string(data, &ext.extnValue);
1578     if (ret) {
1579         hx509_set_error_string(context, 0, ret, "Out of memory");
1580         goto out;
1581     }
1582     ret = add_Extensions(tbsc->extensions, &ext);
1583     if (ret) {
1584         hx509_set_error_string(context, 0, ret, "Out of memory");
1585         goto out;
1586     }
1587 out:
1588     free_Extension(&ext);
1589     return ret;
1590 }
1591
1592 static int
1593 build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
1594 {
1595     char *tstr;
1596     time_t t;
1597     int ret;
1598
1599     ret = copy_Name(issuer, subject);
1600     if (ret) {
1601         hx509_set_error_string(context, 0, ret,
1602                                "Failed to copy subject name");
1603         return ret;
1604     }
1605
1606     t = time(NULL);
1607     ret = asprintf(&tstr, "ts-%lu", (unsigned long)t);
1608     if (ret == -1 || tstr == NULL) {
1609         hx509_set_error_string(context, 0, ENOMEM,
1610                                "Failed to copy subject name");
1611         return ENOMEM;
1612     }
1613     /* prefix with CN=<ts>,...*/
1614     ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
1615     free(tstr);
1616     if (ret)
1617         free_Name(subject);
1618     return ret;
1619 }
1620
1621 static int
1622 ca_sign(hx509_context context,
1623         hx509_ca_tbs tbs,
1624         hx509_private_key signer,
1625         const AuthorityKeyIdentifier *ai,
1626         const Name *issuername,
1627         hx509_cert *certificate)
1628 {
1629     heim_error_t error = NULL;
1630     heim_octet_string data;
1631     Certificate c;
1632     TBSCertificate *tbsc;
1633     size_t size;
1634     int ret;
1635     const AlgorithmIdentifier *sigalg;
1636     time_t notBefore;
1637     time_t notAfter;
1638
1639     sigalg = tbs->sigalg;
1640     if (sigalg == NULL)
1641         sigalg = _hx509_crypto_default_sig_alg;
1642
1643     memset(&c, 0, sizeof(c));
1644
1645     /*
1646      * Default values are: Valid since 24h ago, valid one year into
1647      * the future, KeyUsage digitalSignature and keyEncipherment set,
1648      * and keyCertSign for CA certificates.
1649      */
1650     notBefore = tbs->notBefore;
1651     if (notBefore == 0)
1652         notBefore = time(NULL) - 3600 * 24;
1653     notAfter = tbs->notAfter;
1654     if (notAfter == 0)
1655         notAfter = time(NULL) + 3600 * 24 * 365;
1656
1657     if (tbs->flags.ca) {
1658         tbs->ku.keyCertSign = 1;
1659         tbs->ku.cRLSign = 1;
1660     } else if (KeyUsage2int(tbs->ku) == 0) {
1661         tbs->ku.digitalSignature = 1;
1662         tbs->ku.keyEncipherment = 1;
1663     }
1664
1665     /*
1666      *
1667      */
1668
1669     tbsc = &c.tbsCertificate;
1670
1671     /* Default subject Name to empty */
1672     if (tbs->subject == NULL &&
1673         (ret = hx509_empty_name(context, &tbs->subject)))
1674         return ret;
1675
1676     /* Sanity checks */
1677     if (tbs->flags.key == 0) {
1678         ret = EINVAL;
1679         hx509_set_error_string(context, 0, ret, "No public key set");
1680         return ret;
1681     }
1682     /*
1683      * Don't put restrictions on proxy certificate's subject name, it
1684      * will be generated below.
1685      */
1686     if (!tbs->flags.proxy) {
1687         if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1688             hx509_set_error_string(context, 0, EINVAL,
1689                                    "Empty subject and no SubjectAltNames");
1690             return EINVAL;
1691         }
1692     }
1693     if (tbs->flags.ca && tbs->flags.proxy) {
1694         hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1695                                "at the same time");
1696         return EINVAL;
1697     }
1698     if (tbs->flags.proxy) {
1699         if (tbs->san.len > 0) {
1700             hx509_set_error_string(context, 0, EINVAL,
1701                                    "Proxy certificate is not allowed "
1702                                    "to have SubjectAltNames");
1703             return EINVAL;
1704         }
1705     }
1706
1707     /* version         [0]  Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1708     tbsc->version = calloc(1, sizeof(*tbsc->version));
1709     if (tbsc->version == NULL) {
1710         ret = ENOMEM;
1711         hx509_set_error_string(context, 0, ret, "Out of memory");
1712         goto out;
1713     }
1714     *tbsc->version = rfc3280_version_3;
1715     /* serialNumber         CertificateSerialNumber, */
1716     if (tbs->flags.serial) {
1717         ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1718         if (ret) {
1719             hx509_set_error_string(context, 0, ret, "Out of memory");
1720             goto out;
1721         }
1722     } else {
1723         /*
1724          * If no explicit serial number is specified, 20 random bytes should be
1725          * sufficiently collision resistant.  Since the serial number must be a
1726          * positive integer, ensure minimal ASN.1 DER form by forcing the high
1727          * bit off and the next bit on (thus avoiding an all zero first octet).
1728          */
1729         tbsc->serialNumber.length = 20;
1730         tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1731         if (tbsc->serialNumber.data == NULL){
1732             ret = ENOMEM;
1733             hx509_set_error_string(context, 0, ret, "Out of memory");
1734             goto out;
1735         }
1736         RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1737         ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1738         ((unsigned char *)tbsc->serialNumber.data)[0] |= 0x40;
1739     }
1740     /* signature            AlgorithmIdentifier, */
1741     ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1742     if (ret) {
1743         hx509_set_error_string(context, 0, ret, "Failed to copy signature alg");
1744         goto out;
1745     }
1746     /* issuer               Name, */
1747     if (issuername)
1748         ret = copy_Name(issuername, &tbsc->issuer);
1749     else
1750         ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1751     if (ret) {
1752         hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1753         goto out;
1754     }
1755     /* validity             Validity, */
1756     {
1757         /*
1758          * From RFC 5280, section 4.1.2.5:
1759          *
1760          *    CAs conforming to this profile MUST always encode certificate
1761          *    validity dates through the year 2049 as UTCTime; certificate validity
1762          *    dates in 2050 or later MUST be encoded as GeneralizedTime.
1763          *    Conforming applications MUST be able to process validity dates that
1764          *    are encoded in either UTCTime or GeneralizedTime.
1765          *
1766          * 2524608000 is seconds since the epoch for 2050-01-01T00:00:00Z.
1767          *
1768          * Both, ...u.generalTime and ...u..utcTime are time_t.
1769          */
1770         if (notBefore < 1 || (int64_t)notBefore < 2524608000)
1771             tbsc->validity.notBefore.element = choice_Time_utcTime;
1772         else
1773             tbsc->validity.notBefore.element = choice_Time_generalTime;
1774         tbsc->validity.notBefore.u.generalTime = notBefore;
1775
1776         if (notAfter < 1 || (int64_t)notAfter < 2524608000)
1777             tbsc->validity.notAfter.element = choice_Time_utcTime;
1778         else
1779             tbsc->validity.notAfter.element = choice_Time_generalTime;
1780         tbsc->validity.notAfter.u.generalTime = notAfter;
1781     }
1782     /* subject              Name, */
1783     if (tbs->flags.proxy) {
1784         ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1785         if (ret)
1786             goto out;
1787     } else {
1788         ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1789         if (ret) {
1790             hx509_set_error_string(context, 0, ret,
1791                                    "Failed to copy subject name");
1792             goto out;
1793         }
1794     }
1795     /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1796     ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1797     if (ret) {
1798         hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1799         goto out;
1800     }
1801     /* issuerUniqueID  [1]  IMPLICIT BIT STRING OPTIONAL */
1802     if (tbs->issuerUniqueID.length) {
1803         tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1804         if (tbsc->issuerUniqueID == NULL) {
1805             ret = ENOMEM;
1806             hx509_set_error_string(context, 0, ret, "Out of memory");
1807             goto out;
1808         }
1809         ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1810         if (ret) {
1811             hx509_set_error_string(context, 0, ret, "Out of memory");
1812             goto out;
1813         }
1814     }
1815     /* subjectUniqueID [2]  IMPLICIT BIT STRING OPTIONAL */
1816     if (tbs->subjectUniqueID.length) {
1817         tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1818         if (tbsc->subjectUniqueID == NULL) {
1819             ret = ENOMEM;
1820             hx509_set_error_string(context, 0, ret, "Out of memory");
1821             goto out;
1822         }
1823
1824         ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1825         if (ret) {
1826             hx509_set_error_string(context, 0, ret, "Out of memory");
1827             goto out;
1828         }
1829     }
1830
1831     /* extensions      [3]  EXPLICIT Extensions OPTIONAL */
1832     tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1833     if (tbsc->extensions == NULL) {
1834         ret = ENOMEM;
1835         hx509_set_error_string(context, 0, ret, "Out of memory");
1836         goto out;
1837     }
1838
1839     /* Add the text BMP string Domaincontroller to the cert */
1840     if (tbs->flags.domaincontroller) {
1841         data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1842                                "\x00\x61\x00\x69\x00\x6e\x00\x43"
1843                                "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1844                                "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1845                                "\x00\x72");
1846         data.length = 34;
1847
1848         ret = add_extension(context, tbsc, 0,
1849                             &asn1_oid_id_ms_cert_enroll_domaincontroller,
1850                             &data);
1851         if (ret)
1852             goto out;
1853     }
1854
1855     /* Add KeyUsage */
1856     if (KeyUsage2int(tbs->ku) > 0) {
1857         ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length,
1858                            &tbs->ku, &size, ret);
1859         if (ret) {
1860             hx509_set_error_string(context, 0, ret, "Out of memory");
1861             goto out;
1862         }
1863         if (size != data.length)
1864             _hx509_abort("internal ASN.1 encoder error");
1865         ret = add_extension(context, tbsc, 1,
1866                             &asn1_oid_id_x509_ce_keyUsage, &data);
1867         free(data.data);
1868         if (ret)
1869             goto out;
1870     }
1871
1872     /* Add ExtendedKeyUsage */
1873     if (tbs->eku.len > 0) {
1874         ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1875                            &tbs->eku, &size, ret);
1876         if (ret) {
1877             hx509_set_error_string(context, 0, ret, "Out of memory");
1878             goto out;
1879         }
1880         if (size != data.length)
1881             _hx509_abort("internal ASN.1 encoder error");
1882         ret = add_extension(context, tbsc, 1,
1883                             &asn1_oid_id_x509_ce_extKeyUsage, &data);
1884         free(data.data);
1885         if (ret)
1886             goto out;
1887     }
1888
1889     /* Add Subject Alternative Name */
1890     if (tbs->san.len > 0) {
1891         ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1892                            &tbs->san, &size, ret);
1893         if (ret) {
1894             hx509_set_error_string(context, 0, ret, "Out of memory");
1895             goto out;
1896         }
1897         if (size != data.length)
1898             _hx509_abort("internal ASN.1 encoder error");
1899
1900         /* The SAN extension is critical if the subject Name is empty */
1901         ret = add_extension(context, tbsc, hx509_name_is_null_p(tbs->subject),
1902                             &asn1_oid_id_x509_ce_subjectAltName, &data);
1903         free(data.data);
1904         if (ret)
1905             goto out;
1906     }
1907
1908     /* Add Authority Key Identifier */
1909     if (ai) {
1910         ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1911                            ai, &size, ret);
1912         if (ret) {
1913             hx509_set_error_string(context, 0, ret, "Out of memory");
1914             goto out;
1915         }
1916         if (size != data.length)
1917             _hx509_abort("internal ASN.1 encoder error");
1918         ret = add_extension(context, tbsc, 0,
1919                             &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1920                             &data);
1921         free(data.data);
1922         if (ret)
1923             goto out;
1924     }
1925
1926     /* Add Subject Key Identifier */
1927     {
1928         SubjectKeyIdentifier si;
1929         unsigned char hash[SHA_DIGEST_LENGTH];
1930
1931         {
1932             EVP_MD_CTX *ctx;
1933
1934             ctx = EVP_MD_CTX_create();
1935             EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1936             EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1937                              tbs->spki.subjectPublicKey.length / 8);
1938             EVP_DigestFinal_ex(ctx, hash, NULL);
1939             EVP_MD_CTX_destroy(ctx);
1940         }
1941
1942         si.data = hash;
1943         si.length = sizeof(hash);
1944
1945         ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1946                            &si, &size, ret);
1947         if (ret) {
1948             hx509_set_error_string(context, 0, ret, "Out of memory");
1949             goto out;
1950         }
1951         if (size != data.length)
1952             _hx509_abort("internal ASN.1 encoder error");
1953         ret = add_extension(context, tbsc, 0,
1954                             &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1955                             &data);
1956         free(data.data);
1957         if (ret)
1958             goto out;
1959     }
1960
1961     /* Add BasicConstraints */
1962     {
1963         BasicConstraints bc;
1964         unsigned int path;
1965
1966         memset(&bc, 0, sizeof(bc));
1967
1968         if (tbs->flags.ca) {
1969             bc.cA = 1;
1970             if (tbs->pathLenConstraint >= 0) {
1971                 path = tbs->pathLenConstraint;
1972                 bc.pathLenConstraint = &path;
1973             }
1974         }
1975
1976         ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1977                            &bc, &size, ret);
1978         if (ret) {
1979             hx509_set_error_string(context, 0, ret, "Out of memory");
1980             goto out;
1981         }
1982         if (size != data.length)
1983             _hx509_abort("internal ASN.1 encoder error");
1984         /* Critical if this is a CA */
1985         ret = add_extension(context, tbsc, tbs->flags.ca,
1986                             &asn1_oid_id_x509_ce_basicConstraints,
1987                             &data);
1988         free(data.data);
1989         if (ret)
1990             goto out;
1991     }
1992
1993     /* Add Proxy */
1994     if (tbs->flags.proxy) {
1995         ProxyCertInfo info;
1996
1997         memset(&info, 0, sizeof(info));
1998
1999         if (tbs->pathLenConstraint >= 0) {
2000             info.pCPathLenConstraint =
2001                 malloc(sizeof(*info.pCPathLenConstraint));
2002             if (info.pCPathLenConstraint == NULL) {
2003                 ret = ENOMEM;
2004                 hx509_set_error_string(context, 0, ret, "Out of memory");
2005                 goto out;
2006             }
2007             *info.pCPathLenConstraint = tbs->pathLenConstraint;
2008         }
2009
2010         ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
2011                            &info.proxyPolicy.policyLanguage);
2012         if (ret) {
2013             free_ProxyCertInfo(&info);
2014             hx509_set_error_string(context, 0, ret, "Out of memory");
2015             goto out;
2016         }
2017
2018         ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
2019                            &info, &size, ret);
2020         free_ProxyCertInfo(&info);
2021         if (ret) {
2022             hx509_set_error_string(context, 0, ret, "Out of memory");
2023             goto out;
2024         }
2025         if (size != data.length)
2026             _hx509_abort("internal ASN.1 encoder error");
2027         ret = add_extension(context, tbsc, 0,
2028                             &asn1_oid_id_pkix_pe_proxyCertInfo,
2029                             &data);
2030         free(data.data);
2031         if (ret)
2032             goto out;
2033     }
2034
2035     /* Add CRL distribution point */
2036     if (tbs->crldp.len) {
2037         ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
2038                            &tbs->crldp, &size, ret);
2039         if (ret) {
2040             hx509_set_error_string(context, 0, ret, "Out of memory");
2041             goto out;
2042         }
2043         if (size != data.length)
2044             _hx509_abort("internal ASN.1 encoder error");
2045         ret = add_extension(context, tbsc, FALSE,
2046                             &asn1_oid_id_x509_ce_cRLDistributionPoints,
2047                             &data);
2048         free(data.data);
2049         if (ret)
2050             goto out;
2051     }
2052
2053     /* Add CertificatePolicies */
2054     if (tbs->cps.len) {
2055         ASN1_MALLOC_ENCODE(CertificatePolicies, data.data, data.length,
2056                            &tbs->cps, &size, ret);
2057         if (ret) {
2058             hx509_set_error_string(context, 0, ret, "Out of memory");
2059             goto out;
2060         }
2061         if (size != data.length)
2062             _hx509_abort("internal ASN.1 encoder error");
2063         ret = add_extension(context, tbsc, FALSE,
2064                             &asn1_oid_id_x509_ce_certificatePolicies, &data);
2065         free(data.data);
2066         if (ret)
2067             goto out;
2068     }
2069
2070     /* Add PolicyMappings */
2071     if (tbs->cps.len) {
2072         ASN1_MALLOC_ENCODE(PolicyMappings, data.data, data.length,
2073                            &tbs->pms, &size, ret);
2074         if (ret) {
2075             hx509_set_error_string(context, 0, ret, "Out of memory");
2076             goto out;
2077         }
2078         if (size != data.length)
2079             _hx509_abort("internal ASN.1 encoder error");
2080         ret = add_extension(context, tbsc, FALSE,
2081                             &asn1_oid_id_x509_ce_policyMappings, &data);
2082         free(data.data);
2083         if (ret)
2084             goto out;
2085     }
2086
2087     /* Add Heimdal PKINIT ticket max life extension */
2088     if (tbs->pkinitTicketMaxLife > 0) {
2089         ASN1_MALLOC_ENCODE(HeimPkinitPrincMaxLifeSecs, data.data, data.length,
2090                            &tbs->pkinitTicketMaxLife, &size, ret);
2091         if (ret) {
2092             hx509_set_error_string(context, 0, ret, "Out of memory");
2093             goto out;
2094         }
2095         if (size != data.length)
2096             _hx509_abort("internal ASN.1 encoder error");
2097         ret = add_extension(context, tbsc, FALSE,
2098                             &asn1_oid_id_heim_ce_pkinit_princ_max_life, &data);
2099         free(data.data);
2100         if (ret)
2101             goto out;
2102     }
2103
2104     ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
2105     if (ret) {
2106         hx509_set_error_string(context, 0, ret, "malloc out of memory");
2107         goto out;
2108     }
2109     if (data.length != size)
2110         _hx509_abort("internal ASN.1 encoder error");
2111
2112     ret = _hx509_create_signature_bitstring(context,
2113                                             signer,
2114                                             sigalg,
2115                                             &data,
2116                                             &c.signatureAlgorithm,
2117                                             &c.signatureValue);
2118     free(data.data);
2119     if (ret)
2120         goto out;
2121
2122     *certificate = hx509_cert_init(context, &c, &error);
2123     if (*certificate == NULL) {
2124         ret = heim_error_get_code(error);
2125         heim_release(error);
2126         goto out;
2127     }
2128
2129     free_Certificate(&c);
2130
2131     return 0;
2132
2133 out:
2134     free_Certificate(&c);
2135     return ret;
2136 }
2137
2138 static int
2139 get_AuthorityKeyIdentifier(hx509_context context,
2140                            const Certificate *certificate,
2141                            AuthorityKeyIdentifier *ai)
2142 {
2143     SubjectKeyIdentifier si;
2144     int ret;
2145
2146     ret = _hx509_find_extension_subject_key_id(certificate, &si);
2147     if (ret == 0) {
2148         ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
2149         if (ai->keyIdentifier == NULL) {
2150             free_SubjectKeyIdentifier(&si);
2151             ret = ENOMEM;
2152             hx509_set_error_string(context, 0, ret, "Out of memory");
2153             goto out;
2154         }
2155         ret = der_copy_octet_string(&si, ai->keyIdentifier);
2156         free_SubjectKeyIdentifier(&si);
2157         if (ret) {
2158             hx509_set_error_string(context, 0, ret, "Out of memory");
2159             goto out;
2160         }
2161     } else {
2162         GeneralNames gns;
2163         GeneralName gn;
2164         Name name;
2165
2166         memset(&gn, 0, sizeof(gn));
2167         memset(&gns, 0, sizeof(gns));
2168         memset(&name, 0, sizeof(name));
2169
2170         ai->authorityCertIssuer =
2171             calloc(1, sizeof(*ai->authorityCertIssuer));
2172         if (ai->authorityCertIssuer == NULL) {
2173             ret = ENOMEM;
2174             hx509_set_error_string(context, 0, ret, "Out of memory");
2175             goto out;
2176         }
2177         ai->authorityCertSerialNumber =
2178             calloc(1, sizeof(*ai->authorityCertSerialNumber));
2179         if (ai->authorityCertSerialNumber == NULL) {
2180             ret = ENOMEM;
2181             hx509_set_error_string(context, 0, ret, "Out of memory");
2182             goto out;
2183         }
2184
2185         /*
2186          * XXX unbreak when asn1 compiler handle IMPLICIT
2187          *
2188          * This is so horrible.
2189          */
2190
2191         ret = copy_Name(&certificate->tbsCertificate.subject, &name);
2192         if (ret) {
2193             hx509_set_error_string(context, 0, ret, "Out of memory");
2194             goto out;
2195         }
2196
2197         memset(&gn, 0, sizeof(gn));
2198         gn.element = choice_GeneralName_directoryName;
2199         gn.u.directoryName.element = choice_Name_rdnSequence;
2200         gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
2201
2202         ret = add_GeneralNames(&gns, &gn);
2203         if (ret) {
2204             hx509_set_error_string(context, 0, ret, "Out of memory");
2205             goto out;
2206         }
2207
2208         ai->authorityCertIssuer->val = gns.val;
2209         ai->authorityCertIssuer->len = gns.len;
2210
2211         ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
2212                                     ai->authorityCertSerialNumber);
2213         if (ai->authorityCertSerialNumber == NULL) {
2214             ret = ENOMEM;
2215             hx509_set_error_string(context, 0, ret, "Out of memory");
2216             goto out;
2217         }
2218     }
2219 out:
2220     if (ret)
2221         free_AuthorityKeyIdentifier(ai);
2222     return ret;
2223 }
2224
2225
2226 /**
2227  * Sign a to-be-signed certificate object with a issuer certificate.
2228  *
2229  * The caller needs to at least have called the following functions on the
2230  * to-be-signed certificate object:
2231  * - hx509_ca_tbs_init()
2232  * - hx509_ca_tbs_set_subject()
2233  * - hx509_ca_tbs_set_spki()
2234  *
2235  * When done the to-be-signed certificate object should be freed with
2236  * hx509_ca_tbs_free().
2237  *
2238  * When creating self-signed certificate use hx509_ca_sign_self() instead.
2239  *
2240  * @param context A hx509 context.
2241  * @param tbs object to be signed.
2242  * @param signer the CA certificate object to sign with (need private key).
2243  * @param certificate return cerificate, free with hx509_cert_free().
2244  *
2245  * @return An hx509 error code, see hx509_get_error_string().
2246  *
2247  * @ingroup hx509_ca
2248  */
2249
2250 HX509_LIB_FUNCTION int HX509_LIB_CALL
2251 hx509_ca_sign(hx509_context context,
2252               hx509_ca_tbs tbs,
2253               hx509_cert signer,
2254               hx509_cert *certificate)
2255 {
2256     const Certificate *signer_cert;
2257     AuthorityKeyIdentifier ai;
2258     int ret;
2259
2260     memset(&ai, 0, sizeof(ai));
2261
2262     signer_cert = _hx509_get_cert(signer);
2263
2264     ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
2265     if (ret)
2266         goto out;
2267
2268     ret = ca_sign(context,
2269                   tbs,
2270                   _hx509_cert_private_key(signer),
2271                   &ai,
2272                   &signer_cert->tbsCertificate.subject,
2273                   certificate);
2274
2275 out:
2276     free_AuthorityKeyIdentifier(&ai);
2277
2278     return ret;
2279 }
2280
2281 /**
2282  * Work just like hx509_ca_sign() but signs it-self.
2283  *
2284  * @param context A hx509 context.
2285  * @param tbs object to be signed.
2286  * @param signer private key to sign with.
2287  * @param certificate return cerificate, free with hx509_cert_free().
2288  *
2289  * @return An hx509 error code, see hx509_get_error_string().
2290  *
2291  * @ingroup hx509_ca
2292  */
2293
2294 HX509_LIB_FUNCTION int HX509_LIB_CALL
2295 hx509_ca_sign_self(hx509_context context,
2296                    hx509_ca_tbs tbs,
2297                    hx509_private_key signer,
2298                    hx509_cert *certificate)
2299 {
2300     return ca_sign(context,
2301                    tbs,
2302                    signer,
2303                    NULL,
2304                    NULL,
2305                    certificate);
2306 }
2307
2308 /*
2309  * The following used to be `kdc_issue_certificate()', which was added for
2310  * kx509 support in the kdc, then adapted for bx509d.  It now has no
2311  * kdc-specific code and very little krb5-specific code, and is named
2312  * `hx509_ca_issue_certificate()'.
2313  */
2314
2315 /* From lib/krb5/principal.c */
2316 #define princ_num_comp(P) ((P)->principalName.name_string.len)
2317 #define princ_type(P) ((P)->principalName.name_type)
2318 #define princ_comp(P) ((P)->principalName.name_string.val)
2319 #define princ_ncomp(P, N) ((P)->principalName.name_string.val[(N)])
2320 #define princ_realm(P) ((P)->realm)
2321
2322 static const char *
2323 princ_get_comp_string(KRB5PrincipalName *principal, unsigned int component)
2324 {
2325     if (component >= princ_num_comp(principal))
2326        return NULL;
2327     return princ_ncomp(principal, component);
2328 }
2329 /* XXX Add unparse_name() */
2330
2331 typedef enum {
2332     CERT_NOTSUP = 0,
2333     CERT_CLIENT = 1,
2334     CERT_SERVER = 2,
2335     CERT_MIXED  = 3
2336 } cert_type;
2337
2338 static void
2339 frees(char **s)
2340 {
2341     free(*s);
2342     *s = NULL;
2343 }
2344
2345 static heim_error_code
2346 count_sans(hx509_request req, size_t *n)
2347 {
2348     size_t i;
2349     char *s = NULL;
2350     int ret = 0;
2351
2352     *n = 0;
2353     for (i = 0; ret == 0; i++) {
2354         hx509_san_type san_type;
2355
2356         frees(&s);
2357         ret = hx509_request_get_san(req, i, &san_type, &s);
2358         if (ret)
2359             break;
2360         switch (san_type) {
2361         case HX509_SAN_TYPE_DNSNAME:
2362         case HX509_SAN_TYPE_EMAIL:
2363         case HX509_SAN_TYPE_XMPP:
2364         case HX509_SAN_TYPE_PKINIT:
2365         case HX509_SAN_TYPE_MS_UPN:
2366             (*n)++;
2367             break;
2368         default:
2369             ret = ENOTSUP;
2370         }
2371         frees(&s);
2372     }
2373     return ret == HX509_NO_ITEM ? 0 : ret;
2374 }
2375
2376 static int
2377 has_sans(hx509_request req)
2378 {
2379     hx509_san_type san_type;
2380     char *s = NULL;
2381     int ret = hx509_request_get_san(req, 0, &san_type, &s);
2382
2383     frees(&s);
2384     return ret == HX509_NO_ITEM ? 0 : 1;
2385 }
2386
2387 static cert_type
2388 characterize_cprinc(hx509_context context,
2389                     KRB5PrincipalName *cprinc)
2390 {
2391     unsigned int ncomp = princ_num_comp(cprinc);
2392     const char *comp1 = princ_get_comp_string(cprinc, 1);
2393
2394     switch (ncomp) {
2395     case 1:
2396         return CERT_CLIENT;
2397     case 2:
2398         if (strchr(comp1, '.') == NULL)
2399             return CERT_CLIENT;
2400         return CERT_SERVER;
2401     case 3:
2402         if (strchr(comp1, '.'))
2403             return CERT_SERVER;
2404         return CERT_NOTSUP;
2405     default:
2406         return CERT_NOTSUP;
2407     }
2408 }
2409
2410 /* Characterize request as client or server cert req */
2411 static cert_type
2412 characterize(hx509_context context,
2413              KRB5PrincipalName *cprinc,
2414              hx509_request req)
2415 {
2416     heim_error_code ret = 0;
2417     cert_type res = CERT_NOTSUP;
2418     size_t i;
2419     char *s = NULL;
2420     int want_ekus = 0;
2421
2422     if (!has_sans(req))
2423         return characterize_cprinc(context, cprinc);
2424
2425     for (i = 0; ret == 0; i++) {
2426         heim_oid oid;
2427
2428         frees(&s);
2429         ret = hx509_request_get_eku(req, i, &s);
2430         if (ret)
2431             break;
2432
2433         want_ekus = 1;
2434         ret = der_parse_heim_oid(s, ".", &oid);
2435         if (ret)
2436             break;
2437         /*
2438          * If the client wants only a server certificate, then we'll be
2439          * willing to issue one that may be longer-lived than the client's
2440          * ticket/token.
2441          *
2442          * There may be other server EKUs, but these are the ones we know
2443          * of.
2444          */
2445         if (der_heim_oid_cmp(&asn1_oid_id_pkix_kp_serverAuth, &oid) &&
2446             der_heim_oid_cmp(&asn1_oid_id_pkix_kp_OCSPSigning, &oid) &&
2447             der_heim_oid_cmp(&asn1_oid_id_pkix_kp_secureShellServer, &oid))
2448             res |= CERT_CLIENT;
2449         else
2450             res |= CERT_SERVER;
2451         der_free_oid(&oid);
2452     }
2453     frees(&s);
2454     if (ret == HX509_NO_ITEM)
2455         ret = 0;
2456
2457     for (i = 0; ret == 0; i++) {
2458         hx509_san_type san_type;
2459
2460         frees(&s);
2461         ret = hx509_request_get_san(req, i, &san_type, &s);
2462         if (ret)
2463             break;
2464         switch (san_type) {
2465         case HX509_SAN_TYPE_DNSNAME:
2466             if (!want_ekus)
2467                 res |= CERT_SERVER;
2468             break;
2469         case HX509_SAN_TYPE_EMAIL:
2470         case HX509_SAN_TYPE_XMPP:
2471         case HX509_SAN_TYPE_PKINIT:
2472         case HX509_SAN_TYPE_MS_UPN:
2473             if (!want_ekus)
2474                 res |= CERT_CLIENT;
2475             break;
2476         default:
2477             ret = ENOTSUP;
2478         }
2479         if (ret)
2480             break;
2481     }
2482     frees(&s);
2483     if (ret == HX509_NO_ITEM)
2484         ret = 0;
2485     return ret ? CERT_NOTSUP : res;
2486 }
2487
2488 /*
2489  * Get a configuration sub-tree for kx509 based on what's being requested and
2490  * by whom.
2491  *
2492  * We have a number of cases:
2493  *
2494  *  - default certificate (no CSR used, or no certificate extensions requested)
2495  *     - for client principals
2496  *     - for service principals
2497  *  - client certificate requested (CSR used and client-y SANs/EKUs requested)
2498  *  - server certificate requested (CSR used and server-y SANs/EKUs requested)
2499  *  - mixed client/server certificate requested (...)
2500  */
2501 static heim_error_code
2502 get_cf(hx509_context context,
2503        const heim_config_binding *cf,
2504        heim_log_facility *logf,
2505        hx509_request req,
2506        KRB5PrincipalName *cprinc,
2507        const heim_config_binding **out)
2508 {
2509     heim_error_code ret;
2510     unsigned int ncomp = princ_num_comp(cprinc);
2511     const char *realm = princ_realm(cprinc);
2512     const char *comp0 = princ_get_comp_string(cprinc, 0);
2513     const char *comp1 = princ_get_comp_string(cprinc, 1);
2514     const char *label = NULL;
2515     const char *svc = NULL;
2516     const char *def = NULL;
2517     cert_type certtype = CERT_NOTSUP;
2518     size_t nsans = 0;
2519
2520     *out = NULL;
2521     if (ncomp == 0) {
2522         heim_log_msg(context->hcontext, logf, 5, NULL,
2523                      "Client principal has no components!");
2524         hx509_set_error_string(context, 0, ret = ENOTSUP,
2525                                "Client principal has no components!");
2526         return ret;
2527     }
2528
2529     if ((ret = count_sans(req, &nsans)) ||
2530         (certtype = characterize(context, cprinc, req)) == CERT_NOTSUP) {
2531         heim_log_msg(context->hcontext, logf, 5, NULL,
2532                      "Could not characterize CSR");
2533         hx509_set_error_string(context, 0, ret, "Could not characterize CSR");
2534         return ret;
2535     }
2536
2537     if (nsans) {
2538         def = "custom";
2539         /* Client requested some certificate extension, a SAN or EKU */
2540         switch (certtype) {
2541         case CERT_MIXED:    label = "mixed";  break;
2542         case CERT_CLIENT:   label = "client"; break;
2543         case CERT_SERVER:   label = "server"; break;
2544         default:
2545             hx509_set_error_string(context, 0, ret = ENOTSUP,
2546                                    "Requested SAN/EKU combination not "
2547                                    "supported");
2548             return ret;
2549         }
2550     } else {
2551         def = "default";
2552         /* Default certificate desired */
2553         if (ncomp == 1) {
2554             label = "user";
2555         } else if (ncomp == 2 && strcmp(comp1, "root") == 0) {
2556             label = "root_user";
2557         } else if (ncomp == 2 && strcmp(comp1, "admin") == 0) {
2558             label = "admin_user";
2559         } else if (strchr(comp1, '.')) {
2560             label = "hostbased_service";
2561             svc = comp0;
2562         } else {
2563             label = "other";
2564         }
2565     }
2566
2567     *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL);
2568     if (*out)
2569         ret = 0;
2570     if (ret) {
2571         heim_log_msg(context->hcontext, logf, 3, NULL,
2572                      "No configuration for %s %s certificate's realm "
2573                      "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2574                      svc ? " -> " : "", svc ? svc : "");
2575         hx509_set_error_string(context, 0, EACCES,
2576                 "No configuration for %s %s certificate's realm "
2577                 "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
2578                 svc ? " -> " : "", svc ? svc : "");
2579     }
2580     return ret;
2581 }
2582
2583
2584 /*
2585  * Find and set a certificate template using a configuration sub-tree
2586  * appropriate to the requesting principal.
2587  *
2588  * This allows for the specification of the following in configuration:
2589  *
2590  *  - certificates as templates, with ${var} tokens in subjectName attribute
2591  *    values that will be expanded later
2592  *  - a plain string with ${var} tokens to use as the subjectName
2593  *  - EKUs
2594  *  - whether to include a PKINIT SAN
2595  */
2596 static heim_error_code
2597 set_template(hx509_context context,
2598              heim_log_facility *logf,
2599              const heim_config_binding *cf,
2600              hx509_ca_tbs tbs)
2601 {
2602     heim_error_code ret = 0;
2603     const char *cert_template = NULL;
2604     const char *subj_name = NULL;
2605     char **ekus = NULL;
2606
2607     if (cf == NULL)
2608         return EACCES; /* Can't happen */
2609
2610     cert_template = heim_config_get_string(context->hcontext, cf,
2611                                            "template_cert", NULL);
2612     subj_name = heim_config_get_string(context->hcontext, cf, "subject_name",
2613                                        NULL);
2614     ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
2615
2616     if (cert_template) {
2617         hx509_certs certs;
2618         hx509_cert template;
2619
2620         ret = hx509_certs_init(context, cert_template, 0, NULL, &certs);
2621         if (ret == 0)
2622             ret = hx509_get_one_cert(context, certs, &template);
2623         hx509_certs_free(&certs);
2624         if (ret) {
2625             heim_log_msg(context->hcontext, logf, 1, NULL,
2626                          "Failed to load certificate template from %s",
2627                          cert_template);
2628             hx509_set_error_string(context, 0, EACCES,
2629                                    "Failed to load certificate template from "
2630                                    "%s", cert_template);
2631             return ret;
2632         }
2633
2634         /*
2635          * Only take the subjectName, the keyUsage, and EKUs from the template
2636          * certificate.
2637          */
2638         ret = hx509_ca_tbs_set_template(context, tbs,
2639                                         HX509_CA_TEMPLATE_SUBJECT |
2640                                         HX509_CA_TEMPLATE_KU |
2641                                         HX509_CA_TEMPLATE_EKU,
2642                                         template);
2643         hx509_cert_free(template);
2644         if (ret)
2645             return ret;
2646     }
2647
2648     if (subj_name) {
2649         hx509_name dn = NULL;
2650
2651         ret = hx509_parse_name(context, subj_name, &dn);
2652         if (ret == 0)
2653             ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2654         hx509_name_free(&dn);
2655         if (ret)
2656             return ret;
2657     }
2658
2659     if (cert_template == NULL && subj_name == NULL) {
2660         hx509_name dn = NULL;
2661
2662         ret = hx509_empty_name(context, &dn);
2663         if (ret == 0)
2664             ret = hx509_ca_tbs_set_subject(context, tbs, dn);
2665         hx509_name_free(&dn);
2666         if (ret)
2667             return ret;
2668     }
2669
2670     if (ekus) {
2671         size_t i;
2672
2673         for (i = 0; ret == 0 && ekus[i]; i++) {
2674             heim_oid oid = { 0, 0 };
2675
2676             if ((ret = der_find_or_parse_heim_oid(ekus[i], ".", &oid)) == 0)
2677                 ret = hx509_ca_tbs_add_eku(context, tbs, &oid);
2678             der_free_oid(&oid);
2679         }
2680         heim_config_free_strings(ekus);
2681     }
2682
2683     /*
2684      * XXX A KeyUsage template would be nice, but it needs some smarts to
2685      * remove, e.g., encipherOnly, decipherOnly, keyEncipherment, if the SPKI
2686      * algorithm does not support encryption.  The same logic should be added
2687      * to hx509_ca_tbs_set_template()'s HX509_CA_TEMPLATE_KU functionality.
2688      */
2689     return ret;
2690 }
2691
2692 /*
2693  * Find and set a certificate template, set "variables" in `env', and add add
2694  * default SANs/EKUs as appropriate.
2695  *
2696  * TODO:
2697  *  - lookup a template for the client principal in its HDB entry
2698  *  - lookup subjectName, SANs for a principal in its HDB entry
2699  *  - lookup a host-based client principal's HDB entry and add its canonical
2700  *    name / aliases as dNSName SANs
2701  *    (this would have to be if requested by the client, perhaps)
2702  */
2703 static heim_error_code
2704 set_tbs(hx509_context context,
2705         heim_log_facility *logf,
2706         const heim_config_binding *cf,
2707         hx509_request req,
2708         KRB5PrincipalName *cprinc,
2709         hx509_env *env,
2710         hx509_ca_tbs tbs)
2711 {
2712     KRB5PrincipalName cprinc_no_realm = *cprinc;
2713     heim_error_code ret;
2714     unsigned int ncomp = princ_num_comp(cprinc);
2715     const char *realm = princ_realm(cprinc);
2716     const char *comp0 = princ_get_comp_string(cprinc, 0);
2717     const char *comp1 = princ_get_comp_string(cprinc, 1);
2718     const char *comp2 = princ_get_comp_string(cprinc, 2);
2719     struct rk_strpool *strpool;
2720     char *princ_no_realm = NULL;
2721     char *princ = NULL;
2722
2723     strpool = _hx509_unparse_kerberos_name(NULL, cprinc);
2724     if (strpool)
2725         princ = rk_strpoolcollect(strpool);
2726     cprinc_no_realm.realm = NULL;
2727     strpool = _hx509_unparse_kerberos_name(NULL, &cprinc_no_realm);
2728     if (strpool)
2729         princ_no_realm = rk_strpoolcollect(strpool);
2730     if (princ == NULL || princ_no_realm == NULL) {
2731         free(princ);
2732         return hx509_enomem(context);
2733     }
2734     strpool = NULL;
2735     ret = hx509_env_add(context, env, "principal-name-without-realm",
2736                         princ_no_realm);
2737     if (ret == 0)
2738         ret = hx509_env_add(context, env, "principal-name", princ);
2739     if (ret == 0)
2740         ret = hx509_env_add(context, env, "principal-name-realm",
2741                             realm);
2742
2743     /* Populate requested certificate extensions from CSR/CSRPlus if allowed */
2744     ret = hx509_ca_tbs_set_from_csr(context, tbs, req);
2745     if (ret == 0)
2746         ret = set_template(context, logf, cf, tbs);
2747
2748     /*
2749      * Optionally add PKINIT SAN.
2750      *
2751      * Adding an id-pkinit-san means the client can use the certificate to
2752      * initiate PKINIT.  That might seem odd, but it enables a sort of PKIX
2753      * credential delegation by allowing forwarded Kerberos tickets to be
2754      * used to acquire PKIX credentials.  Thus this can work:
2755      *
2756      *      PKIX (w/ HW token) -> Kerberos ->
2757      *        PKIX (w/ softtoken) -> Kerberos ->
2758      *          PKIX (w/ softtoken) -> Kerberos ->
2759      *            ...
2760      *
2761      * Note that we may not have added the PKINIT EKU -- that depends on the
2762      * template, and host-based service templates might well not include it.
2763      */
2764     if (ret == 0 && !has_sans(req) &&
2765         heim_config_get_bool_default(context->hcontext, cf, FALSE,
2766                                      "include_pkinit_san", NULL)) {
2767         ret = hx509_ca_tbs_add_san_pkinit(context, tbs, princ);
2768     }
2769
2770     if (ret)
2771         goto out;
2772
2773     if (ncomp == 1) {
2774         const char *email_domain;
2775
2776         ret = hx509_env_add(context, env, "principal-component0",
2777                             princ_no_realm);
2778
2779         /*
2780          * If configured, include an rfc822Name that's just the client's
2781          * principal name sans realm @ configured email domain.
2782          */
2783         if (ret == 0 && !has_sans(req) &&
2784             (email_domain = heim_config_get_string(context->hcontext, cf,
2785                                                    "email_domain", NULL))) {
2786             char *email;
2787
2788             if (asprintf(&email, "%s@%s", princ_no_realm, email_domain) == -1 ||
2789                 email == NULL)
2790                 goto enomem;
2791             ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email);
2792             free(email);
2793         }
2794     } else if (ncomp == 2 || ncomp == 3) {
2795         /*
2796          * 2- and 3-component principal name.
2797          *
2798          * We do not have a reliable name-type indicator.  If the second
2799          * component has a '.' in it then we'll assume that the name is a
2800          * host-based (2-component) or domain-based (3-component) service
2801          * principal name.  Else we'll assume it's a two-component admin-style
2802          * username.
2803          */
2804
2805         ret = hx509_env_add(context, env, "principal-component0", comp0);
2806         if (ret == 0)
2807             ret = hx509_env_add(context, env, "principal-component1", comp1);
2808         if (ret == 0 && ncomp == 3)
2809             ret = hx509_env_add(context, env, "principal-component2", comp2);
2810         if (ret == 0 && strchr(comp1, '.')) {
2811             /* Looks like host-based or domain-based service */
2812             ret = hx509_env_add(context, env, "principal-service-name", comp0);
2813             if (ret == 0)
2814                 ret = hx509_env_add(context, env, "principal-host-name",
2815                                     comp1);
2816             if (ret == 0 && ncomp == 3)
2817                 ret = hx509_env_add(context, env, "principal-domain-name",
2818                                     comp2);
2819             if (ret == 0 && !has_sans(req) &&
2820                 heim_config_get_bool_default(context->hcontext, cf, FALSE,
2821                                              "include_dnsname_san", NULL)) {
2822                 ret = hx509_ca_tbs_add_san_hostname(context, tbs, comp1);
2823             }
2824         }
2825     } else {
2826         heim_log_msg(context->hcontext, logf, 5, NULL,
2827                      "kx509/bx509 client %s has too many components!", princ);
2828         hx509_set_error_string(context, 0, ret = EACCES,
2829                                "kx509/bx509 client %s has too many "
2830                                "components!", princ);
2831     }
2832
2833 out:
2834     if (ret == ENOMEM)
2835         goto enomem;
2836     free(princ_no_realm);
2837     free(princ);
2838     return ret;
2839
2840 enomem:
2841     heim_log_msg(context->hcontext, logf, 0, NULL,
2842                  "Could not set up TBSCertificate: Out of memory");
2843     ret = hx509_enomem(context);
2844     goto out;
2845 }
2846
2847 /*
2848  * Set the notBefore/notAfter for the certificate to be issued.
2849  *
2850  * Here `starttime' is the supplicant's credentials' notBefore equivalent,
2851  * while `endtime' is the supplicant's credentials' notAfter equivalent.
2852  *
2853  * `req_life' is the lifetime requested by the supplicant.
2854  *
2855  * `endtime' must be larger than the current time.
2856  *
2857  * `starttime' can be zero or negative, in which case the notBefore will be the
2858  * current time minus five minutes.
2859  *
2860  * `endtime', `req_life' and configuration parameters will be used to compute
2861  * the actual notAfter.
2862  */
2863 static heim_error_code
2864 tbs_set_times(hx509_context context,
2865               const heim_config_binding *cf,
2866               heim_log_facility *logf,
2867               time_t starttime,
2868               time_t endtime,
2869               time_t req_life,
2870               hx509_ca_tbs tbs)
2871 {
2872     time_t now = time(NULL);
2873     time_t force = heim_config_get_time_default(context->hcontext,
2874                                                 cf, 5 * 24 * 3600,
2875                                                 "force_cert_lifetime", NULL);
2876     time_t clamp = heim_config_get_time_default(context->hcontext, cf, 0,
2877                                                 "max_cert_lifetime", NULL);
2878     int allow_more = heim_config_get_bool_default(context->hcontext, cf, FALSE,
2879                                                   "allow_extra_lifetime",
2880                                                   NULL);
2881     starttime = starttime > 0 ? starttime : now - 5 * 60;
2882
2883     if (endtime < now) {
2884         heim_log_msg(context->hcontext, logf, 3, NULL,
2885                      "Endtime is in the past");
2886         hx509_set_error_string(context, 0, ERANGE, "Endtime is in the past");
2887         return ERANGE;
2888     }
2889
2890     /* Apply requested lifetime if shorter or if allowed more */
2891     if (req_life > 0 && req_life <= endtime - now)
2892         endtime = now + req_life;
2893     else if (req_life > 0 && allow_more)
2894         endtime = now + req_life;
2895
2896     /* Apply floor */
2897     if (force > 0 && force > endtime - now)
2898         endtime = now + force;
2899
2900     /* Apply ceiling */
2901     if (clamp > 0 && clamp < endtime - now)
2902         endtime = now + clamp;
2903
2904     hx509_ca_tbs_set_notAfter(context, tbs, endtime);
2905     hx509_ca_tbs_set_notBefore(context, tbs, starttime);
2906     return 0;
2907 }
2908
2909 /*
2910  * Build a certifate for `principal' and its CSR.
2911  *
2912  * XXX Make `cprinc' a GeneralName!  That's why this is private for now.
2913  */
2914 heim_error_code
2915 _hx509_ca_issue_certificate(hx509_context context,
2916                             const heim_config_binding *cf,
2917                             heim_log_facility *logf,
2918                             hx509_request req,
2919                             KRB5PrincipalName *cprinc,
2920                             time_t starttime,
2921                             time_t endtime,
2922                             time_t req_life,
2923                             int send_chain,
2924                             hx509_certs *out)
2925 {
2926     heim_error_code ret;
2927     const char *ca;
2928     hx509_ca_tbs tbs = NULL;
2929     hx509_certs chain = NULL;
2930     hx509_cert signer = NULL;
2931     hx509_cert cert = NULL;
2932     hx509_env env = NULL;
2933     KeyUsage ku;
2934
2935     *out = NULL;
2936     /* Force KU */
2937     ku = int2KeyUsage(0);
2938     ku.digitalSignature = 1;
2939     hx509_request_authorize_ku(req, ku);
2940
2941     ret = get_cf(context, cf, logf, req, cprinc, &cf);
2942
2943     if ((ca = heim_config_get_string(context->hcontext, cf,
2944                                      "ca", NULL)) == NULL) {
2945         heim_log_msg(context->hcontext, logf, 3, NULL,
2946                      "No kx509 CA issuer credential specified");
2947         hx509_set_error_string(context, 0, ret = EACCES,
2948                                "No kx509 CA issuer credential specified");
2949         return ret;
2950     }
2951
2952     ret = hx509_ca_tbs_init(context, &tbs);
2953     if (ret) {
2954         heim_log_msg(context->hcontext, logf, 0, NULL,
2955                      "Failed to create certificate: Out of memory");
2956         return ret;
2957     }
2958
2959     /* Lookup a template and set things in `env' and `tbs' as appropriate */
2960     if (ret == 0)
2961         ret = set_tbs(context, logf, cf, req, cprinc, &env, tbs);
2962
2963     /* Populate generic template "env" variables */
2964
2965     /*
2966      * The `tbs' and `env' are now complete as to naming and EKUs.
2967      *
2968      * We check that the `tbs' is not name-less, after which all remaining
2969      * failures here will not be policy failures.  So we also log the intent to
2970      * issue a certificate now.
2971      */
2972     if (ret == 0 && hx509_name_is_null_p(hx509_ca_tbs_get_name(tbs)) &&
2973         !has_sans(req)) {
2974         heim_log_msg(context->hcontext, logf, 3, NULL,
2975                      "Not issuing certificate because it would have no names");
2976         hx509_set_error_string(context, 0, ret = EACCES,
2977                                "Not issuing certificate because it "
2978                                "would have no names");
2979     }
2980     if (ret)
2981         goto out;
2982
2983     /*
2984      * Still to be done below:
2985      *
2986      *  - set certificate spki
2987      *  - set certificate validity
2988      *  - expand variables in certificate subject name template
2989      *  - sign certificate
2990      *  - encode certificate and chain
2991      */
2992
2993     /* Load the issuer certificate and private key */
2994     {
2995         hx509_certs certs;
2996         hx509_query *q;
2997
2998         ret = hx509_certs_init(context, ca, 0, NULL, &certs);
2999         if (ret) {
3000             heim_log_msg(context->hcontext, logf, 1, NULL,
3001                          "Failed to load CA certificate and private key %s",
3002                          ca);
3003             hx509_set_error_string(context, 0, ret, "Failed to load "
3004                                    "CA certificate and private key %s", ca);
3005             goto out;
3006         }
3007         ret = hx509_query_alloc(context, &q);
3008         if (ret) {
3009             hx509_certs_free(&certs);
3010             goto out;
3011         }
3012
3013         hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
3014         hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
3015
3016         ret = hx509_certs_find(context, certs, q, &signer);
3017         hx509_query_free(context, q);
3018         hx509_certs_free(&certs);
3019         if (ret) {
3020             heim_log_msg(context->hcontext, logf, 1, NULL,
3021                          "Failed to find a CA certificate in %s", ca);
3022             hx509_set_error_string(context, 0, ret,
3023                                    "Failed to find a CA certificate in %s",
3024                                    ca);
3025             goto out;
3026         }
3027     }
3028
3029     /* Populate the subject public key in the TBS context */
3030     {
3031         SubjectPublicKeyInfo spki;
3032
3033         ret = hx509_request_get_SubjectPublicKeyInfo(context,
3034                                                      req, &spki);
3035         if (ret == 0)
3036             ret = hx509_ca_tbs_set_spki(context, tbs, &spki);
3037         free_SubjectPublicKeyInfo(&spki);
3038         if (ret)
3039             goto out;
3040     }
3041
3042     /* Work out cert expiration */
3043     if (ret == 0)
3044         ret = tbs_set_times(context, cf, logf, starttime, endtime, req_life,
3045                             tbs);
3046
3047     /* Expand the subjectName template in the TBS using the env */
3048     if (ret == 0)
3049         ret = hx509_ca_tbs_subject_expand(context, tbs, env);
3050     hx509_env_free(&env);
3051
3052     /* All done with the TBS, sign/issue the certificate */
3053     ret = hx509_ca_sign(context, tbs, signer, &cert);
3054     if (ret)
3055         goto out;
3056
3057     /*
3058      * Gather the certificate and chain into a MEMORY store, being careful not
3059      * to include private keys in the chain.
3060      *
3061      * We could have specified a separate configuration parameter for an hx509
3062      * store meant to have only the chain and no private keys, but expecting
3063      * the full chain in the issuer credential store and copying only the certs
3064      * (but not the private keys) is safer and easier to configure.
3065      */
3066     ret = hx509_certs_init(context, "MEMORY:certs",
3067                            HX509_CERTS_NO_PRIVATE_KEYS, NULL, out);
3068     if (ret == 0)
3069         ret = hx509_certs_add(context, *out, cert);
3070     if (ret == 0 && send_chain) {
3071         ret = hx509_certs_init(context, ca,
3072                                HX509_CERTS_NO_PRIVATE_KEYS, NULL, &chain);
3073         if (ret == 0)
3074             ret = hx509_certs_merge(context, *out, chain);
3075     }
3076
3077 out:
3078     hx509_certs_free(&chain);
3079     if (env)
3080         hx509_env_free(&env);
3081     if (tbs)
3082         hx509_ca_tbs_free(&tbs);
3083     if (cert)
3084         hx509_cert_free(cert);
3085     if (signer)
3086         hx509_cert_free(signer);
3087     if (ret)
3088         hx509_certs_free(out);
3089     return ret;
3090 }