OpenDNSSEC-signer 1.2.1
|
00001 /* 00002 * $Id: confparser.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 "parser/confparser.h" 00035 #include "util/log.h" 00036 #include "util/se_malloc.h" 00037 00038 #include <libxml/xpath.h> /* xmlXPath*() */ 00039 #include <libxml/relaxng.h> /* xmlRelaxNG*() */ 00040 #include <libxml/xmlreader.h> /* xmlParseFile(), xmlFreeDoc() */ 00041 #include <string.h> /* strlen() */ 00042 #include <stdlib.h> /* atoi() */ 00043 00044 00049 int 00050 parse_file_check(const char* cfgfile, const char* rngfile) 00051 { 00052 xmlDocPtr doc = NULL; 00053 xmlDocPtr rngdoc = NULL; 00054 xmlRelaxNGParserCtxtPtr rngpctx = NULL; 00055 xmlRelaxNGValidCtxtPtr rngctx = NULL; 00056 xmlRelaxNGPtr schema = NULL; 00057 int status = 0; 00058 00059 se_log_assert(cfgfile); 00060 se_log_assert(rngfile); 00061 se_log_debug("check config file: %s, use rng file: %s", 00062 cfgfile?cfgfile:"(null)", rngfile?rngfile:"(null)"); 00063 00064 /* Load XML document */ 00065 doc = xmlParseFile(cfgfile); 00066 if (doc == NULL) { 00067 se_log_error("unable to read config file %s", 00068 cfgfile?cfgfile:"(null)"); 00069 return 1; 00070 } 00071 /* Load rng document */ 00072 rngdoc = xmlParseFile(rngfile); 00073 if (rngdoc == NULL) { 00074 se_log_error("unable to read conf rng file %s", 00075 rngfile?rngfile:"(null)"); 00076 xmlFreeDoc(doc); 00077 return 1; 00078 } 00079 /* Create an XML RelaxNGs parser context for the relax-ng document. */ 00080 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc); 00081 if (rngpctx == NULL) { 00082 xmlFreeDoc(rngdoc); 00083 xmlFreeDoc(doc); 00084 se_log_error("unable to create XML RelaxNGs parser context"); 00085 return 1; 00086 } 00087 /* Parse a schema definition resource and 00088 * build an internal XML schema structure. 00089 */ 00090 schema = xmlRelaxNGParse(rngpctx); 00091 if (schema == NULL) { 00092 se_log_error("unable to parse a schema definition resource"); 00093 xmlRelaxNGFreeParserCtxt(rngpctx); 00094 xmlFreeDoc(rngdoc); 00095 xmlFreeDoc(doc); 00096 return 1; 00097 } 00098 /* Create an XML RelaxNGs validation context. */ 00099 rngctx = xmlRelaxNGNewValidCtxt(schema); 00100 if (rngctx == NULL) { 00101 se_log_error("unable to create RelaxNGs validation context"); 00102 xmlRelaxNGFree(schema); 00103 xmlRelaxNGFreeParserCtxt(rngpctx); 00104 xmlFreeDoc(rngdoc); 00105 xmlFreeDoc(doc); 00106 return 1; 00107 } 00108 /* Validate a document tree in memory. */ 00109 status = xmlRelaxNGValidateDoc(rngctx,doc); 00110 if (status != 0) { 00111 se_log_error("configuration file validation failed %s", 00112 cfgfile?cfgfile:"(null)"); 00113 xmlRelaxNGFreeValidCtxt(rngctx); 00114 xmlRelaxNGFree(schema); 00115 xmlRelaxNGFreeParserCtxt(rngpctx); 00116 xmlFreeDoc(rngdoc); 00117 xmlFreeDoc(doc); 00118 return 1; 00119 } 00120 00121 xmlRelaxNGFreeValidCtxt(rngctx); 00122 xmlRelaxNGFree(schema); 00123 xmlRelaxNGFreeParserCtxt(rngpctx); 00124 xmlFreeDoc(rngdoc); 00125 xmlFreeDoc(doc); 00126 00127 return 0; 00128 } 00129 00130 /* TODO: look how the enforcer reads this now */ 00131 00136 const char* 00137 parse_conf_string(const char* cfgfile, const char* expr, int required) 00138 { 00139 xmlDocPtr doc = NULL; 00140 xmlXPathContextPtr xpathCtx = NULL; 00141 xmlXPathObjectPtr xpathObj = NULL; 00142 xmlChar *xexpr = NULL; 00143 const char* string = NULL; 00144 00145 se_log_assert(expr); 00146 se_log_assert(cfgfile); 00147 00148 /* Load XML document */ 00149 doc = xmlParseFile(cfgfile); 00150 if (doc == NULL) { 00151 return NULL; 00152 } 00153 /* Create xpath evaluation context */ 00154 xpathCtx = xmlXPathNewContext(doc); 00155 if (xpathCtx == NULL) { 00156 se_log_error("unable to create new XPath context for cfgile %s expr %s", 00157 cfgfile?cfgfile:"(null)", 00158 expr?(char *)expr:"(null)"); 00159 xmlFreeDoc(doc); 00160 return NULL; 00161 } 00162 /* Get string */ 00163 xexpr = (unsigned char*) expr; 00164 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx); 00165 if (xpathObj == NULL || xpathObj->nodesetval == NULL || 00166 xpathObj->nodesetval->nodeNr <= 0) { 00167 if (required) { 00168 se_log_error("unable to evaluate required element %s in cfgfile %s", 00169 xexpr?(char *)xexpr:"(null)", 00170 cfgfile?cfgfile:"(null)"); 00171 } 00172 xmlXPathFreeContext(xpathCtx); 00173 if (xpathObj) { 00174 xmlXPathFreeObject(xpathObj); 00175 } 00176 xmlFreeDoc(doc); 00177 return NULL; 00178 } 00179 if (xpathObj->nodesetval != NULL && 00180 xpathObj->nodesetval->nodeNr > 0) { 00181 string = (const char*) xmlXPathCastToString(xpathObj); 00182 xmlXPathFreeContext(xpathCtx); 00183 xmlXPathFreeObject(xpathObj); 00184 xmlFreeDoc(doc); 00185 return string; 00186 } 00187 xmlXPathFreeContext(xpathCtx); 00188 xmlXPathFreeObject(xpathObj); 00189 xmlFreeDoc(doc); 00190 return NULL; 00191 } 00192 00193 00194 const char* 00195 parse_conf_zonelist_filename(const char* cfgfile) 00196 { 00197 return parse_conf_string(cfgfile, 00198 "//Configuration/Common/ZoneListFile", 00199 1); 00200 } 00201 00202 00203 const char* 00204 parse_conf_zonefetch_filename(const char* cfgfile) 00205 { 00206 return parse_conf_string(cfgfile, 00207 "//Configuration/Common/ZoneFetchFile", 00208 0); 00209 } 00210 00211 00212 const char* 00213 parse_conf_log_filename(const char* cfgfile) 00214 { 00215 const char* str = parse_conf_string(cfgfile, 00216 "//Configuration/Common/Logging/Syslog/Facility", 00217 0); 00218 if (!str) { 00219 str = parse_conf_string(cfgfile, 00220 "//Configuration/Common/Logging/File/Filename", 00221 0); 00222 } 00223 return str; /* NULL, Facility or Filename */ 00224 } 00225 00226 00227 const char* 00228 parse_conf_pid_filename(const char* cfgfile) 00229 { 00230 const char* str = parse_conf_string(cfgfile, 00231 "//Configuration/Signer/PidFile", 00232 0); 00233 if (!str) { 00234 return se_strdup(ODS_SE_PIDFILE); 00235 } 00236 return str; 00237 } 00238 00239 00240 const char* 00241 parse_conf_notify_command(const char* cfgfile) 00242 { 00243 return parse_conf_string(cfgfile, 00244 "//Configuration/Signer/NotifyCommand", 00245 0); 00246 } 00247 00248 00249 const char* 00250 parse_conf_clisock_filename(const char* cfgfile) 00251 { 00252 const char* str = parse_conf_string(cfgfile, 00253 "//Configuration/Signer/SocketFile", 00254 0); 00255 if (!str) { 00256 return se_strdup(ODS_SE_SOCKFILE); 00257 } 00258 return str; 00259 } 00260 00261 00262 const char* parse_conf_working_dir(const char* cfgfile) 00263 { 00264 const char* str = parse_conf_string(cfgfile, 00265 "//Configuration/Signer/WorkingDirectory", 00266 0); 00267 if (!str) { 00268 return se_strdup(ODS_SE_WORKDIR); 00269 } 00270 return str; 00271 } 00272 00273 00274 const char* 00275 parse_conf_username(const char* cfgfile) 00276 { 00277 return parse_conf_string(cfgfile, 00278 "//Configuration/Signer/Privileges/User", 00279 0); 00280 } 00281 00282 00283 const char* parse_conf_group(const char* cfgfile) 00284 { 00285 return parse_conf_string(cfgfile, 00286 "//Configuration/Signer/Privileges/Group", 00287 0); 00288 } 00289 00290 00291 const char* parse_conf_chroot(const char* cfgfile) 00292 { 00293 return parse_conf_string(cfgfile, 00294 "//Configuration/Signer/Privileges/Directory", 00295 0); 00296 } 00297 00298 00303 int 00304 parse_conf_use_syslog(const char* cfgfile) 00305 { 00306 const char* str = parse_conf_string(cfgfile, 00307 "//Configuration/Common/Logging/Syslog/Facility", 00308 0); 00309 if (str) { 00310 se_free((void*)str); 00311 return 1; 00312 } 00313 return 0; 00314 } 00315 00316 00317 int 00318 parse_conf_worker_threads(const char* cfgfile) 00319 { 00320 int numwt = ODS_SE_WORKERTHREADS; 00321 const char* str = parse_conf_string(cfgfile, 00322 "//Configuration/Signer/WorkerThreads", 00323 0); 00324 if (str) { 00325 if (strlen(str) > 0) { 00326 numwt = atoi(str); 00327 } 00328 se_free((void*)str); 00329 } 00330 return numwt; 00331 } 00332 00333 00334 int 00335 parse_conf_signer_threads(const char* cfgfile) 00336 { 00337 int numwt = ODS_SE_SIGNERTHREADS; 00338 const char* str = parse_conf_string(cfgfile, 00339 "//Configuration/Signer/SignerThreads", 00340 0); 00341 if (str) { 00342 if (strlen(str) > 0) { 00343 numwt = atoi(str); 00344 } 00345 se_free((void*)str); 00346 } 00347 return numwt; 00348 }