OpenDNSSEC-enforcer  2.0.2
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 "file.h"
35 #include "log.h"
36 #include "signer/zonelist.h"
37 #include "signer/zone.h"
38 #include "status.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 
83 static adapter_type*
84 parse_zonelist_adapter_file(xmlNode* curNode, int inbound)
85 {
86  const char* file = NULL;
87  adapter_type* adapter = NULL;
88 
89  file = (const char*) xmlNodeGetContent(curNode);
90  if (!file) {
91  ods_log_error("[%s] unable to read %s file adapter", parser_str,
92  inbound?"input":"output");
93  return NULL;
94  }
95 
96  adapter = adapter_create(file, ADAPTER_FILE, inbound);
97  free((void*)file);
98  return adapter;
99 }
100 
101 
106 static adapter_type*
107 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr,
108  int inbound)
109 {
110  xmlXPathObjectPtr xpathObj = NULL;
111  xmlNode* curNode = NULL;
112  adapter_type* adapter = NULL;
113  int i = 0;
114 
115  if (!xpathCtx || !expr) {
116  return NULL;
117  }
118 
119  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
120  if (xpathObj == NULL) {
121  ods_log_error("[%s] unable to evaluate xpath expression %s",
122  parser_str, expr);
123  return NULL;
124  }
125 
126  if (xpathObj->nodesetval) {
127  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
128  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
129  while (curNode) {
130  if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) {
131  adapter = parse_zonelist_adapter_file(curNode, inbound);
132  }
133  if (adapter) {
134  break;
135  }
136  curNode = curNode->next;
137  }
138  }
139  }
140  xmlXPathFreeObject(xpathObj);
141  return adapter;
142 }
143 
144 
149 static void
150 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone)
151 {
152  xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input";
153  xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output";
154 
155  if (!xpathCtx || !zone) {
156  return;
157  }
158 
159  zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1);
160  zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0);
161 }
162 
163 
168 ods_status
169 parse_zonelist_zones(struct zonelist_struct* zlist, const char* zlfile)
170 {
171  char* tag_name = NULL;
172  char* zone_name = NULL;
173  zone_type* new_zone = NULL;
174  int ret = 0;
175 
176  xmlTextReaderPtr reader = NULL;
177  xmlDocPtr doc = NULL;
178  xmlXPathContextPtr xpathCtx = NULL;
179 
180  xmlChar* name_expr = (unsigned char*) "name";
181  xmlChar* policy_expr = (unsigned char*) "//Zone/Policy";
182  xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration";
183 
184  if (!zlist) {
185  ods_log_error("[%s] unable to parse zone list: no storage",
186  parser_str);
187  return ODS_STATUS_ASSERT_ERR;
188  }
189  ods_log_assert(zlist);
190 
191  if (!zlfile) {
192  ods_log_error("[%s] unable to parse zone list: no filename",
193  parser_str);
194  return ODS_STATUS_ASSERT_ERR;
195  }
196  ods_log_assert(zlfile);
197 
198  reader = xmlNewTextReaderFilename(zlfile);
199  if (!reader) {
200  ods_log_error("[%s] unable to open file %s", parser_str, zlfile);
201  return ODS_STATUS_XML_ERR;
202  }
203 
204  ret = xmlTextReaderRead(reader);
205  while (ret == XML_READER_TYPE_ELEMENT) {
206  tag_name = (char*) xmlTextReaderLocalName(reader);
207  if (strcmp(tag_name, "Zone") == 0 &&
208  strcmp(tag_name, "ZoneList") != 0 &&
209  xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
210  /* Found a zone */
211  zone_name = (char*) xmlTextReaderGetAttribute(reader,
212  name_expr);
213  if (!zone_name || strlen(zone_name) <= 0) {
214  ods_log_error("[%s] unable to extract zone name from zonelist",
215  parser_str);
216  if (zone_name) {
217  free((void*) zone_name);
218  }
219  free((void*) tag_name);
220  ret = xmlTextReaderRead(reader);
221  continue;
222  }
223 
224  /* Expand this node to get the rest of the info */
225  xmlTextReaderExpand(reader);
226  doc = xmlTextReaderCurrentDoc(reader);
227  if (doc) {
228  xpathCtx = xmlXPathNewContext(doc);
229  }
230  if (doc == NULL || xpathCtx == NULL) {
231  ods_log_error("[%s] unable to read zone %s; skipping",
232  parser_str, zone_name);
233  free((void*) zone_name);
234  ret = xmlTextReaderRead(reader);
235  free((void*) tag_name);
236  continue;
237  }
238 
239  /* That worked, now read out the contents */
240  new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN);
241  new_zone->policy_name = parse_zonelist_element(xpathCtx,
242  policy_expr);
243  new_zone->signconf_filename = parse_zonelist_element(xpathCtx,
244  signconf_expr);
245  parse_zonelist_adapters(xpathCtx, new_zone);
246 
247  /* and add it to the list */
248  if (zonelist_add_zone((zonelist_type*) zlist, new_zone) == NULL) {
249  ods_log_error("[%s] unable to add zone %s", parser_str,
250  zone_name);
251  new_zone = NULL;
252  }
253  ods_log_debug("[%s] zone %s added", parser_str, zone_name);
254  free((void*) zone_name);
255  xmlXPathFreeContext(xpathCtx);
256  }
257  free((void*) tag_name);
258  ret = xmlTextReaderRead(reader);
259  }
260  /* no more zones */
261  ods_log_debug("[%s] no more zones", parser_str);
262  xmlFreeTextReader(reader);
263  if (doc) {
264  xmlFreeDoc(doc);
265  }
266  if (ret != 0) {
267  ods_log_error("[%s] error parsing file %s", parser_str, zlfile);
268  return ODS_STATUS_PARSE_ERR;
269  }
270  return ODS_STATUS_OK;
271 }
void ods_log_debug(const char *format,...)
Definition: log.c:41
void ods_log_error(const char *format,...)
Definition: log.c:69
const char * zone_name(const zone_t *zone)
Definition: zone.c:782
ods_status parse_zonelist_zones(struct zonelist_struct *zlist, const char *zlfile)
Definition: zone.h:46
int zone_create(zone_t *zone)
Definition: zone.c:1206