Apache HTTPD
md_acmev2_drive.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <stdlib.h>
19
20#include <apr_lib.h>
21#include <apr_strings.h>
22#include <apr_buckets.h>
23#include <apr_hash.h>
24#include <apr_uri.h>
25
26#include "md.h"
27#include "md_crypt.h"
28#include "md_json.h"
29#include "md_jws.h"
30#include "md_http.h"
31#include "md_log.h"
32#include "md_result.h"
33#include "md_reg.h"
34#include "md_store.h"
35#include "md_util.h"
36
37#include "md_acme.h"
38#include "md_acme_acct.h"
39#include "md_acme_authz.h"
40#include "md_acme_order.h"
41
42#include "md_acme_drive.h"
43#include "md_acmev2_drive.h"
44
45
46
47/**************************************************************************************************/
48/* order setup */
49
55{
56 md_acme_driver_t *ad = d->baton;
57 apr_status_t rv;
58 md_t *md = ad->md;
59
60 assert(ad->md);
61 assert(ad->acme);
62
63 /* For each domain in MD: AUTHZ setup
64 * if an AUTHZ resource is known, check if it is still valid
65 * if known AUTHZ resource is not valid, remove, goto 4.1.1
66 * if no AUTHZ available, create a new one for the domain, store it
67 */
68 if (pis_new) *pis_new = 0;
69 rv = md_acme_order_load(d->store, MD_SG_STAGING, md->name, &ad->order, d->p);
70 if (APR_SUCCESS == rv) {
71 md_result_activity_setn(result, "Loaded order from staging");
72 goto leave;
73 }
74 else if (!APR_STATUS_IS_ENOENT(rv)) {
75 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, d->p, "%s: loading order", md->name);
76 md_acme_order_purge(d->store, d->p, MD_SG_STAGING, md, d->env);
77 }
78
79 md_result_activity_setn(result, "Creating new order");
80 rv = md_acme_order_register(&ad->order, ad->acme, d->p, d->md->name, ad->domains);
81 if (APR_SUCCESS !=rv) goto leave;
82 rv = md_acme_order_save(d->store, d->p, MD_SG_STAGING, d->md->name, ad->order, 0);
83 if (APR_SUCCESS != rv) {
84 md_result_set(result, rv, "saving order in staging");
85 }
86 if (pis_new) *pis_new = 1;
87
88leave:
90 return rv;
91}
92
93/**************************************************************************************************/
94/* ACMEv2 renewal */
95
97{
99 int is_new_order = 0;
100
101 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, d->p, "%s: (ACMEv2) need certificate", d->md->name);
102
103 /* Chose (or create) and ACME account to use */
105 if (APR_SUCCESS != rv) goto leave;
106
107 if (!md_array_is_empty(ad->cred->chain)) goto leave;
108
109 /* ACMEv2 strategy:
110 * 1. load an md_acme_order_t from STAGING, if present
111 * 2. if no order found, register a new order at ACME server
112 * 3. update the order from the server
113 * 4. Switch order state:
114 * * PENDING: process authz challenges
115 * * READY: finalize the order
116 * * PROCESSING: wait and re-assses later
117 * * VALID: retrieve certificate
118 * * COMPLETE: all done, return success
119 * * INVALID and otherwise: fail renewal, delete local order
120 */
121 if (APR_SUCCESS != (rv = ad_setup_order(d, result, &is_new_order))) {
122 goto leave;
123 }
124
125 rv = md_acme_order_update(ad->order, ad->acme, result, d->p);
128 || MD_ACME_ORDER_ST_INVALID == ad->order->status) {
129 /* order is invalid or no longer known at the ACME server */
130 ad->order = NULL;
131 md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
132 }
133 else if (APR_SUCCESS != rv) {
134 goto leave;
135 }
136
137retry:
138 if (!ad->order) {
140 if (APR_SUCCESS != rv) goto leave;
141 }
142
143 rv = md_acme_order_start_challenges(ad->order, ad->acme, ad->ca_challenges,
144 d->store, d->md, d->env, result, d->p);
146 /* found 'invalid' domains in previous order, need to start over */
147 ad->order = NULL;
148 md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md, d->env);
149 goto retry;
150 }
151 if (APR_SUCCESS != rv) goto leave;
152
153 rv = md_acme_order_monitor_authzs(ad->order, ad->acme, d->md,
154 ad->authz_monitor_timeout, result, d->p);
155 if (APR_SUCCESS != rv) goto leave;
156
157 rv = md_acme_order_await_ready(ad->order, ad->acme, d->md,
158 ad->authz_monitor_timeout, result, d->p);
159 if (APR_SUCCESS != rv) goto leave;
160
161 if (MD_ACME_ORDER_ST_READY == ad->order->status) {
163 if (APR_SUCCESS != rv) goto leave;
164 md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, d->p, "%s: finalized order", d->md->name);
165 }
166
167 rv = md_acme_order_await_valid(ad->order, ad->acme, d->md,
168 ad->authz_monitor_timeout, result, d->p);
169 if (APR_SUCCESS != rv) goto leave;
170
171 if (!ad->order->certificate) {
172 md_result_set(result, APR_EINVAL, "Order valid, but certificate url is missing.");
173 goto leave;
174 }
176
177leave:
179 return result->status;
180}
181
APR-UTIL Buckets/Bucket Brigades.
APR Hash Tables.
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
Definition apr_siphash.h:72
APR Strings library.
APR-UTIL URI Routines.
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_STATUS_IS_EINVAL(s)
Definition apr_errno.h:1266
#define APR_STATUS_IS_EACCES(s)
Definition apr_errno.h:1231
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_array_header_t ** result
void md_acme_report_result(md_acme_t *acme, apr_status_t rv, struct md_result_t *result)
Definition md_acme.c:478
apr_status_t md_acme_drive_setup_cred_chain(md_proto_driver_t *d, md_result_t *result)
apr_status_t md_acme_drive_set_acct(md_proto_driver_t *d, md_result_t *result)
apr_status_t md_acme_order_save(struct md_store_t *store, apr_pool_t *p, md_store_group_t group, const char *md_name, md_acme_order_t *authz_set, int create)
apr_status_t md_acme_order_load(struct md_store_t *store, md_store_group_t group, const char *md_name, md_acme_order_t **pauthz_set, apr_pool_t *p)
apr_status_t md_acme_order_update(md_acme_order_t *order, md_acme_t *acme, md_result_t *result, apr_pool_t *p)
apr_status_t md_acme_order_start_challenges(md_acme_order_t *order, md_acme_t *acme, apr_array_header_t *challenge_types, md_store_t *store, const md_t *md, apr_table_t *env, md_result_t *result, apr_pool_t *p)
apr_status_t md_acme_order_purge(md_store_t *store, apr_pool_t *p, md_store_group_t group, const md_t *md, apr_table_t *env)
apr_status_t md_acme_order_await_ready(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
apr_status_t md_acme_order_monitor_authzs(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
apr_status_t md_acme_order_register(md_acme_order_t **porder, md_acme_t *acme, apr_pool_t *p, const char *name, apr_array_header_t *domains)
apr_status_t md_acme_order_await_valid(md_acme_order_t *order, md_acme_t *acme, const md_t *md, apr_interval_time_t timeout, md_result_t *result, apr_pool_t *p)
@ MD_ACME_ORDER_ST_INVALID
@ MD_ACME_ORDER_ST_READY
apr_status_t md_acmev2_drive_renew(md_acme_driver_t *ad, md_proto_driver_t *d, md_result_t *result)
static apr_status_t ad_setup_order(md_proto_driver_t *d, md_result_t *result, int *pis_new)
void md_log_perror(const char *file, int line, md_log_level_t level, apr_status_t rv, apr_pool_t *p, const char *fmt,...)
Definition md_log.c:68
#define MD_LOG_MARK
Definition md_log.h:39
@ MD_LOG_DEBUG
Definition md_log.h:28
void md_result_activity_setn(md_result_t *result, const char *activity)
Definition md_result.c:74
void md_result_log(md_result_t *result, unsigned int level)
Definition md_result.c:227
void md_result_set(md_result_t *result, apr_status_t status, const char *detail)
Definition md_result.c:91
@ MD_SG_STAGING
Definition md_store.h:67
int md_array_is_empty(const struct apr_array_header_t *array)
Definition md_util.c:235
return NULL
Definition mod_so.c:359
Definition md.h:76
const char * name
Definition md.h:77