OpenDNSSEC-signer 1.2.1
|
00001 /* 00002 * $Id: zonelistparser.c 4294 2011-01-13 19:58:29Z jakob $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "adapter/adapter.h" 00035 #include "parser/zonelistparser.h" 00036 #include "signer/zonelist.h" 00037 #include "signer/zone.h" 00038 #include "util/file.h" 00039 #include "util/log.h" 00040 #include "util/se_malloc.h" 00041 00042 #include <libxml/xpath.h> /* xmlXPath*() */ 00043 #include <libxml/xmlreader.h> /* xmlNewTextReaderFilename(), xmlTextReader*(), xmlNodeGetContent(), 00044 xmlFreeTextReader(), xmlFreeDoc(), xmlStrEqual() */ 00045 #include <string.h> /* strlen() */ 00046 00047 00052 static const char* 00053 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr) 00054 { 00055 xmlXPathObjectPtr xpathObj = NULL; 00056 const char* str = NULL; 00057 00058 se_log_assert(xpathCtx); 00059 se_log_assert(expr); 00060 00061 xpathObj = xmlXPathEvalExpression(expr, xpathCtx); 00062 if (xpathObj == NULL) { 00063 se_log_error("unable to evaluate xpath expression %s", expr); 00064 return NULL; 00065 } 00066 str = (const char*) xmlXPathCastToString(xpathObj); 00067 xmlXPathFreeObject(xpathObj); 00068 return str; 00069 } 00070 00071 00076 static adapter_type* 00077 parse_zonelist_adapters_expr(xmlXPathContextPtr xpathCtx, xmlChar* expr, 00078 int inbound) 00079 { 00080 xmlXPathObjectPtr xpathObj = NULL; 00081 xmlNode* curNode = NULL; 00082 adapter_type* adapter = NULL; 00083 char* file = NULL; 00084 int i = 0; 00085 00086 se_log_assert(xpathCtx); 00087 se_log_assert(expr); 00088 00089 xpathObj = xmlXPathEvalExpression(expr, xpathCtx); 00090 if (xpathObj == NULL) { 00091 se_log_error("unable to evaluate xpath expression %s", expr); 00092 return NULL; 00093 } 00094 00095 if (xpathObj->nodesetval) { 00096 for (i=0; i < xpathObj->nodesetval->nodeNr; i++) { 00097 file = NULL; 00098 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 00099 while (curNode) { 00100 if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) { 00101 if (file) { 00102 se_free((void*)file); 00103 } 00104 file = (char*) xmlNodeGetContent(curNode); 00105 } 00106 curNode = curNode->next; 00107 } 00108 if (file) { 00109 if (!adapter) { 00110 adapter = adapter_create(file, ADAPTER_FILE, inbound); 00111 } else { 00112 /* [TODO] fix this ugly hack, possible bug in libxml2 ? */ 00113 } 00114 se_free((void*)file); 00115 } 00116 } 00117 } 00118 xmlXPathFreeObject(xpathObj); 00119 return adapter; 00120 } 00121 00122 00127 static void 00128 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone) 00129 { 00130 xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input"; 00131 xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output"; 00132 00133 se_log_assert(xpathCtx); 00134 se_log_assert(zone); 00135 00136 zone->inbound_adapter = 00137 parse_zonelist_adapters_expr(xpathCtx, i_expr, 1); 00138 zone->outbound_adapter = 00139 parse_zonelist_adapters_expr(xpathCtx, o_expr, 0); 00140 return; 00141 } 00142 00143 00148 struct zonelist_struct* 00149 parse_zonelist_zones(const char* zlfile) 00150 { 00151 char* tag_name = NULL; 00152 char* zone_name = NULL; 00153 zone_type* new_zone = NULL; 00154 int ret = 0; 00155 zonelist_type* zl = (zonelist_type*) zonelist_create(); 00156 00157 xmlTextReaderPtr reader = NULL; 00158 xmlDocPtr doc = NULL; 00159 xmlXPathContextPtr xpathCtx = NULL; 00160 00161 xmlChar* name_expr = (unsigned char*) "name"; 00162 xmlChar* policy_expr = (unsigned char*) "//Zone/Policy"; 00163 xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration"; 00164 00165 se_log_assert(zlfile); 00166 00167 reader = xmlNewTextReaderFilename(zlfile); 00168 if (!reader) { 00169 se_log_error("unable to open zone list file %s", zlfile?zlfile:"(null)"); 00170 zonelist_cleanup(zl); 00171 return NULL; 00172 } 00173 00174 ret = xmlTextReaderRead(reader); 00175 while (ret == XML_READER_TYPE_ELEMENT) { 00176 tag_name = (char*) xmlTextReaderLocalName(reader); 00177 if (se_strcmp(tag_name, "Zone") == 0 && 00178 se_strcmp(tag_name, "ZoneList") != 0 && 00179 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { 00180 /* Found a zone */ 00181 zone_name = (char*) xmlTextReaderGetAttribute(reader, 00182 name_expr); 00183 if (!zone_name || strlen(zone_name) <= 0) { 00184 se_log_error("unable to extract zone name from zonelist"); 00185 if (zone_name) { 00186 se_free((void*) zone_name); 00187 } 00188 se_free((void*) tag_name); 00189 ret = xmlTextReaderRead(reader); 00190 continue; 00191 } 00192 00193 /* Expand this node to get the rest of the info */ 00194 xmlTextReaderExpand(reader); 00195 doc = xmlTextReaderCurrentDoc(reader); 00196 if (doc) { 00197 xpathCtx = xmlXPathNewContext(doc); 00198 } 00199 if (doc == NULL || xpathCtx == NULL) { 00200 se_log_error("unable to read zone %s; skipping", 00201 zone_name); 00202 se_free((void*) zone_name); 00203 ret = xmlTextReaderRead(reader); 00204 se_free((void*) tag_name); 00205 continue; 00206 } 00207 00208 /* That worked, now read out the contents */ 00209 new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN); 00210 new_zone->policy_name = parse_zonelist_element(xpathCtx, 00211 policy_expr); 00212 new_zone->signconf_filename = parse_zonelist_element(xpathCtx, 00213 signconf_expr); 00214 parse_zonelist_adapters(xpathCtx, new_zone); 00215 00216 /* and add it to the list */ 00217 if (zonelist_add_zone(zl, new_zone) == NULL) { 00218 se_log_error("unable to add zone %s to zone list", zone_name); 00219 } 00220 se_free((void*) zone_name); 00221 xmlXPathFreeContext(xpathCtx); 00222 } 00223 se_free((void*) tag_name); 00224 ret = xmlTextReaderRead(reader); 00225 } 00226 /* no more zones */ 00227 se_log_debug("no more zones"); 00228 xmlFreeTextReader(reader); 00229 if (ret != 0) { 00230 se_log_error("error parsing zone list file %s", zlfile?zlfile:"(null)"); 00231 } 00232 if (doc) { 00233 xmlFreeDoc(doc); 00234 } 00235 return zl; 00236 }