|
Packit |
90a5c9 |
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
Packit |
90a5c9 |
* contributor license agreements. See the NOTICE file distributed with
|
|
Packit |
90a5c9 |
* this work for additional information regarding copyright ownership.
|
|
Packit |
90a5c9 |
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
Packit |
90a5c9 |
* (the "License"); you may not use this file except in compliance with
|
|
Packit |
90a5c9 |
* the License. You may obtain a copy of the License at
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
90a5c9 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
90a5c9 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
90a5c9 |
* See the License for the specific language governing permissions and
|
|
Packit |
90a5c9 |
* limitations under the License.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include <assert.h>
|
|
Packit |
90a5c9 |
#include <stddef.h>
|
|
Packit |
90a5c9 |
#include <stdio.h>
|
|
Packit |
90a5c9 |
#include <stdlib.h>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include <apr_lib.h>
|
|
Packit |
90a5c9 |
#include <apr_hash.h>
|
|
Packit |
90a5c9 |
#include <apr_strings.h>
|
|
Packit |
90a5c9 |
#include <apr_uri.h>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "md.h"
|
|
Packit |
90a5c9 |
#include "md_crypt.h"
|
|
Packit |
90a5c9 |
#include "md_log.h"
|
|
Packit |
90a5c9 |
#include "md_json.h"
|
|
Packit |
90a5c9 |
#include "md_reg.h"
|
|
Packit |
90a5c9 |
#include "md_store.h"
|
|
Packit |
90a5c9 |
#include "md_util.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "md_acme.h"
|
|
Packit |
90a5c9 |
#include "md_acme_acct.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct md_reg_t {
|
|
Packit |
90a5c9 |
struct md_store_t *store;
|
|
Packit |
90a5c9 |
struct apr_hash_t *protos;
|
|
Packit |
90a5c9 |
int can_http;
|
|
Packit |
90a5c9 |
int can_https;
|
|
Packit |
90a5c9 |
const char *proxy_url;
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* life cycle */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t load_props(md_reg_t *reg, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_json_t *json;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = md_store_load(reg->store, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON,
|
|
Packit |
90a5c9 |
MD_SV_JSON, (void**)&json, p);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL)) {
|
|
Packit |
90a5c9 |
reg->can_http = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTP, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md_json_has_key(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL)) {
|
|
Packit |
90a5c9 |
reg->can_https = md_json_getb(json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (APR_STATUS_IS_ENOENT(rv)) {
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_init(md_reg_t **preg, apr_pool_t *p, struct md_store_t *store,
|
|
Packit |
90a5c9 |
const char *proxy_url)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
reg = apr_pcalloc(p, sizeof(*reg));
|
|
Packit |
90a5c9 |
reg->store = store;
|
|
Packit |
90a5c9 |
reg->protos = apr_hash_make(p);
|
|
Packit |
90a5c9 |
reg->can_http = 1;
|
|
Packit |
90a5c9 |
reg->can_https = 1;
|
|
Packit |
90a5c9 |
reg->proxy_url = proxy_url? apr_pstrdup(p, proxy_url) : NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (rv = md_acme_protos_add(reg->protos, p))) {
|
|
Packit |
90a5c9 |
rv = load_props(reg, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
*preg = (rv == APR_SUCCESS)? reg : NULL;
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct md_store_t *md_reg_store_get(md_reg_t *reg)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return reg->store;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* checks */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t check_values(md_reg_t *reg, apr_pool_t *p, const md_t *md, int fields)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
const char *err = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (MD_UPD_DOMAINS & fields) {
|
|
Packit |
90a5c9 |
const md_t *other;
|
|
Packit |
90a5c9 |
const char *domain;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!md->domains || md->domains->nelts <= 0) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"empty domain list: %s", md->name);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 0; i < md->domains->nelts; ++i) {
|
|
Packit |
90a5c9 |
domain = APR_ARRAY_IDX(md->domains, i, const char *);
|
|
Packit |
90a5c9 |
if (!md_util_is_dns_name(p, domain, 1)) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"md %s with invalid domain name: %s", md->name, domain);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (NULL != (other = md_reg_find_overlap(reg, md, &domain, p))) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"md %s shares domain '%s' with md %s",
|
|
Packit |
90a5c9 |
md->name, domain, other->name);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (MD_UPD_CONTACTS & fields) {
|
|
Packit |
90a5c9 |
const char *contact;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 0; i < md->contacts->nelts && !err; ++i) {
|
|
Packit |
90a5c9 |
contact = APR_ARRAY_IDX(md->contacts, i, const char *);
|
|
Packit |
90a5c9 |
rv = md_util_abs_uri_check(p, contact, &err;;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (err) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"contact for %s invalid (%s): %s", md->name, err, contact);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((MD_UPD_CA_URL & fields) && md->ca_url) { /* setting to empty is ok */
|
|
Packit |
90a5c9 |
rv = md_util_abs_uri_check(p, md->ca_url, &err;;
|
|
Packit |
90a5c9 |
if (err) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"CA url for %s invalid (%s): %s", md->name, err, md->ca_url);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((MD_UPD_CA_PROTO & fields) && md->ca_proto) { /* setting to empty is ok */
|
|
Packit |
90a5c9 |
/* Do we want to restrict this to "known" protocols? */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((MD_UPD_CA_ACCOUNT & fields) && md->ca_account) { /* setting to empty is ok */
|
|
Packit |
90a5c9 |
/* hmm, in case we know the protocol, some checks could be done */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((MD_UPD_AGREEMENT & fields) && md->ca_agreement) { /* setting to empty is ok */
|
|
Packit |
90a5c9 |
rv = md_util_abs_uri_check(p, md->ca_agreement, &err;;
|
|
Packit |
90a5c9 |
if (err) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, p,
|
|
Packit |
90a5c9 |
"CA url for %s invalid (%s): %s", md->name, err, md->ca_agreement);
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* state assessment */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t state_init(md_reg_t *reg, apr_pool_t *p, md_t *md, int save_changes)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_state_t state = MD_S_UNKNOWN;
|
|
Packit |
90a5c9 |
const md_creds_t *creds;
|
|
Packit |
90a5c9 |
const md_cert_t *cert;
|
|
Packit |
90a5c9 |
apr_time_t expires = 0, valid_from = 0;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (rv = md_reg_creds_get(&creds, reg, MD_SG_DOMAINS, md, p))) {
|
|
Packit |
90a5c9 |
state = MD_S_INCOMPLETE;
|
|
Packit |
90a5c9 |
if (!creds->privkey) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: incomplete, without private key", md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (!creds->cert) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: incomplete, has key but no certificate", md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
valid_from = md_cert_get_not_before(creds->cert);
|
|
Packit |
90a5c9 |
expires = md_cert_get_not_after(creds->cert);
|
|
Packit |
90a5c9 |
if (md_cert_has_expired(creds->cert)) {
|
|
Packit |
90a5c9 |
state = MD_S_EXPIRED;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: expired, certificate has expired", md->name);
|
|
Packit |
90a5c9 |
goto out;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!md_cert_is_valid_now(creds->cert)) {
|
|
Packit |
90a5c9 |
state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: error, certificate valid in future (clock wrong?)",
|
|
Packit |
90a5c9 |
md->name);
|
|
Packit |
90a5c9 |
goto out;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!md_cert_covers_md(creds->cert, md)) {
|
|
Packit |
90a5c9 |
state = MD_S_INCOMPLETE;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: incomplete, cert no longer covers all domains, "
|
|
Packit |
90a5c9 |
"needs sign up for a new certificate", md->name);
|
|
Packit |
90a5c9 |
goto out;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!md->must_staple != !md_cert_must_staple(creds->cert)) {
|
|
Packit |
90a5c9 |
state = MD_S_INCOMPLETE;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_INFO, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: OCSP Stapling is%s requested, but certificate "
|
|
Packit |
90a5c9 |
"has it%s enabled. Need to get a new certificate.", md->name,
|
|
Packit |
90a5c9 |
md->must_staple? "" : " not",
|
|
Packit |
90a5c9 |
!md->must_staple? "" : " not");
|
|
Packit |
90a5c9 |
goto out;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 1; i < creds->pubcert->nelts; ++i) {
|
|
Packit |
90a5c9 |
cert = APR_ARRAY_IDX(creds->pubcert, i, const md_cert_t *);
|
|
Packit |
90a5c9 |
if (!md_cert_is_valid_now(cert)) {
|
|
Packit |
90a5c9 |
state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p,
|
|
Packit |
90a5c9 |
"md{%s}: error, the certificate itself is valid, however the %d. "
|
|
Packit |
90a5c9 |
"certificate in the chain is not valid now (clock wrong?).",
|
|
Packit |
90a5c9 |
md->name, i);
|
|
Packit |
90a5c9 |
goto out;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
state = MD_S_COMPLETE;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "md{%s}: is complete", md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
out:
|
|
Packit |
90a5c9 |
if (APR_SUCCESS != rv) {
|
|
Packit |
90a5c9 |
state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p, "md{%s}: error", md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (save_changes && md->state == state
|
|
Packit |
90a5c9 |
&& md->valid_from == valid_from && md->expires == expires) {
|
|
Packit |
90a5c9 |
save_changes = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md->state = state;
|
|
Packit |
90a5c9 |
md->valid_from = valid_from;
|
|
Packit |
90a5c9 |
md->expires = expires;
|
|
Packit |
90a5c9 |
if (save_changes && APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
return md_save(reg->store, p, MD_SG_DOMAINS, md, 0);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_assess(md_reg_t *reg, md_t *md, int *perrored, int *prenew, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int renew = 0;
|
|
Packit |
90a5c9 |
int errored = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)reg;
|
|
Packit |
90a5c9 |
switch (md->state) {
|
|
Packit |
90a5c9 |
case MD_S_UNKNOWN:
|
|
Packit |
90a5c9 |
md_log_perror( MD_LOG_MARK, MD_LOG_ERR, 0, p, "md(%s): in unknown state.", md->name);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_S_ERROR:
|
|
Packit |
90a5c9 |
md_log_perror( MD_LOG_MARK, MD_LOG_ERR, 0, p,
|
|
Packit |
90a5c9 |
"md(%s): in error state, unable to drive forward. If unable to "
|
|
Packit |
90a5c9 |
" detect the cause, you may remove the staging or even domain "
|
|
Packit |
90a5c9 |
" sub-directory for this MD and start all over.", md->name);
|
|
Packit |
90a5c9 |
errored = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_S_COMPLETE:
|
|
Packit |
90a5c9 |
if (!md->expires) {
|
|
Packit |
90a5c9 |
md_log_perror( MD_LOG_MARK, MD_LOG_WARNING, 0, p,
|
|
Packit |
90a5c9 |
"md(%s): looks complete, but has unknown expiration date.", md->name);
|
|
Packit |
90a5c9 |
errored = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (md->expires <= apr_time_now()) {
|
|
Packit |
90a5c9 |
/* Maybe we hibernated in the meantime? */
|
|
Packit |
90a5c9 |
md->state = MD_S_EXPIRED;
|
|
Packit |
90a5c9 |
renew = 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
renew = md_should_renew(md);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_S_INCOMPLETE:
|
|
Packit |
90a5c9 |
case MD_S_EXPIRED:
|
|
Packit |
90a5c9 |
renew = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_S_MISSING:
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
*prenew = renew;
|
|
Packit |
90a5c9 |
*perrored = errored;
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* iteration */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
md_reg_t *reg;
|
|
Packit |
90a5c9 |
md_reg_do_cb *cb;
|
|
Packit |
90a5c9 |
void *baton;
|
|
Packit |
90a5c9 |
const char *exclude;
|
|
Packit |
90a5c9 |
const void *result;
|
|
Packit |
90a5c9 |
} reg_do_ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int reg_md_iter(void *baton, md_store_t *store, md_t *md, apr_pool_t *ptemp)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
reg_do_ctx *ctx = baton;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)store;
|
|
Packit |
90a5c9 |
if (!ctx->exclude || strcmp(ctx->exclude, md->name)) {
|
|
Packit |
90a5c9 |
state_init(ctx->reg, ptemp, (md_t*)md, 1);
|
|
Packit |
90a5c9 |
return ctx->cb(ctx->baton, ctx->reg, md);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int reg_do(md_reg_do_cb *cb, void *baton, md_reg_t *reg, apr_pool_t *p, const char *exclude)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
reg_do_ctx ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ctx.reg = reg;
|
|
Packit |
90a5c9 |
ctx.cb = cb;
|
|
Packit |
90a5c9 |
ctx.baton = baton;
|
|
Packit |
90a5c9 |
ctx.exclude = exclude;
|
|
Packit |
90a5c9 |
return md_store_md_iter(reg_md_iter, &ctx, reg->store, p, MD_SG_DOMAINS, "*");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_reg_do(md_reg_do_cb *cb, void *baton, md_reg_t *reg, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return reg_do(cb, baton, reg, p, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* lookup */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_reg_get(md_reg_t *reg, const char *name, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == md_load(reg->store, MD_SG_DOMAINS, name, &md, p)) {
|
|
Packit |
90a5c9 |
state_init(reg, p, md, 1);
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
const char *domain;
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
} find_domain_ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int find_domain(void *baton, md_reg_t *reg, md_t *md)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
find_domain_ctx *ctx = baton;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)reg;
|
|
Packit |
90a5c9 |
if (md_contains(md, ctx->domain, 0)) {
|
|
Packit |
90a5c9 |
ctx->md = md;
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_reg_find(md_reg_t *reg, const char *domain, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
find_domain_ctx ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ctx.domain = domain;
|
|
Packit |
90a5c9 |
ctx.md = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_reg_do(find_domain, &ctx, reg, p);
|
|
Packit |
90a5c9 |
if (ctx.md) {
|
|
Packit |
90a5c9 |
state_init(reg, p, ctx.md, 1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return ctx.md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
const md_t *md_checked;
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
const char *s;
|
|
Packit |
90a5c9 |
} find_overlap_ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int find_overlap(void *baton, md_reg_t *reg, md_t *md)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
find_overlap_ctx *ctx = baton;
|
|
Packit |
90a5c9 |
const char *overlap;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)reg;
|
|
Packit |
90a5c9 |
if ((overlap = md_common_name(ctx->md_checked, md))) {
|
|
Packit |
90a5c9 |
ctx->md = md;
|
|
Packit |
90a5c9 |
ctx->s = overlap;
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_reg_find_overlap(md_reg_t *reg, const md_t *md, const char **pdomain, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
find_overlap_ctx ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ctx.md_checked = md;
|
|
Packit |
90a5c9 |
ctx.md = NULL;
|
|
Packit |
90a5c9 |
ctx.s = NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
reg_do(find_overlap, &ctx, reg, p, md->name);
|
|
Packit |
90a5c9 |
if (pdomain && ctx.s) {
|
|
Packit |
90a5c9 |
*pdomain = ctx.s;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (ctx.md) {
|
|
Packit |
90a5c9 |
state_init(reg, p, ctx.md, 1);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return ctx.md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_get_cred_files(md_reg_t *reg, const md_t *md, apr_pool_t *p,
|
|
Packit |
90a5c9 |
const char **pkeyfile, const char **pcertfile)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = md_store_get_fname(pkeyfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_PRIVKEY, p);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
rv = md_store_get_fname(pcertfile, reg->store, MD_SG_DOMAINS, md->name, MD_FN_PUBCERT, p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* manipulation */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t p_md_add(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg = baton;
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
md_t *md, *mine;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md = va_arg(ap, md_t *);
|
|
Packit |
90a5c9 |
mine = md_clone(ptemp, md);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (rv = check_values(reg, ptemp, md, MD_UPD_ALL))
|
|
Packit |
90a5c9 |
&& APR_SUCCESS == (rv = state_init(reg, ptemp, mine, 0))
|
|
Packit |
90a5c9 |
&& APR_SUCCESS == (rv = md_save(reg->store, p, MD_SG_DOMAINS, mine, 1))) {
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_add(md_reg_t *reg, md_t *md, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_util_pool_vdo(p_md_add, reg, p, md, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t p_md_update(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg = baton;
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
const char *name;
|
|
Packit |
90a5c9 |
const md_t *md, *updates;
|
|
Packit |
90a5c9 |
int fields;
|
|
Packit |
90a5c9 |
md_t *nmd;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
name = va_arg(ap, const char *);
|
|
Packit |
90a5c9 |
updates = va_arg(ap, const md_t *);
|
|
Packit |
90a5c9 |
fields = va_arg(ap, int);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (NULL == (md = md_reg_get(reg, name, ptemp))) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, APR_ENOENT, ptemp, "md %s", name);
|
|
Packit |
90a5c9 |
return APR_ENOENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, ptemp, "update md %s", name);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS != (rv = check_values(reg, ptemp, updates, fields))) {
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
nmd = md_copy(ptemp, md);
|
|
Packit |
90a5c9 |
if (MD_UPD_DOMAINS & fields) {
|
|
Packit |
90a5c9 |
nmd->domains = updates->domains;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update domains: %s", name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CA_URL & fields) {
|
|
Packit |
90a5c9 |
nmd->ca_url = updates->ca_url;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update ca url: %s", name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CA_PROTO & fields) {
|
|
Packit |
90a5c9 |
nmd->ca_proto = updates->ca_proto;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update ca protocol: %s", name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CA_ACCOUNT & fields) {
|
|
Packit |
90a5c9 |
nmd->ca_account = updates->ca_account;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update account: %s", name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CONTACTS & fields) {
|
|
Packit |
90a5c9 |
nmd->contacts = updates->contacts;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update contacts: %s", name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_AGREEMENT & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update agreement: %s", name);
|
|
Packit |
90a5c9 |
nmd->ca_agreement = updates->ca_agreement;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CERT_URL & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update cert url: %s", name);
|
|
Packit |
90a5c9 |
nmd->cert_url = updates->cert_url;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_DRIVE_MODE & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update drive-mode: %s", name);
|
|
Packit |
90a5c9 |
nmd->drive_mode = updates->drive_mode;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_RENEW_WINDOW & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update renew-window: %s", name);
|
|
Packit |
90a5c9 |
nmd->renew_norm = updates->renew_norm;
|
|
Packit |
90a5c9 |
nmd->renew_window = updates->renew_window;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_CA_CHALLENGES & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update ca challenges: %s", name);
|
|
Packit |
90a5c9 |
nmd->ca_challenges = (updates->ca_challenges?
|
|
Packit |
90a5c9 |
apr_array_copy(p, updates->ca_challenges) : NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_PKEY_SPEC & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update pkey spec: %s", name);
|
|
Packit |
90a5c9 |
nmd->pkey_spec = NULL;
|
|
Packit |
90a5c9 |
if (updates->pkey_spec) {
|
|
Packit |
90a5c9 |
nmd->pkey_spec = apr_pmemdup(p, updates->pkey_spec, sizeof(md_pkey_spec_t));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_REQUIRE_HTTPS & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update require-https: %s", name);
|
|
Packit |
90a5c9 |
nmd->require_https = updates->require_https;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_TRANSITIVE & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update transitive: %s", name);
|
|
Packit |
90a5c9 |
nmd->transitive = updates->transitive;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_UPD_MUST_STAPLE & fields) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, ptemp, "update must-staple: %s", name);
|
|
Packit |
90a5c9 |
nmd->must_staple = updates->must_staple;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (fields && APR_SUCCESS == (rv = md_save(reg->store, p, MD_SG_DOMAINS, nmd, 0))) {
|
|
Packit |
90a5c9 |
rv = state_init(reg, ptemp, nmd, 0);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_update(md_reg_t *reg, apr_pool_t *p,
|
|
Packit |
90a5c9 |
const char *name, const md_t *md, int fields)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_util_pool_vdo(p_md_update, reg, p, name, md, fields, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* certificate related */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int ok_or_noent(apr_status_t rv)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return (APR_SUCCESS == rv || APR_ENOENT == rv);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t creds_load(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg = baton;
|
|
Packit |
90a5c9 |
md_pkey_t *privkey;
|
|
Packit |
90a5c9 |
apr_array_header_t *pubcert;
|
|
Packit |
90a5c9 |
md_creds_t *creds, **pcreds;
|
|
Packit |
90a5c9 |
const md_t *md;
|
|
Packit |
90a5c9 |
md_cert_state_t cert_state;
|
|
Packit |
90a5c9 |
md_store_group_t group;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
pcreds = va_arg(ap, md_creds_t **);
|
|
Packit |
90a5c9 |
group = (md_store_group_t)va_arg(ap, int);
|
|
Packit |
90a5c9 |
md = va_arg(ap, const md_t *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (ok_or_noent(rv = md_pkey_load(reg->store, group, md->name, &privkey, p))
|
|
Packit |
90a5c9 |
&& ok_or_noent(rv = md_pubcert_load(reg->store, group, md->name, &pubcert, p))) {
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
creds = apr_pcalloc(p, sizeof(*creds));
|
|
Packit |
90a5c9 |
creds->privkey = privkey;
|
|
Packit |
90a5c9 |
if (pubcert && pubcert->nelts > 0) {
|
|
Packit |
90a5c9 |
creds->pubcert = pubcert;
|
|
Packit |
90a5c9 |
creds->cert = APR_ARRAY_IDX(pubcert, 0, md_cert_t *);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (creds->cert) {
|
|
Packit |
90a5c9 |
switch ((cert_state = md_cert_state_get(creds->cert))) {
|
|
Packit |
90a5c9 |
case MD_CERT_VALID:
|
|
Packit |
90a5c9 |
creds->expired = 0;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_CERT_EXPIRED:
|
|
Packit |
90a5c9 |
creds->expired = 1;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
default:
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, APR_EINVAL, ptemp,
|
|
Packit |
90a5c9 |
"md %s has unexpected cert state: %d", md->name, cert_state);
|
|
Packit |
90a5c9 |
rv = APR_ENOTIMPL;
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
*pcreds = (APR_SUCCESS == rv)? creds : NULL;
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_creds_get(const md_creds_t **pcreds, md_reg_t *reg,
|
|
Packit |
90a5c9 |
md_store_group_t group, const md_t *md, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
md_creds_t *creds;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
rv = md_util_pool_vdo(creds_load, reg, p, &creds, group, md, NULL);
|
|
Packit |
90a5c9 |
*pcreds = (APR_SUCCESS == rv)? creds : NULL;
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* synching */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
typedef struct {
|
|
Packit |
90a5c9 |
apr_pool_t *p;
|
|
Packit |
90a5c9 |
apr_array_header_t *store_mds;
|
|
Packit |
90a5c9 |
} sync_ctx;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static int do_add_md(void *baton, md_store_t *store, md_t *md, apr_pool_t *ptemp)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
sync_ctx *ctx = baton;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)store;
|
|
Packit |
90a5c9 |
(void)ptemp;
|
|
Packit |
90a5c9 |
APR_ARRAY_PUSH(ctx->store_mds, const md_t*) = md_clone(ctx->p, md);
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t read_store_mds(md_reg_t *reg, sync_ctx *ctx)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_array_clear(ctx->store_mds);
|
|
Packit |
90a5c9 |
rv = md_store_md_iter(do_add_md, ctx, reg->store, ctx->p, MD_SG_DOMAINS, "*");
|
|
Packit |
90a5c9 |
if (APR_STATUS_IS_ENOENT(rv)) {
|
|
Packit |
90a5c9 |
rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_set_props(md_reg_t *reg, apr_pool_t *p, int can_http, int can_https)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
if (reg->can_http != can_http || reg->can_https != can_https) {
|
|
Packit |
90a5c9 |
md_json_t *json;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
reg->can_http = can_http;
|
|
Packit |
90a5c9 |
reg->can_https = can_https;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
json = md_json_create(p);
|
|
Packit |
90a5c9 |
md_json_setb(can_http, json, MD_KEY_PROTO, MD_KEY_HTTP, NULL);
|
|
Packit |
90a5c9 |
md_json_setb(can_https, json, MD_KEY_PROTO, MD_KEY_HTTPS, NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return md_store_save(reg->store, p, MD_SG_NONE, NULL, MD_FN_HTTPD_JSON, MD_SV_JSON, json, 0);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**
|
|
Packit |
90a5c9 |
* Procedure:
|
|
Packit |
90a5c9 |
* 1. Collect all defined "managed domains" (MD). It does not matter where a MD is defined.
|
|
Packit |
90a5c9 |
* All MDs need to be unique and have no overlaps in their domain names.
|
|
Packit |
90a5c9 |
* Fail the config otherwise. Also, if a vhost matches an MD, it
|
|
Packit |
90a5c9 |
* needs to *only* have ServerAliases from that MD. There can be no more than one
|
|
Packit |
90a5c9 |
* matching MD for a vhost. But an MD can apply to several vhosts.
|
|
Packit |
90a5c9 |
* 2. Synchronize with the persistent store. Iterate over all configured MDs and
|
|
Packit |
90a5c9 |
* a. create them in the store if they do not already exist, neither under the
|
|
Packit |
90a5c9 |
* name or with a common domain.
|
|
Packit |
90a5c9 |
* b. compare domain lists from store and config, if
|
|
Packit |
90a5c9 |
* - store has dns name in other MD than from config, remove dns name from store def,
|
|
Packit |
90a5c9 |
* issue WARNING.
|
|
Packit |
90a5c9 |
* - store misses dns name from config, add dns name and update store
|
|
Packit |
90a5c9 |
* c. compare MD acme url/protocol, update if changed
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
apr_status_t md_reg_sync(md_reg_t *reg, apr_pool_t *p, apr_pool_t *ptemp,
|
|
Packit |
90a5c9 |
apr_array_header_t *master_mds)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
sync_ctx ctx;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ctx.p = ptemp;
|
|
Packit |
90a5c9 |
ctx.store_mds = apr_array_make(ptemp,100, sizeof(md_t *));
|
|
Packit |
90a5c9 |
rv = read_store_mds(reg, &ctx;;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"sync: found %d mds in store", ctx.store_mds->nelts);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
int i, fields;
|
|
Packit |
90a5c9 |
md_t *md, *config_md, *smd, *omd;
|
|
Packit |
90a5c9 |
const char *common;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 0; i < master_mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
md = APR_ARRAY_IDX(master_mds, i, md_t *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* find the store md that is closest match for the configured md */
|
|
Packit |
90a5c9 |
smd = md_find_closest_match(ctx.store_mds, md);
|
|
Packit |
90a5c9 |
if (smd) {
|
|
Packit |
90a5c9 |
fields = 0;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Once stored, we keep the name */
|
|
Packit |
90a5c9 |
if (strcmp(md->name, smd->name)) {
|
|
Packit |
90a5c9 |
md->name = apr_pstrdup(p, smd->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Make the stored domain list *exactly* the same, even if
|
|
Packit |
90a5c9 |
* someone only changed upper/lowercase, we'd like to persist that. */
|
|
Packit |
90a5c9 |
if (!md_equal_domains(md, smd, 1)) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"%s: domains changed", smd->name);
|
|
Packit |
90a5c9 |
smd->domains = md_array_str_clone(ptemp, md->domains);
|
|
Packit |
90a5c9 |
fields |= MD_UPD_DOMAINS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Look for other store mds which have domains now being part of smd */
|
|
Packit |
90a5c9 |
while (APR_SUCCESS == rv && (omd = md_get_by_dns_overlap(ctx.store_mds, md))) {
|
|
Packit |
90a5c9 |
/* find the name now duplicate */
|
|
Packit |
90a5c9 |
common = md_common_name(md, omd);
|
|
Packit |
90a5c9 |
assert(common);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Is this md still configured or has it been abandoned in the config? */
|
|
Packit |
90a5c9 |
config_md = md_get_by_name(master_mds, omd->name);
|
|
Packit |
90a5c9 |
if (config_md && md_contains(config_md, common, 0)) {
|
|
Packit |
90a5c9 |
/* domain used in two configured mds, not allowed */
|
|
Packit |
90a5c9 |
rv = APR_EINVAL;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p,
|
|
Packit |
90a5c9 |
"domain %s used in md %s and %s",
|
|
Packit |
90a5c9 |
common, md->name, omd->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
/* remove it from the other md and update store, or, if it
|
|
Packit |
90a5c9 |
* is now empty, move it into the archive */
|
|
Packit |
90a5c9 |
omd->domains = md_array_str_remove(ptemp, omd->domains, common, 0);
|
|
Packit |
90a5c9 |
if (apr_is_empty_array(omd->domains)) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p,
|
|
Packit |
90a5c9 |
"All domains of the MD %s have moved elsewhere, "
|
|
Packit |
90a5c9 |
" moving it to the archive. ", omd->name);
|
|
Packit |
90a5c9 |
md_reg_remove(reg, ptemp, omd->name, 1); /* best effort */
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
rv = md_reg_update(reg, ptemp, omd->name, omd, MD_UPD_DOMAINS);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (MD_SVAL_UPDATE(md, smd, ca_url)) {
|
|
Packit |
90a5c9 |
smd->ca_url = md->ca_url;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_CA_URL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_SVAL_UPDATE(md, smd, ca_proto)) {
|
|
Packit |
90a5c9 |
smd->ca_proto = md->ca_proto;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_CA_PROTO;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_SVAL_UPDATE(md, smd, ca_agreement)) {
|
|
Packit |
90a5c9 |
smd->ca_agreement = md->ca_agreement;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_AGREEMENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_VAL_UPDATE(md, smd, transitive)) {
|
|
Packit |
90a5c9 |
smd->transitive = md->transitive;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_TRANSITIVE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_VAL_UPDATE(md, smd, drive_mode)) {
|
|
Packit |
90a5c9 |
smd->drive_mode = md->drive_mode;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_DRIVE_MODE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!apr_is_empty_array(md->contacts)
|
|
Packit |
90a5c9 |
&& !md_array_str_eq(md->contacts, smd->contacts, 0)) {
|
|
Packit |
90a5c9 |
smd->contacts = md->contacts;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_CONTACTS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_VAL_UPDATE(md, smd, renew_window)
|
|
Packit |
90a5c9 |
|| MD_VAL_UPDATE(md, smd, renew_norm)) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
|
|
Packit |
90a5c9 |
"%s: update renew norm=%ld, window=%ld",
|
|
Packit |
90a5c9 |
smd->name, (long)md->renew_norm, (long)md->renew_window);
|
|
Packit |
90a5c9 |
smd->renew_norm = md->renew_norm;
|
|
Packit |
90a5c9 |
smd->renew_window = md->renew_window;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_RENEW_WINDOW;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md->ca_challenges) {
|
|
Packit |
90a5c9 |
md->ca_challenges = md_array_str_compact(p, md->ca_challenges, 0);
|
|
Packit |
90a5c9 |
if (!smd->ca_challenges
|
|
Packit |
90a5c9 |
|| !md_array_str_eq(md->ca_challenges, smd->ca_challenges, 0)) {
|
|
Packit |
90a5c9 |
smd->ca_challenges = apr_array_copy(ptemp, md->ca_challenges);
|
|
Packit |
90a5c9 |
fields |= MD_UPD_CA_CHALLENGES;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (smd->ca_challenges) {
|
|
Packit |
90a5c9 |
smd->ca_challenges = NULL;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_CA_CHALLENGES;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (!md_pkey_spec_eq(md->pkey_spec, smd->pkey_spec)) {
|
|
Packit |
90a5c9 |
fields |= MD_UPD_PKEY_SPEC;
|
|
Packit |
90a5c9 |
smd->pkey_spec = NULL;
|
|
Packit |
90a5c9 |
if (md->pkey_spec) {
|
|
Packit |
90a5c9 |
smd->pkey_spec = apr_pmemdup(p, md->pkey_spec, sizeof(md_pkey_spec_t));
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_VAL_UPDATE(md, smd, require_https)) {
|
|
Packit |
90a5c9 |
smd->require_https = md->require_https;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_REQUIRE_HTTPS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (MD_VAL_UPDATE(md, smd, must_staple)) {
|
|
Packit |
90a5c9 |
smd->must_staple = md->must_staple;
|
|
Packit |
90a5c9 |
fields |= MD_UPD_MUST_STAPLE;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (fields) {
|
|
Packit |
90a5c9 |
rv = md_reg_update(reg, ptemp, smd->name, smd, fields);
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "md %s updated", smd->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
/* new managed domain */
|
|
Packit |
90a5c9 |
rv = md_reg_add(reg, md, ptemp);
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p, "new md %s added", md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "loading mds");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_remove(md_reg_t *reg, apr_pool_t *p, const char *name, int archive)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_store_move(reg->store, p, MD_SG_DOMAINS, MD_SG_ARCHIVE, name, archive);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* driving */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t init_proto_driver(md_proto_driver_t *driver, const md_proto_t *proto,
|
|
Packit |
90a5c9 |
md_reg_t *reg, const md_t *md,
|
|
Packit |
90a5c9 |
const char *challenge, int reset, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_status_t rv = APR_SUCCESS;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* If this registry instance was not synched before (and obtained server
|
|
Packit |
90a5c9 |
* properties that way), read them from the store.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
driver->proto = proto;
|
|
Packit |
90a5c9 |
driver->p = p;
|
|
Packit |
90a5c9 |
driver->challenge = challenge;
|
|
Packit |
90a5c9 |
driver->can_http = reg->can_http;
|
|
Packit |
90a5c9 |
driver->can_https = reg->can_https;
|
|
Packit |
90a5c9 |
driver->reg = reg;
|
|
Packit |
90a5c9 |
driver->store = md_reg_store_get(reg);
|
|
Packit |
90a5c9 |
driver->proxy_url = reg->proxy_url;
|
|
Packit |
90a5c9 |
driver->md = md;
|
|
Packit |
90a5c9 |
driver->reset = reset;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t run_stage(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg = baton;
|
|
Packit |
90a5c9 |
const md_proto_t *proto;
|
|
Packit |
90a5c9 |
const md_t *md;
|
|
Packit |
90a5c9 |
int reset;
|
|
Packit |
90a5c9 |
md_proto_driver_t *driver;
|
|
Packit |
90a5c9 |
const char *challenge;
|
|
Packit |
90a5c9 |
apr_time_t *pvalid_from;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(void)p;
|
|
Packit |
90a5c9 |
proto = va_arg(ap, const md_proto_t *);
|
|
Packit |
90a5c9 |
md = va_arg(ap, const md_t *);
|
|
Packit |
90a5c9 |
challenge = va_arg(ap, const char *);
|
|
Packit |
90a5c9 |
reset = va_arg(ap, int);
|
|
Packit |
90a5c9 |
pvalid_from = va_arg(ap, apr_time_t*);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
driver = apr_pcalloc(ptemp, sizeof(*driver));
|
|
Packit |
90a5c9 |
rv = init_proto_driver(driver, proto, reg, md, challenge, reset, ptemp);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv &&
|
|
Packit |
90a5c9 |
APR_SUCCESS == (rv = proto->init(driver))) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, ptemp, "%s: run staging", md->name);
|
|
Packit |
90a5c9 |
rv = proto->stage(driver);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv && pvalid_from) {
|
|
Packit |
90a5c9 |
*pvalid_from = driver->stage_valid_from;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "%s: staging done", md->name);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_stage(md_reg_t *reg, const md_t *md, const char *challenge,
|
|
Packit |
90a5c9 |
int reset, apr_time_t *pvalid_from, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const md_proto_t *proto;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!md->ca_proto) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "md %s has no CA protocol", md->name);
|
|
Packit |
90a5c9 |
((md_t *)md)->state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
return APR_SUCCESS;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
proto = apr_hash_get(reg->protos, md->ca_proto, (apr_ssize_t)strlen(md->ca_proto));
|
|
Packit |
90a5c9 |
if (!proto) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p,
|
|
Packit |
90a5c9 |
"md %s has unknown CA protocol: %s", md->name, md->ca_proto);
|
|
Packit |
90a5c9 |
((md_t *)md)->state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return md_util_pool_vdo(run_stage, reg, p, proto, md, challenge, reset, pvalid_from, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
static apr_status_t run_load(void *baton, apr_pool_t *p, apr_pool_t *ptemp, va_list ap)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_reg_t *reg = baton;
|
|
Packit |
90a5c9 |
const char *name;
|
|
Packit |
90a5c9 |
const md_proto_t *proto;
|
|
Packit |
90a5c9 |
const md_t *md, *nmd;
|
|
Packit |
90a5c9 |
md_proto_driver_t *driver;
|
|
Packit |
90a5c9 |
apr_status_t rv;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
name = va_arg(ap, const char *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_STATUS_IS_ENOENT(rv = md_load(reg->store, MD_SG_STAGING, name, NULL, ptemp))) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, ptemp, "%s: nothing staged", name);
|
|
Packit |
90a5c9 |
return APR_ENOENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md = md_reg_get(reg, name, p);
|
|
Packit |
90a5c9 |
if (!md) {
|
|
Packit |
90a5c9 |
return APR_ENOENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!md->ca_proto) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p, "md %s has no CA protocol", name);
|
|
Packit |
90a5c9 |
((md_t *)md)->state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
proto = apr_hash_get(reg->protos, md->ca_proto, (apr_ssize_t)strlen(md->ca_proto));
|
|
Packit |
90a5c9 |
if (!proto) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, 0, p,
|
|
Packit |
90a5c9 |
"md %s has unknown CA protocol: %s", md->name, md->ca_proto);
|
|
Packit |
90a5c9 |
((md_t *)md)->state = MD_S_ERROR;
|
|
Packit |
90a5c9 |
return APR_EINVAL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
driver = apr_pcalloc(ptemp, sizeof(*driver));
|
|
Packit |
90a5c9 |
init_proto_driver(driver, proto, reg, md, NULL, 0, ptemp);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (rv = proto->init(driver))) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, ptemp, "%s: run load", md->name);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == (rv = proto->preload(driver, MD_SG_TMP))) {
|
|
Packit |
90a5c9 |
/* swap */
|
|
Packit |
90a5c9 |
rv = md_store_move(reg->store, p, MD_SG_TMP, MD_SG_DOMAINS, md->name, 1);
|
|
Packit |
90a5c9 |
if (APR_SUCCESS == rv) {
|
|
Packit |
90a5c9 |
/* load again */
|
|
Packit |
90a5c9 |
nmd = md_reg_get(reg, md->name, p);
|
|
Packit |
90a5c9 |
if (!nmd) {
|
|
Packit |
90a5c9 |
rv = APR_ENOENT;
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "loading md after staging");
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (nmd->state != MD_S_COMPLETE) {
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_WARNING, rv, p,
|
|
Packit |
90a5c9 |
"md has state %d after load", nmd->state);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_store_purge(reg->store, p, MD_SG_STAGING, md->name);
|
|
Packit |
90a5c9 |
md_store_purge(reg->store, p, MD_SG_CHALLENGES, md->name);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "%s: load done", md->name);
|
|
Packit |
90a5c9 |
return rv;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_status_t md_reg_load(md_reg_t *reg, const char *name, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_util_pool_vdo(run_load, reg, p, name, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|