X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fautoca.c;h=73a57476174dc938cb57fa90b56a7aa21b32310f;hb=59e9ff6243465640956b58ad1756a3ede53eca7c;hp=a109d4fea76c53f6fef5e696932ec912972dcc26;hpb=0f9ec8322f5641aae68852ab5a32daf31417f261;p=openldap diff --git a/servers/slapd/overlays/autoca.c b/servers/slapd/overlays/autoca.c index a109d4fea7..73a5747617 100644 --- a/servers/slapd/overlays/autoca.c +++ b/servers/slapd/overlays/autoca.c @@ -2,8 +2,8 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2009-2017 The OpenLDAP Foundation. - * Copyright 2009-2017 by Howard Chu. + * Copyright 2009-2018 The OpenLDAP Foundation. + * Copyright 2009-2018 by Howard Chu. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -21,8 +21,6 @@ #include "portable.h" -#define SLAPD_OVER_AUTOCA SLAPD_MOD_DYNAMIC - #ifdef SLAPD_OVER_AUTOCA #include @@ -34,8 +32,21 @@ #include "slap.h" #include "config.h" +#include #include #include +#include + +/* Starting with OpenSSL 1.1.0, rsa.h is no longer included in + * x509.h, so we need to explicitly include it for the + * call to EVP_PKEY_CTX_set_rsa_keygen_bits + */ + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 +#include +#define X509_get_notBefore(x) X509_getm_notBefore(x) +#define X509_get_notAfter(x) X509_getm_notAfter(x) +#endif /* This overlay implements a certificate authority that can generate * certificates automatically for any entry in the directory. @@ -260,17 +271,16 @@ static int autoca_gencert( Operation *op, genargs *args ) X509_NAME *subj_name, *issuer_name; X509 *subj_cert; struct berval derdn; - const unsigned char *p; + unsigned char *pp; EVP_PKEY *evpk = NULL; int rc; - unsigned char *pp; if ((subj_cert = X509_new()) == NULL) return -1; autoca_dnbv2der( op, args->subjectDN, &derdn ); - p = (const unsigned char *)derdn.bv_val; - subj_name = d2i_X509_NAME( NULL, &p, derdn.bv_len ); + pp = (unsigned char *)derdn.bv_val; + subj_name = d2i_X509_NAME( NULL, (const unsigned char **)&pp, derdn.bv_len ); op->o_tmpfree( derdn.bv_val, op->o_tmpmemctx ); if ( subj_name == NULL ) { @@ -286,10 +296,17 @@ fail2: if ( subj_name ) X509_NAME_free( subj_name ); goto fail1; } - args->derpkey.bv_len = i2d_PrivateKey( evpk, NULL ); - args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx ); - pp = args->derpkey.bv_val; - i2d_PrivateKey( evpk, &pp ); + /* encode DER in PKCS#8 */ + { + PKCS8_PRIV_KEY_INFO *p8inf; + if (( p8inf = EVP_PKEY2PKCS8( evpk )) == NULL ) + goto fail2; + args->derpkey.bv_len = i2d_PKCS8_PRIV_KEY_INFO( p8inf, NULL ); + args->derpkey.bv_val = op->o_tmpalloc( args->derpkey.bv_len, op->o_tmpmemctx ); + pp = (unsigned char *)args->derpkey.bv_val; + i2d_PKCS8_PRIV_KEY_INFO( p8inf, &pp ); + PKCS8_PRIV_KEY_INFO_free( p8inf ); + } args->newpkey = evpk; /* set random serial */ @@ -365,7 +382,7 @@ fail3: goto fail3; args->dercert.bv_len = i2d_X509( subj_cert, NULL ); args->dercert.bv_val = op->o_tmpalloc( args->dercert.bv_len, op->o_tmpmemctx ); - pp = args->dercert.bv_val; + pp = (unsigned char *)args->dercert.bv_val; i2d_X509( subj_cert, &pp ); args->newcert = subj_cert; return 0; @@ -440,24 +457,29 @@ static int autoca_savecert( Operation *op, saveargs *args ) static const struct berval configDN = BER_BVC("cn=config"); -static int -autoca_setca( Operation *op, struct berval *cacert ) +/* must run as a pool thread to avoid cn=config deadlock */ +static void * +autoca_setca_task( void *ctx, void *arg ) { - Operation op2; + Connection conn = { 0 }; + OperationBuffer opbuf; + Operation *op; + struct berval *cacert = arg; Modifications mod; struct berval bvs[2]; - BackendInfo *bi; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; const char *text; - op2 = *op; + connection_fake_init( &conn, &opbuf, ctx ); + op = &opbuf.ob_op; + mod.sml_numvals = 1; mod.sml_values = bvs; mod.sml_nvalues = NULL; mod.sml_desc = NULL; if ( slap_str2ad( "olcTLSCACertificate;binary", &mod.sml_desc, &text )) - return -1; + goto leave; mod.sml_op = LDAP_MOD_REPLACE; mod.sml_flags = SLAP_MOD_INTERNAL; bvs[0] = *cacert; @@ -465,20 +487,32 @@ autoca_setca( Operation *op, struct berval *cacert ) mod.sml_next = NULL; cb.sc_response = slap_null_cb; - op2.o_bd = select_backend( (struct berval *)&configDN, 0 ); - if ( !op2.o_bd ) - return -1; + op->o_bd = select_backend( (struct berval *)&configDN, 0 ); + if ( !op->o_bd ) + goto leave; - op2.o_tag = LDAP_REQ_MODIFY; - op2.o_callback = &cb; - op2.orm_modlist = &mod; - op2.orm_no_opattrs = 1; - op2.o_req_dn = configDN; - op2.o_req_ndn = configDN; - op2.o_dn = op2.o_bd->be_rootdn; - op2.o_ndn = op2.o_bd->be_rootndn; - op2.o_bd->be_modify( &op2, &rs ); - return rs.sr_err; + op->o_tag = LDAP_REQ_MODIFY; + op->o_callback = &cb; + op->orm_modlist = &mod; + op->orm_no_opattrs = 1; + op->o_req_dn = configDN; + op->o_req_ndn = configDN; + op->o_dn = op->o_bd->be_rootdn; + op->o_ndn = op->o_bd->be_rootndn; + op->o_bd->be_modify( op, &rs ); +leave: + ch_free( arg ); + return NULL; +} + +static int +autoca_setca( struct berval *cacert ) +{ + struct berval *bv = ch_malloc( sizeof(struct berval) + cacert->bv_len ); + bv->bv_len = cacert->bv_len; + bv->bv_val = (char *)(bv+1); + AC_MEMCPY( bv->bv_val, cacert->bv_val, bv->bv_len ); + return ldap_pvt_thread_pool_submit( &connection_pool, autoca_setca_task, bv ); } static int @@ -486,11 +520,9 @@ autoca_setlocal( Operation *op, struct berval *cert, struct berval *pkey ) { Modifications mod[2]; struct berval bvs[4]; - BackendInfo *bi; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; const char *text; - static const struct berval config = BER_BVC("cn=config"); mod[0].sml_numvals = 1; mod[0].sml_values = bvs; @@ -827,6 +859,12 @@ autoca_op_response( arg2.oc = NULL; else arg2.oc = oc_usrObj; + if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) + { + Entry *e = entry_dup( rs->sr_entry ); + rs_replace_entry( op, rs, on, e ); + rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; + } arg2.dercert = &args.dercert; arg2.derpkey = &args.derpkey; arg2.on = on; @@ -840,12 +878,6 @@ autoca_op_response( /* If this is our cert DN, configure it */ if ( dn_match( &rs->sr_entry->e_nname, &ai->ai_localndn )) autoca_setlocal( &op2, &args.dercert, &args.derpkey ); - if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) - { - Entry *e = entry_dup( rs->sr_entry ); - rs_replace_entry( op, rs, on, e ); - rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; - } attr_merge_one( rs->sr_entry, ad_usrCert, &args.dercert, NULL ); attr_merge_one( rs->sr_entry, ad_usrPkey, &args.derpkey, NULL ); } @@ -863,7 +895,7 @@ autoca_op_search( ) { /* we only act on a search that returns just our cert/key attrs */ - if ( op->ors_attrs[0].an_desc == ad_usrCert && + if ( op->ors_attrs && op->ors_attrs[0].an_desc == ad_usrCert && op->ors_attrs[1].an_desc == ad_usrPkey && op->ors_attrs[2].an_name.bv_val == NULL ) { @@ -939,6 +971,24 @@ autoca_db_open( if (slapMode & SLAP_TOOL_MODE) return 0; + if ( ! *aca_attr2[0].ad ) { + int i, code; + const char *text; + + for ( i=0; aca_attr2[i].at; i++ ) { + code = slap_str2ad( aca_attr2[i].at, aca_attr2[i].ad, &text ); + if ( code ) return code; + } + + /* Schema may not be loaded, ignore if missing */ + slap_str2ad( "ipHostNumber", &ad_ipaddr, &text ); + + for ( i=0; aca_ocs[i].ot; i++ ) { + code = register_oc( aca_ocs[i].ot, aca_ocs[i].oc, 0 ); + if ( code ) return code; + } + } + thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn, &opbuf, thrctx, 0 ); op = &opbuf.ob_op; @@ -955,18 +1005,18 @@ autoca_db_open( a = attr_find( e->e_attrs, ad_caPkey ); if ( a ) { const unsigned char *pp; - pp = a->a_vals[0].bv_val; + pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_pkey = d2i_AutoPrivateKey( NULL, &pp, a->a_vals[0].bv_len ); if ( ai->ai_pkey ) { a = attr_find( e->e_attrs, ad_caCert ); if ( a ) { - pp = a->a_vals[0].bv_val; + pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_cert = d2i_X509( NULL, &pp, a->a_vals[0].bv_len ); /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) - autoca_setca( op, a->a_vals ); + autoca_setca( a->a_vals ); } } gotat = 1; @@ -1008,7 +1058,7 @@ autoca_db_open( /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) - autoca_setca( op, &args.dercert ); + autoca_setca( &args.dercert ); op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx ); op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx ); @@ -1027,7 +1077,6 @@ static slap_overinst autoca; int autoca_initialize() { int i, code; - const char *text; autoca.on_bi.bi_type = "autoca"; autoca.on_bi.bi_db_init = autoca_db_init; @@ -1044,19 +1093,6 @@ int autoca_initialize() { if ( code ) return code; } - for ( i=0; aca_attr2[i].at; i++ ) { - code = slap_str2ad( aca_attr2[i].at, aca_attr2[i].ad, &text ); - if ( code ) return code; - } - - /* Schema may not be loaded, ignore if missing */ - slap_str2ad( "ipHostNumber", &ad_ipaddr, &text ); - - for ( i=0; aca_ocs[i].ot; i++ ) { - code = register_oc( aca_ocs[i].ot, aca_ocs[i].oc, 0 ); - if ( code ) return code; - } - return overlay_register( &autoca ); }