@@ -1292,55 +1292,95 @@ static int md_add_fallback_cert_files(server_rec *s, apr_pool_t *p,
12921292 return DECLINED ;
12931293}
12941294
1295- static int md_answer_challenge (conn_rec * c , const char * servername ,
1296- const char * * pcert_pem , const char * * pkey_pem )
1295+ static int md_get_challenge_cert (conn_rec * c , const char * servername ,
1296+ md_srv_conf_t * sc ,
1297+ md_pkey_type_t key_type ,
1298+ const char * * pcert_pem ,
1299+ const char * * pkey_pem )
12971300{
1298- const char * protocol ;
1299- int hook_rv = DECLINED ;
13001301 apr_status_t rv = APR_ENOENT ;
1301- md_srv_conf_t * sc ;
1302- md_store_t * store ;
1302+ int i ;
13031303 char * cert_name , * pkey_name ;
13041304 const char * cert_pem , * key_pem ;
1305- int i ;
1305+ md_store_t * store = md_reg_store_get (sc -> mc -> reg );
1306+ md_pkey_spec_t * key_spec ;
13061307
1307- if (!servername
1308- || !(protocol = md_protocol_get (c ))
1309- || strcmp (PROTO_ACME_TLS_1 , protocol )) {
1310- goto cleanup ;
1311- }
1312- sc = md_config_get (c -> base_server );
1313- if (!sc || !sc -> mc -> reg ) goto cleanup ;
1314-
1315- ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , 0 , c ,
1316- "Answer challenge[tls-alpn-01] for %s" , servername );
1317- store = md_reg_store_get (sc -> mc -> reg );
1308+ for (i = 0 ; i < md_pkeys_spec_count (sc -> pks ); i ++ ) {
1309+ key_spec = md_pkeys_spec_get (sc -> pks , i );
1310+ if (key_spec -> type != key_type )
1311+ continue ;
13181312
1319- for (i = 0 ; i < md_pkeys_spec_count ( sc -> pks ); i ++ ) {
1320- tls_alpn01_fnames (c -> pool , md_pkeys_spec_get (sc -> pks ,i ),
1321- & pkey_name , & cert_name );
1313+ tls_alpn01_fnames (c -> pool , key_spec , & pkey_name , & cert_name );
13221314
13231315 rv = md_store_load (store , MD_SG_CHALLENGES , servername , cert_name , MD_SV_TEXT ,
13241316 (void * * )& cert_pem , c -> pool );
1317+ ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , rv , c ,
1318+ "Load challenge: cert %s" , cert_name );
13251319 if (APR_STATUS_IS_ENOENT (rv )) continue ;
13261320 if (APR_SUCCESS != rv ) goto cleanup ;
13271321
13281322 rv = md_store_load (store , MD_SG_CHALLENGES , servername , pkey_name , MD_SV_TEXT ,
13291323 (void * * )& key_pem , c -> pool );
1324+ ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , rv , c ,
1325+ "Load challenge: key %s" , pkey_name );
13301326 if (APR_STATUS_IS_ENOENT (rv )) continue ;
13311327 if (APR_SUCCESS != rv ) goto cleanup ;
13321328
13331329 ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , 0 , c ,
1334- "Found challenge cert %s, key %s for %s" ,
1330+ "Found challenge: cert %s, key %s for %s" ,
13351331 cert_name , pkey_name , servername );
13361332 * pcert_pem = cert_pem ;
13371333 * pkey_pem = key_pem ;
1338- hook_rv = OK ;
1339- break ;
1334+ return OK ;
1335+ }
1336+ cleanup :
1337+ return DECLINED ;
1338+ }
1339+
1340+ static int md_answer_challenge (conn_rec * c , const char * servername ,
1341+ const char * * pcert_pem , const char * * pkey_pem )
1342+ {
1343+ const char * protocol ;
1344+ int hook_rv = DECLINED ;
1345+ md_srv_conf_t * sc ;
1346+
1347+ * pcert_pem = * pkey_pem = NULL ;
1348+
1349+ if (!servername
1350+ || !(protocol = md_protocol_get (c ))
1351+ || strcmp (PROTO_ACME_TLS_1 , protocol )) {
1352+ goto cleanup ;
13401353 }
1354+ sc = md_config_get (c -> base_server );
1355+ if (!sc || !sc -> mc -> reg ) goto cleanup ;
1356+
1357+ ap_log_cerror (APLOG_MARK , APLOG_TRACE1 , 0 , c ,
1358+ "Answer challenge[tls-alpn-01] for %s" , servername );
1359+
1360+ /* A challenge for TLS-ALPN-01 used to have a single certificate,
1361+ * overriding the single fallback certificate already installed in
1362+ * the connections SSL* instance.
1363+ * Since the addition of `MDPrivateKeys`, there can be more than one,
1364+ * but the server API for a challenge cert can return only one. This
1365+ * is a short coming of the API.
1366+ * This means we cannot override all fallback certificates present, just
1367+ * a single one. If there is an RSA cert in fallback, we need to override
1368+ * that, because the ACME server has a preference for that (at least LE
1369+ * has). So we look for an RSA challenge cert first.
1370+ * The fallback is an EC cert and that works since without RSA challenges,
1371+ * there should also be no RSA fallbacks.
1372+ * Bit of a mess. */
1373+ hook_rv = md_get_challenge_cert (c , servername , sc , MD_PKEY_TYPE_DEFAULT ,
1374+ pcert_pem , pkey_pem );
1375+ if (hook_rv == DECLINED )
1376+ hook_rv = md_get_challenge_cert (c , servername , sc , MD_PKEY_TYPE_RSA ,
1377+ pcert_pem , pkey_pem );
1378+ if (hook_rv == DECLINED )
1379+ hook_rv = md_get_challenge_cert (c , servername , sc , MD_PKEY_TYPE_EC ,
1380+ pcert_pem , pkey_pem );
13411381
13421382 if (DECLINED == hook_rv ) {
1343- ap_log_cerror (APLOG_MARK , APLOG_INFO , rv , c , APLOGNO (10080 )
1383+ ap_log_cerror (APLOG_MARK , APLOG_INFO , 0 , c , APLOGNO (10080 )
13441384 "%s: unknown tls-alpn-01 challenge host" , servername );
13451385 }
13461386
0 commit comments