dnl # list of module object files
md_objs="dnl
mod_md.lo dnl
-md_config.lo dnl
-md_os.lo dnl
+mod_md_config.lo dnl
+mod_md_os.lo dnl
"
dnl # hook module into the Autoconf mechanism (--enable-md)
#define MD_KEY_RESOURCE "resource"
#define MD_KEY_STATE "state"
#define MD_KEY_STATUS "status"
+#define MD_KEY_STORE "store"
#define MD_KEY_TOKEN "token"
#define MD_KEY_TYPE "type"
#define MD_KEY_URL "url"
apr_file_t *f;
} j_write_ctx;
+/* Convert from md_json_fmt_t to the Jansson json_dumpX flags. */
+static size_t fmt_to_flags(md_json_fmt_t fmt)
+{
+ /* NOTE: JSON_PRESERVE_ORDER is off by default before Jansson 2.8. It
+ * doesn't have any semantic effect on the protocol, but it does let the
+ * md_json_writeX unit tests run deterministically. */
+ return JSON_PRESERVE_ORDER |
+ ((fmt == MD_JSON_FMT_COMPACT) ? JSON_COMPACT : JSON_INDENT(2));
+}
+
static int dump_cb(const char *buffer, size_t len, void *baton)
{
apr_bucket_brigade *bb = baton;
apr_status_t md_json_writeb(md_json_t *json, md_json_fmt_t fmt, apr_bucket_brigade *bb)
{
- size_t flags = (fmt == MD_JSON_FMT_COMPACT)? JSON_COMPACT : JSON_INDENT(2);
- int rv = json_dump_callback(json->j, dump_cb, bb, flags);
+ int rv = json_dump_callback(json->j, dump_cb, bb, fmt_to_flags(fmt));
return rv? APR_EGENERAL : APR_SUCCESS;
}
const char *md_json_writep(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt)
{
- size_t flags = (fmt == MD_JSON_FMT_COMPACT)? JSON_COMPACT : JSON_INDENT(2);
apr_array_header_t *chunks;
int rv;
chunks = apr_array_make(p, 10, sizeof(char *));
- rv = json_dump_callback(json->j, chunk_cb, chunks, flags);
+ rv = json_dump_callback(json->j, chunk_cb, chunks, fmt_to_flags(fmt));
if (rv) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p,
/**************************************************************************************************/
/* file system based implementation of md_store_t */
+#define MD_STORE_VERSION 1.0
+
typedef struct {
apr_fileperms_t dir;
apr_fileperms_t file;
int i;
md_json_sets(MOD_MD_VERSION, json, MD_KEY_VERSION, NULL);
+ md_json_setn(MD_STORE_VERSION, json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
/*if (APR_SUCCESS != (rv = md_rand_bytes(key, sizeof(key), p))) {
return rv;
md_json_t *json;
const char *s, *key64;
apr_status_t rv;
+ double store_version;
if (APR_SUCCESS == (rv = md_json_readf(&json, p, fname))) {
- s = md_json_gets(json, MD_KEY_VERSION, NULL);
- if (!s) {
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "missing key: %s", MD_KEY_VERSION);
- return APR_EINVAL;
+ store_version = md_json_getn(json, MD_KEY_STORE, MD_KEY_VERSION, NULL);
+ if (store_version <= 0.0) {
+ /* ok, an old one, compatible to 1.0 */
+ store_version = 1.0;
}
- if (strcmp(MOD_MD_VERSION, s) < 0) {
+ if (store_version > MD_STORE_VERSION) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, 0, p, "version too new: %s", s);
return APR_EINVAL;
}
- /* TODO: need to migrate store? */
+ else if (store_version > MD_STORE_VERSION) {
+ /* migrate future store version changes */
+ }
key64 = md_json_dups(p, json, MD_KEY_KEY, NULL);
if (!key64) {
rv = md_util_path_merge(&arch_dir, ptemp, dir, name, NULL);
if (APR_SUCCESS != rv) goto out;
- while (1) {
+#ifdef WIN32
+ /* WIN32 and handling of files/dirs. What can one say? */
+
+ while (n < 1000) {
+ narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
+ rv = md_util_is_dir(narch_dir, ptemp);
+ if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, ptemp, "using archive dir: %s",
+ narch_dir);
+ break;
+ }
+ else {
+ ++n;
+ narch_dir = NULL;
+ }
+ }
+
+#else /* ifdef WIN32 */
+
+ while (n < 1000) {
narch_dir = apr_psprintf(ptemp, "%s.%d", arch_dir, n);
rv = apr_dir_make(narch_dir, MD_FPROT_D_UONLY, ptemp);
if (APR_SUCCESS == rv) {
}
else if (APR_EEXIST == rv) {
++n;
+ narch_dir = NULL;
}
else {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "creating archive dir: %s",
narch_dir);
goto out;
}
- }
+ }
+
+#endif /* ifdef WIN32 (else part) */
+
+ if (!narch_dir) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "ran out of numbers less than 1000 "
+ "while looking for an available one in %s to archive the data "
+ "from %s. Either something is generally wrong or you need to "
+ "clean up some of those directories.", arch_dir, from_dir);
+ rv = APR_EGENERAL;
+ goto out;
+ }
if (APR_SUCCESS != (rv = apr_file_rename(to_dir, narch_dir, ptemp))) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, ptemp, "rename from %s to %s",
* @macro
* Version number of the md module as c string
*/
-#define MOD_MD_VERSION "0.5.0-git"
+#define MOD_MD_VERSION "0.6.0"
/**
* @macro
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_MD_VERSION_NUM 0x000500
+#define MOD_MD_VERSION_NUM 0x000600
#define MD_EXPERIMENTAL 1
#define MD_ACME_DEF_URL "https://acme-staging.api.letsencrypt.org/directory"
#include <ap_listen.h>
#include "md.h"
-#include "mod_md.h"
-#include "md_config.h"
#include "md_curl.h"
#include "md_crypt.h"
#include "md_http.h"
#include "md_acme.h"
#include "md_acme_authz.h"
-#include "md_os.h"
+#include "mod_md.h"
+#include "mod_md_config.h"
+#include "mod_md_os.h"
#include "mod_watchdog.h"
static void md_hooks(apr_pool_t *pool);
#include <http_vhost.h>
#include "md.h"
-#include "md_config.h"
#include "md_util.h"
+#include "mod_md_private.h"
+#include "mod_md_config.h"
-extern module AP_MODULE_DECLARE_DATA md_module;
-APLOG_USE_MODULE(md);
#define DEF_VAL (-1)
#endif
#include "md_util.h"
-#include "md_os.h"
+#include "mod_md_os.h"
apr_status_t md_try_chown(const char *fname, int uid, int gid, apr_pool_t *p)
{
--- /dev/null
+/* Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef mod_md_md_private_h
+#define mod_md_md_private_h
+
+extern module AP_MODULE_DECLARE_DATA md_module;
+
+APLOG_USE_MODULE(md);
+
+#endif