return KNOT_CTL_EZONE;
}
+ zone_backup_ctx_t *ctx = latest_backup_ctx(args);
+
+ /* QUIC - server key and cert backup. */
+ ret = backup_quic(ctx);
+ if (ret != KNOT_EOK) {
+ log_ctl_error("control, QUIC %s error (%s)",
+ restore_mode ? "restore" : "backup",
+ knot_strerror(ret));
+ send_error(args, knot_strerror(ret));
+ ret = KNOT_EOK;
+ goto done;
+ }
+
/* Global catalog zones backup. */
if (args->data[KNOT_CTL_IDX_ZONE] == NULL) {
- zone_backup_ctx_t *ctx = latest_backup_ctx(args);
ctx->backup_global = true;
ret = global_backup(ctx, &args->server->catalog, NULL);
if (ret != KNOT_EOK) {
#include "knot/dnssec/kasp/kasp_zone.h"
#include "knot/dnssec/kasp/keystore.h"
#include "knot/journal/journal_metadata.h"
+#include "knot/server/server.h"
#include "knot/zone/backup_dir.h"
#include "knot/zone/zonefile.h"
#include "libdnssec/error.h"
}
return ret;
}
+
+static int backup_quic_file(zone_backup_ctx_t *ctx, char *file, char *subdir,
+ const char *desc, bool required, bool *success)
+{
+ char *backup_quic_dir = NULL, *backup_orig = NULL, *backup;
+ int ret;
+
+ backup_quic_dir = dir_file(ctx->backup_dir, subdir);
+ ABORT_IF_ENOMEM(backup_quic_dir);
+ backup_orig = backup = dir_file(backup_quic_dir, file);
+ ABORT_IF_ENOMEM(backup);
+
+ BACKUP_SWAP(ctx, backup, file);
+ ret = backup_file(backup, file);
+ if (ret == KNOT_EOK) {
+ *success = true;
+ } else if (!required && ret == KNOT_ENOENT) {
+ ret = KNOT_EOK;
+ } else {
+ log_ctl_error("control, QUIC %s file %s failed (%s)", desc,
+ ctx->restore_mode ? "restore" : "backup",
+ knot_strerror(ret));
+ }
+done:
+ free(backup_orig);
+ free(backup_quic_dir);
+ return ret;
+}
+
+#define DONE_ON_ERROR if (ret != KNOT_EOK) { \
+ goto done; \
+ }
+
+int backup_quic(zone_backup_ctx_t *ctx)
+{
+ if (!ctx->backup_quic) {
+ return KNOT_EOK;
+ }
+
+ const char *str_auto = "auto-generated key";
+ const char *str_key = "configured key";
+ const char *str_cert = "certificate";
+
+ bool log_auto = false;
+ bool log_key = false;
+ bool log_cert = false;
+ int ret;
+
+ conf_val_t liquic_val = conf_get(conf(), C_SRV, C_LISTEN_QUIC);
+ bool quic_on = (conf_val_count(&liquic_val) > 0);
+
+ char *cert_file = conf_tls(conf(), C_CERT_FILE);
+ char *key_file = conf_tls(conf(), C_KEY_FILE);
+ bool user_keys = (key_file != NULL);
+
+ char *kasp_dir = conf_db(conf(), C_KASP_DB);
+ char *auto_file = abs_path(DFLT_QUIC_KEY_FILE, kasp_dir);
+ ABORT_IF_ENOMEM(auto_file);
+ free(kasp_dir);
+
+ // Backup/restore of auto-generated key is required if it's in active use,
+ // otherwise use it if the file is found (no fail if missing).
+ ret = backup_quic_file(ctx, auto_file, "keys", str_auto,
+ quic_on && !user_keys, &log_auto);
+ DONE_ON_ERROR;
+
+ // If QUIC isn't configured, backup of configured key and cert is possible,
+ // but it isn't required (no fail if missing).
+ if (user_keys && !ctx->restore_mode) {
+ char *quic_subdir = "quic";
+ ret = backup_quic_file(ctx, key_file, quic_subdir, str_key,
+ quic_on, &log_key);
+ DONE_ON_ERROR;
+
+ ret = backup_quic_file(ctx, cert_file, quic_subdir, str_cert,
+ quic_on, &log_cert);
+ DONE_ON_ERROR;
+ }
+
+ if (log_auto || log_key) {
+ log_ctl_info("control, QUIC %s%s%s%s%s %s '%s'",
+ log_auto ? str_auto : "",
+ (log_auto && log_key) ? ", " : "",
+ log_key ? str_key : "",
+ log_cert ? " and " : "",
+ log_cert ? str_cert : "",
+ ctx->restore_mode ? "restored from" : "backed up to",
+ ctx->backup_dir);
+ }
+
+done:
+ free(auto_file);
+ free(key_file);
+ free(cert_file);
+
+ if (ret != KNOT_EOK) {
+ ctx->failed = true;
+ }
+
+ return ret;
+}