OpenDNSSEC-signer 1.3.0rc3
|
00001 /* 00002 * $Id: confparser.c 5227 2011-06-12 08:51:24Z 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 "parser/zonelistparser.h" 00036 #include "shared/allocator.h" 00037 #include "shared/file.h" 00038 #include "shared/log.h" 00039 #include "shared/status.h" 00040 00041 #include <libxml/xpath.h> 00042 #include <libxml/relaxng.h> 00043 #include <libxml/xmlreader.h> 00044 #include <string.h> 00045 #include <stdlib.h> 00046 00047 static const char* parser_str = "parser"; 00048 00049 00054 ods_status 00055 parse_file_check(const char* cfgfile, const char* rngfile) 00056 { 00057 xmlDocPtr doc = NULL; 00058 xmlDocPtr rngdoc = NULL; 00059 xmlRelaxNGParserCtxtPtr rngpctx = NULL; 00060 xmlRelaxNGValidCtxtPtr rngctx = NULL; 00061 xmlRelaxNGPtr schema = NULL; 00062 00063 if (!cfgfile || !rngfile) { 00064 ods_log_error("[%s] no cfgfile or rngfile", parser_str); 00065 return ODS_STATUS_ASSERT_ERR; 00066 } 00067 ods_log_assert(cfgfile); 00068 ods_log_assert(rngfile); 00069 ods_log_debug("[%s] check cfgfile %s with rngfile %s", parser_str, 00070 cfgfile, rngfile); 00071 00072 /* Load XML document */ 00073 doc = xmlParseFile(cfgfile); 00074 if (doc == NULL) { 00075 ods_log_error("[%s] unable to read cfgfile %s", parser_str, 00076 cfgfile); 00077 return ODS_STATUS_XML_ERR; 00078 } 00079 /* Load rng document */ 00080 rngdoc = xmlParseFile(rngfile); 00081 if (rngdoc == NULL) { 00082 ods_log_error("[%s] unable to read rngfile %s", parser_str, 00083 rngfile); 00084 xmlFreeDoc(doc); 00085 return ODS_STATUS_XML_ERR; 00086 } 00087 /* Create an XML RelaxNGs parser context for the relax-ng document. */ 00088 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc); 00089 if (rngpctx == NULL) { 00090 xmlFreeDoc(rngdoc); 00091 xmlFreeDoc(doc); 00092 ods_log_error("[%s] unable to create XML RelaxNGs parser context", 00093 parser_str); 00094 return ODS_STATUS_XML_ERR; 00095 } 00096 /* Parse a schema definition resource and 00097 * build an internal XML schema structure. 00098 */ 00099 schema = xmlRelaxNGParse(rngpctx); 00100 if (schema == NULL) { 00101 ods_log_error("[%s] unable to parse a schema definition resource", 00102 parser_str); 00103 xmlRelaxNGFreeParserCtxt(rngpctx); 00104 xmlFreeDoc(rngdoc); 00105 xmlFreeDoc(doc); 00106 return ODS_STATUS_PARSE_ERR; 00107 } 00108 /* Create an XML RelaxNGs validation context. */ 00109 rngctx = xmlRelaxNGNewValidCtxt(schema); 00110 if (rngctx == NULL) { 00111 ods_log_error("[%s] unable to create RelaxNGs validation context", 00112 parser_str); 00113 xmlRelaxNGFree(schema); 00114 xmlRelaxNGFreeParserCtxt(rngpctx); 00115 xmlFreeDoc(rngdoc); 00116 xmlFreeDoc(doc); 00117 return ODS_STATUS_RNG_ERR; 00118 } 00119 /* Validate a document tree in memory. */ 00120 /* 00121 better not check: if not correct, this will segfault. 00122 status = xmlRelaxNGValidateDoc(rngctx,doc); 00123 if (status != 0) { 00124 ods_log_error("[%s] cfgfile validation failed %s", parser_str, 00125 cfgfile); 00126 xmlRelaxNGFreeValidCtxt(rngctx); 00127 xmlRelaxNGFree(schema); 00128 xmlRelaxNGFreeParserCtxt(rngpctx); 00129 xmlFreeDoc(rngdoc); 00130 xmlFreeDoc(doc); 00131 return ODS_STATUS_RNG_ERR; 00132 } 00133 */ 00134 xmlRelaxNGFreeValidCtxt(rngctx); 00135 xmlRelaxNGFree(schema); 00136 xmlRelaxNGFreeParserCtxt(rngpctx); 00137 xmlFreeDoc(rngdoc); 00138 xmlFreeDoc(doc); 00139 return ODS_STATUS_OK; 00140 } 00141 00142 /* TODO: look how the enforcer reads this now */ 00143 00144 00149 adapter_type** 00150 parse_conf_adapters(allocator_type* allocator, const char* cfgfile, 00151 int* count) 00152 { 00153 char* tag_name = NULL; 00154 adapter_type** adapters = NULL; 00155 int ret = 0; 00156 size_t adcount = 0; 00157 00158 xmlTextReaderPtr reader = NULL; 00159 xmlDocPtr doc = NULL; 00160 xmlXPathContextPtr xpathCtx = NULL; 00161 00162 xmlChar* expr = (xmlChar*) "//Adapter"; 00163 00164 ods_log_assert(allocator); 00165 ods_log_assert(cfgfile); 00166 00167 reader = xmlNewTextReaderFilename(cfgfile); 00168 if (!reader) { 00169 ods_log_error("[%s] unable to open file %s", parser_str, cfgfile); 00170 return NULL; 00171 } 00172 00173 ret = xmlTextReaderRead(reader); 00174 adapters = (adapter_type**) allocator_alloc(allocator, 00175 ADMAX * sizeof(adapter_type*)); 00176 while (ret == XML_READER_TYPE_ELEMENT) { 00177 if (adcount >= ADMAX) { 00178 ods_log_warning("[%s] too many adapters in config file %s, " 00179 "skipping additional adapters", parser_str, cfgfile); 00180 break; 00181 } 00182 00183 tag_name = (char*) xmlTextReaderLocalName(reader); 00184 00185 /* This assumes that there is no other <Adapters> element in 00186 * conf.xml 00187 */ 00188 if (ods_strcmp(tag_name, "Adapter") == 0 && 00189 ods_strcmp(tag_name, "Adapters") != 0 && 00190 xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { 00191 /* Found an adapter */ 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 ods_log_error("[%s] unable to read adapter; skipping", 00201 parser_str); 00202 ret = xmlTextReaderRead(reader); 00203 free((void*) tag_name); 00204 continue; 00205 } 00206 /* That worked, reuse the parse_zonelist_adapter() function */ 00207 adapters[adcount] = parse_zonelist_adapter(xpathCtx, expr, 1); 00208 adcount++; 00209 ods_log_debug("[%s] adapter added", parser_str); 00210 xmlXPathFreeContext(xpathCtx); 00211 } 00212 free((void*) tag_name); 00213 ret = xmlTextReaderRead(reader); 00214 } 00215 00216 /* no more adapters */ 00217 ods_log_debug("[%s] no more adapters", parser_str); 00218 xmlFreeTextReader(reader); 00219 if (doc) { 00220 xmlFreeDoc(doc); 00221 } 00222 if (ret != 0) { 00223 ods_log_error("[%s] error parsing file %s", parser_str, cfgfile); 00224 return NULL; 00225 } 00226 *count = (int) adcount; 00227 return adapters; 00228 } 00229 00230 00235 const char* 00236 parse_conf_string(const char* cfgfile, const char* expr, int required) 00237 { 00238 xmlDocPtr doc = NULL; 00239 xmlXPathContextPtr xpathCtx = NULL; 00240 xmlXPathObjectPtr xpathObj = NULL; 00241 xmlChar *xexpr = NULL; 00242 const char* string = NULL; 00243 00244 ods_log_assert(expr); 00245 ods_log_assert(cfgfile); 00246 00247 /* Load XML document */ 00248 doc = xmlParseFile(cfgfile); 00249 if (doc == NULL) { 00250 return NULL; 00251 } 00252 /* Create xpath evaluation context */ 00253 xpathCtx = xmlXPathNewContext(doc); 00254 if (xpathCtx == NULL) { 00255 ods_log_error("[%s] unable to create new XPath context for cfgile " 00256 "%s expr %s", parser_str, cfgfile, (char*) expr); 00257 xmlFreeDoc(doc); 00258 return NULL; 00259 } 00260 /* Get string */ 00261 xexpr = (unsigned char*) expr; 00262 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx); 00263 if (xpathObj == NULL || xpathObj->nodesetval == NULL || 00264 xpathObj->nodesetval->nodeNr <= 0) { 00265 if (required) { 00266 ods_log_error("[%s] unable to evaluate required element %s in " 00267 "cfgfile %s", parser_str, (char*) xexpr, cfgfile); 00268 } 00269 xmlXPathFreeContext(xpathCtx); 00270 if (xpathObj) { 00271 xmlXPathFreeObject(xpathObj); 00272 } 00273 xmlFreeDoc(doc); 00274 return NULL; 00275 } 00276 if (xpathObj->nodesetval != NULL && 00277 xpathObj->nodesetval->nodeNr > 0) { 00278 string = (const char*) xmlXPathCastToString(xpathObj); 00279 xmlXPathFreeContext(xpathCtx); 00280 xmlXPathFreeObject(xpathObj); 00281 xmlFreeDoc(doc); 00282 return string; 00283 } 00284 xmlXPathFreeContext(xpathCtx); 00285 xmlXPathFreeObject(xpathObj); 00286 xmlFreeDoc(doc); 00287 return NULL; 00288 } 00289 00290 00291 const char* 00292 parse_conf_zonelist_filename(allocator_type* allocator, const char* cfgfile) 00293 { 00294 const char* dup = NULL; 00295 const char* str = parse_conf_string( 00296 cfgfile, 00297 "//Configuration/Common/ZoneListFile", 00298 1); 00299 00300 if (str) { 00301 dup = allocator_strdup(allocator, str); 00302 free((void*)str); 00303 } 00304 return dup; 00305 } 00306 00307 00308 const char* 00309 parse_conf_zonefetch_filename(allocator_type* allocator, const char* cfgfile) 00310 { 00311 const char* dup = NULL; 00312 const char* str = parse_conf_string( 00313 cfgfile, 00314 "//Configuration/Common/ZoneFetchFile", 00315 0); 00316 00317 if (str) { 00318 dup = allocator_strdup(allocator, str); 00319 free((void*)str); 00320 } 00321 return dup; 00322 } 00323 00324 00325 const char* 00326 parse_conf_log_filename(allocator_type* allocator, const char* cfgfile) 00327 { 00328 const char* dup = NULL; 00329 const char* str = parse_conf_string(cfgfile, 00330 "//Configuration/Common/Logging/Syslog/Facility", 00331 0); 00332 if (!str) { 00333 str = parse_conf_string(cfgfile, 00334 "//Configuration/Common/Logging/File/Filename", 00335 0); 00336 } 00337 if (str) { 00338 dup = allocator_strdup(allocator, str); 00339 free((void*)str); 00340 } 00341 return dup; /* NULL, Facility or Filename */ 00342 } 00343 00344 00345 const char* 00346 parse_conf_pid_filename(allocator_type* allocator, const char* cfgfile) 00347 { 00348 const char* dup = NULL; 00349 const char* str = parse_conf_string( 00350 cfgfile, 00351 "//Configuration/Signer/PidFile", 00352 0); 00353 00354 if (str) { 00355 dup = allocator_strdup(allocator, str); 00356 free((void*)str); 00357 } else { 00358 dup = allocator_strdup(allocator, ODS_SE_PIDFILE); 00359 } 00360 return dup; 00361 } 00362 00363 00364 const char* 00365 parse_conf_notify_command(allocator_type* allocator, const char* cfgfile) 00366 { 00367 const char* dup = NULL; 00368 const char* str = parse_conf_string( 00369 cfgfile, 00370 "//Configuration/Signer/NotifyCommand", 00371 0); 00372 00373 if (str) { 00374 dup = allocator_strdup(allocator, str); 00375 free((void*)str); 00376 } 00377 return dup; 00378 } 00379 00380 00381 const char* 00382 parse_conf_clisock_filename(allocator_type* allocator, const char* cfgfile) 00383 { 00384 const char* dup = NULL; 00385 const char* str = parse_conf_string( 00386 cfgfile, 00387 "//Configuration/Signer/SocketFile", 00388 0); 00389 00390 if (str) { 00391 dup = allocator_strdup(allocator, str); 00392 free((void*)str); 00393 } else { 00394 dup = allocator_strdup(allocator, ODS_SE_SOCKFILE); 00395 } 00396 return dup; 00397 } 00398 00399 00400 const char* 00401 parse_conf_working_dir(allocator_type* allocator, const char* cfgfile) 00402 { 00403 const char* dup = NULL; 00404 const char* str = parse_conf_string( 00405 cfgfile, 00406 "//Configuration/Signer/WorkingDirectory", 00407 0); 00408 00409 if (str) { 00410 dup = allocator_strdup(allocator, str); 00411 free((void*)str); 00412 } else { 00413 dup = allocator_strdup(allocator, ODS_SE_WORKDIR); 00414 } 00415 return dup; 00416 } 00417 00418 00419 const char* 00420 parse_conf_username(allocator_type* allocator, const char* cfgfile) 00421 { 00422 const char* dup = NULL; 00423 const char* str = parse_conf_string( 00424 cfgfile, 00425 "//Configuration/Signer/Privileges/User", 00426 0); 00427 00428 if (str) { 00429 dup = allocator_strdup(allocator, str); 00430 free((void*)str); 00431 } 00432 return dup; 00433 } 00434 00435 00436 const char* 00437 parse_conf_group(allocator_type* allocator, const char* cfgfile) 00438 { 00439 const char* dup = NULL; 00440 const char* str = parse_conf_string( 00441 cfgfile, 00442 "//Configuration/Signer/Privileges/Group", 00443 0); 00444 00445 if (str) { 00446 dup = allocator_strdup(allocator, str); 00447 free((void*)str); 00448 } 00449 return dup; 00450 } 00451 00452 00453 const char* 00454 parse_conf_chroot(allocator_type* allocator, const char* cfgfile) 00455 { 00456 const char* dup = NULL; 00457 const char* str = parse_conf_string( 00458 cfgfile, 00459 "//Configuration/Signer/Privileges/Directory", 00460 0); 00461 00462 if (str) { 00463 dup = allocator_strdup(allocator, str); 00464 free((void*)str); 00465 } 00466 return dup; 00467 } 00468 00469 00474 int 00475 parse_conf_use_syslog(const char* cfgfile) 00476 { 00477 const char* str = parse_conf_string(cfgfile, 00478 "//Configuration/Common/Logging/Syslog/Facility", 00479 0); 00480 if (str) { 00481 free((void*)str); 00482 return 1; 00483 } 00484 return 0; 00485 } 00486 00487 00488 int 00489 parse_conf_worker_threads(const char* cfgfile) 00490 { 00491 int numwt = ODS_SE_WORKERTHREADS; 00492 const char* str = parse_conf_string(cfgfile, 00493 "//Configuration/Signer/WorkerThreads", 00494 0); 00495 if (str) { 00496 if (strlen(str) > 0) { 00497 numwt = atoi(str); 00498 } 00499 free((void*)str); 00500 } 00501 return numwt; 00502 } 00503 00504 00505 int 00506 parse_conf_signer_threads(const char* cfgfile) 00507 { 00508 int numwt = ODS_SE_WORKERTHREADS; 00509 const char* str = parse_conf_string(cfgfile, 00510 "//Configuration/Signer/SignerThreads", 00511 0); 00512 if (str) { 00513 if (strlen(str) > 0) { 00514 numwt = atoi(str); 00515 } 00516 free((void*)str); 00517 return numwt; 00518 } 00519 /* no SignerThreads value configured, look at WorkerThreads */ 00520 return parse_conf_worker_threads(cfgfile); 00521 }