OpenDNSSEC-enforcer 2.1.13
signconf_xml.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
3 * Copyright (c) 2014 OpenDNSSEC AB (svb)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#include "log.h"
30#include "str.h"
31#include "clientpipe.h"
32#include "duration.h"
33#include "db/key_data.h"
34#include "db/hsm_key.h"
35#include "utils/kc_helper.h"
36
38
39#include <libxml/parser.h>
40#include <libxml/tree.h>
41#include <limits.h>
42#include <unistd.h>
43
54static int signconf_xml_export(int sockfd, const policy_t* policy, zone_db_t* zone, int force);
55
56int
57signconf_export_zone(char const *zonename, db_connection_t* dbconn)
58{
59 zone_db_t* zone;
60 int ret;
62
63 zone = zone_db_new_get_by_name(dbconn, zonename);
64 if (!zone) {
65 ods_log_error("[signconf_export] Unable to fetch zone %s from"
66 " database", zonename);
68 }
70 if (!policy) {
71 ods_log_error("[signconf_export] Unable to fetch policy for zone"
72 " %s from database", zonename);
73 zone_db_free(zone);
75 }
76
77 /* We always force. Since now it is scheduled per zone */
78 ret = signconf_xml_export(-1, policy, zone, 1);
80 zone_db_free(zone);
81 return ret;
82}
83
84int signconf_export_all(int sockfd, const db_connection_t* connection, int force) {
85 zone_list_db_t* zone_list;
86 zone_db_t* zone;
87 int ret;
88 policy_t *policy = NULL;
89 int cmp;
90 int change = 0;
91
92 if (!connection) {
94 }
95
96 if (!(zone_list = zone_list_db_new(connection))
97 || zone_list_db_get(zone_list))
98 {
99 if (zone_list) {
100 zone_list_db_free(zone_list);
102 }
104 }
105
106 for (zone = zone_list_db_get_next(zone_list); zone; zone = zone_list_db_get_next(zone_list)) {
107 if (policy) {
108 /*
109 * If we already have a policy object; If policy_id compare fails
110 * or if they are not the same, free the policy object so we will
111 * later retrieve the correct policy
112 */
114 || cmp)
115 {
117 policy = NULL;
118 }
119 }
120 if (!policy) {
121 if (!(policy = zone_db_get_policy(zone))) {
122 zone_db_free(zone);
123 zone_list_db_free(zone_list);
125 }
126 }
127
128 ret = signconf_xml_export(sockfd, policy, zone, force);
129 if (ret == SIGNCONF_EXPORT_OK) {
130 change = 1;
131 }
132 else if (ret != SIGNCONF_EXPORT_NO_CHANGE) {
133 zone_db_free(zone);
134 zone_list_db_free(zone_list);
135 return ret;
136 }
137 zone_db_free(zone);
138 }
140 zone_list_db_free(zone_list);
141
142 if (change) {
143 return SIGNCONF_EXPORT_OK;
144 }
146}
147
148static int __free(char **p) {
149 if (!p || !*p) {
150 return 1;
151 }
152 free(*p);
153 *p = NULL;
154 return 0;
155}
156
157static int signconf_xml_export(int sockfd, const policy_t* policy, zone_db_t* zone, int force) {
158 char path[PATH_MAX];
159 xmlDocPtr doc;
160 xmlNodePtr root;
161 xmlNodePtr node;
162 xmlNodePtr node2;
163 xmlNodePtr node3;
164 xmlNodePtr node4;
165 xmlNodePtr node5;
166 xmlNodePtr keys;
167 duration_type* duration;
168 char* duration_text = NULL;
169 char text[1024];
171 const key_data_t* key_data;
173 int error;
174
175 if (!policy) {
177 }
178 if (!zone) {
180 }
181
182 if (!force && !zone_db_signconf_needs_writing(zone)) {
184 }
185
186 if (snprintf(path, sizeof(path), "%s.new", zone_db_signconf_path(zone)) >= (int)sizeof(path)) {
187 ods_log_error("[signconf_export] Unable to write updated XML for zone %s, path to long!", zone_db_name(zone));
188 if (sockfd > -1) client_printf_err(sockfd, "Unable to write updated XML for zone %s, path to long!\n", zone_db_name(zone));
190 }
191
192 if (!(duration = duration_create())) {
193 ods_log_error("[signconf_export] Unable to process signconf for zone %s, memory allocation error!", zone_db_name(zone));
194 if (sockfd > -1) client_printf_err(sockfd, "Unable to process signconf for zone %s, memory allocation error!\n", zone_db_name(zone));
196 }
197
198 if (!(doc = xmlNewDoc((xmlChar*)"1.0"))
199 || !(root = xmlNewNode(NULL, (xmlChar*)"SignerConfiguration"))
200 || !(node = xmlNewChild(root, NULL, (xmlChar*)"Zone", NULL)))
201 {
202 ods_log_error("[signconf_export] Unable to create XML elements for zone %s, memory allocation error!", zone_db_name(zone));
203 if (sockfd > -1) client_printf_err(sockfd, "Unable to create XML elements for zone %s, memory allocation error!\n", zone_db_name(zone));
204 if (doc) {
205 xmlFreeDoc(doc);
206 }
207 duration_cleanup(duration);
209 }
210
211 xmlDocSetRootElement(doc, root);
212
213 error = 1;
214 if (!xmlNewProp(node, (xmlChar*)"name", (xmlChar*)zone_db_name(zone))
215 || !(error = 26)
216 || (policy_passthrough(policy) && !(node2 = xmlNewChild(node, NULL, (xmlChar*)"Passthrough", NULL)))
217 || !(error = 2)
218 || !(node2 = xmlNewChild(node, NULL, (xmlChar*)"Signatures", NULL))
219 || !(error = 3)
220 || duration_set_time(duration, policy_signatures_resign(policy))
221 || !(duration_text = duration2string(duration))
222 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Resign", (xmlChar*)duration_text))
223 || __free(&duration_text)
224 || !(error = 4)
225 || duration_set_time(duration, policy_signatures_refresh(policy))
226 || !(duration_text = duration2string(duration))
227 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Refresh", (xmlChar*)duration_text))
228 || __free(&duration_text)
229 || !(error = 5)
230 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Validity", NULL))
231 || !(error = 6)
232 || duration_set_time(duration, policy_signatures_validity_default(policy))
233 || !(duration_text = duration2string(duration))
234 || !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"Default", (xmlChar*)duration_text))
235 || __free(&duration_text)
236 || !(error = 7)
237 || duration_set_time(duration, policy_signatures_validity_denial(policy))
238 || !(duration_text = duration2string(duration))
239 || !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"Denial", (xmlChar*)duration_text))
240 || __free(&duration_text)
241 || !(error = 8)
243 duration_set_time(duration, policy_signatures_validity_keyset(policy))
244 || !(duration_text = duration2string(duration))
245 || !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"Keyset", (xmlChar*)duration_text))
246 || __free(&duration_text)
247 || !(error = 100) : 0)
248 || duration_set_time(duration, policy_signatures_jitter(policy))
249 || !(duration_text = duration2string(duration))
250 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Jitter", (xmlChar*)duration_text))
251 || __free(&duration_text)
252 || !(error = 9)
253 || duration_set_time(duration, policy_signatures_inception_offset(policy))
254 || !(duration_text = duration2string(duration))
255 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"InceptionOffset", (xmlChar*)duration_text))
256 || __free(&duration_text)
257 || !(error = 10)
259 && (duration_set_time(duration, policy_signatures_max_zone_ttl(policy))
260 || !(duration_text = duration2string(duration))
261 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"MaxZoneTTL", (xmlChar*)duration_text))
262 || __free(&duration_text)))
263
264 || !(error = 11)
265 || !(node2 = xmlNewChild(node, NULL, (xmlChar*)"Denial", NULL))
266 || !(error = 12)
268 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"NSEC", NULL)))
269 || !(error = 13)
271 && (!(node3 = xmlNewChild(node2, NULL, (xmlChar*)"NSEC3", NULL))
272 || !(error = 14)
274 && (duration_set_time(duration, policy_denial_ttl(policy))
275 || !(duration_text = duration2string(duration))
276 || !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"TTL", (xmlChar*)duration_text))
277 || __free(&duration_text)))
278 || !(error = 15)
280 && !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"OptOut", NULL)))
281 || !(error = 16)
282 || !(node4 = xmlNewChild(node3, NULL, (xmlChar*)"Hash", NULL))
283 || !(error = 17)
284 || snprintf(text, sizeof(text), "%u", policy_denial_algorithm(policy)) >= (int)sizeof(text)
285 || !(node5 = xmlNewChild(node4, NULL, (xmlChar*)"Algorithm", (xmlChar*)text))
286 || !(error = 18)
287 || snprintf(text, sizeof(text), "%u", policy_denial_iterations(policy)) >= (int)sizeof(text)
288 || !(node5 = xmlNewChild(node4, NULL, (xmlChar*)"Iterations", (xmlChar*)text))
289 || !(error = 19)
290 || !(node5 = xmlNewChild(node4, NULL, (xmlChar*)"Salt", (xmlChar*)policy_denial_salt(policy)))))
291
292 || !(error = 20)
293 || !(keys = xmlNewChild(node, NULL, (xmlChar*)"Keys", NULL))
294 || !(error = 21)
295 || duration_set_time(duration, policy_keys_ttl(policy))
296 || !(duration_text = duration2string(duration))
297 || !(node3 = xmlNewChild(keys, NULL, (xmlChar*)"TTL", (xmlChar*)duration_text))
298 || __free(&duration_text)
299
300 || !(error = 22)
301 || !(node2 = xmlNewChild(node, NULL, (xmlChar*)"SOA", NULL))
302 || !(error = 23)
303 || duration_set_time(duration, policy_zone_soa_ttl(policy))
304 || !(duration_text = duration2string(duration))
305 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"TTL", (xmlChar*)duration_text))
306 || __free(&duration_text)
307 || !(error = 24)
308 || duration_set_time(duration, policy_zone_soa_minimum(policy))
309 || !(duration_text = duration2string(duration))
310 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Minimum", (xmlChar*)duration_text))
311 || __free(&duration_text)
312 || !(error = 25)
313 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Serial", (xmlChar*)policy_zone_soa_serial_text(policy)))
314 )
315 {
316 ods_log_error("[signconf_export] Unable to create XML elements for zone %s! [%d]", zone_db_name(zone), error);
317 if (sockfd > -1) client_printf_err(sockfd, "Unable to create XML elements for zone %s!\n", zone_db_name(zone));
318 __free(&duration_text);
319 duration_cleanup(duration);
320 xmlFreeDoc(doc);
322 }
323 __free(&duration_text);
324 duration_cleanup(duration);
325
326 if (!(key_data_list = zone_db_get_keys(zone))) {
327 ods_log_error("[signconf_export] Unable to get keys for zone %s!", zone_db_name(zone));
328 if (sockfd > -1) client_printf_err(sockfd, "Unable to get keys for zone %s!\n", zone_db_name(zone));
329 xmlFreeDoc(doc);
331 }
332
335 ods_log_error("[signconf_export] Unable to get HSM key from database for zone %s!", zone_db_name(zone));
336 if (sockfd > -1) client_printf_err(sockfd, "Unable to get HSM key from database for zone %s!\n", zone_db_name(zone));
338 xmlFreeDoc(doc);
340 }
341 error = 100;
342 if (!(node2 = xmlNewChild(keys, NULL, (xmlChar*)"Key", NULL))
343 || !(error = 101)
345 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Flags", (xmlChar*)"256")))
346 || !(error = 102)
348 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Flags", (xmlChar*)"257")))
349 || !(error = 103)
350 || snprintf(text, sizeof(text), "%u", key_data_algorithm(key_data)) >= (int)sizeof(text)
351 || !(error = 104)
352 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Algorithm", (xmlChar*)text))
353 || !(error = 105)
354 || !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Locator",(xmlChar*)hsm_key_locator(hsm_key)))
355 || !(error = 106)
359 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"KSK", NULL)))
360 || !(error = 107)
364 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"ZSK", NULL)))
365 || !(error = 108)
367 && !(node3 = xmlNewChild(node2, NULL, (xmlChar*)"Publish", NULL)))
368 /* TODO:
369 * What about <Deactivate/> ?
370 */
371 )
372 {
373 ods_log_error("[signconf_export] Unable to create key XML elements for zone %s! [%d]", zone_db_name(zone), error);
374 if (sockfd > -1) client_printf_err(sockfd, "Unable to create key XML elements for zone %s!\n", zone_db_name(zone));
377 xmlFreeDoc(doc);
379 }
381 }
383
384 unlink(path);
385 if (xmlSaveFormatFileEnc(path, doc, "UTF-8", 1) == -1) {
386 ods_log_error("[signconf_export] Unable to write signconf for zone %s, LibXML error!", zone_db_name(zone));
387 if (sockfd > -1) client_printf_err(sockfd, "Unable to write signconf for zone %s, LibXML error!\n", zone_db_name(zone));
388 xmlFreeDoc(doc);
390 }
391 xmlFreeDoc(doc);
392
393 if (check_rng(path, OPENDNSSEC_SCHEMA_DIR "/signconf.rng", 0)) {
394 ods_log_error("[signconf_export] Unable to validate the exported signconf XML for zone %s!", zone_db_name(zone));
395 if (sockfd > -1) client_printf_err(sockfd, "Unable to validate the exported signconf XML for zone %s!\n", zone_db_name(zone));
397 }
398
399 if (rename(path, zone_db_signconf_path(zone))) {
400 ods_log_error("[signconf_export] Unable to write signconf for zone %s, rename failed!", zone_db_name(zone));
401 if (sockfd > -1) client_printf_err(sockfd, "Unable to write signconf for zone %s, rename failed!\n", zone_db_name(zone));
402 unlink(path);
404 }
405
407 zone_db_update(zone);
408
409 return SIGNCONF_EXPORT_OK;
410}
int db_value_cmp(const db_value_t *value_a, const db_value_t *value_b, int *result)
Definition: db_value.c:102
void hsm_key_free(hsm_key_t *hsm_key)
Definition: hsm_key.c:286
const char * hsm_key_locator(const hsm_key_t *hsm_key)
Definition: hsm_key.c:520
int check_rng(const char *filename, const char *rngfilename, int verbose)
Definition: kc_helper.c:88
unsigned int key_data_active_ksk(const key_data_t *key_data)
Definition: key_data.c:751
hsm_key_t * key_data_get_hsm_key(const key_data_t *key_data)
Definition: key_data.c:649
unsigned int key_data_publish(const key_data_t *key_data)
Definition: key_data.c:743
void key_data_list_free(key_data_list_t *key_data_list)
Definition: key_data.c:1694
unsigned int key_data_active_zsk(const key_data_t *key_data)
Definition: key_data.c:735
const key_data_t * key_data_list_next(key_data_list_t *key_data_list)
Definition: key_data.c:2359
unsigned int key_data_algorithm(const key_data_t *key_data)
Definition: key_data.c:687
key_data_role
Definition: key_data.h:40
@ KEY_DATA_ROLE_ZSK
Definition: key_data.h:43
@ KEY_DATA_ROLE_KSK
Definition: key_data.h:42
@ KEY_DATA_ROLE_CSK
Definition: key_data.h:44
unsigned int policy_denial_iterations(const policy_t *policy)
Definition: policy.c:933
unsigned int policy_denial_optout(const policy_t *policy)
Definition: policy.c:901
unsigned int policy_signatures_validity_denial(const policy_t *policy)
Definition: policy.c:869
unsigned int policy_signatures_resign(const policy_t *policy)
Definition: policy.c:829
unsigned int policy_keys_ttl(const policy_t *policy)
Definition: policy.c:965
unsigned int policy_zone_soa_ttl(const policy_t *policy)
Definition: policy.c:1013
unsigned int policy_zone_soa_minimum(const policy_t *policy)
Definition: policy.c:1021
unsigned int policy_passthrough(const policy_t *policy)
Definition: policy.c:1085
const char * policy_denial_salt(const policy_t *policy)
Definition: policy.c:949
unsigned int policy_signatures_refresh(const policy_t *policy)
Definition: policy.c:837
unsigned int policy_denial_ttl(const policy_t *policy)
Definition: policy.c:909
unsigned int policy_signatures_max_zone_ttl(const policy_t *policy)
Definition: policy.c:885
const db_value_t * policy_id(const policy_t *policy)
Definition: policy.c:805
unsigned int policy_signatures_jitter(const policy_t *policy)
Definition: policy.c:845
unsigned int policy_signatures_inception_offset(const policy_t *policy)
Definition: policy.c:853
const char * policy_zone_soa_serial_text(const policy_t *policy)
Definition: policy.c:1029
unsigned int policy_denial_algorithm(const policy_t *policy)
Definition: policy.c:925
unsigned int policy_signatures_validity_default(const policy_t *policy)
Definition: policy.c:861
void policy_free(policy_t *policy)
Definition: policy.c:518
unsigned int policy_signatures_validity_keyset(const policy_t *policy)
Definition: policy.c:877
policy_denial_type
Definition: policy.h:40
@ POLICY_DENIAL_TYPE_NSEC
Definition: policy.h:42
@ POLICY_DENIAL_TYPE_NSEC3
Definition: policy.h:43
int signconf_export_zone(char const *zonename, db_connection_t *dbconn)
Definition: signconf_xml.c:57
int signconf_export_all(int sockfd, const db_connection_t *connection, int force)
Definition: signconf_xml.c:84
#define SIGNCONF_EXPORT_ERR_DATABASE
Definition: signconf_xml.h:52
#define SIGNCONF_EXPORT_ERR_MEMORY
Definition: signconf_xml.h:56
#define SIGNCONF_EXPORT_NO_CHANGE
Definition: signconf_xml.h:64
#define SIGNCONF_EXPORT_ERR_ARGS
Definition: signconf_xml.h:44
#define SIGNCONF_EXPORT_ERR_FILE
Definition: signconf_xml.h:60
#define SIGNCONF_EXPORT_OK
Definition: signconf_xml.h:40
#define SIGNCONF_EXPORT_ERR_XML
Definition: signconf_xml.h:48
Definition: policy.h:60
void zone_db_free(zone_db_t *zone)
Definition: zone_db.c:325
int zone_db_set_signconf_needs_writing(zone_db_t *zone, unsigned int signconf_needs_writing)
Definition: zone_db.c:959
const char * zone_db_signconf_path(const zone_db_t *zone)
Definition: zone_db.c:798
const db_value_t * zone_db_policy_id(const zone_db_t *zone)
Definition: zone_db.c:736
policy_t * zone_db_get_policy(const zone_db_t *zone)
Definition: zone_db.c:744
const char * zone_db_name(const zone_db_t *zone)
Definition: zone_db.c:782
zone_db_t * zone_list_db_get_next(zone_list_db_t *zone_list)
Definition: zone_db.c:2669
zone_list_db_t * zone_list_db_new(const db_connection_t *connection)
Definition: zone_db.c:1946
int zone_db_update(zone_db_t *zone)
Definition: zone_db.c:1589
int zone_list_db_get(zone_list_db_t *zone_list)
Definition: zone_db.c:2363
unsigned int zone_db_signconf_needs_writing(const zone_db_t *zone)
Definition: zone_db.c:790
zone_db_t * zone_db_new_get_by_name(const db_connection_t *connection, const char *name)
Definition: zone_db.c:1569
void zone_list_db_free(zone_list_db_t *zone_list)
Definition: zone_db.c:1989
key_data_list_t * zone_db_get_keys(const zone_db_t *zone)
Definition: zone_db_ext.c:56