OpenDNSSEC-signer  1.4.5
zonelistparser.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "adapter/adapter.h"
33 #include "parser/zonelistparser.h"
34 #include "shared/file.h"
35 #include "shared/log.h"
36 #include "shared/status.h"
37 #include "signer/zonelist.h"
38 #include "signer/zone.h"
39 
40 #include <libxml/xpath.h>
41 #include <libxml/xmlreader.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 static const char* parser_str = "parser";
46 
47 
52 static const char*
53 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr)
54 {
55  xmlXPathObjectPtr xpathObj = NULL;
56  const char* str = NULL;
57 
58  ods_log_assert(xpathCtx);
59  ods_log_assert(expr);
60 
61  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
62  if (xpathObj == NULL) {
63  ods_log_error("[%s] unable to evaluate xpath expression %s",
64  parser_str, expr);
65  return NULL;
66  }
67  str = (const char*) xmlXPathCastToString(xpathObj);
68  xmlXPathFreeObject(xpathObj);
69  return str;
70 }
71 
72 
77 static adapter_type*
78 zlp_adapter(xmlNode* curNode, adapter_mode type, unsigned inbound)
79 {
80  const char* file = NULL;
81  adapter_type* adapter = NULL;
82  file = (const char*) xmlNodeGetContent(curNode);
83  if (!file) {
84  ods_log_error("[%s] unable to read %s adapter", parser_str,
85  inbound?"input":"output");
86  return NULL;
87  }
88  adapter = adapter_create(file, type, inbound);
89  free((void*)file);
90  return adapter;
91 }
92 
93 
99 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr,
100  int inbound)
101 {
102  xmlXPathObjectPtr xpathObj = NULL;
103  xmlNode* curNode = NULL;
104  xmlChar* type = NULL;
105  adapter_type* adapter = NULL;
106  int i = 0;
107 
108  if (!xpathCtx || !expr) {
109  return NULL;
110  }
111  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
112  if (xpathObj == NULL) {
113  ods_log_error("[%s] unable to parse adapter: xmlPathEvalExpression() "
114  "failed (expr %s)", parser_str, expr);
115  return NULL;
116  }
117  if (xpathObj->nodesetval) {
118  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
119  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
120  while (curNode) {
121  if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) {
122  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
123  } else if (xmlStrEqual(curNode->name,
124  (const xmlChar*)"Adapter")) {
125  type = xmlGetProp(curNode, (const xmlChar*)"type");
126  if (xmlStrEqual(type, (const xmlChar*)"File")) {
127  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
128  } else if (xmlStrEqual(type, (const xmlChar*)"DNS")) {
129  adapter = zlp_adapter(curNode, ADAPTER_DNS, inbound);
130  } else {
131  ods_log_error("[%s] unable to parse %s adapter: "
132  "unknown type", parser_str, (const char*) type);
133  }
134  free((void*)type);
135  type = NULL;
136  }
137  if (adapter) {
138  break;
139  }
140  curNode = curNode->next;
141  }
142  }
143  }
144  xmlXPathFreeObject(xpathObj);
145  return adapter;
146 }
147 
148 
153 static void
154 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone)
155 {
156  xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input";
157  xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output";
158 
159  if (!xpathCtx || !zone) {
160  return;
161  }
162  zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1);
163  zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0);
164  return;
165 }
166 
167 
173 parse_zonelist_zones(void* zlist, const char* zlfile)
174 {
175  char* tag_name = NULL;
176  char* zone_name = NULL;
177  zone_type* new_zone = NULL;
178  int ret = 0;
179  int error = 0;
180  xmlTextReaderPtr reader = NULL;
181  xmlDocPtr doc = NULL;
182  xmlXPathContextPtr xpathCtx = NULL;
183  xmlChar* name_expr = (unsigned char*) "name";
184  xmlChar* policy_expr = (unsigned char*) "//Zone/Policy";
185  xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration";
186 
187  if (!zlist || !zlfile) {
188  return ODS_STATUS_ASSERT_ERR;
189  }
190  reader = xmlNewTextReaderFilename(zlfile);
191  if (!reader) {
192  ods_log_error("[%s] unable to parse zonelist: failed to open file %s",
193  parser_str, zlfile);
194  return ODS_STATUS_XML_ERR;
195  }
196  ret = xmlTextReaderRead(reader);
197  while (ret == XML_READER_TYPE_ELEMENT) {
198  tag_name = (char*) xmlTextReaderLocalName(reader);
199  if (ods_strcmp(tag_name, "Zone") == 0 &&
200  ods_strcmp(tag_name, "ZoneList") != 0 &&
201  xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
202  /* Found a zone */
203  zone_name = (char*) xmlTextReaderGetAttribute(reader,
204  name_expr);
205  if (!zone_name || strlen(zone_name) <= 0) {
206  ods_log_alert("[%s] unable to extract zone name from "
207  "zonelist %s, skipping...", parser_str, zlfile);
208  if (zone_name) {
209  free((void*) zone_name);
210  }
211  free((void*) tag_name);
212  ret = xmlTextReaderRead(reader);
213  continue;
214  }
215  /* Expand this node to get the rest of the info */
216  xmlTextReaderExpand(reader);
217  doc = xmlTextReaderCurrentDoc(reader);
218  if (doc) {
219  xpathCtx = xmlXPathNewContext(doc);
220  }
221  if (doc == NULL || xpathCtx == NULL) {
222  ods_log_alert("[%s] unable to read zone %s, skipping...",
223  parser_str, zone_name);
224  ret = xmlTextReaderRead(reader);
225  free((void*) zone_name);
226  free((void*) tag_name);
227  continue;
228  }
229  /* That worked, now read out the contents... */
230  new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN);
231  if (new_zone) {
232  new_zone->policy_name = parse_zonelist_element(xpathCtx,
233  policy_expr);
234  new_zone->signconf_filename = parse_zonelist_element(xpathCtx,
235  signconf_expr);
236  parse_zonelist_adapters(xpathCtx, new_zone);
237  if (!new_zone->policy_name || !new_zone->signconf_filename ||
238  !new_zone->adinbound || !new_zone->adoutbound) {
239  zone_cleanup(new_zone);
240  new_zone = NULL;
241  ods_log_crit("[%s] unable to create zone %s", parser_str,
242  zone_name);
243  error = 1;
244  } else if (zonelist_add_zone((zonelist_type*) zlist, new_zone)
245  == NULL) {
246  ods_log_crit("[%s] unable to add zone %s", parser_str,
247  zone_name);
248  zone_cleanup(new_zone);
249  new_zone = NULL;
250  error = 1;
251  }
252  } else {
253  ods_log_crit("[%s] unable to create zone %s", parser_str,
254  zone_name);
255  error = 1;
256  }
257  xmlXPathFreeContext(xpathCtx);
258  xpathCtx = NULL;
259  free((void*) zone_name);
260  if (error) {
261  free((void*) tag_name);
262  tag_name = NULL;
263  ret = 1;
264  break;
265  }
266  ods_log_debug("[%s] zone %s added", parser_str, new_zone->name);
267  }
268  free((void*) tag_name);
269  ret = xmlTextReaderRead(reader);
270  }
271  /* no more zones */
272  ods_log_debug("[%s] no more zones", parser_str);
273  xmlFreeTextReader(reader);
274  if (doc) {
275  xmlFreeDoc(doc);
276  }
277  if (ret != 0) {
278  ods_log_error("[%s] unable to parse zonelist: parse error in %s",
279  parser_str, zlfile);
280  return ODS_STATUS_PARSE_ERR;
281  }
282  return ODS_STATUS_OK;
283 }