OpenDNSSEC-signer
1.3.8
|
00001 /* 00002 * $Id: zonelistparser.c 5817 2011-10-26 14:35:36Z matthijs $ 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 "shared/file.h" 00037 #include "shared/log.h" 00038 #include "signer/zonelist.h" 00039 #include "signer/zone.h" 00040 #include "shared/status.h" 00041 00042 #include <libxml/xpath.h> 00043 #include <libxml/xmlreader.h> 00044 #include <stdlib.h> 00045 #include <string.h> 00046 00047 static const char* parser_str = "parser"; 00048 00049 00054 static const char* 00055 parse_zonelist_element(xmlXPathContextPtr xpathCtx, xmlChar* expr) 00056 { 00057 xmlXPathObjectPtr xpathObj = NULL; 00058 const char* str = NULL; 00059 00060 ods_log_assert(xpathCtx); 00061 ods_log_assert(expr); 00062 00063 xpathObj = xmlXPathEvalExpression(expr, xpathCtx); 00064 if (xpathObj == NULL) { 00065 ods_log_error("[%s] unable to evaluate xpath expression %s", 00066 parser_str, expr); 00067 return NULL; 00068 } 00069 str = (const char*) xmlXPathCastToString(xpathObj); 00070 xmlXPathFreeObject(xpathObj); 00071 return str; 00072 } 00073 00074 00079 static adapter_type* 00080 zlp_adapter(xmlNode* curNode, adapter_mode type, int inbound) 00081 { 00082 const char* file = NULL; 00083 adapter_type* adapter = NULL; 00084 00085 file = (const char*) xmlNodeGetContent(curNode); 00086 if (!file) { 00087 ods_log_error("[%s] unable to read %s adapter", parser_str, 00088 inbound?"input":"output"); 00089 return NULL; 00090 } 00091 00092 adapter = adapter_create(file, type, inbound); 00093 free((void*)file); 00094 return adapter; 00095 } 00096 00097 00102 adapter_type* 00103 parse_zonelist_adapter(xmlXPathContextPtr xpathCtx, xmlChar* expr, 00104 int inbound) 00105 { 00106 xmlXPathObjectPtr xpathObj = NULL; 00107 xmlNode* curNode = NULL; 00108 adapter_type* adapter = NULL; 00109 int i = 0; 00110 00111 if (!xpathCtx || !expr) { 00112 return NULL; 00113 } 00114 00115 xpathObj = xmlXPathEvalExpression(expr, xpathCtx); 00116 if (xpathObj == NULL) { 00117 ods_log_error("[%s] unable to evaluate xpath expression %s", 00118 parser_str, expr); 00119 return NULL; 00120 } 00121 00122 if (xpathObj->nodesetval) { 00123 for (i=0; i < xpathObj->nodesetval->nodeNr; i++) { 00124 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode; 00125 while (curNode) { 00126 if (xmlStrEqual(curNode->name, (const xmlChar*)"File")) { 00127 adapter = zlp_adapter(curNode, ADAPTER_FILE, inbound); 00128 } 00129 if (adapter) { 00130 break; 00131 } 00132 curNode = curNode->next; 00133 } 00134 } 00135 } 00136 xmlXPathFreeObject(xpathObj); 00137 return adapter; 00138 } 00139 00140 00145 static void 00146 parse_zonelist_adapters(xmlXPathContextPtr xpathCtx, zone_type* zone) 00147 { 00148 xmlChar* i_expr = (xmlChar*) "//Zone/Adapters/Input"; 00149 xmlChar* o_expr = (xmlChar*) "//Zone/Adapters/Output"; 00150 00151 if (!xpathCtx || !zone) { 00152 return; 00153 } 00154 00155 zone->adinbound = parse_zonelist_adapter(xpathCtx, i_expr, 1); 00156 zone->adoutbound = parse_zonelist_adapter(xpathCtx, o_expr, 0); 00157 return; 00158 } 00159 00160 00165 ods_status 00166 parse_zonelist_zones(struct zonelist_struct* zlist, const char* zlfile) 00167 { 00168 char* tag_name = NULL; 00169 char* zone_name = NULL; 00170 zone_type* new_zone = NULL; 00171 int ret = 0; 00172 int error = 0; 00173 xmlTextReaderPtr reader = NULL; 00174 xmlDocPtr doc = NULL; 00175 xmlXPathContextPtr xpathCtx = NULL; 00176 00177 xmlChar* name_expr = (unsigned char*) "name"; 00178 xmlChar* policy_expr = (unsigned char*) "//Zone/Policy"; 00179 xmlChar* signconf_expr = (unsigned char*) "//Zone/SignerConfiguration"; 00180 00181 if (!zlist) { 00182 ods_log_error("[%s] unable to parse zone list: no storage", 00183 parser_str); 00184 return ODS_STATUS_ASSERT_ERR; 00185 } 00186 ods_log_assert(zlist); 00187 00188 if (!zlfile) { 00189 ods_log_error("[%s] unable to parse zone list: no filename", 00190 parser_str); 00191 return ODS_STATUS_ASSERT_ERR; 00192 } 00193 ods_log_assert(zlfile); 00194 00195 reader = xmlNewTextReaderFilename(zlfile); 00196 if (!reader) { 00197 ods_log_error("[%s] unable to open file %s", parser_str, zlfile); 00198 return ODS_STATUS_XML_ERR; 00199 } 00200 00201 ret = xmlTextReaderRead(reader); 00202 while (ret == XML_READER_TYPE_ELEMENT) { 00203 tag_name = (char*) xmlTextReaderLocalName(reader); 00204 if (ods_strcmp(tag_name, "Zone") == 0 && 00205 ods_strcmp(tag_name, "ZoneList") != 0 && 00206 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { 00207 /* Found a zone */ 00208 zone_name = (char*) xmlTextReaderGetAttribute(reader, 00209 name_expr); 00210 if (!zone_name || strlen(zone_name) <= 0) { 00211 ods_log_error("[%s] unable to extract zone name from " 00212 "zonelist", parser_str); 00213 if (zone_name) { 00214 free((void*) zone_name); 00215 } 00216 free((void*) tag_name); 00217 ret = xmlTextReaderRead(reader); 00218 continue; 00219 } 00220 00221 /* Expand this node to get the rest of the info */ 00222 xmlTextReaderExpand(reader); 00223 doc = xmlTextReaderCurrentDoc(reader); 00224 if (doc) { 00225 xpathCtx = xmlXPathNewContext(doc); 00226 } 00227 if (doc == NULL || xpathCtx == NULL) { 00228 ods_log_error("[%s] unable to read zone %s; skipping", 00229 parser_str, zone_name); 00230 ret = xmlTextReaderRead(reader); 00231 free((void*) zone_name); 00232 free((void*) tag_name); 00233 if (xpathCtx) { 00234 xmlXPathFreeContext(xpathCtx); 00235 xpathCtx = NULL; 00236 } 00237 continue; 00238 } 00239 00240 /* That worked, now read out the contents... */ 00241 new_zone = zone_create(zone_name, LDNS_RR_CLASS_IN); 00242 new_zone->policy_name = parse_zonelist_element(xpathCtx, 00243 policy_expr); 00244 new_zone->signconf_filename = parse_zonelist_element(xpathCtx, 00245 signconf_expr); 00246 parse_zonelist_adapters(xpathCtx, new_zone); 00247 if (!new_zone->policy_name || !new_zone->signconf_filename || 00248 !new_zone->adinbound || !new_zone->adoutbound) { 00249 zone_cleanup(new_zone); 00250 new_zone = NULL; 00251 ods_log_crit("[%s] unable to create zone %s", parser_str, 00252 zone_name); 00253 error = 1; 00254 } else if (zonelist_add_zone((zonelist_type*) zlist, new_zone) 00255 == NULL) { 00256 ods_log_error("[%s] unable to add zone %s", parser_str, 00257 zone_name); 00258 zone_cleanup(new_zone); 00259 new_zone = NULL; 00260 error = 1; 00261 } 00262 xmlXPathFreeContext(xpathCtx); 00263 xpathCtx = NULL; 00264 free((void*) zone_name); 00265 if (error) { 00266 free((void*) tag_name); 00267 tag_name = NULL; 00268 ret = 1; 00269 break; 00270 } 00271 ods_log_debug("[%s] zone %s added", parser_str, new_zone->name); 00272 } 00273 free((void*) tag_name); 00274 ret = xmlTextReaderRead(reader); 00275 } 00276 /* no more zones */ 00277 ods_log_debug("[%s] no more zones", parser_str); 00278 xmlFreeTextReader(reader); 00279 if (doc) { 00280 xmlFreeDoc(doc); 00281 } 00282 if (ret != 0) { 00283 ods_log_error("[%s] error parsing file %s", parser_str, zlfile); 00284 return ODS_STATUS_PARSE_ERR; 00285 } 00286 return ODS_STATUS_OK; 00287 }