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
27 /**
28 * Parsing DNS Adapter.
29 *
30 */
31
32 #include "parser/addnsparser.h"
33 #include "log.h"
34
35 #include <libxml/xpath.h>
36 #include <libxml/xmlreader.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 static const char* parser_str = "parser";
41
42
43 /**
44 * Parse the remote servers.
45 *
46 */
47 static acl_type*
parse_addns_remote(const char * filename,tsig_type * tsig,char * expr)48 parse_addns_remote(const char* filename,
49 tsig_type* tsig, char* expr)
50 {
51 acl_type* acl = NULL;
52 acl_type* new_acl = NULL;
53 int i = 0;
54 char* address = NULL;
55 char* port = NULL;
56 char* key = NULL;
57 xmlDocPtr doc = NULL;
58 xmlXPathContextPtr xpathCtx = NULL;
59 xmlXPathObjectPtr xpathObj = NULL;
60 xmlNode* curNode = NULL;
61 xmlChar* xexpr = NULL;
62
63 if (!filename || !expr) {
64 return NULL;
65 }
66 /* Load XML document */
67 doc = xmlParseFile(filename);
68 if (doc == NULL) {
69 ods_log_error("[%s] could not parse %s: xmlParseFile() failed",
70 parser_str, expr);
71 return NULL;
72 }
73 /* Create xpath evaluation context */
74 xpathCtx = xmlXPathNewContext(doc);
75 if(xpathCtx == NULL) {
76 xmlFreeDoc(doc);
77 ods_log_error("[%s] could not parse %s: xmlXPathNewContext() failed",
78 parser_str, expr);
79 return NULL;
80 }
81 /* Evaluate xpath expression */
82 xexpr = (xmlChar*) expr;
83 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
84 if(xpathObj == NULL) {
85 xmlXPathFreeContext(xpathCtx);
86 xmlFreeDoc(doc);
87 ods_log_error("[%s] could not parse %s: xmlXPathEvalExpression() "
88 "failed", parser_str, expr);
89 return NULL;
90 }
91 /* Parse interfaces */
92 if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
93 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
94 address = NULL;
95 port = NULL;
96 key = NULL;
97
98 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
99 while (curNode) {
100 if (xmlStrEqual(curNode->name, (const xmlChar *)"Address")) {
101 address = (char *) xmlNodeGetContent(curNode);
102 } else if (xmlStrEqual(curNode->name,
103 (const xmlChar *)"Port")) {
104 port = (char *) xmlNodeGetContent(curNode);
105 } else if (xmlStrEqual(curNode->name,
106 (const xmlChar *)"Key")) {
107 key = (char *) xmlNodeGetContent(curNode);
108 }
109 curNode = curNode->next;
110 }
111 if (address) {
112 new_acl = acl_create(address, port, key, tsig);
113 if (!new_acl) {
114 ods_log_error("[%s] unable to add server %s:%s %s to list "
115 "%s: acl_create() failed", parser_str, address,
116 port?port:"", key?key:"", (char*) expr);
117 } else {
118 new_acl->next = acl;
119 acl = new_acl;
120 ods_log_debug("[%s] added server %s:%s %s to list %s",
121 parser_str, address, port?port:"", key?key:"",
122 (char*) expr);
123 }
124 }
125 free((void*)address);
126 free((void*)port);
127 free((void*)key);
128 }
129 }
130 xmlXPathFreeObject(xpathObj);
131 xmlXPathFreeContext(xpathCtx);
132 if (doc) {
133 xmlFreeDoc(doc);
134 }
135 return acl;
136 }
137
138
139 /**
140 * Parse the ACL interfaces.
141 *
142 */
143 static acl_type*
parse_addns_acl(const char * filename,tsig_type * tsig,char * expr)144 parse_addns_acl(const char* filename,
145 tsig_type* tsig, char* expr)
146 {
147 acl_type* acl = NULL;
148 acl_type* new_acl = NULL;
149 int i = 0;
150 char* prefix = NULL;
151 char* key = NULL;
152 xmlDocPtr doc = NULL;
153 xmlXPathContextPtr xpathCtx = NULL;
154 xmlXPathObjectPtr xpathObj = NULL;
155 xmlNode* curNode = NULL;
156 xmlChar* xexpr = NULL;
157
158 if (!filename || !expr) {
159 return NULL;
160 }
161 /* Load XML document */
162 doc = xmlParseFile(filename);
163 if (doc == NULL) {
164 ods_log_error("[%s] could not parse %s: xmlParseFile() failed",
165 parser_str, expr);
166 return NULL;
167 }
168 /* Create xpath evaluation context */
169 xpathCtx = xmlXPathNewContext(doc);
170 if(xpathCtx == NULL) {
171 xmlFreeDoc(doc);
172 ods_log_error("[%s] could not parse %s: xmlXPathNewContext() failed",
173 parser_str, expr);
174 return NULL;
175 }
176 /* Evaluate xpath expression */
177 xexpr = (xmlChar*) expr;
178 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
179 if(xpathObj == NULL) {
180 xmlXPathFreeContext(xpathCtx);
181 xmlFreeDoc(doc);
182 ods_log_error("[%s] could not parse %s: xmlXPathEvalExpression() "
183 "failed", parser_str, expr);
184 return NULL;
185 }
186 /* Parse interfaces */
187 if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
188 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
189 prefix = NULL;
190 key = NULL;
191
192 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
193 while (curNode) {
194 if (xmlStrEqual(curNode->name, (const xmlChar *)"Prefix")) {
195 prefix = (char *) xmlNodeGetContent(curNode);
196 } else if (xmlStrEqual(curNode->name,
197 (const xmlChar *)"Key")) {
198 key = (char *) xmlNodeGetContent(curNode);
199 }
200 curNode = curNode->next;
201 }
202 if (prefix || key) {
203 new_acl = acl_create(prefix, NULL, key, tsig);
204 if (!new_acl) {
205 ods_log_error("[%s] unable to add acl for %s %s to list "
206 "%s: acl_create() failed", parser_str, prefix?prefix:"",
207 key?key:"", (char*) expr);
208 } else {
209 new_acl->next = acl;
210 acl = new_acl;
211 ods_log_debug("[%s] added %s %s interface to list %s",
212 parser_str, prefix?prefix:"", key?key:"", (char*) expr);
213 }
214 }
215 free((void*)prefix);
216 free((void*)key);
217 }
218 }
219 xmlXPathFreeObject(xpathObj);
220 xmlXPathFreeContext(xpathCtx);
221 if (doc) {
222 xmlFreeDoc(doc);
223 }
224 return acl;
225 }
226
227
228 /**
229 * Parse the TSIG credentials.
230 *
231 */
232 static tsig_type*
parse_addns_tsig_static(const char * filename,char * expr)233 parse_addns_tsig_static(const char* filename,
234 char* expr)
235 {
236 tsig_type* tsig = NULL;
237 tsig_type* new_tsig = NULL;
238 int i = 0;
239 char* name = NULL;
240 char* algo = NULL;
241 char* secret = NULL;
242 xmlDocPtr doc = NULL;
243 xmlXPathContextPtr xpathCtx = NULL;
244 xmlXPathObjectPtr xpathObj = NULL;
245 xmlNode* curNode = NULL;
246 xmlChar* xexpr = NULL;
247
248 if (!filename || !expr) {
249 return NULL;
250 }
251 /* Load XML document */
252 doc = xmlParseFile(filename);
253 if (doc == NULL) {
254 ods_log_error("[%s] could not parse %s: xmlParseFile() failed",
255 parser_str, expr);
256 return NULL;
257 }
258 /* Create xpath evaluation context */
259 xpathCtx = xmlXPathNewContext(doc);
260 if(xpathCtx == NULL) {
261 xmlFreeDoc(doc);
262 ods_log_error("[%s] could not parse %s: xmlXPathNewContext() failed",
263 parser_str, expr);
264 return NULL;
265 }
266 /* Evaluate xpath expression */
267 xexpr = (xmlChar*) expr;
268 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
269 if(xpathObj == NULL) {
270 xmlXPathFreeContext(xpathCtx);
271 xmlFreeDoc(doc);
272 ods_log_error("[%s] could not parse %s: xmlXPathEvalExpression() "
273 "failed", parser_str, expr);
274 return NULL;
275 }
276 /* Parse interfaces */
277 if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
278 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
279 name = NULL;
280 algo = NULL;
281 secret = NULL;
282
283 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
284 while (curNode) {
285 if (xmlStrEqual(curNode->name, (const xmlChar *)"Name")) {
286 name = (char *) xmlNodeGetContent(curNode);
287 } else if (xmlStrEqual(curNode->name,
288 (const xmlChar *)"Algorithm")) {
289 algo = (char *) xmlNodeGetContent(curNode);
290 } else if (xmlStrEqual(curNode->name,
291 (const xmlChar *)"Secret")) {
292 secret = (char *) xmlNodeGetContent(curNode);
293 }
294 curNode = curNode->next;
295 }
296 if (name && algo && secret) {
297 new_tsig = tsig_create(name, algo, secret);
298 if (!new_tsig) {
299 ods_log_error("[%s] unable to add tsig %s: "
300 "tsig_create() failed", parser_str, name);
301 } else {
302 new_tsig->next = tsig;
303 tsig = new_tsig;
304 ods_log_debug("[%s] added %s tsig to list %s",
305 parser_str, name, (char*) expr);
306 }
307 }
308 free((void*)name);
309 free((void*)algo);
310 free((void*)secret);
311 }
312 }
313 xmlXPathFreeObject(xpathObj);
314 xmlXPathFreeContext(xpathCtx);
315 if (doc) {
316 xmlFreeDoc(doc);
317 }
318 return tsig;
319 }
320
321
322 /**
323 * Parse <RequestTransfer/>.
324 *
325 */
326 acl_type*
parse_addns_request_xfr(const char * filename,tsig_type * tsig)327 parse_addns_request_xfr(const char* filename,
328 tsig_type* tsig)
329 {
330 return parse_addns_remote(filename, tsig,
331 (char *)"//Adapter/DNS/Inbound/RequestTransfer/Remote");
332 }
333
334
335 /**
336 * Parse <AllowNotify/>.
337 *
338 */
339 acl_type*
parse_addns_allow_notify(const char * filename,tsig_type * tsig)340 parse_addns_allow_notify(const char* filename,
341 tsig_type* tsig)
342 {
343 return parse_addns_acl(filename, tsig,
344 (char *)"//Adapter/DNS/Inbound/AllowNotify/Peer");
345 }
346
347
348 /**
349 * Parse <ProvideTransfer/>.
350 *
351 */
352 acl_type*
parse_addns_provide_xfr(const char * filename,tsig_type * tsig)353 parse_addns_provide_xfr(const char* filename,
354 tsig_type* tsig)
355 {
356 return parse_addns_acl(filename, tsig,
357 (char *)"//Adapter/DNS/Outbound/ProvideTransfer/Peer");
358 }
359
360
361 /**
362 * Parse <Notify/>.
363 *
364 */
365 acl_type*
parse_addns_do_notify(const char * filename,tsig_type * tsig)366 parse_addns_do_notify(const char* filename,
367 tsig_type* tsig)
368 {
369 return parse_addns_remote(filename, tsig,
370 (char *)"//Adapter/DNS/Outbound/Notify/Remote");
371 }
372
373
374 /**
375 * Parse <TSIG/>.
376 *
377 */
378 tsig_type*
parse_addns_tsig(const char * filename)379 parse_addns_tsig(const char* filename)
380 {
381 return parse_addns_tsig_static(filename,
382 (char *)"//Adapter/DNS/TSIG");
383 }
384
385