OpenDNSSEC-enforcer 2.1.12
zonelist_import.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 "config.h"
30
31#include "log.h"
32#include "clientpipe.h"
33#include "db/zone_db.h"
34#include "db/key_data.h"
35#include "db/key_state.h"
36#include "utils/kc_helper.h"
38
40
41#include <string.h>
42#include <libxml/parser.h>
43#include <libxml/tree.h>
44
45static const char* module_str = "zonelist_import";
46
50 char* name;
52};
53
54int zonelist_import(int sockfd, engine_type* engine, db_connection_t *dbconn,
55 int do_delete, const char* zonelist_path)
56{
57 xmlDocPtr doc;
58 xmlNodePtr root;
59 xmlNodePtr node;
60 xmlChar* name;
61 int updated;
62 int database_error = 0;
63 int xml_error = 0;
64 zone_db_t* zone;
65 const zone_db_t* zone_walk;
66 zone_list_db_t* zone_list;
67 struct __zonelist_import_zone* zones = NULL;
68 struct __zonelist_import_zone* zone2;
69 int successful;
74 int any_update = 0;
75
76 if (!engine) {
78 }
79 if (!engine->config) {
81 }
82 if (!engine->config->zonelist_filename) {
84 }
85 if (!dbconn) {
87 }
88
89 /*
90 * Retrieve all the current zones so they can be marked processed later and
91 * then the unprocessed can be deleted
92 */
93 if (!(zone_list = zone_list_db_new_get(dbconn))) {
94 client_printf_err(sockfd, "Unable to fetch all the current zones in the database!\n");
96 }
97 for (zone_walk = zone_list_db_next(zone_list); zone_walk; zone_walk = zone_list_db_next(zone_list)) {
98 if (!(zone2 = calloc(1, sizeof(struct __zonelist_import_zone)))
99 || !(zone2->name = strdup(zone_db_name(zone_walk))))
100 {
101 client_printf_err(sockfd, "Memory allocation error!\n");
102 zone_list_db_free(zone_list);
103 if (zone2) {
104 free(zone2);
105 }
106 for (zone2 = zones; zone2; zone2 = zones) {
107 free(zone2->name);
108 zones = zone2->next;
109 free(zone2);
110 }
112 }
113
114 zone2->next = zones;
115 zones = zone2;
116 }
117 zone_list_db_free(zone_list);
118
119 /*
120 * Validate, parse and walk the XML.
121 */
122 if (!zonelist_path)
123 zonelist_path = engine->config->zonelist_filename;
124
125 if (check_zonelist(zonelist_path, 0, NULL, 0)) {
126 client_printf_err(sockfd, "Unable to validate the zonelist XML!\n");
127 for (zone2 = zones; zone2; zone2 = zones) {
128 free(zone2->name);
129 zones = zone2->next;
130 free(zone2);
131 }
133 }
134
135 if (!(doc = xmlParseFile(zonelist_path))) {
136 client_printf_err(sockfd, "Unable to read/parse zonelist XML file %s!\n",
137 zonelist_path);
138 for (zone2 = zones; zone2; zone2 = zones) {
139 free(zone2->name);
140 zones = zone2->next;
141 free(zone2);
142 }
144 }
145
146 if (!(root = xmlDocGetRootElement(doc))) {
147 client_printf_err(sockfd, "Unable to get the root element in the zonelist XML!\n");
148 xmlFreeDoc(doc);
149 for (zone2 = zones; zone2; zone2 = zones) {
150 free(zone2->name);
151 zones = zone2->next;
152 free(zone2);
153 }
155 }
156
157 for (; root; root = root->next) {
158 if (root->type != XML_ELEMENT_NODE) {
159 continue;
160 }
161
162 if (!strcmp((char*)root->name, "ZoneList")) {
163 for (node = root->children; node; node = node->next) {
164 if (node->type != XML_ELEMENT_NODE) {
165 continue;
166 }
167 if (strcmp((char*)node->name, "Zone")) {
168 continue;
169 }
170
171 if (!(name = xmlGetProp(node, (const xmlChar*)"name"))) {
172 client_printf_err(sockfd, "Invalid Zone element in zonelist XML!\n");
173 xmlFreeDoc(doc);
174 for (zone2 = zones; zone2; zone2 = zones) {
175 free(zone2->name);
176 zones = zone2->next;
177 free(zone2);
178 }
180 }
181
182 if (!(zone = zone_db_new(dbconn))) {
183 client_printf_err(sockfd, "Memory allocation error!\n");
184 xmlFree(name);
185 xmlFreeDoc(doc);
186 for (zone2 = zones; zone2; zone2 = zones) {
187 free(zone2->name);
188 zones = zone2->next;
189 free(zone2);
190 }
192 }
193
194 /*
195 * Fetch the zone by name, if we can't find it create a new
196 * one otherwise update the existing one
197 */
198 if (zone_db_get_by_name(zone, (char*)name)) {
199 if (zone_db_create_from_xml(zone, node)) {
200 client_printf_err(sockfd,
201 "Unable to create zone %s from XML, XML content may be invalid!\n",
202 (char*)name);
203 zone_db_free(zone);
204 xmlFree(name);
205 xml_error = 1;
206 continue;
207 }
208
209 if (zone_db_create(zone)) {
210 client_printf_err(sockfd,
211 "Unable to create zone %s in the database!\n",
212 (char*)name);
213 zone_db_free(zone);
214 xmlFree(name);
215 database_error = 1;
216 continue;
217 }
218
219 if(!strcmp(zone_db_input_adapter_type(zone),"File")){
220 if(access(zone_db_input_adapter_uri(zone), F_OK) == -1) {
221 client_printf_err(sockfd, "WARNING: The input file %s for zone %s does not currently exist. The zone will be added to the database anyway.\n", zone_db_input_adapter_uri(zone), zone_db_name(zone));
222 ods_log_warning("[%s] WARNING: The input file %s for zone %s does not currently exist. The zone will be added to the database anyway.", module_str, zone_db_input_adapter_uri(zone), zone_db_name(zone));
223 }
224 else if (access(zone_db_input_adapter_uri(zone), R_OK)) {
225 client_printf_err(sockfd, module_str, "WARNING: Read access to input file %s for zone %s denied! \n", zone_db_input_adapter_uri(zone), zone_db_name(zone));
226 ods_log_warning("[%s] WARNING: Read access to input file %s for zone %s denied!", module_str, zone_db_input_adapter_uri(zone), zone_db_name(zone));
227 }
228 }
229
230 ods_log_info("[%s] zone %s created", module_str, (char*)name);
231 client_printf(sockfd, "Zone %s created successfully\n",
232 (char*)name);
233 any_update = 1;
234 }
235 else {
236 /*
237 * Mark it processed even if update fails so its not deleted
238 */
239 for (zone2 = zones; zone2; zone2 = zone2->next) {
240 if (zone2->processed) {
241 continue;
242 }
243 if (!strcmp(zone2->name, (char*)name)) {
244 zone2->processed = 1;
245 break;
246 }
247 }
248
249 /*
250 * Update the zone, if any data has changed then updated
251 * will be set to non-zero and if so we update the database
252 */
253 if (zone_db_update_from_xml(zone, node, &updated)) {
254 client_printf_err(sockfd,
255 "Unable to update zone %s from XML, XML content may be invalid!\n",
256 (char*)name);
257 zone_db_free(zone);
258 xmlFree(name);
259 xml_error = 1;
260 for (zone2 = zones; zone2; zone2 = zones) {
261 free(zone2->name);
262 zones = zone2->next;
263 free(zone2);
264 }
265 continue;
266 }
267
268 /*
269 * Update the zone in the database
270 */
271 if (updated) {
272 if (zone_db_update(zone)) {
273 client_printf_err(sockfd, "Unable to update zone %s in database!\n",
274 (char*)name);
275 zone_db_free(zone);
276 xmlFree(name);
277 database_error = 1;
278 continue;
279 }
280
281 ods_log_info("[%s] zone %s updated", module_str, (char*)name);
282 client_printf(sockfd, "Updated zone %s successfully\n",
283 (char*)name);
284 any_update = 1;
285 }
286 else {
287 client_printf(sockfd, "Zone %s already up-to-date\n",
288 (char*)name);
289 }
290 }
291 zone_db_free(zone);
292 xmlFree(name);
293 }
294 }
295 }
296
297 if (do_delete) {
298 /*
299 * Delete zones that have not been processed
300 */
301 for (zone2 = zones; zone2; zone2 = zone2->next) {
302 if (zone2->processed) {
303 continue;
304 }
305
306 if (!(zone = zone_db_new(dbconn))) {
307 client_printf_err(sockfd, "Memory allocation error!\n");
308 xmlFreeDoc(doc);
309 for (zone2 = zones; zone2; zone2 = zones) {
310 free(zone2->name);
311 zones = zone2->next;
312 free(zone2);
313 }
315 }
316
317 /*
318 * Fetch the zone by name, if it exists we try and delete it
319 */
320 if (!zone_db_get_by_name(zone, zone2->name)) {
321 /*
322 * Get key data for the zone and for each key data get the key state
323 * and try to delete all key state then the key data
324 */
326 client_printf_err(sockfd, "Unable to get key data for zone %s from database!\n", zone2->name);
327 zone_db_free(zone);
328 database_error = 1;
329 continue;
330 }
331 successful = 1;
334 client_printf_err(sockfd, "Unable to get key states for key data %s of zone %s from database!\n", key_data_role_text(key_data), zone2->name);
335 database_error = 1;
336 successful = 0;
337 continue;
338 }
339
342 client_printf_err(sockfd, "Unable to delete key state %s for key data %s of zone %s from database!\n", key_state_type_text(key_state), key_data_role_text(key_data), zone2->name);
343 database_error = 1;
344 successful = 0;
345 continue;
346 }
347 }
349
351 client_printf_err(sockfd, "Unable to delete key data %s of zone %s from database!\n", key_data_role_text(key_data), zone2->name);
352 database_error = 1;
353 successful = 0;
354 continue;
355 }
356
358 client_printf_err(sockfd, "Unable to release HSM key for key data %s of zone %s from database!\n", key_data_role_text(key_data), zone2->name);
359 successful = 0;
360 continue;
361 }
362 }
364
365 if (!successful) {
366 zone_db_free(zone);
367 continue;
368 }
369 if (zone_db_delete(zone)) {
370 client_printf_err(sockfd, "Unable to delete zone %s from database!\n", zone2->name);
371 zone_db_free(zone);
372 database_error = 1;
373 continue;
374 }
375
376 ods_log_info("[%s] zone %s deleted", module_str, zone2->name);
377 client_printf(sockfd, "Deleted zone %s successfully\n", zone2->name);
378 }
379 else {
380 client_printf_err(sockfd, "Unable to delete zone %s from database!\n", zone2->name);
381 database_error = 1;
382 }
383 zone_db_free(zone);
384 }
385 }
386
387 if (any_update && !engine->config->manual_keygen) {
389 }
390
391 for (zone2 = zones; zone2; zone2 = zones) {
392 free(zone2->name);
393 zones = zone2->next;
394 free(zone2);
395 }
396 xmlFreeDoc(doc);
397 if (database_error) {
399 }
400 if (xml_error) {
402 }
403 if (!any_update) {
405 }
406 return ZONELIST_IMPORT_OK;
407}
int hsm_key_factory_release_key_id(const db_value_t *hsm_key_id, const db_connection_t *connection)
int hsm_key_factory_schedule_generate_all(engine_type *engine, time_t duration)
int check_zonelist(const char *zonelist, int verbose, char **policy_names, int policy_count)
Definition: kc_helper.c:1673
const db_value_t * key_data_id(const key_data_t *key_data)
Definition: key_data.c:553
int key_data_delete(key_data_t *key_data)
Definition: key_data.c:1587
void key_data_free(key_data_t *key_data)
Definition: key_data.c:304
const char * key_data_role_text(const key_data_t *key_data)
Definition: key_data.c:711
void key_data_list_free(key_data_list_t *key_data_list)
Definition: key_data.c:1694
key_data_list_t * key_data_list_new_get_by_zone_id(const db_connection_t *connection, const db_value_t *zone_id)
Definition: key_data.c:2244
key_data_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition: key_data.c:2425
const db_value_t * key_data_hsm_key_id(const key_data_t *key_data)
Definition: key_data.c:607
key_state_t * key_state_list_get_next(key_state_list_t *key_state_list)
Definition: key_state.c:1398
int key_state_delete(const key_state_t *key_state)
Definition: key_state.c:831
void key_state_free(key_state_t *key_state)
Definition: key_state.c:214
key_state_list_t * key_state_list_new_get_by_key_data_id(const db_connection_t *connection, const db_value_t *key_data_id)
Definition: key_state.c:1217
void key_state_list_free(key_state_list_t *key_state_list)
Definition: key_state.c:924
const char * key_state_type_text(const key_state_t *key_state)
Definition: key_state.c:353
struct __zonelist_import_zone * next
engineconfig_type * config
Definition: engine.h:48
const char * zonelist_filename
Definition: cfg.h:57
int manual_keygen
Definition: cfg.h:74
zone_list_db_t * zone_list_db_new_get(const db_connection_t *connection)
Definition: zone_db.c:2402
void zone_db_free(zone_db_t *zone)
Definition: zone_db.c:325
int zone_db_delete(zone_db_t *zone)
Definition: zone_db.c:1884
const char * zone_db_name(const zone_db_t *zone)
Definition: zone_db.c:782
int zone_db_create(zone_db_t *zone)
Definition: zone_db.c:1206
const char * zone_db_input_adapter_uri(const zone_db_t *zone)
Definition: zone_db.c:870
int zone_db_update(zone_db_t *zone)
Definition: zone_db.c:1589
zone_db_t * zone_db_new(const db_connection_t *connection)
Definition: zone_db.c:287
const db_value_t * zone_db_id(const zone_db_t *zone)
Definition: zone_db.c:728
int zone_db_get_by_name(zone_db_t *zone, const char *name)
Definition: zone_db.c:1519
const zone_db_t * zone_list_db_next(zone_list_db_t *zone_list)
Definition: zone_db.c:2603
const char * zone_db_input_adapter_type(const zone_db_t *zone)
Definition: zone_db.c:862
void zone_list_db_free(zone_list_db_t *zone_list)
Definition: zone_db.c:1989
int zone_db_update_from_xml(zone_db_t *zone, xmlNodePtr zone_node, int *updated)
Definition: zone_db_ext.c:543
int zone_db_create_from_xml(zone_db_t *zone, xmlNodePtr zone_node)
Definition: zone_db_ext.c:532
int zonelist_import(int sockfd, engine_type *engine, db_connection_t *dbconn, int do_delete, const char *zonelist_path)
#define ZONELIST_IMPORT_NO_CHANGE
#define ZONELIST_IMPORT_ERR_DATABASE
#define ZONELIST_IMPORT_ERR_MEMORY
#define ZONELIST_IMPORT_OK
#define ZONELIST_IMPORT_ERR_XML
#define ZONELIST_IMPORT_ERR_ARGS