|
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 <stdlib.h>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include <apr_lib.h>
|
|
Packit |
90a5c9 |
#include <apr_strings.h>
|
|
Packit |
90a5c9 |
#include <apr_tables.h>
|
|
Packit |
90a5c9 |
#include <apr_time.h>
|
|
Packit |
90a5c9 |
#include <apr_date.h>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
#include "md_json.h"
|
|
Packit |
90a5c9 |
#include "md.h"
|
|
Packit |
90a5c9 |
#include "md_crypt.h"
|
|
Packit |
90a5c9 |
#include "md_log.h"
|
|
Packit |
90a5c9 |
#include "md_store.h"
|
|
Packit |
90a5c9 |
#include "md_util.h"
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_contains(const md_t *md, const char *domain, int case_sensitive)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_array_str_index(md->domains, domain, 0, case_sensitive) >= 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
const char *md_common_name(const md_t *md1, const md_t *md2)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (md1 == NULL || md1->domains == NULL
|
|
Packit |
90a5c9 |
|| md2 == NULL || md2->domains == NULL) {
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for (i = 0; i < md1->domains->nelts; ++i) {
|
|
Packit |
90a5c9 |
const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
|
|
Packit |
90a5c9 |
if (md_contains(md2, name1, 0)) {
|
|
Packit |
90a5c9 |
return name1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_domains_overlap(const md_t *md1, const md_t *md2)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
return md_common_name(md1, md2) != NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
apr_size_t md_common_name_count(const md_t *md1, const md_t *md2)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
apr_size_t hits;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (md1 == NULL || md1->domains == NULL
|
|
Packit |
90a5c9 |
|| md2 == NULL || md2->domains == NULL) {
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
hits = 0;
|
|
Packit |
90a5c9 |
for (i = 0; i < md1->domains->nelts; ++i) {
|
|
Packit |
90a5c9 |
const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
|
|
Packit |
90a5c9 |
if (md_contains(md2, name1, 0)) {
|
|
Packit |
90a5c9 |
++hits;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return hits;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_create_empty(apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *md = apr_pcalloc(p, sizeof(*md));
|
|
Packit |
90a5c9 |
if (md) {
|
|
Packit |
90a5c9 |
md->domains = apr_array_make(p, 5, sizeof(const char *));
|
|
Packit |
90a5c9 |
md->contacts = apr_array_make(p, 5, sizeof(const char *));
|
|
Packit |
90a5c9 |
md->drive_mode = MD_DRIVE_DEFAULT;
|
|
Packit |
90a5c9 |
md->require_https = MD_REQUIRE_UNSET;
|
|
Packit |
90a5c9 |
md->must_staple = -1;
|
|
Packit |
90a5c9 |
md->transitive = -1;
|
|
Packit |
90a5c9 |
md->defn_name = "unknown";
|
|
Packit |
90a5c9 |
md->defn_line_number = 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_equal_domains(const md_t *md1, const md_t *md2, int case_sensitive)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
if (md1->domains->nelts == md2->domains->nelts) {
|
|
Packit |
90a5c9 |
for (i = 0; i < md1->domains->nelts; ++i) {
|
|
Packit |
90a5c9 |
const char *name1 = APR_ARRAY_IDX(md1->domains, i, const char*);
|
|
Packit |
90a5c9 |
if (!md_contains(md2, name1, case_sensitive)) {
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_contains_domains(const md_t *md1, const md_t *md2)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
if (md1->domains->nelts >= md2->domains->nelts) {
|
|
Packit |
90a5c9 |
for (i = 0; i < md2->domains->nelts; ++i) {
|
|
Packit |
90a5c9 |
const char *name2 = APR_ARRAY_IDX(md2->domains, i, const char*);
|
|
Packit |
90a5c9 |
if (!md_contains(md1, name2, 0)) {
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_find_closest_match(apr_array_header_t *mds, const md_t *md)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *candidate, *m;
|
|
Packit |
90a5c9 |
apr_size_t cand_n, n;
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
candidate = md_get_by_name(mds, md->name);
|
|
Packit |
90a5c9 |
if (!candidate) {
|
|
Packit |
90a5c9 |
/* try to find an instance that contains all domain names from md */
|
|
Packit |
90a5c9 |
for (i = 0; i < mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
m = APR_ARRAY_IDX(mds, i, md_t *);
|
|
Packit |
90a5c9 |
if (md_contains_domains(m, md)) {
|
|
Packit |
90a5c9 |
return m;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
/* no matching name and no md in the list has all domains.
|
|
Packit |
90a5c9 |
* We consider that managed domain as closest match that contains at least one
|
|
Packit |
90a5c9 |
* domain name from md, ONLY if there is no other one that also has.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
cand_n = 0;
|
|
Packit |
90a5c9 |
for (i = 0; i < mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
m = APR_ARRAY_IDX(mds, i, md_t *);
|
|
Packit |
90a5c9 |
n = md_common_name_count(md, m);
|
|
Packit |
90a5c9 |
if (n > cand_n) {
|
|
Packit |
90a5c9 |
candidate = m;
|
|
Packit |
90a5c9 |
cand_n = n;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return candidate;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_get_by_name(struct apr_array_header_t *mds, const char *name)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
for (i = 0; i < mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
md_t *md = APR_ARRAY_IDX(mds, i, md_t *);
|
|
Packit |
90a5c9 |
if (!strcmp(name, md->name)) {
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_get_by_domain(struct apr_array_header_t *mds, const char *domain)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
for (i = 0; i < mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
md_t *md = APR_ARRAY_IDX(mds, i, md_t *);
|
|
Packit |
90a5c9 |
if (md_contains(md, domain, 0)) {
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_get_by_dns_overlap(struct apr_array_header_t *mds, const md_t *md)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
for (i = 0; i < mds->nelts; ++i) {
|
|
Packit |
90a5c9 |
md_t *o = APR_ARRAY_IDX(mds, i, md_t *);
|
|
Packit |
90a5c9 |
if (strcmp(o->name, md->name) && md_common_name(o, md)) {
|
|
Packit |
90a5c9 |
return o;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_create(apr_pool_t *p, apr_array_header_t *domains)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md = md_create_empty(p);
|
|
Packit |
90a5c9 |
md->domains = md_array_str_compact(p, domains, 0);
|
|
Packit |
90a5c9 |
md->name = APR_ARRAY_IDX(md->domains, 0, const char *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int md_should_renew(const md_t *md)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
apr_time_t now = apr_time_now();
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (md->expires <= now) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (md->expires > 0) {
|
|
Packit |
90a5c9 |
double renew_win, life;
|
|
Packit |
90a5c9 |
apr_interval_time_t left;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
renew_win = (double)md->renew_window;
|
|
Packit |
90a5c9 |
if (md->renew_norm > 0
|
|
Packit |
90a5c9 |
&& md->renew_norm > renew_win
|
|
Packit |
90a5c9 |
&& md->expires > md->valid_from) {
|
|
Packit |
90a5c9 |
/* Calc renewal days as fraction of cert lifetime - if known */
|
|
Packit |
90a5c9 |
life = (double)(md->expires - md->valid_from);
|
|
Packit |
90a5c9 |
renew_win = life * renew_win / (double)md->renew_norm;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
left = md->expires - now;
|
|
Packit |
90a5c9 |
if (left <= renew_win) {
|
|
Packit |
90a5c9 |
return 1;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return 0;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* lifetime */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_copy(apr_pool_t *p, const md_t *src)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md = apr_pcalloc(p, sizeof(*md));
|
|
Packit |
90a5c9 |
if (md) {
|
|
Packit |
90a5c9 |
memcpy(md, src, sizeof(*md));
|
|
Packit |
90a5c9 |
md->domains = apr_array_copy(p, src->domains);
|
|
Packit |
90a5c9 |
md->contacts = apr_array_copy(p, src->contacts);
|
|
Packit |
90a5c9 |
if (src->ca_challenges) {
|
|
Packit |
90a5c9 |
md->ca_challenges = apr_array_copy(p, src->ca_challenges);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_clone(apr_pool_t *p, const md_t *src)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *md;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md = apr_pcalloc(p, sizeof(*md));
|
|
Packit |
90a5c9 |
if (md) {
|
|
Packit |
90a5c9 |
md->state = src->state;
|
|
Packit |
90a5c9 |
md->name = apr_pstrdup(p, src->name);
|
|
Packit |
90a5c9 |
md->require_https = src->require_https;
|
|
Packit |
90a5c9 |
md->must_staple = src->must_staple;
|
|
Packit |
90a5c9 |
md->drive_mode = src->drive_mode;
|
|
Packit |
90a5c9 |
md->domains = md_array_str_compact(p, src->domains, 0);
|
|
Packit |
90a5c9 |
md->pkey_spec = src->pkey_spec;
|
|
Packit |
90a5c9 |
md->renew_norm = src->renew_norm;
|
|
Packit |
90a5c9 |
md->renew_window = src->renew_window;
|
|
Packit |
90a5c9 |
md->contacts = md_array_str_clone(p, src->contacts);
|
|
Packit |
90a5c9 |
if (src->ca_url) md->ca_url = apr_pstrdup(p, src->ca_url);
|
|
Packit |
90a5c9 |
if (src->ca_proto) md->ca_proto = apr_pstrdup(p, src->ca_proto);
|
|
Packit |
90a5c9 |
if (src->ca_account) md->ca_account = apr_pstrdup(p, src->ca_account);
|
|
Packit |
90a5c9 |
if (src->ca_agreement) md->ca_agreement = apr_pstrdup(p, src->ca_agreement);
|
|
Packit |
90a5c9 |
if (src->defn_name) md->defn_name = apr_pstrdup(p, src->defn_name);
|
|
Packit |
90a5c9 |
if (src->cert_url) md->cert_url = apr_pstrdup(p, src->cert_url);
|
|
Packit |
90a5c9 |
md->defn_line_number = src->defn_line_number;
|
|
Packit |
90a5c9 |
if (src->ca_challenges) {
|
|
Packit |
90a5c9 |
md->ca_challenges = md_array_str_clone(p, src->ca_challenges);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_merge(apr_pool_t *p, const md_t *add, const md_t *base)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_t *n = apr_pcalloc(p, sizeof(*n));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
n->ca_url = add->ca_url? add->ca_url : base->ca_url;
|
|
Packit |
90a5c9 |
n->ca_proto = add->ca_proto? add->ca_proto : base->ca_proto;
|
|
Packit |
90a5c9 |
n->ca_agreement = add->ca_agreement? add->ca_agreement : base->ca_agreement;
|
|
Packit |
90a5c9 |
n->require_https = (add->require_https != MD_REQUIRE_UNSET)? add->require_https : base->require_https;
|
|
Packit |
90a5c9 |
n->must_staple = (add->must_staple >= 0)? add->must_staple : base->must_staple;
|
|
Packit |
90a5c9 |
n->drive_mode = (add->drive_mode != MD_DRIVE_DEFAULT)? add->drive_mode : base->drive_mode;
|
|
Packit |
90a5c9 |
n->pkey_spec = add->pkey_spec? add->pkey_spec : base->pkey_spec;
|
|
Packit |
90a5c9 |
n->renew_norm = (add->renew_norm > 0)? add->renew_norm : base->renew_norm;
|
|
Packit |
90a5c9 |
n->renew_window = (add->renew_window > 0)? add->renew_window : base->renew_window;
|
|
Packit |
90a5c9 |
n->transitive = (add->transitive >= 0)? add->transitive : base->transitive;
|
|
Packit |
90a5c9 |
if (add->ca_challenges) {
|
|
Packit |
90a5c9 |
n->ca_challenges = apr_array_copy(p, add->ca_challenges);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (base->ca_challenges) {
|
|
Packit |
90a5c9 |
n->ca_challenges = apr_array_copy(p, base->ca_challenges);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return n;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/**************************************************************************************************/
|
|
Packit |
90a5c9 |
/* format conversion */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_json_t *md_to_json(const md_t *md, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
md_json_t *json = md_json_create(p);
|
|
Packit |
90a5c9 |
if (json) {
|
|
Packit |
90a5c9 |
apr_array_header_t *domains = md_array_str_compact(p, md->domains, 0);
|
|
Packit |
90a5c9 |
md_json_sets(md->name, json, MD_KEY_NAME, NULL);
|
|
Packit |
90a5c9 |
md_json_setsa(domains, json, MD_KEY_DOMAINS, NULL);
|
|
Packit |
90a5c9 |
md_json_setsa(md->contacts, json, MD_KEY_CONTACTS, NULL);
|
|
Packit |
90a5c9 |
md_json_setl(md->transitive, json, MD_KEY_TRANSITIVE, NULL);
|
|
Packit |
90a5c9 |
md_json_sets(md->ca_account, json, MD_KEY_CA, MD_KEY_ACCOUNT, NULL);
|
|
Packit |
90a5c9 |
md_json_sets(md->ca_proto, json, MD_KEY_CA, MD_KEY_PROTO, NULL);
|
|
Packit |
90a5c9 |
md_json_sets(md->ca_url, json, MD_KEY_CA, MD_KEY_URL, NULL);
|
|
Packit |
90a5c9 |
md_json_sets(md->ca_agreement, json, MD_KEY_CA, MD_KEY_AGREEMENT, NULL);
|
|
Packit |
90a5c9 |
if (md->cert_url) {
|
|
Packit |
90a5c9 |
md_json_sets(md->cert_url, json, MD_KEY_CERT, MD_KEY_URL, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md->pkey_spec) {
|
|
Packit |
90a5c9 |
md_json_setj(md_pkey_spec_to_json(md->pkey_spec, p), json, MD_KEY_PKEY, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md_json_setl(md->state, json, MD_KEY_STATE, NULL);
|
|
Packit |
90a5c9 |
md_json_setl(md->drive_mode, json, MD_KEY_DRIVE_MODE, NULL);
|
|
Packit |
90a5c9 |
if (md->expires > 0) {
|
|
Packit |
90a5c9 |
char *ts = apr_pcalloc(p, APR_RFC822_DATE_LEN);
|
|
Packit |
90a5c9 |
apr_rfc822_date(ts, md->expires);
|
|
Packit |
90a5c9 |
md_json_sets(ts, json, MD_KEY_CERT, MD_KEY_EXPIRES, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md->valid_from > 0) {
|
|
Packit |
90a5c9 |
char *ts = apr_pcalloc(p, APR_RFC822_DATE_LEN);
|
|
Packit |
90a5c9 |
apr_rfc822_date(ts, md->valid_from);
|
|
Packit |
90a5c9 |
md_json_sets(ts, json, MD_KEY_CERT, MD_KEY_VALID_FROM, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md->renew_norm > 0) {
|
|
Packit |
90a5c9 |
md_json_sets(apr_psprintf(p, "%ld%%", (long)(md->renew_window * 100L / md->renew_norm)),
|
|
Packit |
90a5c9 |
json, MD_KEY_RENEW_WINDOW, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
md_json_setl((long)apr_time_sec(md->renew_window), json, MD_KEY_RENEW_WINDOW, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md_json_setb(md_should_renew(md), json, MD_KEY_RENEW, NULL);
|
|
Packit |
90a5c9 |
if (md->ca_challenges && md->ca_challenges->nelts > 0) {
|
|
Packit |
90a5c9 |
apr_array_header_t *na;
|
|
Packit |
90a5c9 |
na = md_array_str_compact(p, md->ca_challenges, 0);
|
|
Packit |
90a5c9 |
md_json_setsa(na, json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
switch (md->require_https) {
|
|
Packit |
90a5c9 |
case MD_REQUIRE_TEMPORARY:
|
|
Packit |
90a5c9 |
md_json_sets(MD_KEY_TEMPORARY, json, MD_KEY_REQUIRE_HTTPS, NULL);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
case MD_REQUIRE_PERMANENT:
|
|
Packit |
90a5c9 |
md_json_sets(MD_KEY_PERMANENT, json, MD_KEY_REQUIRE_HTTPS, NULL);
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
default:
|
|
Packit |
90a5c9 |
break;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md_json_setb(md->must_staple > 0, json, MD_KEY_MUST_STAPLE, NULL);
|
|
Packit |
90a5c9 |
return json;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
md_t *md_from_json(md_json_t *json, apr_pool_t *p)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
const char *s;
|
|
Packit |
90a5c9 |
md_t *md = md_create_empty(p);
|
|
Packit |
90a5c9 |
if (md) {
|
|
Packit |
90a5c9 |
md->name = md_json_dups(p, json, MD_KEY_NAME, NULL);
|
|
Packit |
90a5c9 |
md_json_dupsa(md->domains, p, json, MD_KEY_DOMAINS, NULL);
|
|
Packit |
90a5c9 |
md_json_dupsa(md->contacts, p, json, MD_KEY_CONTACTS, NULL);
|
|
Packit |
90a5c9 |
md->ca_account = md_json_dups(p, json, MD_KEY_CA, MD_KEY_ACCOUNT, NULL);
|
|
Packit |
90a5c9 |
md->ca_proto = md_json_dups(p, json, MD_KEY_CA, MD_KEY_PROTO, NULL);
|
|
Packit |
90a5c9 |
md->ca_url = md_json_dups(p, json, MD_KEY_CA, MD_KEY_URL, NULL);
|
|
Packit |
90a5c9 |
md->ca_agreement = md_json_dups(p, json, MD_KEY_CA, MD_KEY_AGREEMENT, NULL);
|
|
Packit |
90a5c9 |
md->cert_url = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_URL, NULL);
|
|
Packit |
90a5c9 |
if (md_json_has_key(json, MD_KEY_PKEY, MD_KEY_TYPE, NULL)) {
|
|
Packit |
90a5c9 |
md->pkey_spec = md_pkey_spec_from_json(md_json_getj(json, MD_KEY_PKEY, NULL), p);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md->state = (md_state_t)md_json_getl(json, MD_KEY_STATE, NULL);
|
|
Packit |
90a5c9 |
md->drive_mode = (int)md_json_getl(json, MD_KEY_DRIVE_MODE, NULL);
|
|
Packit |
90a5c9 |
md->domains = md_array_str_compact(p, md->domains, 0);
|
|
Packit |
90a5c9 |
md->transitive = (int)md_json_getl(json, MD_KEY_TRANSITIVE, NULL);
|
|
Packit |
90a5c9 |
s = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_EXPIRES, NULL);
|
|
Packit |
90a5c9 |
if (s && *s) {
|
|
Packit |
90a5c9 |
md->expires = apr_date_parse_rfc(s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
s = md_json_dups(p, json, MD_KEY_CERT, MD_KEY_VALID_FROM, NULL);
|
|
Packit |
90a5c9 |
if (s && *s) {
|
|
Packit |
90a5c9 |
md->valid_from = apr_date_parse_rfc(s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md->renew_norm = 0;
|
|
Packit |
90a5c9 |
md->renew_window = apr_time_from_sec(md_json_getl(json, MD_KEY_RENEW_WINDOW, NULL));
|
|
Packit |
90a5c9 |
if (md->renew_window <= 0) {
|
|
Packit |
90a5c9 |
s = md_json_gets(json, MD_KEY_RENEW_WINDOW, NULL);
|
|
Packit |
90a5c9 |
if (s && strchr(s, '%')) {
|
|
Packit |
90a5c9 |
int percent = atoi(s);
|
|
Packit |
90a5c9 |
if (0 < percent && percent < 100) {
|
|
Packit |
90a5c9 |
md->renew_norm = apr_time_from_sec(100 * MD_SECS_PER_DAY);
|
|
Packit |
90a5c9 |
md->renew_window = apr_time_from_sec(percent * MD_SECS_PER_DAY);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
if (md_json_has_key(json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL)) {
|
|
Packit |
90a5c9 |
md->ca_challenges = apr_array_make(p, 5, sizeof(const char*));
|
|
Packit |
90a5c9 |
md_json_dupsa(md->ca_challenges, p, json, MD_KEY_CA, MD_KEY_CHALLENGES, NULL);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md->require_https = MD_REQUIRE_OFF;
|
|
Packit |
90a5c9 |
s = md_json_gets(json, MD_KEY_REQUIRE_HTTPS, NULL);
|
|
Packit |
90a5c9 |
if (s && !strcmp(MD_KEY_TEMPORARY, s)) {
|
|
Packit |
90a5c9 |
md->require_https = MD_REQUIRE_TEMPORARY;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else if (s && !strcmp(MD_KEY_PERMANENT, s)) {
|
|
Packit |
90a5c9 |
md->require_https = MD_REQUIRE_PERMANENT;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
md->must_staple = (int)md_json_getb(json, MD_KEY_MUST_STAPLE, NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return md;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|