OpenDNSSEC-enforcer  2.1.4
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"
37 #include "hsmkey/hsm_key_factory.h"
38 
40 
41 #include <string.h>
42 #include <libxml/parser.h>
43 #include <libxml/tree.h>
44 
45 static const char* module_str = "zonelist_import";
46 
50  char* name;
51  int processed;
52 };
53 
54 int 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  */
325  if (!(key_data_list = key_data_list_new_get_by_zone_id(dbconn, zone_db_id(zone)))) {
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;
332  for (key_data = key_data_list_get_next(key_data_list); key_data; key_data_free(key_data), key_data = key_data_list_get_next(key_data_list)) {
333  if (!(key_state_list = key_state_list_new_get_by_key_data_id(dbconn, key_data_id(key_data)))) {
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 
340  for (key_state = key_state_list_get_next(key_state_list); key_state; key_state_free(key_state), key_state = key_state_list_get_next(key_state_list)) {
341  if (key_state_delete(key_state)) {
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  }
348  key_state_list_free(key_state_list);
349 
350  if (key_data_delete(key_data)) {
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 
357  if (hsm_key_factory_release_key_id(key_data_hsm_key_id(key_data), dbconn)) {
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  }
363  key_data_list_free(key_data_list);
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 }
const char * key_data_role_text(const key_data_t *key_data)
Definition: key_data.c:711
void zone_db_free(zone_db_t *zone)
Definition: zone_db.c:325
#define ZONELIST_IMPORT_OK
#define ZONELIST_IMPORT_ERR_DATABASE
int key_state_delete(const key_state_t *key_state)
Definition: key_state.c:831
int zonelist_import(int sockfd, engine_type *engine, db_connection_t *dbconn, int do_delete, const char *zonelist_path)
const char * key_state_type_text(const key_state_t *key_state)
Definition: key_state.c:353
const char * zonelist_filename
Definition: cfg.h:57
key_state_t * key_state_list_get_next(key_state_list_t *key_state_list)
Definition: key_state.c:1398
const db_value_t * key_data_id(const key_data_t *key_data)
Definition: key_data.c:553
int check_zonelist(const char *zonelist, int verbose, char **policy_names, int policy_count)
Definition: kc_helper.c:1664
#define ZONELIST_IMPORT_ERR_ARGS
int zone_db_create_from_xml(zone_db_t *zone, xmlNodePtr zone_node)
Definition: zone_db_ext.c:532
key_data_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition: key_data.c:2425
void zone_list_db_free(zone_list_db_t *zone_list)
Definition: zone_db.c:1989
const zone_db_t * zone_list_db_next(zone_list_db_t *zone_list)
Definition: zone_db.c:2603
int zone_db_create(zone_db_t *zone)
Definition: zone_db.c:1206
engineconfig_type * config
Definition: engine.h:48
void key_state_free(key_state_t *key_state)
Definition: key_state.c:214
#define ZONELIST_IMPORT_ERR_MEMORY
const char * zone_db_input_adapter_uri(const zone_db_t *zone)
Definition: zone_db.c:870
const char * zone_db_name(const zone_db_t *zone)
Definition: zone_db.c:782
int hsm_key_factory_schedule_generate_all(engine_type *engine, time_t duration)
void key_state_list_free(key_state_list_t *key_state_list)
Definition: key_state.c:924
struct __zonelist_import_zone * next
int manual_keygen
Definition: cfg.h:74
int zone_db_delete(zone_db_t *zone)
Definition: zone_db.c:1884
zone_list_db_t * zone_list_db_new_get(const db_connection_t *connection)
Definition: zone_db.c:2402
void key_data_list_free(key_data_list_t *key_data_list)
Definition: key_data.c:1694
const db_value_t * key_data_hsm_key_id(const key_data_t *key_data)
Definition: key_data.c:607
void key_data_free(key_data_t *key_data)
Definition: key_data.c:304
int zone_db_get_by_name(zone_db_t *zone, const char *name)
Definition: zone_db.c:1519
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
int zone_db_update_from_xml(zone_db_t *zone, xmlNodePtr zone_node, int *updated)
Definition: zone_db_ext.c:543
int zone_db_update(zone_db_t *zone)
Definition: zone_db.c:1589
const db_value_t * zone_db_id(const zone_db_t *zone)
Definition: zone_db.c:728
#define ZONELIST_IMPORT_NO_CHANGE
int key_data_delete(key_data_t *key_data)
Definition: key_data.c:1587
const char * zone_db_input_adapter_type(const zone_db_t *zone)
Definition: zone_db.c:862
#define ZONELIST_IMPORT_ERR_XML
int hsm_key_factory_release_key_id(const db_value_t *hsm_key_id, const db_connection_t *connection)
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
zone_db_t * zone_db_new(const db_connection_t *connection)
Definition: zone_db.c:287