41 #include <libxml/tree.h> 42 #include <libxml/parser.h> 43 #include <libxml/xpath.h> 44 #include <libxml/xpathInternals.h> 45 #include <libxml/relaxng.h> 47 #define StrFree(ptr) {if(ptr != NULL) {free(ptr); (ptr) = NULL;}} 51 void log_init(
int facility,
const char *program_name)
53 openlog(program_name, 0, facility);
57 #pragma GCC diagnostic push 58 #pragma GCC diagnostic ignored "-Wformat-nonliteral" 64 va_start(args, format);
67 if (strncmp(format,
"ERROR:", 6) == 0) {
68 vsyslog(LOG_ERR, format, args);
69 }
else if (strncmp(format,
"WARNING:", 8) == 0) {
70 vsyslog(LOG_WARNING, format, args);
71 }
else if (strncmp(format,
"DEBUG:", 6) == 0) {
72 vsyslog(LOG_DEBUG, format, args);
74 vsyslog(LOG_INFO, format, args);
78 vprintf(format, args2);
85 #pragma GCC diagnostic pop 88 int check_rng(
const char *filename,
const char *rngfilename,
int verbose)
91 xmlDocPtr rngdoc = NULL;
92 xmlRelaxNGParserCtxtPtr rngpctx = NULL;
93 xmlRelaxNGValidCtxtPtr rngctx = NULL;
94 xmlRelaxNGPtr schema = NULL;
97 dual_log(
"DEBUG: About to check XML validity in %s with %s",
98 filename, rngfilename);
102 doc = xmlParseFile(filename);
104 dual_log(
"ERROR: unable to parse file \"%s\"", filename);
112 rngdoc = xmlParseFile(rngfilename);
113 if (rngdoc == NULL) {
114 dual_log(
"ERROR: unable to parse file \"%s\"", rngfilename);
124 rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
125 if (rngpctx == NULL) {
126 dual_log(
"ERROR: unable to create XML RelaxNGs parser context");
134 xmlRelaxNGSetParserErrors(rngpctx,
135 (xmlRelaxNGValidityErrorFunc) fprintf,
136 (xmlRelaxNGValidityWarningFunc) fprintf,
141 schema = xmlRelaxNGParse(rngpctx);
142 if (schema == NULL) {
143 dual_log(
"ERROR: unable to parse a schema definition resource");
145 xmlRelaxNGFreeParserCtxt(rngpctx);
153 rngctx = xmlRelaxNGNewValidCtxt(schema);
154 if (rngctx == NULL) {
155 dual_log(
"ERROR: unable to create RelaxNGs validation context based on the schema");
157 xmlRelaxNGFree(schema);
158 xmlRelaxNGFreeParserCtxt(rngpctx);
165 xmlRelaxNGSetValidErrors(rngctx,
166 (xmlRelaxNGValidityErrorFunc) fprintf,
167 (xmlRelaxNGValidityWarningFunc) fprintf,
171 if (xmlRelaxNGValidateDoc(rngctx,doc) != 0) {
172 dual_log(
"ERROR: %s fails to validate", filename);
174 xmlRelaxNGFreeValidCtxt(rngctx);
175 xmlRelaxNGFree(schema);
176 xmlRelaxNGFreeParserCtxt(rngpctx);
183 xmlRelaxNGFreeValidCtxt(rngctx);
184 xmlRelaxNGFree(schema);
185 xmlRelaxNGFreeParserCtxt(rngpctx);
192 int check_file(
const char *filename,
const char *log_string) {
193 struct stat stat_ret;
195 if (stat(filename, &stat_ret) != 0) {
197 if (errno != ENOENT) {
198 dual_log(
"ERROR: cannot stat file %s: %s",
199 filename, strerror(errno));
203 dual_log(
"ERROR: %s (%s) does not exist", log_string, filename);
207 if (S_ISREG(stat_ret.st_mode)) {
212 dual_log(
"ERROR: %s (%s) does not exist", log_string, filename);
218 xmlXPathObjectPtr xpath_obj;
219 char* temp_char = NULL;
222 xpath_obj = xmlXPathEvalExpression(file_xexpr, xpath_ctx);
223 if(xpath_obj == NULL) {
224 dual_log(
"ERROR: unable to evaluate xpath expression: %s", file_xexpr);
227 if (xpath_obj->nodesetval != NULL && xpath_obj->nodesetval->nodeNr > 0) {
228 temp_char = (
char*) xmlXPathCastToString(xpath_obj);
231 str = strrchr(temp_char,
' ');
241 xmlXPathFreeObject(xpath_obj);
245 xmlXPathFreeObject(xpath_obj);
249 int check_path(
const char *pathname,
const char *log_string) {
250 struct stat stat_ret;
252 if (stat(pathname, &stat_ret) != 0) {
253 if (errno != ENOENT) {
254 dual_log(
"ERROR: cannot stat directory %s: %s",
255 pathname, strerror(errno));
259 dual_log(
"ERROR: %s (%s) does not exist", log_string, pathname);
263 if (S_ISDIR(stat_ret.st_mode)) {
268 dual_log(
"ERROR: %s (%s) is not a directory", log_string, pathname);
274 xmlXPathObjectPtr xpath_obj;
275 char* temp_char = NULL;
277 xpath_obj = xmlXPathEvalExpression(path_xexpr, xpath_ctx);
278 if(xpath_obj == NULL) {
279 dual_log(
"ERROR: unable to evaluate xpath expression: %s", path_xexpr);
282 if (xpath_obj->nodesetval != NULL && xpath_obj->nodesetval->nodeNr > 0) {
283 temp_char = (
char*) xmlXPathCastToString(xpath_obj);
290 xmlXPathFreeObject(xpath_obj);
294 xmlXPathFreeObject(xpath_obj);
298 int check_user_group(xmlXPathContextPtr xpath_ctx,
const xmlChar *user_xexpr,
const xmlChar *group_xexpr) {
300 xmlXPathObjectPtr xpath_obj;
301 char* temp_char = NULL;
307 xpath_obj = xmlXPathEvalExpression(group_xexpr, xpath_ctx);
308 if(xpath_obj == NULL) {
309 dual_log(
"ERROR: unable to evaluate xpath expression: %s", group_xexpr);
312 if (xpath_obj->nodesetval != NULL && xpath_obj->nodesetval->nodeNr > 0) {
313 temp_char = (
char*) xmlXPathCastToString(xpath_obj);
315 if ((grp = getgrnam(temp_char)) == NULL) {
316 dual_log(
"ERROR: Group '%s' does not exist", temp_char);
323 xmlXPathFreeObject(xpath_obj);
326 xpath_obj = xmlXPathEvalExpression(user_xexpr, xpath_ctx);
327 if(xpath_obj == NULL) {
328 dual_log(
"ERROR: unable to evaluate xpath expression: %s", user_xexpr);
331 if (xpath_obj->nodesetval != NULL && xpath_obj->nodesetval->nodeNr > 0) {
332 temp_char = (
char*) xmlXPathCastToString(xpath_obj);
334 if ((pwd = getpwnam(temp_char)) == NULL) {
335 dual_log(
"ERROR: User '%s' does not exist", temp_char);
343 xmlXPathFreeObject(xpath_obj);
348 int check_time_def(
const char *time_expr,
const char *location,
const char *field,
const char *filename,
int* interval) {
355 dual_log(
"WARNING: In %s M used in duration field for %s (%s) in %s - this will be interpreted as 31 days", location, field, time_expr, filename);
358 dual_log(
"WARNING: In %s Y used in duration field for %s (%s) in %s - this will be interpreted as 365 days", location, field, time_expr, filename);
361 dual_log(
"WARNING: In %s M & Y used in duration field for %s (%s) in %s - these will be interpreted as 31 and 365 days respectively", location, field, time_expr, filename);
364 dual_log(
"ERROR: unable to translate %s (%s) to seconds.", field, time_expr);
367 dual_log(
"ERROR: %s (%s) too long to be an int. E.g. Maximum is ~68 years on a system with 32-bit integers.", field, time_expr);
370 dual_log(
"ERROR: invalid pointers or text string NULL in %s (%s).", field, time_expr);
373 dual_log(
"ERROR: unknown error converting %s (%s) to seconds", field, time_expr);
385 int check_time_def_from_xpath(xmlXPathContextPtr xpath_ctx,
const xmlChar *time_xexpr,
const char *location,
const char *field,
const char *filename) {
387 xmlXPathObjectPtr xpath_obj;
388 char* temp_char = NULL;
392 xpath_obj = xmlXPathEvalExpression(time_xexpr, xpath_ctx);
393 if(xpath_obj == NULL) {
394 dual_log(
"ERROR: unable to evaluate xpath expression: %s", time_xexpr);
397 if (xpath_obj->nodesetval != NULL && xpath_obj->nodesetval->nodeNr > 0) {
398 temp_char = (
char *)xmlXPathCastToString(xpath_obj);
399 status +=
check_time_def(temp_char, location, field, filename, &ignore);
403 xmlXPathFreeObject(xpath_obj);
409 const xmlChar *interval_xexpr,
const char *filename)
412 xmlXPathObjectPtr xpath_obj;
413 xpath_obj = xmlXPathEvalExpression(interval_xexpr, xpath_ctx);
416 dual_log(
"ERROR: unable to evaluate xpath expression: %s", interval_xexpr);
419 temp_char = (
char*) xmlXPathCastToString(xpath_obj);
420 xmlXPathFreeObject(xpath_obj);
421 if ( strlen(temp_char) != 0) {
422 dual_log(
"WARNING: Deprecated tag %s found in %s.", interval_xexpr, filename);
433 char* temp_char = NULL;
439 int resigns_per_day = 0;
454 enum {KSK = 1, ZSK, CSK};
463 struct key *tmpkey, *firstkey = NULL, *curkey = NULL;
469 if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Signatures")) {
470 childNode = curNode->children;
472 if (xmlStrEqual(childNode->name, (
const xmlChar *)
"Resign")) {
473 temp_char = (
char *) xmlNodeGetContent(childNode);
474 status +=
check_time_def(temp_char, my_policy,
"Signatures/Resign", kasp, &resign);
477 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"Refresh")) {
478 temp_char = (
char *) xmlNodeGetContent(childNode);
479 status +=
check_time_def(temp_char, my_policy,
"Signatures/Refresh", kasp, &refresh);
482 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"Validity")) {
483 childNode2 = childNode->children;
485 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Default")) {
486 temp_char = (
char *) xmlNodeGetContent(childNode2);
487 status +=
check_time_def(temp_char, my_policy,
"Signatures/Validity/Default", kasp, &defalt);
490 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Denial")) {
491 temp_char = (
char *) xmlNodeGetContent(childNode2);
492 status +=
check_time_def(temp_char, my_policy,
"Signatures/Validity/Denial", kasp, &denial);
495 childNode2 = childNode2->next;
498 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"Jitter")) {
499 temp_char = (
char *) xmlNodeGetContent(childNode);
500 status +=
check_time_def(temp_char, my_policy,
"Signatures/Jitter", kasp, &jitter);
503 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"InceptionOffset")) {
504 temp_char = (
char *) xmlNodeGetContent(childNode);
505 status +=
check_time_def(temp_char, my_policy,
"Signatures/InceptionOffset", kasp, &inception);
508 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"MaxZoneTTL")) {
509 temp_char = (
char *) xmlNodeGetContent(childNode);
510 status +=
check_time_def(temp_char, my_policy,
"Signatures/MaxZoneTTL", kasp, &maxzone_ttl);
514 childNode = childNode->next;
517 else if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Denial")) {
518 childNode = curNode->children;
521 if (xmlStrEqual(childNode->name, (
const xmlChar *)
"NSEC")) {
524 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"NSEC3")) {
526 childNode2 = childNode->children;
529 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Resalt")) {
530 temp_char = (
char *) xmlNodeGetContent(childNode2);
531 status +=
check_time_def(temp_char, my_policy,
"Denial/NSEC3/Resalt", kasp, &resalt);
533 }
else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Hash")) {
534 childNode3 = childNode2->children;
536 if (xmlStrEqual(childNode3->name, (
const xmlChar *)
"Algorithm")) {
537 temp_char = (
char *) xmlNodeGetContent(childNode3);
539 hash_algo = atoi(temp_char);
540 if (hash_algo != 1) {
541 dual_log(
"ERROR: NSEC3 Hash algorithm for %s Policy " 542 "in %s is %d but should be 1", policy_name,
548 childNode3 = childNode3->next;
552 childNode2 = childNode2->next;
556 childNode = childNode->next;
559 else if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Keys")) {
560 childNode = curNode->children;
563 if (xmlStrEqual(childNode->name, (
const xmlChar *)
"TTL")) {
564 temp_char = (
char *) xmlNodeGetContent(childNode);
565 status +=
check_time_def(temp_char, my_policy,
"Keys/TTL", kasp, &ttl);
568 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"RetireSafety")) {
569 temp_char = (
char *) xmlNodeGetContent(childNode);
570 status +=
check_time_def(temp_char, my_policy,
"Keys/RetireSafety", kasp, &retire);
573 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"PublishSafety")) {
574 temp_char = (
char *) xmlNodeGetContent(childNode);
575 status +=
check_time_def(temp_char, my_policy,
"Keys/PublishSafety", kasp, &publish);
578 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"KSK")) {
579 childNode2 = childNode->children;
581 firstkey = curkey = (
struct key*) malloc(
sizeof *curkey);
583 curkey->next = (
struct key*) malloc(
sizeof *curkey);
584 curkey = curkey->next;
586 memset(curkey, 0,
sizeof *curkey);
591 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Algorithm")) {
592 temp_char = (
char *) xmlNodeGetContent(childNode2);
596 temp_char = (
char *)xmlGetProp(childNode2, (
const xmlChar *)
"length");
600 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Lifetime")) {
601 temp_char = (
char *) xmlNodeGetContent(childNode2);
602 status +=
check_time_def(temp_char, my_policy,
"Keys/KSK Lifetime", kasp, &curkey->life);
605 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Repository")) {
606 curkey->repo = (
char *) xmlNodeGetContent(childNode2);
609 childNode2 = childNode2->next;
612 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"ZSK")) {
613 childNode2 = childNode->children;
615 firstkey = curkey = (
struct key*) malloc(
sizeof *curkey);
617 curkey->next = (
struct key*) malloc(
sizeof *curkey);
618 curkey = curkey->next;
620 memset(curkey, 0,
sizeof *curkey);
625 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Algorithm")) {
626 temp_char = (
char *) xmlNodeGetContent(childNode2);
630 temp_char = (
char *)xmlGetProp(childNode2, (
const xmlChar *)
"length");
635 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Lifetime")) {
636 temp_char = (
char *) xmlNodeGetContent(childNode2);
637 status +=
check_time_def(temp_char, my_policy,
"Keys/ZSK Lifetime", kasp, &curkey->life);
640 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Repository")) {
641 curkey->repo = (
char *) xmlNodeGetContent(childNode2);
644 childNode2 = childNode2->next;
647 else if (xmlStrEqual(childNode->name, (
const xmlChar *)
"CSK")) {
648 childNode2 = childNode->children;
650 firstkey = curkey = (
struct key*) malloc(
sizeof *curkey);
652 curkey->next = (
struct key*) malloc(
sizeof *curkey);
653 curkey = curkey->next;
655 memset(curkey, 0,
sizeof *curkey);
660 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Algorithm")) {
661 temp_char = (
char *) xmlNodeGetContent(childNode2);
665 temp_char = (
char *)xmlGetProp(childNode2, (
const xmlChar *)
"length");
670 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Lifetime")) {
671 temp_char = (
char *) xmlNodeGetContent(childNode2);
672 status +=
check_time_def(temp_char, my_policy,
"Keys/CSK Lifetime", kasp, &curkey->life);
675 else if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Repository")) {
676 curkey->repo = (
char *) xmlNodeGetContent(childNode2);
679 childNode2 = childNode2->next;
683 childNode = childNode->next;
686 else if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Zone")) {
687 childNode = curNode->children;
690 if (xmlStrEqual(childNode->name, (
const xmlChar *)
"SOA")) {
691 childNode2 = childNode->children;
694 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"Serial")) {
695 serial = (
char *) xmlNodeGetContent(childNode2);
698 childNode2 = childNode2->next;
702 childNode = childNode->next;
705 else if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Parent")) {
706 childNode = curNode->children;
709 if (xmlStrEqual(childNode->name, (
const xmlChar *)
"DS")) {
710 childNode2 = childNode->children;
713 if (xmlStrEqual(childNode2->name, (
const xmlChar *)
"TTL")) {
714 temp_char = (
char *) xmlNodeGetContent(childNode2);
715 status +=
check_time_def(temp_char, my_policy,
"Parent/DS/TTL", kasp, &ds_ttl);
719 childNode2 = childNode2->next;
723 childNode = childNode->next;
728 curNode = curNode->next;
734 for (curkey = firstkey; curkey; curkey = curkey->next) {
735 if ((curkey->type & KSK) && ds_ttl + ttl >= curkey->life) {
736 dual_log(
"ERROR: KSK/Lifetime (%d seconds) for policy '%s' " 737 "must be greater than the DNSKEY record TTL (%d seconds) plus " 738 "the DS record TTL (%d seconds). This time is needed to pass for the " 739 "KSK to be able to reach the ready state.",
740 curkey->life, policy_name, ttl, ds_ttl);
744 if ((curkey->type & ZSK) && maxzone_ttl + ttl >= curkey->life) {
745 dual_log(
"ERROR: ZSK/Lifetime (%d seconds) for policy '%s' " 746 "must be greater than the DNSKEY record TTL (%d seconds) plus " 747 "the MaxZoneTTL (%d seconds). This time is needed to pass for the " 748 "ZSK to be able to reach the ready state.",
749 curkey->life, policy_name, ttl, maxzone_ttl);
755 if (refresh <= resign) {
756 dual_log(
"ERROR: The Refresh interval (%d seconds) for " 757 "%s Policy in %s is less than or equal to the Resign interval " 758 "(%d seconds)", refresh, policy_name, kasp, resign);
764 if (defalt <= refresh) {
765 dual_log(
"ERROR: Validity/Default (%d seconds) for " 766 "%s policy in %s is less than or equal to the Refresh interval " 767 "(%d seconds)", defalt, policy_name, kasp, refresh);
770 if (denial <= refresh) {
771 dual_log(
"ERROR: Validity/Denial (%d seconds) for " 772 "%s policy in %s is less than or equal to the Refresh interval " 773 "(%d seconds)", denial, policy_name, kasp, refresh);
781 if (defalt > denial) {
782 if (jitter > (defalt * 0.5)) {
783 dual_log(
"WARNING: Jitter time (%d seconds) is large " 784 "compared to Validity/Default (%d seconds) " 785 "for %s policy in %s", jitter, defalt, policy_name, kasp);
788 if (jitter > (denial * 0.5)) {
789 dual_log(
"WARNING: Jitter time (%d seconds) is large " 790 "compared to Validity/Denial (%d seconds) " 791 "for %s policy in %s", jitter, denial, policy_name, kasp);
799 if (inception > 3600) {
800 dual_log(
"WARNING: InceptionOffset is higher than expected " 801 "(%d seconds) for %s policy in %s",
802 inception, policy_name, kasp);
807 if (publish < (ttl * 0.1)) {
808 dual_log(
"WARNING: Keys/PublishSafety (%d seconds) is less than " 809 "0.1 * TTL (%d seconds) for %s policy in %s",
810 publish, ttl, policy_name, kasp);
812 else if (publish > (ttl * 5)) {
813 dual_log(
"WARNING: Keys/PublishSafety (%d seconds) is greater than " 814 "5 * TTL (%d seconds) for %s policy in %s",
815 publish, ttl, policy_name, kasp);
818 if (retire < (ttl * 0.1)) {
819 dual_log(
"WARNING: Keys/RetireSafety (%d seconds) is less than " 820 "0.1 * TTL (%d seconds) for %s policy in %s",
821 retire, ttl, policy_name, kasp);
823 else if (retire > (ttl * 5)) {
824 dual_log(
"WARNING: Keys/RetireSafety (%d seconds) is greater than " 825 "5 * TTL (%d seconds) for %s policy in %s",
826 retire, ttl, policy_name, kasp);
833 else if (nsec == 3) {
834 for (curkey = firstkey; curkey; curkey = curkey->next) {
835 if ((curkey->type & KSK) && curkey->algo <= 5) {
836 dual_log(
"ERROR: In policy %s, incompatible algorithm (%d) used for " 837 "KSK NSEC3 in %s.", policy_name, curkey->algo, kasp);
840 if ((curkey->type & ZSK) && curkey->algo <= 5) {
841 dual_log(
"ERROR: In policy %s, incompatible algorithm (%d) used for " 842 "ZSK NSEC3 in %s.", policy_name, curkey->algo, kasp);
848 if (resalt < resign) {
849 dual_log(
"WARNING: NSEC3 resalt interval (%d secs) is less than " 850 "signature resign interval (%d secs) for %s Policy",
851 resalt, resign, policy_name);
859 if (serial != NULL && strncmp(serial,
"datecounter", 11) == 0) {
861 resigns_per_day = (60 * 60 * 24) / resign;
862 if (resigns_per_day > 99) {
863 dual_log(
"ERROR: In %s, policy %s, serial type datecounter used " 864 "but %d re-signs requested. No more than 99 re-signs per " 865 "day should be used with datecounter as only 2 digits are " 866 "allocated for the version number.",
867 kasp, policy_name, resigns_per_day);
876 for (curkey = firstkey; curkey; curkey = curkey->next) {
877 if ((curkey->type & KSK) && (curkey->algo == 5 ||
878 curkey->algo == 7 ||curkey->algo == 8 ||
879 curkey->algo == 10)) {
880 if (curkey->length < 1024) {
881 dual_log(
"WARNING: Key length of %d used for KSK in %s policy in %s. Should " 882 "probably be 1024 or more", curkey->length, policy_name, kasp);
884 else if (curkey->length > 4096) {
885 dual_log(
"ERROR: Key length of %d used for KSK in %s policy in %s. Should " 886 "be 4096 or less", curkey->length, policy_name, kasp);
890 if ((curkey->type & ZSK) && (curkey->algo == 5 ||
891 curkey->algo == 7 || curkey->algo == 8 ||
892 curkey->algo == 10)) {
893 if (curkey->length < 1024) {
894 dual_log(
"WARNING: Key length of %d used for ZSK in %s policy in %s. Should " 895 "probably be 1024 or more", curkey->length, policy_name, kasp);
897 else if (curkey->length > 4096) {
898 dual_log(
"ERROR: Key length of %d used for ZSK in %s policy in %s. Should " 899 "be 4096 or less", curkey->length, policy_name, kasp);
908 for (curkey = firstkey; curkey; curkey = curkey->next) {
909 if ((curkey->type & KSK) && curkey->repo != NULL) {
910 for (i = 0; i < repo_count; i++) {
911 if (strcmp(curkey->repo, repo_list[i]) == 0) {
915 if (i >= repo_count) {
916 dual_log(
"ERROR: Unknown repository (%s) defined for KSK in " 917 "%s policy in %s", curkey->repo, policy_name, kasp);
922 if ((curkey->type & ZSK) && curkey->repo != NULL) {
923 for (i = 0; i < repo_count; i++) {
924 if (strcmp(curkey->repo, repo_list[i]) == 0) {
928 if (i >= repo_count) {
929 dual_log(
"ERROR: Unknown repository (%s) defined for ZSK in " 930 "%s policy", curkey->repo, policy_name);
937 for (curkey = firstkey; curkey; curkey = curkey->next) {
938 if (!(curkey->type & KSK))
continue;
939 for (tmpkey = firstkey; tmpkey; tmpkey = tmpkey->next) {
940 if (!(tmpkey->type & ZSK))
continue;
941 if (tmpkey->algo != curkey->algo)
continue;
943 if (curkey->life < tmpkey->life) {
944 dual_log(
"WARNING: KSK minimum lifetime (%d seconds) is less than " 945 "ZSK minimum lifetime (%d seconds) for %s Policy in %s",
946 curkey->life, tmpkey->life, policy_name, kasp);
954 if (jitter > defalt) {
955 dual_log(
"ERROR: Jitter time (%d seconds) is greater than the " 956 "Default Validity (%d seconds) for %s policy in %s",
957 jitter, defalt, policy_name, kasp);
960 if (jitter > denial) {
961 dual_log(
"ERROR: Jitter time (%d seconds) is greater than the " 962 "Denial Validity (%d seconds) for %s policy in %s",
963 jitter, denial, policy_name, kasp);
968 curkey = curkey->next;
1040 const char *ptr = text;
1042 long temp_interval = 0;
1044 if (!text || !interval || !*text)
return 4;
1045 length = strlen(text);
1046 if (length <= 2)
return 2;
1052 if (*ptr !=
'P')
return 2;
1055 end = text + length;
1059 if (!got_temp || !is_time)
return 2;
1060 temp_interval += temp;
1066 if (!got_temp)
return 2;
1068 temp_interval += 60 * temp;
1070 temp_interval += 31 * 24 * 60 * 60 * temp;
1078 if (!got_temp || !is_time)
return 2;
1079 temp_interval += 60 * 60 * temp;
1085 if (!got_temp || is_time)
return 2;
1086 temp_interval += 24 * 60 * 60 * temp;
1092 if (!got_temp || is_time)
return 2;
1093 temp_interval += 7 * 24 * 60 * 60 * temp;
1099 if (!got_temp || is_time)
return 2;
1100 temp_interval += 365 * 24 * 60 * 60 * temp;
1122 temp = strtol(ptr, &endptr, 10);
1123 if (temp == LONG_MIN || temp == LONG_MAX)
1132 if (ptr != end)
return 2;
1139 if (temp && !is_time)
return 2;
1140 temp_interval += temp;
1142 if (is_neg) temp_interval *= -1;
1143 *interval = (int) temp_interval;
1173 if (value == NULL) {
1174 dual_log(
"ERROR: NULL value passed to StrStrtoi");
1179 if ((longval >= INT_MIN) && (longval <= INT_MAX)) {
1180 *value = (int) longval;
1219 if (value == NULL) {
1220 dual_log(
"ERROR: NULL value passed to StrStrtol");
1232 *value = strtol(start, &endptr, 10);
1237 status = (*endptr ==
'\0') ? 0 : 1;
1268 char* duplicate = NULL;
1271 duplicate = strdup(
string);
1272 if (duplicate == NULL) {
1273 dual_log(
"ERROR: StrStrdup: Call to malloc() returned null - out of swap space?");
1330 int textlen = strlen(text);
1331 while (-- textlen >= 0) {
1332 if (! isspace((
int) text[textlen])) {
1333 text[textlen + 1] =
'\0';
1365 while (*text && isspace((
int) *text)) {
1375 void *ptr = calloc(nmemb, size);
1377 dual_log(
"ERROR: calloc: Out of swap space");
1384 static void quiet_error_func(
void * ctx,
const char * msg, ...)
1386 (void)ctx; (void)msg;
1396 char ***repo_listout,
int *repo_countout,
int verbose)
1401 int temp_status = 0;
1406 xmlXPathContextPtr xpath_ctx;
1407 xmlXPathObjectPtr xpath_obj;
1410 char* signer_dir = NULL;
1411 int signer_dir_default = 0;
1412 char* enforcer_dir = NULL;
1413 int enforcer_dir_default = 0;
1416 int* repo_mods = NULL;
1419 xmlSetGenericErrorFunc(NULL, quiet_error_func);
1422 status =
check_rng(conf, OPENDNSSEC_SCHEMA_DIR
"/conf.rng", verbose);
1425 if (status != 0)
return status;
1426 dual_log(
"INFO: The XML in %s is valid", conf);
1429 doc = xmlParseFile(conf);
1430 if (doc == NULL)
return 1;
1433 xpath_ctx = xmlXPathNewContext(doc);
1434 if(xpath_ctx == NULL) {
1440 xexpr = (xmlChar *)
"//Configuration/RepositoryList/Repository";
1441 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1442 if(xpath_obj == NULL) {
1443 xmlXPathFreeContext(xpath_ctx);
1448 if (xpath_obj->nodesetval) {
1449 repo_count = xpath_obj->nodesetval->nodeNr;
1450 *repo_countout = repo_count;
1453 repo_mods = (
int*)malloc(
sizeof(
int) * repo_count);
1454 repo_list = (
char**)malloc(
sizeof(
char*) * repo_count);
1455 *repo_listout = repo_list;
1457 if (repo == NULL || repo_mods == NULL || repo_list == NULL) {
1458 dual_log(
"ERROR: malloc for repo information failed");
1462 for (i = 0; i < repo_count; i++) {
1465 curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode;
1468 repo[i].
name = (
char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i],
1469 (
const xmlChar *)
"name");
1473 if (xmlStrEqual(curNode->name, (
const xmlChar *)
"TokenLabel"))
1474 repo[i].
TokenLabel = (
char *) xmlNodeGetContent(curNode);
1475 if (xmlStrEqual(curNode->name, (
const xmlChar *)
"Module"))
1476 repo[i].module = (
char *) xmlNodeGetContent(curNode);
1477 curNode = curNode->next;
1481 xmlXPathFreeObject(xpath_obj);
1484 for (i = 0; i < repo_count; i++) {
1486 if (repo_mods[i] == 0) {
1489 status +=
check_file(repo[i].module,
"Module");
1494 for (j = i+1; j < repo_count; j++) {
1495 if ( repo_mods[j] == 0 &&
1496 (strcmp(repo[i].module, repo[j].module) == 0) ) {
1499 if (strcmp(repo[i].TokenLabel, repo[j].TokenLabel) == 0) {
1500 dual_log(
"ERROR: Multiple Repositories (%s and %s) in %s have the same Module (%s) and TokenLabel (%s)", repo[i].name, repo[j].name, conf, repo[i].module, repo[i].TokenLabel);
1508 for (j = i+1; j < repo_count; j++) {
1509 if (strcmp(repo[i].name, repo[j].name) == 0) {
1510 dual_log(
"ERROR: Two repositories exist with the same name (%s)", repo[i].name);
1518 if (*kasp == NULL) {
1519 xexpr = (xmlChar *)
"//Configuration/Common/PolicyFile";
1520 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1521 if(xpath_obj == NULL) {
1522 xmlXPathFreeContext(xpath_ctx);
1525 for (i = 0; i < repo_count; i++) {
1527 free(repo[i].module);
1528 free(repo[i].TokenLabel);
1535 *kasp = (
char*) xmlXPathCastToString(xpath_obj);
1536 xmlXPathFreeObject(xpath_obj);
1539 if (*zonelist == NULL) {
1540 xexpr = (xmlChar *)
"//Configuration/Common/ZoneListFile";
1541 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1542 if(xpath_obj == NULL) {
1543 xmlXPathFreeContext(xpath_ctx);
1546 for (i = 0; i < repo_count; i++) {
1548 free(repo[i].module);
1549 free(repo[i].TokenLabel);
1556 *zonelist = (
char*) xmlXPathCastToString(xpath_obj);
1557 xmlXPathFreeObject(xpath_obj);
1564 (xmlChar *)
"//Configuration/Enforcer/Privileges/User",
1565 (xmlChar *)
"//Configuration/Enforcer/Privileges/Group");
1570 (xmlChar *)
"//Configuration/Enforcer/Datastore/SQLite");
1571 if (temp_status == -1) {
1577 status += temp_status;
1585 status +=
check_time_def_from_xpath(xpath_ctx, (xmlChar *)
"//Configuration/Enforcer/Interval",
"Configuration",
"Enforcer/Interval", conf);
1588 status +=
check_time_def_from_xpath(xpath_ctx, (xmlChar *)
"//Configuration/Enforcer/RolloverNotification",
"Configuration",
"Enforcer/RolloverNotification", conf);
1591 (xmlChar *)
"//Configuration/Enforcer/Interval", conf);
1595 (xmlChar *)
"//Configuration/Enforcer/DelegationSignerSubmitCommand");
1596 if (temp_status > 0) {
1597 status += temp_status;
1602 (xmlChar *)
"//Configuration/Enforcer/WorkingDirectory");
1603 if (temp_status == -1) {
1605 temp_status =
check_path(OPENDNSSEC_STATE_DIR
"/enforcer",
1606 "default Enforcer WorkingDirectory");
1608 if (temp_status > 0) {
1609 status += temp_status;
1615 (xmlChar *)
"//Configuration/Signer/Privileges/User",
1616 (xmlChar *)
"//Configuration/Signer/Privileges/Group");
1620 (xmlChar *)
"//Configuration/Signer/WorkingDirectory");
1621 if (temp_status == -1) {
1623 temp_status =
check_path(OPENDNSSEC_STATE_DIR
"/signer",
1624 "default Signer WorkingDirectory");
1626 if (temp_status > 0) {
1627 status += temp_status;
1631 xexpr = (xmlChar *)
"//Configuration/Signer/WorkingDirectory";
1632 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1633 if (NULL == xpath_obj) {
1634 signer_dir = (
char*) OPENDNSSEC_STATE_DIR
"/signer";
1635 signer_dir_default = 1;
1638 signer_dir = (
char*) xmlXPathCastToString(xpath_obj);
1639 xmlXPathFreeObject(xpath_obj);
1641 xexpr = (xmlChar *)
"//Configuration/Enforcer/WorkingDirectory";
1642 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1643 if (NULL == xpath_obj) {
1644 enforcer_dir = (
char*) OPENDNSSEC_STATE_DIR
"/enforcer";
1645 enforcer_dir_default = 1;
1648 enforcer_dir = (
char*) xmlXPathCastToString(xpath_obj);
1649 xmlXPathFreeObject(xpath_obj);
1651 temp_status = strcmp(signer_dir, enforcer_dir);
1652 if (0 == temp_status) {
1654 dual_log(
"ERROR: signer workingdirectory is the same as the one of enforcer");
1656 if (0 == signer_dir_default)
1658 if (0 == enforcer_dir_default)
1661 xmlXPathFreeContext(xpath_ctx);
1664 for (i = 0; i < repo_count; i++) {
1666 free(repo[i].module);
1667 free(repo[i].TokenLabel);
1683 xmlXPathContextPtr xpath_ctx;
1684 xmlXPathObjectPtr xpath_obj;
1686 int i, j, found, status = 0;
1689 if (!zonelist || !strncmp(zonelist,
"", 1)) {
1690 dual_log(
"ERROR: No location for zonelist.xml set");
1695 xmlSetGenericErrorFunc(NULL, quiet_error_func);
1698 if (
check_rng(zonelist, OPENDNSSEC_SCHEMA_DIR
"/zonelist.rng", verbose) != 0)
1702 doc = xmlParseFile(zonelist);
1707 xpath_ctx = xmlXPathNewContext(doc);
1708 if(xpath_ctx == NULL) {
1713 xexpr = (xmlChar *)
"//ZoneList/Zone/Policy";
1714 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1715 if(xpath_obj == NULL) {
1716 xmlXPathFreeContext(xpath_ctx);
1721 if (xpath_obj->nodesetval) {
1722 for (i = 0; i < xpath_obj->nodesetval->nodeNr; i++) {
1723 policy_name = (
char*)xmlNodeGetContent(xpath_obj->nodesetval->nodeTab[i]);
1727 for (j = 0; j < policy_count; j++) {
1728 if (!strcmp(policy_name, policy_names[j])) {
1735 dual_log(
"ERROR: Policy %s in zonelist does not exist!", policy_name);
1738 if (policy_name) free(policy_name);
1742 xmlXPathFreeObject(xpath_obj);
1743 xmlXPathFreeContext(xpath_ctx);
1747 if (!status)
dual_log(
"INFO: The XML in %s is valid", zonelist);
1755 int check_kasp(
const char *kasp,
char **repo_list,
int repo_count,
int verbose,
1756 char ***policy_names_out,
int *policy_count_out)
1762 xmlXPathContextPtr xpath_ctx;
1763 xmlXPathObjectPtr xpath_obj;
1767 int policy_count = 0;
1768 char **policy_names = NULL;
1769 int default_found = 0;
1772 xmlSetGenericErrorFunc(NULL, quiet_error_func);
1775 dual_log(
"ERROR: No location for kasp.xml set");
1780 status =
check_rng(kasp, OPENDNSSEC_SCHEMA_DIR
"/kasp.rng", verbose);
1783 dual_log(
"INFO: The XML in %s is valid", kasp);
1789 doc = xmlParseFile(kasp);
1795 xpath_ctx = xmlXPathNewContext(doc);
1796 if(xpath_ctx == NULL) {
1803 xexpr = (xmlChar *)
"//KASP/Policy";
1804 xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx);
1805 if(xpath_obj == NULL) {
1806 xmlXPathFreeContext(xpath_ctx);
1811 if (xpath_obj->nodesetval) {
1812 policy_count = xpath_obj->nodesetval->nodeNr;
1814 policy_names = (
char**)malloc(
sizeof(
char*) * policy_count);
1815 if (policy_names == NULL) {
1816 dual_log(
"ERROR: Malloc for policy names failed");
1820 for (i = 0; i < policy_count; i++) {
1822 policy_names[i] = (
char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i],
1823 (
const xmlChar *)
"name");
1828 for (i = 0; i < policy_count; i++) {
1829 if (strcmp(policy_names[i],
"default") == 0) {
1832 for (j = i+1; j < policy_count; j++) {
1833 if ( (strcmp(policy_names[i], policy_names[j]) == 0) ) {
1834 dual_log(
"ERROR: Two policies exist with the same name (%s)", policy_names[i]);
1839 if (default_found == 0) {
1840 dual_log(
"WARNING: No policy named 'default' in %s. This means you will need to refer explicitly to the policy for each zone", kasp);
1844 for (i = 0; i < policy_count; i++) {
1845 curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode;
1847 status +=
check_policy(curNode, policy_names[i], repo_list, repo_count, kasp);
1850 if (!status && policy_names_out && policy_count_out) {
1851 *policy_names_out = policy_names;
1852 *policy_count_out = policy_count;
1855 for (i = 0; i < policy_count; i++) {
1856 free(policy_names[i]);
1861 xmlXPathFreeObject(xpath_obj);
1862 xmlXPathFreeContext(xpath_ctx);
int check_time_def(const char *time_expr, const char *location, const char *field, const char *filename, int *interval)
char * StrStrdup(const char *string)
int check_path(const char *pathname, const char *log_string)
int check_conf(const char *conf, char **kasp, char **zonelist, char ***repo_listout, int *repo_countout, int verbose)
int DtXMLIntervalSeconds(const char *text, int *interval)
void StrTrimR(char *text)
const char * policy_name(const policy_t *policy)
int check_policy(xmlNode *curNode, const char *policy_name, char **repo_list, int repo_count, const char *kasp)
int check_kasp(const char *kasp, char **repo_list, int repo_count, int verbose, char ***policy_names_out, int *policy_count_out)
int check_zonelist(const char *zonelist, int verbose, char **policy_names, int policy_count)
void * MemCalloc(size_t nmemb, size_t size)
int check_rng(const char *filename, const char *rngfilename, int verbose)
int check_path_from_xpath(xmlXPathContextPtr xpath_ctx, const char *log_string, const xmlChar *path_xexpr)
int check_file(const char *filename, const char *log_string)
int StrStrtol(const char *string, long *value)
int kc_helper_printto_stdout
void log_init(int facility, const char *program_name)
int StrStrtoi(const char *string, int *value)
int check_interval(xmlXPathContextPtr xpath_ctx, const xmlChar *interval_xexpr, const char *filename)
void dual_log(const char *format,...)
int check_time_def_from_xpath(xmlXPathContextPtr xpath_ctx, const xmlChar *time_xexpr, const char *location, const char *field, const char *filename)
int check_user_group(xmlXPathContextPtr xpath_ctx, const xmlChar *user_xexpr, const xmlChar *group_xexpr)
int check_file_from_xpath(xmlXPathContextPtr xpath_ctx, const char *log_string, const xmlChar *file_xexpr)
char * StrTrimL(char *text)