OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-mips-p9AT07/opendnssec-1.2.1.dfsg/signer/src/parser/zonelistparser.c

Go to the documentation of this file.
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 }