]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/autoca.c
Fix autoca build with OpenSSL 1.1.0
[openldap] / servers / slapd / overlays / autoca.c
1 /* autoca.c - Automatic Certificate Authority */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2009-2017 The OpenLDAP Foundation.
6  * Copyright 2009-2017 by Howard Chu.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Howard Chu for inclusion in
19  * OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #define SLAPD_OVER_AUTOCA       SLAPD_MOD_DYNAMIC
25
26 #ifdef SLAPD_OVER_AUTOCA
27
28 #include <stdio.h>
29
30 #include <ac/string.h>
31 #include <ac/socket.h>
32
33 #include "lutil.h"
34 #include "slap.h"
35 #include "config.h"
36
37 #include <openssl/x509v3.h>
38 #include <openssl/evp.h>
39
40 /* Starting with OpenSSL 1.1.0, rsa.h is no longer included in
41  * x509.h, so we need to explicitly include it for the
42  * call to EVP_PKEY_CTX_set_rsa_keygen_bits
43  */
44
45 #if OPENSSL_VERSION_NUMBER >= 0x10100000
46 #include <openssl/rsa.h>
47 #endif
48
49 /* This overlay implements a certificate authority that can generate
50  * certificates automatically for any entry in the directory.
51  * On startup it generates a self-signed CA cert for the directory's
52  * suffix entry and uses this to sign all other certs that it generates.
53  * User and server certs are generated on demand, using a Search request.
54  */
55
56 #define LBER_TAG_OID        ((ber_tag_t) 0x06UL)
57 #define LBER_TAG_UTF8       ((ber_tag_t) 0x0cUL)
58
59 #define KEYBITS 2048
60 #define MIN_KEYBITS     512
61
62 #define ACA_SCHEMA_ROOT "1.3.6.1.4.1.4203.666.11.11"
63
64 #define ACA_SCHEMA_AT ACA_SCHEMA_ROOT ".1"
65 #define ACA_SCHEMA_OC ACA_SCHEMA_ROOT ".2"
66
67 static AttributeDescription *ad_caCert, *ad_caPkey, *ad_usrCert, *ad_usrPkey;
68 static AttributeDescription *ad_mail, *ad_ipaddr;
69 static ObjectClass *oc_caObj, *oc_usrObj;
70
71 static char *aca_attrs[] = {
72         "( " ACA_SCHEMA_AT ".1 NAME 'cAPrivateKey' "
73                 "DESC 'X.509 CA private key, use ;binary' "
74                 "SUP x509PrivateKey )",
75         "( " ACA_SCHEMA_AT ".2 NAME 'userPrivateKey' "
76                 "DESC 'X.509 user private key, use ;binary' "
77                 "SUP x509PrivateKey )",
78         NULL
79 };
80
81 static struct {
82         char *at;
83         AttributeDescription **ad;
84 } aca_attr2[] = {
85         { "cACertificate;binary", &ad_caCert },
86         { "cAPrivateKey;binary", &ad_caPkey },
87         { "userCertificate;binary", &ad_usrCert },
88         { "userPrivateKey;binary", &ad_usrPkey },
89         { "mail", &ad_mail },
90         { NULL }
91 };
92
93 static struct {
94         char *ot;
95         ObjectClass **oc;
96 } aca_ocs[] = {
97         { "( " ACA_SCHEMA_OC ".1 NAME 'autoCA' "
98                 "DESC 'Automated PKI certificate authority' "
99                 "SUP pkiCA AUXILIARY "
100                 "MAY cAPrivateKey )", &oc_caObj },
101         { "( " ACA_SCHEMA_OC ".2 NAME 'autoCAuser' "
102                 "DESC 'Automated PKI CA user' "
103                 "SUP pkiUser AUXILIARY "
104                 "MAY userPrivateKey )", &oc_usrObj },
105         { NULL }
106 };
107
108 typedef struct autoca_info {
109         X509 *ai_cert;
110         EVP_PKEY *ai_pkey;
111         ObjectClass *ai_usrclass;
112         ObjectClass *ai_srvclass;
113         struct berval ai_localdn;
114         struct berval ai_localndn;
115         int ai_usrkeybits;
116         int ai_srvkeybits;
117         int ai_cakeybits;
118         int ai_usrdays;
119         int ai_srvdays;
120         int ai_cadays;
121 } autoca_info;
122
123 /* Rewrite an LDAP DN in DER form
124  * Input must be valid DN, therefore no error checking is done here.
125  */
126 static int autoca_dnbv2der( Operation *op, struct berval *bv, struct berval *der )
127 {
128         BerElementBuffer berbuf;
129         BerElement *ber = (BerElement *)&berbuf;
130         LDAPDN dn;
131         LDAPRDN rdn;
132         LDAPAVA *ava;
133         AttributeDescription *ad;
134         int irdn, iava;
135
136         ldap_bv2dn_x( bv, &dn, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx );
137
138         ber_init2( ber, NULL, LBER_USE_DER );
139         ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
140
141         /* count RDNs, we need them in reverse order */
142         for (irdn = 0; dn[irdn]; irdn++);
143         irdn--;
144
145         /* DN is a SEQuence of RDNs */
146         ber_start_seq( ber, LBER_SEQUENCE );
147         for (; irdn >=0; irdn--)
148         {
149                 /* RDN is a SET of AVAs */
150                 ber_start_set( ber, LBER_SET );
151                 rdn = dn[irdn];
152                 for (iava = 0; rdn[iava]; iava++)
153                 {
154                         const char *text;
155                         char oid[1024];
156                         struct berval bvo = { sizeof(oid), oid };
157                         struct berval bva;
158
159                         /* AVA is a SEQuence of attr and value */
160                         ber_start_seq( ber, LBER_SEQUENCE );
161                         ava = rdn[iava];
162                         ad = NULL;
163                         slap_bv2ad( &ava->la_attr, &ad, &text );
164                         ber_str2bv( ad->ad_type->sat_oid, 0, 0, &bva );
165                         ber_encode_oid( &bva, &bvo );
166                         ber_put_berval( ber, &bvo, LBER_TAG_OID );
167                         ber_put_berval( ber, &ava->la_value, LBER_TAG_UTF8 );
168                         ber_put_seq( ber );
169                 }
170                 ber_put_set( ber );
171         }
172         ber_put_seq( ber );
173         ber_flatten2( ber, der, 0 );
174         ldap_dnfree_x( dn, op->o_tmpmemctx );
175         return 0;
176 }
177
178 static int autoca_genpkey(int bits, EVP_PKEY **pkey)
179 {
180         EVP_PKEY_CTX *kctx;
181         int rc;
182
183         kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
184         if (kctx == NULL)
185                 return -1;
186         if (EVP_PKEY_keygen_init(kctx) <= 0)
187         {
188                 EVP_PKEY_CTX_free(kctx);
189                 return -1;
190         }
191         if (EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, bits) <= 0)
192         {
193                 EVP_PKEY_CTX_free(kctx);
194                 return -1;
195         }
196         rc = EVP_PKEY_keygen(kctx, pkey);
197         EVP_PKEY_CTX_free(kctx);
198         return rc;
199 }
200
201 static int autoca_signcert(X509 *cert, EVP_PKEY *pkey)
202 {
203         EVP_MD_CTX *ctx = EVP_MD_CTX_create();
204         EVP_PKEY_CTX *pkctx = NULL;
205         int rc = -1;
206
207         if ( ctx == NULL )
208                 return -1;
209         if (EVP_DigestSignInit(ctx, &pkctx, NULL, NULL, pkey))
210         {
211                 rc = X509_sign_ctx(cert, ctx);
212         }
213         EVP_MD_CTX_destroy(ctx);
214         return rc;
215 }
216
217 #define SERIAL_BITS     64      /* should be less than 160 */
218
219 typedef struct myext {
220         char *name;
221         char *value;
222 } myext;
223
224 static myext CAexts[] = {
225         { "subjectKeyIdentifier", "hash" },
226         { "authorityKeyIdentifier", "keyid:always,issuer" },
227         { "basicConstraints", "critical,CA:true" },
228         { "keyUsage", "digitalSignature,cRLSign,keyCertSign" },
229         { "nsComment", "OpenLDAP automatic certificate" },
230         { NULL }
231 };
232
233 static myext usrExts[] = {
234         { "subjectKeyIdentifier", "hash" },
235         { "authorityKeyIdentifier", "keyid:always,issuer" },
236         { "basicConstraints", "CA:false" },
237         { "keyUsage", "digitalSignature,nonRepudiation,keyEncipherment" },
238         { "extendedKeyUsage", "clientAuth,emailProtection,codeSigning" },
239         { "nsComment", "OpenLDAP automatic certificate" },
240         { NULL }
241 };
242
243 static myext srvExts[] = {
244         { "subjectKeyIdentifier", "hash" },
245         { "authorityKeyIdentifier", "keyid:always,issuer" },
246         { "basicConstraints", "CA:false" },
247         { "keyUsage", "digitalSignature,keyEncipherment" },
248         { "extendedKeyUsage", "serverAuth,clientAuth" },
249         { "nsComment", "OpenLDAP automatic certificate" },
250         { NULL }
251 };
252
253 typedef struct genargs {
254         X509 *issuer_cert;
255         EVP_PKEY *issuer_pkey;
256         struct berval *subjectDN;
257         myext *cert_exts;
258         myext *more_exts;
259         X509 *newcert;
260         EVP_PKEY *newpkey;
261         struct berval dercert;
262         struct berval derpkey;
263         int keybits;
264         int days;
265 } genargs;
266
267 static int autoca_gencert( Operation *op, genargs *args )
268 {
269         X509_NAME *subj_name, *issuer_name;
270         X509 *subj_cert;
271         struct berval derdn;
272         unsigned char *pp;
273         EVP_PKEY *evpk = NULL;
274         int rc;
275
276         if ((subj_cert = X509_new()) == NULL)
277                 return -1;
278
279         autoca_dnbv2der( op, args->subjectDN, &derdn );
280         pp = (unsigned char *)derdn.bv_val;
281         subj_name = d2i_X509_NAME( NULL, (const unsigned char **)&pp, derdn.bv_len );
282         op->o_tmpfree( derdn.bv_val, op->o_tmpmemctx );
283         if ( subj_name == NULL )
284         {
285 fail1:
286                 X509_free( subj_cert );
287                 return -1;
288         }
289
290         rc = autoca_genpkey( args->keybits, &evpk );
291         if ( rc <= 0 )
292         {
293 fail2:
294                 if ( subj_name ) X509_NAME_free( subj_name );
295                 goto fail1;
296         }
297         /* encode DER in PKCS#8 */
298         {
299                 PKCS8_PRIV_KEY_INFO *p8inf;
300                 if (( p8inf = EVP_PKEY2PKCS8( evpk )) == NULL )
301                         goto fail2;
302                 args->derpkey.bv_len = i2d_PKCS8_PRIV_KEY_INFO( p8inf, NULL );
303                 args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx );
304                 pp = (unsigned char *)args->derpkey.bv_val;
305                 i2d_PKCS8_PRIV_KEY_INFO( p8inf, &pp );
306                 PKCS8_PRIV_KEY_INFO_free( p8inf );
307         }
308         args->newpkey = evpk;
309
310         /* set random serial */
311         {
312                 BIGNUM *bn = BN_new();
313                 if ( bn == NULL )
314                 {
315 fail3:
316                         EVP_PKEY_free( evpk );
317                         goto fail2;
318                 }
319                 if (!BN_pseudo_rand(bn, SERIAL_BITS, 0, 0))
320                 {
321                         BN_free( bn );
322                         goto fail3;
323                 }
324                 if (!BN_to_ASN1_INTEGER(bn, X509_get_serialNumber(subj_cert)))
325                 {
326                         BN_free( bn );
327                         goto fail3;
328                 }
329                 BN_free(bn);
330         }
331         if (args->issuer_cert) {
332                 issuer_name = X509_get_subject_name(args->issuer_cert);
333         } else {
334                 issuer_name = subj_name;
335                 args->issuer_cert = subj_cert;
336                 args->issuer_pkey = evpk;
337         }
338         if (!X509_set_version(subj_cert, 2) ||  /* set version to V3 */
339                 !X509_set_issuer_name(subj_cert, issuer_name) ||
340                 !X509_set_subject_name(subj_cert, subj_name) ||
341                 !X509_gmtime_adj(X509_get_notBefore(subj_cert), 0) ||
342                 !X509_time_adj_ex(X509_get_notAfter(subj_cert), args->days, 0, NULL) ||
343                 !X509_set_pubkey(subj_cert, evpk))
344         {
345                 goto fail3;
346         }
347         X509_NAME_free(subj_name);
348         subj_name = NULL;
349
350         /* set cert extensions */
351         {
352                 X509V3_CTX ctx;
353                 X509_EXTENSION *ext;
354                 int i;
355
356                 X509V3_set_ctx(&ctx, args->issuer_cert, subj_cert, NULL, NULL, 0);
357                 for (i=0; args->cert_exts[i].name; i++) {
358                         ext = X509V3_EXT_nconf(NULL, &ctx, args->cert_exts[i].name, args->cert_exts[i].value);
359                         if ( ext == NULL )
360                                 goto fail3;
361                         rc = X509_add_ext(subj_cert, ext, -1);
362                         X509_EXTENSION_free(ext);
363                         if ( !rc )
364                                 goto fail3;
365                 }
366                 if (args->more_exts) {
367                         for (i=0; args->more_exts[i].name; i++) {
368                                 ext = X509V3_EXT_nconf(NULL, &ctx, args->more_exts[i].name, args->more_exts[i].value);
369                                 if ( ext == NULL )
370                                         goto fail3;
371                                 rc = X509_add_ext(subj_cert, ext, -1);
372                                 X509_EXTENSION_free(ext);
373                                 if ( !rc )
374                                         goto fail3;
375                         }
376                 }
377         }
378         rc = autoca_signcert( subj_cert, args->issuer_pkey );
379         if ( rc < 0 )
380                 goto fail3;
381         args->dercert.bv_len = i2d_X509( subj_cert, NULL );
382         args->dercert.bv_val = op->o_tmpalloc( args->dercert.bv_len, op->o_tmpmemctx );
383         pp = (unsigned char *)args->dercert.bv_val;
384         i2d_X509( subj_cert, &pp );
385         args->newcert = subj_cert;
386         return 0;
387 }
388
389 typedef struct saveargs {
390         ObjectClass *oc;
391         struct berval *dercert;
392         struct berval *derpkey;
393         slap_overinst *on;
394         struct berval *dn;
395         struct berval *ndn;
396         int isca;
397 } saveargs;
398
399 static int autoca_savecert( Operation *op, saveargs *args )
400 {
401         Modifications mod[3], *mp = mod;
402         struct berval bvs[6], *bp = bvs;
403         BackendInfo *bi;
404         slap_callback cb = {0};
405         SlapReply rs = {REP_RESULT};
406
407         if ( args->oc ) {
408                 mp->sml_numvals = 1;
409                 mp->sml_values = bp;
410                 mp->sml_nvalues = NULL;
411                 mp->sml_desc = slap_schema.si_ad_objectClass;
412                 mp->sml_op = LDAP_MOD_ADD;
413                 mp->sml_flags = SLAP_MOD_INTERNAL;
414                 *bp++ = args->oc->soc_cname;
415                 BER_BVZERO( bp );
416                 bp++;
417                 mp->sml_next = mp+1;
418                 mp++;
419         }
420         mp->sml_numvals = 1;
421         mp->sml_values = bp;
422         mp->sml_nvalues = NULL;
423         mp->sml_desc = args->isca ? ad_caCert : ad_usrCert;
424         mp->sml_op = LDAP_MOD_REPLACE;
425         mp->sml_flags = SLAP_MOD_INTERNAL;
426         *bp++ = *args->dercert;
427         BER_BVZERO( bp );
428         bp++;
429         mp->sml_next = mp+1;
430         mp++;
431
432         mp->sml_numvals = 1;
433         mp->sml_values = bp;
434         mp->sml_nvalues = NULL;
435         mp->sml_desc = args->isca ? ad_caPkey : ad_usrPkey;
436         mp->sml_op = LDAP_MOD_ADD;
437         mp->sml_flags = SLAP_MOD_INTERNAL;
438         *bp++ = *args->derpkey;
439         BER_BVZERO( bp );
440         mp->sml_next = NULL;
441
442         cb.sc_response = slap_null_cb;
443         bi = op->o_bd->bd_info;
444         op->o_bd->bd_info = args->on->on_info->oi_orig;
445         op->o_tag = LDAP_REQ_MODIFY;
446         op->o_callback = &cb;
447         op->orm_modlist = mod;
448         op->orm_no_opattrs = 1;
449         op->o_req_dn = *args->dn;
450         op->o_req_ndn = *args->ndn;
451         op->o_bd->be_modify( op, &rs );
452         op->o_bd->bd_info = bi;
453         return rs.sr_err;
454 }
455
456 static const struct berval configDN = BER_BVC("cn=config");
457
458 /* must run as a pool thread to avoid cn=config deadlock */
459 static void *
460 autoca_setca_task( void *ctx, void *arg )
461 {
462         Connection conn = { 0 };
463         OperationBuffer opbuf;
464         Operation *op;
465         struct berval *cacert = arg;
466         Modifications mod;
467         struct berval bvs[2];
468         slap_callback cb = {0};
469         SlapReply rs = {REP_RESULT};
470         const char *text;
471
472         connection_fake_init( &conn, &opbuf, ctx );
473         op = &opbuf.ob_op;
474
475         mod.sml_numvals = 1;
476         mod.sml_values = bvs;
477         mod.sml_nvalues = NULL;
478         mod.sml_desc = NULL;
479         if ( slap_str2ad( "olcTLSCACertificate;binary", &mod.sml_desc, &text ))
480                 goto leave;
481         mod.sml_op = LDAP_MOD_REPLACE;
482         mod.sml_flags = SLAP_MOD_INTERNAL;
483         bvs[0] = *cacert;
484         BER_BVZERO( &bvs[1] );
485         mod.sml_next = NULL;
486
487         cb.sc_response = slap_null_cb;
488         op->o_bd = select_backend( (struct berval *)&configDN, 0 );
489         if ( !op->o_bd )
490                 goto leave;
491
492         op->o_tag = LDAP_REQ_MODIFY;
493         op->o_callback = &cb;
494         op->orm_modlist = &mod;
495         op->orm_no_opattrs = 1;
496         op->o_req_dn = configDN;
497         op->o_req_ndn = configDN;
498         op->o_dn = op->o_bd->be_rootdn;
499         op->o_ndn = op->o_bd->be_rootndn;
500         op->o_bd->be_modify( op, &rs );
501 leave:
502         ch_free( arg );
503         return NULL;
504 }
505
506 static int
507 autoca_setca( struct berval *cacert )
508 {
509         struct berval *bv = ch_malloc( sizeof(struct berval) + cacert->bv_len );
510         bv->bv_len = cacert->bv_len;
511         bv->bv_val = (char *)(bv+1);
512         AC_MEMCPY( bv->bv_val, cacert->bv_val, bv->bv_len );
513         return ldap_pvt_thread_pool_submit( &connection_pool, autoca_setca_task, bv );
514 }
515
516 static int
517 autoca_setlocal( Operation *op, struct berval *cert, struct berval *pkey )
518 {
519         Modifications mod[2];
520         struct berval bvs[4];
521         slap_callback cb = {0};
522         SlapReply rs = {REP_RESULT};
523         const char *text;
524
525         mod[0].sml_numvals = 1;
526         mod[0].sml_values = bvs;
527         mod[0].sml_nvalues = NULL;
528         mod[0].sml_desc = NULL;
529         if ( slap_str2ad( "olcTLSCertificate;binary", &mod[0].sml_desc, &text ))
530                 return -1;
531         mod[0].sml_op = LDAP_MOD_REPLACE;
532         mod[0].sml_flags = SLAP_MOD_INTERNAL;
533         bvs[0] = *cert;
534         BER_BVZERO( &bvs[1] );
535         mod[0].sml_next = &mod[1];
536
537         mod[1].sml_numvals = 1;
538         mod[1].sml_values = &bvs[2];
539         mod[1].sml_nvalues = NULL;
540         mod[1].sml_desc = NULL;
541         if ( slap_str2ad( "olcTLSCertificateKey;binary", &mod[1].sml_desc, &text ))
542                 return -1;
543         mod[1].sml_op = LDAP_MOD_REPLACE;
544         mod[1].sml_flags = SLAP_MOD_INTERNAL;
545         bvs[2] = *pkey;
546         BER_BVZERO( &bvs[3] );
547         mod[1].sml_next = NULL;
548
549         cb.sc_response = slap_null_cb;
550         op->o_bd = select_backend( (struct berval *)&configDN, 0 );
551         if ( !op->o_bd )
552                 return -1;
553
554         op->o_tag = LDAP_REQ_MODIFY;
555         op->o_callback = &cb;
556         op->orm_modlist = mod;
557         op->orm_no_opattrs = 1;
558         op->o_req_dn = configDN;
559         op->o_req_ndn = configDN;
560         op->o_dn = op->o_bd->be_rootdn;
561         op->o_ndn = op->o_bd->be_rootndn;
562         op->o_bd->be_modify( op, &rs );
563         return rs.sr_err;
564 }
565
566 enum {
567         ACA_USRCLASS = 1,
568         ACA_SRVCLASS,
569         ACA_USRKEYBITS,
570         ACA_SRVKEYBITS,
571         ACA_CAKEYBITS,
572         ACA_USRDAYS,
573         ACA_SRVDAYS,
574         ACA_CADAYS,
575         ACA_LOCALDN
576 };
577
578 static int autoca_cf( ConfigArgs *c )
579 {
580         slap_overinst *on = (slap_overinst *)c->bi;
581         autoca_info *ai = on->on_bi.bi_private;
582         int rc = 0;
583
584         switch( c->op ) {
585         case SLAP_CONFIG_EMIT:
586                 switch( c->type ) {
587                 case ACA_USRCLASS:
588                         if ( ai->ai_usrclass ) {
589                                 c->value_string = ch_strdup( ai->ai_usrclass->soc_cname.bv_val );
590                         } else {
591                                 rc = 1;
592                         }
593                         break;
594                 case ACA_SRVCLASS:
595                         if ( ai->ai_srvclass ) {
596                                 c->value_string = ch_strdup( ai->ai_srvclass->soc_cname.bv_val );
597                         } else {
598                                 rc = 1;
599                         }
600                         break;
601                 case ACA_USRKEYBITS:
602                         c->value_int = ai->ai_usrkeybits;
603                         break;
604                 case ACA_SRVKEYBITS:
605                         c->value_int = ai->ai_srvkeybits;
606                         break;
607                 case ACA_CAKEYBITS:
608                         c->value_int = ai->ai_cakeybits;
609                         break;
610                 case ACA_USRDAYS:
611                         c->value_int = ai->ai_usrdays;
612                         break;
613                 case ACA_SRVDAYS:
614                         c->value_int = ai->ai_srvdays;
615                         break;
616                 case ACA_CADAYS:
617                         c->value_int = ai->ai_cadays;
618                         break;
619                 case ACA_LOCALDN:
620                         if ( !BER_BVISNULL( &ai->ai_localdn )) {
621                                 rc = value_add_one( &c->rvalue_vals, &ai->ai_localdn );
622                         } else {
623                                 rc = 1;
624                         }
625                         break;
626                 }
627                 break;
628         case LDAP_MOD_DELETE:
629                 switch( c->type ) {
630                 case ACA_USRCLASS:
631                         ai->ai_usrclass = NULL;
632                         break;
633                 case ACA_SRVCLASS:
634                         ai->ai_srvclass = NULL;
635                         break;
636                 case ACA_LOCALDN:
637                         if ( ai->ai_localdn.bv_val ) {
638                                 ch_free( ai->ai_localdn.bv_val );
639                                 ch_free( ai->ai_localndn.bv_val );
640                                 BER_BVZERO( &ai->ai_localdn );
641                                 BER_BVZERO( &ai->ai_localndn );
642                         }
643                         break;
644                 /* single-valued attrs, all no-ops */
645                 }
646                 break;
647         case SLAP_CONFIG_ADD:
648         case LDAP_MOD_ADD:
649                 switch( c->type ) {
650                 case ACA_USRCLASS:
651                         {
652                                 ObjectClass *oc = oc_find( c->value_string );
653                                 if ( oc )
654                                         ai->ai_usrclass = oc;
655                                 else
656                                         rc = 1;
657                         }
658                         break;
659                 case ACA_SRVCLASS:
660                         {
661                                 ObjectClass *oc = oc_find( c->value_string );
662                                 if ( oc )
663                                         ai->ai_srvclass = oc;
664                                 else
665                                         rc = 1;
666                         }
667                 case ACA_USRKEYBITS:
668                         if ( c->value_int < MIN_KEYBITS )
669                                 rc = 1;
670                         else
671                                 ai->ai_usrkeybits = c->value_int;
672                         break;
673                 case ACA_SRVKEYBITS:
674                         if ( c->value_int < MIN_KEYBITS )
675                                 rc = 1;
676                         else
677                                 ai->ai_srvkeybits = c->value_int;
678                         break;
679                 case ACA_CAKEYBITS:
680                         if ( c->value_int < MIN_KEYBITS )
681                                 rc = 1;
682                         else
683                                 ai->ai_cakeybits = c->value_int;
684                         break;
685                 case ACA_USRDAYS:
686                         ai->ai_usrdays = c->value_int;
687                         break;
688                 case ACA_SRVDAYS:
689                         ai->ai_srvdays = c->value_int;
690                         break;
691                 case ACA_CADAYS:
692                         ai->ai_cadays = c->value_int;
693                         break;
694                 case ACA_LOCALDN:
695                         if ( c->be->be_nsuffix == NULL ) {
696                                 snprintf( c->cr_msg, sizeof( c->cr_msg ),
697                                         "suffix must be set" );
698                                 Debug( LDAP_DEBUG_CONFIG, "autoca_config: %s\n",
699                                         c->cr_msg, NULL, NULL );
700                                 rc = ARG_BAD_CONF;
701                                 break;
702                         }
703                         if ( !dnIsSuffix( &c->value_ndn, c->be->be_nsuffix )) {
704                                 snprintf( c->cr_msg, sizeof( c->cr_msg ),
705                                         "DN is not a subordinate of backend" );
706                                 Debug( LDAP_DEBUG_CONFIG, "autoca_config: %s\n",
707                                         c->cr_msg, NULL, NULL );
708                                 rc = ARG_BAD_CONF;
709                                 break;
710                         }
711                         if ( ai->ai_localdn.bv_val ) {
712                                 ch_free( ai->ai_localdn.bv_val );
713                                 ch_free( ai->ai_localndn.bv_val );
714                         }
715                         ai->ai_localdn = c->value_dn;
716                         ai->ai_localndn = c->value_ndn;
717                 }
718         }
719         return rc;
720 }
721
722 static ConfigTable autoca_cfg[] = {
723         { "userClass", "objectclass", 2, 2, 0,
724           ARG_STRING|ARG_MAGIC|ACA_USRCLASS, autoca_cf,
725           "( OLcfgOvAt:22.1 NAME 'olcACAuserClass' "
726           "DESC 'ObjectClass of user entries' "
727           "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
728         { "serverClass", "objectclass", 2, 2, 0,
729           ARG_STRING|ARG_MAGIC|ACA_SRVCLASS, autoca_cf,
730           "( OLcfgOvAt:22.2 NAME 'olcACAserverClass' "
731           "DESC 'ObjectClass of server entries' "
732           "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
733         { "userKeybits", "integer", 2, 2, 0,
734           ARG_INT|ARG_MAGIC|ACA_USRKEYBITS, autoca_cf,
735           "( OLcfgOvAt:22.3 NAME 'olcACAuserKeybits' "
736           "DESC 'Size of PrivateKey for user entries' "
737           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
738         { "serverKeybits", "integer", 2, 2, 0,
739           ARG_INT|ARG_MAGIC|ACA_SRVKEYBITS, autoca_cf,
740           "( OLcfgOvAt:22.4 NAME 'olcACAserverKeybits' "
741           "DESC 'Size of PrivateKey for server entries' "
742           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
743         { "caKeybits", "integer", 2, 2, 0,
744           ARG_INT|ARG_MAGIC|ACA_CAKEYBITS, autoca_cf,
745           "( OLcfgOvAt:22.5 NAME 'olcACAKeybits' "
746           "DESC 'Size of PrivateKey for CA certificate' "
747           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
748         { "userDays", "integer", 2, 2, 0,
749           ARG_INT|ARG_MAGIC|ACA_USRDAYS, autoca_cf,
750           "( OLcfgOvAt:22.6 NAME 'olcACAuserDays' "
751           "DESC 'Lifetime of user certificates in days' "
752           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
753         { "serverDays", "integer", 2, 2, 0,
754           ARG_INT|ARG_MAGIC|ACA_SRVDAYS, autoca_cf,
755           "( OLcfgOvAt:22.7 NAME 'olcACAserverDays' "
756           "DESC 'Lifetime of server certificates in days' "
757           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
758         { "caDays", "integer", 2, 2, 0,
759           ARG_INT|ARG_MAGIC|ACA_CADAYS, autoca_cf,
760           "( OLcfgOvAt:22.8 NAME 'olcACADays' "
761           "DESC 'Lifetime of CA certificate in days' "
762           "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
763         { "localdn", "dn", 2, 2, 0,
764           ARG_DN|ARG_MAGIC|ACA_LOCALDN, autoca_cf,
765           "( OLcfgOvAt:22.9 NAME 'olcACAlocalDN' "
766           "DESC 'DN of local server cert' "
767           "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
768         { NULL, NULL, 0, 0, 0, ARG_IGNORED }
769 };
770
771 static ConfigOCs autoca_ocs[] = {
772         { "( OLcfgOvOc:22.1 "
773           "NAME 'olcACAConfig' "
774           "DESC 'AutoCA configuration' "
775           "SUP olcOverlayConfig "
776           "MAY ( olcACAuserClass $ olcACAserverClass $ "
777            "olcACAuserKeybits $ olcACAserverKeybits $ olcACAKeyBits $ "
778            "olcACAuserDays $ olcACAserverDays $ olcACADays $ "
779            "olcACAlocalDN ) )",
780           Cft_Overlay, autoca_cfg },
781         { NULL, 0, NULL }
782 };
783
784 static int
785 autoca_op_response(
786         Operation *op,
787         SlapReply *rs
788 )
789 {
790         slap_overinst *on = op->o_callback->sc_private;
791         autoca_info *ai = on->on_bi.bi_private;
792         Attribute *a;
793         int isusr = 0;
794
795         if (rs->sr_type != REP_SEARCH)
796                 return SLAP_CB_CONTINUE;
797
798         /* If root or self */
799         if ( !be_isroot( op ) &&
800                 !dn_match( &rs->sr_entry->e_nname, &op->o_ndn ))
801                 return SLAP_CB_CONTINUE;
802
803         isusr = is_entry_objectclass( rs->sr_entry, ai->ai_usrclass, SLAP_OCF_CHECK_SUP );
804         if ( !isusr )
805         {
806                 if (!is_entry_objectclass( rs->sr_entry, ai->ai_srvclass, SLAP_OCF_CHECK_SUP ))
807                         return SLAP_CB_CONTINUE;
808         }
809         a = attr_find( rs->sr_entry->e_attrs, ad_usrPkey );
810         if ( !a )
811         {
812                 Operation op2;
813                 genargs args;
814                 saveargs arg2;
815                 myext extras[2];
816                 int rc;
817
818                 args.issuer_cert = ai->ai_cert;
819                 args.issuer_pkey = ai->ai_pkey;
820                 args.subjectDN = &rs->sr_entry->e_name;
821                 args.more_exts = NULL;
822                 if ( isusr )
823                 {
824                         args.cert_exts = usrExts;
825                         args.keybits = ai->ai_usrkeybits;
826                         args.days = ai->ai_usrdays;
827                         a = attr_find( rs->sr_entry->e_attrs, ad_mail );
828                         if ( a )
829                         {
830                                 extras[0].name = "subjectAltName";
831                                 extras[1].name = NULL;
832                                 extras[0].value = op->o_tmpalloc( sizeof("email:") + a->a_vals[0].bv_len, op->o_tmpmemctx );
833                                 sprintf(extras[0].value, "email:%s", a->a_vals[0].bv_val);
834                                 args.more_exts = extras;
835                         }
836                 } else
837                 {
838                         args.cert_exts = srvExts;
839                         args.keybits = ai->ai_srvkeybits;
840                         args.days = ai->ai_srvdays;
841                         if ( ad_ipaddr && (a = attr_find( rs->sr_entry->e_attrs, ad_ipaddr )))
842                         {
843                                 extras[0].name = "subjectAltName";
844                                 extras[1].name = NULL;
845                                 extras[0].value = op->o_tmpalloc( sizeof("IP:") + a->a_vals[0].bv_len, op->o_tmpmemctx );
846                                 sprintf(extras[0].value, "IP:%s", a->a_vals[0].bv_val);
847                                 args.more_exts = extras;
848                         }
849                 }
850                 rc = autoca_gencert( op, &args );
851                 if ( rc )
852                         return SLAP_CB_CONTINUE;
853                 X509_free( args.newcert );
854                 EVP_PKEY_free( args.newpkey );
855
856                 if ( is_entry_objectclass( rs->sr_entry, oc_usrObj, 0 ))
857                         arg2.oc = NULL;
858                 else
859                         arg2.oc = oc_usrObj;
860                 if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ))
861                 {
862                         Entry *e = entry_dup( rs->sr_entry );
863                         rs_replace_entry( op, rs, on, e );
864                         rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
865                 }
866                 arg2.dercert = &args.dercert;
867                 arg2.derpkey = &args.derpkey;
868                 arg2.on = on;
869                 arg2.dn = &rs->sr_entry->e_name;
870                 arg2.ndn = &rs->sr_entry->e_nname;
871                 arg2.isca = 0;
872                 op2 = *op;
873                 rc = autoca_savecert( &op2, &arg2 );
874                 if ( !rc )
875                 {
876                         /* If this is our cert DN, configure it */
877                         if ( dn_match( &rs->sr_entry->e_nname, &ai->ai_localndn ))
878                                 autoca_setlocal( &op2, &args.dercert, &args.derpkey );
879                         attr_merge_one( rs->sr_entry, ad_usrCert, &args.dercert, NULL );
880                         attr_merge_one( rs->sr_entry, ad_usrPkey, &args.derpkey, NULL );
881                 }
882                 op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx );
883                 op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx );
884         }
885
886         return SLAP_CB_CONTINUE;
887 }
888
889 static int
890 autoca_op_search(
891         Operation *op,
892         SlapReply *rs
893 )
894 {
895         /* we only act on a search that returns just our cert/key attrs */
896         if ( op->ors_attrs && op->ors_attrs[0].an_desc == ad_usrCert &&
897                 op->ors_attrs[1].an_desc == ad_usrPkey &&
898                 op->ors_attrs[2].an_name.bv_val == NULL )
899         {
900                 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
901                 slap_callback *sc = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
902                 sc->sc_response = autoca_op_response;
903                 sc->sc_private = on;
904                 sc->sc_next = op->o_callback;
905                 op->o_callback = sc;
906         }
907         return SLAP_CB_CONTINUE;
908 }
909
910 static int
911 autoca_db_init(
912         BackendDB *be,
913         ConfigReply *cr
914 )
915 {
916         slap_overinst *on = (slap_overinst *) be->bd_info;
917         autoca_info *ai;
918
919         ai = ch_calloc(1, sizeof(autoca_info));
920         on->on_bi.bi_private = ai;
921
922         /* set defaults */
923         ai->ai_usrclass = oc_find( "person" );
924         ai->ai_srvclass = oc_find( "ipHost" );
925         ai->ai_usrkeybits = KEYBITS;
926         ai->ai_srvkeybits = KEYBITS;
927         ai->ai_cakeybits = KEYBITS;
928         ai->ai_usrdays = 365;   /* 1 year */
929         ai->ai_srvdays = 1826;  /* 5 years */
930         ai->ai_cadays = 3652;   /* 10 years */
931         return 0;
932 }
933
934 static int
935 autoca_db_destroy(
936         BackendDB *be,
937         ConfigReply *cr
938 )
939 {
940         slap_overinst *on = (slap_overinst *) be->bd_info;
941         autoca_info *ai = on->on_bi.bi_private;
942
943         if ( ai->ai_cert )
944                 X509_free( ai->ai_cert );
945         if ( ai->ai_pkey )
946                 EVP_PKEY_free( ai->ai_pkey );
947         ch_free( ai );
948
949         return 0;
950 }
951
952 static int
953 autoca_db_open(
954         BackendDB *be,
955         ConfigReply *cr
956 )
957 {
958         slap_overinst *on = (slap_overinst *)be->bd_info;
959         autoca_info *ai = on->on_bi.bi_private;
960
961         Connection conn = { 0 };
962         OperationBuffer opbuf;
963         Operation *op;
964         void *thrctx;
965         Entry *e;
966         Attribute *a;
967         int rc;
968
969         if (slapMode & SLAP_TOOL_MODE)
970                 return 0;
971
972         if ( ! *aca_attr2[0].ad ) {
973                 int i, code;
974                 const char *text;
975
976                 for ( i=0; aca_attr2[i].at; i++ ) {
977                         code = slap_str2ad( aca_attr2[i].at, aca_attr2[i].ad, &text );
978                         if ( code ) return code;
979                 }
980
981                 /* Schema may not be loaded, ignore if missing */
982                 slap_str2ad( "ipHostNumber", &ad_ipaddr, &text );
983
984                 for ( i=0; aca_ocs[i].ot; i++ ) {
985                         code = register_oc( aca_ocs[i].ot, aca_ocs[i].oc, 0 );
986                         if ( code ) return code;
987                 }
988         }
989
990         thrctx = ldap_pvt_thread_pool_context();
991         connection_fake_init2( &conn, &opbuf, thrctx, 0 );
992         op = &opbuf.ob_op;
993         op->o_bd = be;
994         op->o_dn = be->be_rootdn;
995         op->o_ndn = be->be_rootndn;
996         rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL, 
997                 NULL, 0, &e, on );
998
999         if ( e ) {
1000                 int gotoc = 0, gotat = 0;
1001                 if ( is_entry_objectclass( e, oc_caObj, 0 )) {
1002                         gotoc = 1;
1003                         a = attr_find( e->e_attrs, ad_caPkey );
1004                         if ( a ) {
1005                                 const unsigned char *pp;
1006                                 pp = (unsigned char *)a->a_vals[0].bv_val;
1007                                 ai->ai_pkey = d2i_AutoPrivateKey( NULL, &pp, a->a_vals[0].bv_len );
1008                                 if ( ai->ai_pkey )
1009                                 {
1010                                         a = attr_find( e->e_attrs, ad_caCert );
1011                                         if ( a )
1012                                         {
1013                                                 pp = (unsigned char *)a->a_vals[0].bv_val;
1014                                                 ai->ai_cert = d2i_X509( NULL, &pp, a->a_vals[0].bv_len );
1015                                                 /* If TLS wasn't configured yet, set this as our CA */
1016                                                 if ( !slap_tls_ctx )
1017                                                         autoca_setca( a->a_vals );
1018                                         }
1019                                 }
1020                                 gotat = 1;
1021                         }
1022                 }
1023                 overlay_entry_release_ov( op, e, 0, on );
1024                 /* generate attrs, store... */
1025                 if ( !gotat ) {
1026                         genargs args;
1027                         saveargs arg2;
1028
1029                         args.issuer_cert = NULL;
1030                         args.issuer_pkey = NULL;
1031                         args.subjectDN = &be->be_suffix[0];
1032                         args.cert_exts = CAexts;
1033                         args.more_exts = NULL;
1034                         args.keybits = ai->ai_cakeybits;
1035                         args.days = ai->ai_cadays;
1036
1037                         rc = autoca_gencert( op, &args );
1038                         if ( rc )
1039                                 return -1;
1040
1041                         ai->ai_cert = args.newcert;
1042                         ai->ai_pkey = args.newpkey;
1043
1044                         arg2.dn = be->be_suffix;
1045                         arg2.ndn = be->be_nsuffix;
1046                         arg2.isca = 1;
1047                         if ( !gotoc )
1048                                 arg2.oc = oc_caObj;
1049                         else
1050                                 arg2.oc = NULL;
1051                         arg2.on = on;
1052                         arg2.dercert = &args.dercert;
1053                         arg2.derpkey = &args.derpkey;
1054
1055                         autoca_savecert( op, &arg2 );
1056
1057                         /* If TLS wasn't configured yet, set this as our CA */
1058                         if ( !slap_tls_ctx )
1059                                 autoca_setca( &args.dercert );
1060
1061                         op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx );
1062                         op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx );
1063                 }
1064         }
1065
1066         return 0;
1067 }
1068
1069 static slap_overinst autoca;
1070
1071 /* This overlay is set up for dynamic loading via moduleload. For static
1072  * configuration, you'll need to arrange for the slap_overinst to be
1073  * initialized and registered by some other function inside slapd.
1074  */
1075
1076 int autoca_initialize() {
1077         int i, code;
1078
1079         autoca.on_bi.bi_type = "autoca";
1080         autoca.on_bi.bi_db_init = autoca_db_init;
1081         autoca.on_bi.bi_db_destroy = autoca_db_destroy;
1082         autoca.on_bi.bi_db_open = autoca_db_open;
1083         autoca.on_bi.bi_op_search = autoca_op_search;
1084
1085         autoca.on_bi.bi_cf_ocs = autoca_ocs;
1086         code = config_register_schema( autoca_cfg, autoca_ocs );
1087         if ( code ) return code;
1088
1089         for ( i=0; aca_attrs[i]; i++ ) {
1090                 code = register_at( aca_attrs[i], NULL, 0 );
1091                 if ( code ) return code;
1092         }
1093
1094         return overlay_register( &autoca );
1095 }
1096
1097 #if SLAPD_OVER_AUTOCA == SLAPD_MOD_DYNAMIC
1098 int
1099 init_module( int argc, char *argv[] )
1100 {
1101         return autoca_initialize();
1102 }
1103 #endif
1104
1105 #endif /* defined(SLAPD_OVER_AUTOCA) */