OpenDNSSEC-signer  1.3.9
zonelistparser.c
Go to the documentation of this file.
1 /*
2  * $Id: zonelistparser.c 5817 2011-10-26 14:35:36Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. 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 
34 #include "adapter/adapter.h"
35 #include "parser/zonelistparser.h"
36 #include "shared/file.h"
37 #include "shared/log.h"
38 #include "signer/zonelist.h"
39 #include "signer/zone.h"
40 #include "shared/status.h"
41 
42 #include <libxml/xpath.h>
43 #include <libxml/xmlreader.h>
44 #include <stdlib.h>
45 #include <string.h>
46 
47 static const char* parser_str = "parser";
48 
49 
54 static const char*
55 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr)
56 {
57  xmlXPathObjectPtr xpathObj = NULL;
58  const char* str = NULL;
59 
60  ods_log_assert(xpathCtx);
61  ods_log_assert(expr);
62 
63  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
64  if (xpathObj == NULL) {
65  ods_log_error("[%s] unable to evaluate xpath expression %s",
66  parser_str, expr);
67  return NULL;
68  }
69  str = (const char*) xmlXPathCastToString(xpathObj);
70  xmlXPathFreeObject(xpathObj);
71  return str;
72 }
73 
74 
79 static adapter_type*
80 zlp_adapter(xmlNode* curNode, adapter_mode type, int inbound)
81 {
82  const char* file = NULL;
83  adapter_type* adapter = NULL;
84 
85  file = (const char*) xmlNodeGetContent(curNode);
86  if (!file) {
87  ods_log_error("[%s] unable to read %s adapter", parser_str,
88  inbound?"input":"output");
89  return NULL;
90  }
91 
92  adapter = adapter_create(file, type, inbound);
93  free((void*)file);
94  return adapter;
95 }
96 
97 
103 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr,
104  int inbound)
105 {
106  xmlXPathObjectPtr xpathObj = NULL;
107  xmlNode* curNode = NULL;
108  adapter_type* adapter = NULL;
109  int i = 0;
110 
111  if (!xpathCtx || !expr) {
112  return NULL;
113  }
114 
115  xpathObj = xmlXPathEvalExpression(expr, xpathCtx);
116  if (xpathObj == NULL) {
117  ods_log_error("[%s] unable to evaluate xpath expression %s",
118  parser_str, expr);
119  return NULL;
120  }
121 
122  if (xpathObj->nodesetval) {
123  for (i=0; i < xpathObj->nodesetval->nodeNr; i++) {
124  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
125  while (curNode) {
126  if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) {
127  adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound);
128  }
129  if (adapter) {
130  break;
131  }
132  curNode = curNode->next;
133  }
134  }
135  }
136  xmlXPathFreeObject(xpathObj);
137  return adapter;
138 }
139 
140 
145 static void
146 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone)
147 {
148  xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input";
149  xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output";
150 
151  if (!xpathCtx || !zone) {
152  return;
153  }
154 
155  zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1);
156  zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0);
157  return;
158 }
159 
160 
166 parse_zonelist_zones(struct zonelist_struct* zlist, const char* zlfile)
167 {
168  char* tag_name = NULL;
169  char* zone_name = NULL;
170  zone_type* new_zone = NULL;
171  int ret = 0;
172  int error = 0;
173  xmlTextReaderPtr reader = NULL;
174  xmlDocPtr doc = NULL;
175  xmlXPathContextPtr xpathCtx = NULL;
176 
177  xmlChar* name_expr = (unsigned char*) "name";
178  xmlChar* policy_expr = (unsigned char*) "//Zone/Policy";
179  xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration";
180 
181  if (!zlist) {
182  ods_log_error("[%s] unable to parse zone list: no storage",
183  parser_str);
184  return ODS_STATUS_ASSERT_ERR;
185  }
186  ods_log_assert(zlist);
187 
188  if (!zlfile) {
189  ods_log_error("[%s] unable to parse zone list: no filename",
190  parser_str);
191  return ODS_STATUS_ASSERT_ERR;
192  }
193  ods_log_assert(zlfile);
194 
195  reader = xmlNewTextReaderFilename(zlfile);
196  if (!reader) {
197  ods_log_error("[%s] unable to open file %s", parser_str, zlfile);
198  return ODS_STATUS_XML_ERR;
199  }
200 
201  ret = xmlTextReaderRead(reader);
202  while (ret == XML_READER_TYPE_ELEMENT) {
203  tag_name = (char*) xmlTextReaderLocalName(reader);
204  if (ods_strcmp(tag_name, "Zone") == 0 &&
205  ods_strcmp(tag_name, "ZoneList") != 0 &&
206  xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
207  /* Found a zone */
208  zone_name = (char*) xmlTextReaderGetAttribute(reader,
209  name_expr);
210  if (!zone_name || strlen(zone_name) <= 0) {
211  ods_log_error("[%s] unable to extract zone name from "
212  "zonelist", parser_str);
213  if (zone_name) {
214  free((void*) zone_name);
215  }
216  free((void*) tag_name);
217  ret = xmlTextReaderRead(reader);
218  continue;
219  }
220 
221  /* Expand this node to get the rest of the info */
222  xmlTextReaderExpand(reader);
223  doc = xmlTextReaderCurrentDoc(reader);
224  if (doc) {
225  xpathCtx = xmlXPathNewContext(doc);
226  }
227  if (doc == NULL || xpathCtx == NULL) {
228  ods_log_error("[%s] unable to read zone %s; skipping",
229  parser_str, zone_name);
230  ret = xmlTextReaderRead(reader);
231  free((void*) zone_name);
232  free((void*) tag_name);
233  if (xpathCtx) {
234  xmlXPathFreeContext(xpathCtx);
235  xpathCtx = NULL;
236  }
237  continue;
238  }
239 
240  /* That worked, now read out the contents... */
241  new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN);
242  new_zone->policy_name = parse_zonelist_element(xpathCtx,
243  policy_expr);
244  new_zone->signconf_filename = parse_zonelist_element(xpathCtx,
245  signconf_expr);
246  parse_zonelist_adapters(xpathCtx, new_zone);
247  if (!new_zone->policy_name || !new_zone->signconf_filename ||
248  !new_zone->adinbound || !new_zone->adoutbound) {
249  zone_cleanup(new_zone);
250  new_zone = NULL;
251  ods_log_crit("[%s] unable to create zone %s", parser_str,
252  zone_name);
253  error = 1;
254  } else if (zonelist_add_zone((zonelist_type*) zlist, new_zone)
255  == NULL) {
256  ods_log_error("[%s] unable to add zone %s", parser_str,
257  zone_name);
258  zone_cleanup(new_zone);
259  new_zone = NULL;
260  error = 1;
261  }
262  xmlXPathFreeContext(xpathCtx);
263  xpathCtx = NULL;
264  free((void*) zone_name);
265  if (error) {
266  free((void*) tag_name);
267  tag_name = NULL;
268  ret = 1;
269  break;
270  }
271  ods_log_debug("[%s] zone %s added", parser_str, new_zone->name);
272  }
273  free((void*) tag_name);
274  ret = xmlTextReaderRead(reader);
275  }
276  /* no more zones */
277  ods_log_debug("[%s] no more zones", parser_str);
278  xmlFreeTextReader(reader);
279  if (doc) {
280  xmlFreeDoc(doc);
281  }
282  if (ret != 0) {
283  ods_log_error("[%s] error parsing file %s", parser_str, zlfile);
284  return ODS_STATUS_PARSE_ERR;
285  }
286  return ODS_STATUS_OK;
287 }