@@ -256,7 +256,7 @@ static apr_status_t get_cert(void *baton, int attempt)
256256 (void )attempt ;
257257 md_log_perror (MD_LOG_MARK , MD_LOG_TRACE1 , 0 , d -> p , "retrieving cert from %s" ,
258258 ad -> order -> certificate );
259- return md_acme_GET (ad -> acme , ad -> order -> certificate , NULL , NULL , on_add_cert , NULL , d );
259+ return md_acme_GET (ad -> acme , ad -> order -> certificate , NULL , NULL , on_add_cert , NULL , 1 , d );
260260}
261261
262262apr_status_t md_acme_drive_cert_poll (md_proto_driver_t * d , int only_once )
@@ -429,7 +429,7 @@ static apr_status_t get_chain(void *baton, int attempt)
429429
430430 md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
431431 "next chain cert at %s" , ad -> chain_up_link );
432- rv = md_acme_GET (ad -> acme , ad -> chain_up_link , NULL , NULL , on_add_chain , NULL , d );
432+ rv = md_acme_GET (ad -> acme , ad -> chain_up_link , NULL , NULL , on_add_chain , NULL , 1 , d );
433433
434434 if (APR_SUCCESS == rv && nelts == ad -> cred -> chain -> nelts ) {
435435 break ;
@@ -1094,10 +1094,155 @@ static apr_status_t acme_complete_md(md_t *md, apr_pool_t *p)
10941094 return APR_SUCCESS ;
10951095}
10961096
1097+ static apr_status_t acme_get_ari (md_proto_driver_t * d ,
1098+ struct md_result_t * result ,
1099+ apr_time_t * prenew_at ,
1100+ const char * * purl )
1101+ {
1102+ md_acme_driver_t * ad = d -> baton ;
1103+ apr_status_t rv = APR_SUCCESS ;
1104+ const char * ca_effective = NULL ;
1105+ apr_array_header_t * certs ;
1106+ const md_cert_t * cert ;
1107+ int i ;
1108+
1109+ * prenew_at = 0 ;
1110+ * purl = NULL ;
1111+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1112+ "get ARI status for %s" , d -> md -> name );
1113+
1114+ if (d -> md -> cert_files && d -> md -> cert_files -> nelts ) {
1115+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1116+ "%s is configured with static files, no ARI" , d -> md -> name );
1117+ goto out ;
1118+ }
1119+
1120+ if (!d -> md -> ca_urls || d -> md -> ca_urls -> nelts <= 0 ) {
1121+ /* No CA defined? This is checked in several other places, but lets be sure */
1122+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1123+ "%s is missing MDCertificateAuthority" , d -> md -> name );
1124+ goto out ;
1125+ }
1126+
1127+ /* always pick the first CA for this */
1128+ ca_effective = APR_ARRAY_IDX (d -> md -> ca_urls , 0 , const char * );
1129+
1130+ certs = apr_array_make (d -> p , 5 , sizeof (md_cert_t * ));
1131+ for (i = 0 ; i < md_pkeys_spec_count (d -> md -> pks ); ++ i ) {
1132+ const md_pubcert_t * pubcert ;
1133+ if (APR_SUCCESS == md_reg_get_pubcert (& pubcert , d -> reg , d -> md , i , d -> p )) {
1134+ cert = APR_ARRAY_IDX (pubcert -> certs , 0 , const md_cert_t * );
1135+ APR_ARRAY_PUSH (certs , const md_cert_t * ) = cert ;
1136+ }
1137+ }
1138+
1139+ if (!certs -> nelts ) {
1140+ rv = APR_SUCCESS ;
1141+ goto out ;
1142+ }
1143+
1144+ if (APR_SUCCESS != (rv = md_acme_create (& ad -> acme , d -> p , ca_effective ,
1145+ d -> proxy_url , d -> ca_file ))) {
1146+ md_log_perror (MD_LOG_MARK , MD_LOG_ERR , rv , d -> p ,
1147+ "create ACME communications" );
1148+ goto out ;
1149+ }
1150+ if (APR_SUCCESS != (rv = md_acme_setup (ad -> acme , result ))) {
1151+ md_log_perror (MD_LOG_MARK , MD_LOG_ERR , rv , d -> p ,
1152+ "setup ACME communications" );
1153+ goto out ;
1154+ }
1155+ if (ad -> acme -> version != MD_ACME_VERSION_2 || !ad -> acme -> api .v2 .renewal_info ) {
1156+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1157+ "ARI not supported by ACME CA %s" , ca_effective );
1158+ goto out ;
1159+ }
1160+
1161+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1162+ "assessing ARI status for %d certificates" , certs -> nelts );
1163+ for (i = 0 ; i < certs -> nelts ; ++ i ) {
1164+ const char * ari_cert_id ;
1165+ const char * ari_url = NULL , * ari_expl_url ;
1166+ const char * renew_start , * renew_end ;
1167+ apr_time_t start , end ;
1168+ md_json_t * json ;
1169+ unsigned char c ;
1170+
1171+ cert = APR_ARRAY_IDX (certs , i , md_cert_t * );
1172+ if (md_cert_get_ari_cert_id (& ari_cert_id , cert , d -> p ) != APR_SUCCESS )
1173+ continue ;
1174+
1175+ ari_url = apr_psprintf (d -> p , "%s/%s" , ad -> acme -> api .v2 .renewal_info ,
1176+ ari_cert_id );
1177+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1178+ "GET #%d ARI from %s" , i , ari_url );
1179+ if ((rv = md_acme_get_json (& json , ad -> acme , ari_url , 0 , d -> p )) != APR_SUCCESS ) {
1180+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1181+ "error retrieving ARI from %s" , ari_url );
1182+ continue ;
1183+ }
1184+
1185+ if (!json ) {
1186+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1187+ "ARI returned no JSON from %s" , ari_url );
1188+ continue ;
1189+ }
1190+
1191+ renew_start = md_json_gets (json , "suggestedWindow" , "start" , NULL );
1192+ renew_end = md_json_gets (json , "suggestedWindow" , "end" , NULL );
1193+ ari_expl_url = md_json_gets (json , "explanationURL" , NULL );
1194+ if (!renew_start || !renew_end ) {
1195+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1196+ "renewal info from CA incomplete for %s" , ari_url );
1197+ continue ;
1198+ }
1199+ start = md_time_parse_rfc3339 (renew_start );
1200+ end = md_time_parse_rfc3339 (renew_end );
1201+ if (!start ) {
1202+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1203+ "error parsing CA renew start time: '%s'" ,
1204+ renew_start );
1205+ continue ;
1206+ }
1207+ if (!end ) {
1208+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1209+ "error parsing CA renew end time: '%s'" ,
1210+ renew_end );
1211+ continue ;
1212+ }
1213+ if (start > end ) {
1214+ md_log_perror (MD_LOG_MARK , MD_LOG_WARNING , rv , d -> p ,
1215+ "CA advises weird renewal between '%s' and '%s'" ,
1216+ renew_start , renew_end );
1217+ continue ;
1218+ }
1219+ md_log_perror (MD_LOG_MARK , MD_LOG_DEBUG , rv , d -> p ,
1220+ "CA advises renew via ARI between %s and %s"
1221+ " (explantion: %s)" ,
1222+ renew_start , renew_end ,
1223+ ari_expl_url ? ari_expl_url : "none given" );
1224+ /* select a random value between start and end */
1225+ md_rand_bytes (& c , sizeof (c ), d -> p );
1226+ start += apr_time_from_sec ((apr_time_sec (end - start ) * (c - 128 )) / 256 );
1227+ if (!* prenew_at || (start < * prenew_at )) {
1228+ * prenew_at = start ;
1229+ * purl = apr_pstrdup (d -> p , ari_expl_url );
1230+ }
1231+ }
1232+
1233+ rv = APR_SUCCESS ;
1234+ out :
1235+ return rv ;
1236+ }
1237+
10971238static md_proto_t ACME_PROTO = {
1098- MD_PROTO_ACME , acme_driver_init , acme_driver_renew ,
1099- acme_driver_preload_init , acme_driver_preload ,
1239+ MD_PROTO_ACME ,
1240+ acme_driver_init ,
1241+ acme_driver_renew ,
1242+ acme_driver_preload_init ,
1243+ acme_driver_preload ,
11001244 acme_complete_md ,
1245+ acme_get_ari ,
11011246};
11021247
11031248apr_status_t md_acme_protos_add (apr_hash_t * protos , apr_pool_t * p )
0 commit comments