OpenDNSSEC-enforcer  1.4.8.2
daemon_util.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*
28  * daemon_util.c code needed to get a daemon up and running
29  *
30  * edit the DAEMONCONFIG and cmlParse function
31  * in daemon_util.[c|h] to add options specific
32  * to your app
33  *
34  * gcc -o daemon daemon_util.c daemon.c
35  *
36  * Most of this is based on stuff I have seen in NSD
37  */
38 #include "config.h"
39 
40 #ifndef _GNU_SOURCE
41 #define _GNU_SOURCE
42 #endif
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <syslog.h>
48 #include <stdarg.h>
49 #include <errno.h>
50 #include <pwd.h>
51 #include <grp.h>
52 #include <ctype.h>
53 #include <signal.h>
54 #include <fcntl.h>
55 #include <syslog.h>
56 
57 #include <sys/select.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 
61 #include <libxml/tree.h>
62 #include <libxml/parser.h>
63 #include <libxml/xpath.h>
64 #include <libxml/xpathInternals.h>
65 #include <libxml/relaxng.h>
66 
67 #include "daemon.h"
68 #include "daemon_util.h"
69 
70 #include "ksm/database.h"
71 #include "ksm/datetime.h"
72 #include "ksm/string_util.h"
73 #include "ksm/string_util2.h"
74 
75 
81 #if defined(HAVE_SYSLOG_R) && defined(HAVE_OPENLOG_R) && defined(HAVE_CLOSELOG_R) && defined(HAVE_VSYSLOG_R)
82 struct syslog_data sdata = SYSLOG_DATA_INIT;
83 #else
84 #undef HAVE_SYSLOG_R
85 #undef HAVE_OPENLOG_R
86 #undef HAVE_CLOSELOG_R
87 #undef HAVE_VSYSLOG_R
88 #endif
89 
90  int
92 {
93  int status = 0;
94 
95  xmlDocPtr doc = NULL;
96  xmlDocPtr rngdoc = NULL;
97  xmlXPathContextPtr xpathCtx = NULL;
98  xmlXPathObjectPtr xpathObj = NULL;
99  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
100  xmlRelaxNGValidCtxtPtr rngctx = NULL;
101  xmlRelaxNGPtr schema = NULL;
102  xmlChar *user_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/User";
103  xmlChar *group_expr = (unsigned char*) "//Configuration/Enforcer/Privileges/Group";
104 
105  char* filename = NULL;
106  char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
107  char* temp_char = NULL;
108 
109  struct passwd *pwd;
110  struct group *grp;
111 
112  FILE *file;
113 
114  if (config->configfile != NULL) {
115  filename = StrStrdup(config->configfile);
116  } else {
117  filename = StrStrdup(OPENDNSSEC_CONFIG_FILE);
118  }
119 
120  /* Load XML document */
121  doc = xmlParseFile(filename);
122  if (doc == NULL) {
123  /* To get a better error message try to open the file */
124  file = fopen(filename, "r");
125  if (file == NULL) {
126  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", filename);
127  } else {
128  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", filename);
129  fclose(file);
130  }
131  return(-1);
132  }
133 
134  /* Load rng document */
135  rngdoc = xmlParseFile(rngfilename);
136  if (rngdoc == NULL) {
137  /* To get a better error message try to open the file */
138  file = fopen(rngfilename, "r");
139  if (file == NULL) {
140  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", rngfilename);
141  } else {
142  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", rngfilename);
143  fclose(file);
144  }
145  return(-1);
146  }
147 
148  /* Create an XML RelaxNGs parser context for the relax-ng document. */
149  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
150  if (rngpctx == NULL) {
151  log_msg(config, LOG_ERR, "Error: unable to create XML RelaxNGs parser context");
152  return(-1);
153  }
154 
155  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
156  schema = xmlRelaxNGParse(rngpctx);
157  if (schema == NULL) {
158  log_msg(config, LOG_ERR, "Error: unable to parse a schema definition resource");
159  return(-1);
160  }
161 
162  /* Create an XML RelaxNGs validation context based on the given schema */
163  rngctx = xmlRelaxNGNewValidCtxt(schema);
164  if (rngctx == NULL) {
165  log_msg(config, LOG_ERR, "Error: unable to create RelaxNGs validation context based on the schema");
166  return(-1);
167  }
168 
169  xmlRelaxNGSetValidErrors(rngctx,
170  (xmlRelaxNGValidityErrorFunc) log_xml_error,
171  (xmlRelaxNGValidityWarningFunc) log_xml_warn,
172  NULL);
173 
174  /* Validate a document tree in memory. */
175  status = xmlRelaxNGValidateDoc(rngctx,doc);
176  if (status != 0) {
177  log_msg(config, LOG_ERR, "Error validating file \"%s\"", filename);
178  return(-1);
179  }
180 
181  /* Now parse a value out of the conf */
182  /* Create xpath evaluation context */
183  xpathCtx = xmlXPathNewContext(doc);
184  if(xpathCtx == NULL) {
185  log_msg(config, LOG_ERR,"Error: unable to create new XPath context");
186  xmlFreeDoc(doc);
187  return(-1);
188  }
189 
190  /* Set the group if specified */
191  xpathObj = xmlXPathEvalExpression(group_expr, xpathCtx);
192  if(xpathObj == NULL) {
193  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", group_expr);
194  xmlXPathFreeContext(xpathCtx);
195  xmlFreeDoc(doc);
196  return(-1);
197  }
198  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
199  temp_char = (char*) xmlXPathCastToString(xpathObj);
200  StrAppend(&config->groupname, temp_char);
201  StrFree(temp_char);
202  } else {
203  config->groupname = NULL;
204  }
205  xmlXPathFreeObject(xpathObj);
206 
207  /* Set the user to drop to if specified */
208  xpathObj = xmlXPathEvalExpression(user_expr, xpathCtx);
209  if(xpathObj == NULL) {
210  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", user_expr);
211  xmlXPathFreeContext(xpathCtx);
212  xmlFreeDoc(doc);
213  return(-1);
214  }
215  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
216  temp_char = (char*) xmlXPathCastToString(xpathObj);
217  StrAppend(&config->username, temp_char);
218  StrFree(temp_char);
219  } else {
220  config->username = NULL;
221  }
222  xmlXPathFreeObject(xpathObj);
223 
224  /* Set uid and gid if required */
225  if (config->username != NULL) {
226  /* Lookup the user id in /etc/passwd */
227  if ((pwd = getpwnam(config->username)) == NULL) {
228 #ifdef HAVE_SYSLOG_R
229  syslog_r(LOG_ERR, &sdata, "user '%s' does not exist. exiting...\n", config->username);
230 #else
231  syslog(LOG_ERR, "user '%s' does not exist. exiting...\n", config->username);
232 #endif
233  exit(1);
234  } else {
235  config->uid = pwd->pw_uid;
236  }
237  endpwent();
238  }
239  if (config->groupname) {
240  /* Lookup the group id in /etc/groups */
241  if ((grp = getgrnam(config->groupname)) == NULL) {
242 #ifdef HAVE_SYSLOG_R
243  syslog_r(LOG_ERR, &sdata, "group '%s' does not exist. exiting...\n", config->groupname);
244 #else
245  syslog(LOG_ERR, "group '%s' does not exist. exiting...\n", config->groupname);
246 #endif
247  exit(1);
248  } else {
249  config->gid = grp->gr_gid;
250  }
251  endgrent();
252  }
253 
254  xmlRelaxNGFree(schema);
255  xmlRelaxNGFreeValidCtxt(rngctx);
256  xmlRelaxNGFreeParserCtxt(rngpctx);
257  xmlFreeDoc(doc);
258  xmlFreeDoc(rngdoc);
259  StrFree(filename);
260 
261  return 0;
262 }
263 
264 /* Set up logging as per default (facility may be switched based on config file) */
265 void log_init(int facility, const char *program_name)
266 {
267 #ifdef HAVE_OPENLOG_R
268  openlog_r(program_name, 0, facility, &sdata);
269 #else
270  openlog(program_name, 0, facility);
271 #endif
272 }
273 
274 /* Switch log to new facility */
275 void log_switch(int facility, const char *facility_name, const char *program_name, int verbose)
276 {
277 #ifdef HAVE_CLOSELOG_R
278  closelog_r(&sdata);
279 #else
280  closelog();
281 #endif
282 #ifdef HAVE_OPENLOG_R
283  openlog_r(program_name, 0, facility, &sdata);
284 #else
285  openlog(program_name, 0, facility);
286 #endif
287  if (verbose) {
288  log_msg(NULL, LOG_INFO, "Switched log facility to: %s", facility_name);
289  }
290 }
291 
292 
293 void
294 log_msg(DAEMONCONFIG *config, int priority, const char *format, ...)
295 {
296  /* If the variable arg list is bad then random errors can occur */
297  va_list args;
298  if (config && config->debug) priority = LOG_ERR;
299  va_start(args, format);
300 
301 #ifdef HAVE_VSYSLOG_R
302  vsyslog_r(priority, &sdata, format, args);
303 #else
304  vsyslog(priority, format, args);
305 #endif
306  va_end(args);
307 }
308 
309 /*
310  * log function suitable for libksm callback
311  */
312  void
313 ksm_log_msg(const char *format)
314 {
315  if (strncmp(format, "ERROR:", 6) == 0) {
316 #ifdef HAVE_SYSLOG_R
317  syslog_r(LOG_ERR, &sdata, "%s", format);
318 #else
319  syslog(LOG_ERR, "%s", format);
320 #endif
321  }
322  else if (strncmp(format, "INFO:", 5) == 0) {
323 #ifdef HAVE_SYSLOG_R
324  syslog_r(LOG_INFO, &sdata, "%s", format);
325 #else
326  syslog(LOG_INFO, "%s", format);
327 #endif
328  }
329  else if (strncmp(format, "WARNING:", 8) == 0) {
330 #ifdef HAVE_SYSLOG_R
331  syslog_r(LOG_WARNING, &sdata, "%s", format);
332 #else
333  syslog(LOG_WARNING, "%s", format);
334 #endif
335  }
336  else if (strncmp(format, "DEBUG:", 6) == 0) {
337 #ifdef HAVE_SYSLOG_R
338  syslog_r(LOG_DEBUG, &sdata, "%s", format);
339 #else
340  syslog(LOG_DEBUG, "%s", format);
341 #endif
342  }
343  else {
344 #ifdef HAVE_SYSLOG_R
345  syslog_r(LOG_ERR, &sdata, "%s", format);
346 #else
347  syslog(LOG_ERR, "%s", format);
348 #endif
349  }
350 }
351 
352 /* XML Error Message */
353  void
354 log_xml_error(void *ignore, const char *format, ...)
355 {
356  va_list args;
357 
358  (void) ignore;
359 
360  /* If the variable arg list is bad then random errors can occur */
361  va_start(args, format);
362 #ifdef HAVE_VSYSLOG_R
363  vsyslog_r(LOG_ERR, &sdata, format, args);
364 #else
365  vsyslog(LOG_ERR, format, args);
366 #endif
367  va_end(args);
368 }
369 
370 /* XML Warning Message */
371  void
372 log_xml_warn(void *ignore, const char *format, ...)
373 {
374  va_list args;
375 
376  (void) ignore;
377 
378  /* If the variable arg list is bad then random errors can occur */
379  va_start(args, format);
380 #ifdef HAVE_VSYSLOG_R
381  vsyslog_r(LOG_INFO, &sdata, format, args);
382 #else
383  vsyslog(LOG_INFO, format, args);
384 #endif
385  va_end(args);
386 }
387 
388  static void
389 usage(const char* prog)
390 {
391  fprintf(stderr, "Usage: %s [OPTION]...\n", prog);
392  fprintf(stderr, "OpenDNSSEC Enforcer version %s\n\n", VERSION);
393  fprintf(stderr, "Supported options:\n");
394  fprintf(stderr, " -c <file> Use alternate conf.xml.\n");
395  fprintf(stderr, " -d Debug.\n");
396  fprintf(stderr, " -1 Run once, then exit.\n");
397  fprintf(stderr, " -p <policy> Run once processing only the specified policy, then exit.\n");
398 /* fprintf(stderr, " -u user Change effective uid to the specified user.\n");*/
399  fprintf(stderr, " -P <pidfile> Specify the PID file to write.\n");
400 
401  fprintf(stderr, " -V Print version.\n");
402  fprintf(stderr, " -[?|h] This help.\n");
403 }
404 
405  static void
406 version(void)
407 {
408  fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
409  fprintf(stderr, "Written by %s.\n\n", AUTHOR_NAME);
410  fprintf(stderr, "%s. This is free software.\n", COPYRIGHT_STR);
411  fprintf(stderr, "See source files for more license information\n");
412  exit(0);
413 }
414 
415  int
416 write_data(DAEMONCONFIG *config, FILE *file, const void *data, size_t size)
417 {
418  size_t result;
419 
420  if (size == 0)
421  return 1;
422 
423  result = fwrite(data, 1, size, file);
424 
425  if (result == 0) {
426  log_msg(config, LOG_ERR, "write failed: %s", strerror(errno));
427  return 0;
428  } else if (result < size) {
429  log_msg(config, LOG_ERR, "short write (disk full?)");
430  return 0;
431  } else {
432  return 1;
433  }
434 }
435 
436  static pid_t
437 readpid(const char *file)
438 {
439  int fd;
440  pid_t pid;
441  char pidbuf[32];
442  char *t;
443  int l;
444 
445  if ((fd = open(file, O_RDONLY)) == -1) {
446  return -1;
447  }
448  if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) {
449  close(fd);
450  return -1;
451  }
452  close(fd);
453  /* Empty pidfile means no pidfile... */
454  if (l == 0) {
455  errno = ENOENT;
456  return -1;
457  }
458  pid = strtol(pidbuf, &t, 10);
459 
460  if (*t && *t != '\n') {
461  return -1;
462  }
463  return pid;
464 }
465 
466  int
468 {
469  FILE * fd;
470  char pidbuf[32];
471  struct stat stat_ret;
472  pid_t oldpid;
473 
474  /* If the file exists then either we didn't shutdown cleanly or an enforcer is
475  * already running; in either case shutdown */
476  if (stat(config->pidfile, &stat_ret) != 0) {
477 
478  if (errno != ENOENT) {
479  log_msg(config, LOG_ERR, "cannot stat pidfile %s: %s",
480  config->pidfile, strerror(errno));
481  return -1;
482  }
483  } else {
484  if (S_ISREG(stat_ret.st_mode)) {
485  /* The file exists already */
486  if ((oldpid = readpid(config->pidfile)) == -1) {
487  /* consider stale pidfile */
488  if (errno != ENOENT) {
489  log_msg(config, LOG_ERR, "cannot read pidfile %s: %s",
490  config->pidfile, strerror(errno));
491  }
492  } else {
493  if (kill(oldpid, 0) == 0 || errno == EPERM) {
494  log_msg(config, LOG_ERR, "pidfile %s already exists, "
495  "a process with pid %u is already running. "
496  "If no ods-enforcerd process is running, a previous "
497  "instance didn't shutdown cleanly, please remove this "
498  "file and try again.", config->pidfile, oldpid);
499  exit(1);
500  } else {
501  log_msg(config, LOG_WARNING, "pidfile %s already exists, "
502  "but no process with pid %u is running. "
503  "A previous instance didn't shutdown cleanly, this "
504  "pidfile is stale.", config->pidfile, oldpid);
505  }
506  }
507  }
508  }
509 
510  /* All good, carry on */
511  snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) config->pid);
512 
513  if ((fd = fopen(config->pidfile, "w")) == NULL ) {
514  return -1;
515  }
516 
517  if (!write_data(config, fd, pidbuf, strlen(pidbuf))) {
518  fclose(fd);
519  return -1;
520  }
521  fclose(fd);
522 
523  if (chown(config->pidfile, config->uid, config->gid) == -1) {
524  log_msg(config, LOG_ERR, "cannot chown(%u,%u) %s: %s",
525  (unsigned) config->uid, (unsigned) config->gid,
526  config->pidfile, strerror(errno));
527  return -1;
528  }
529 
530  /* Mark this our pidfile so exit_function unlink's it */
531  daemon_our_pidfile = 1;
532  return 0;
533 }
534 
535  int
537 {
538  char* directory = NULL;
539  char* slash;
540  struct stat stat_ret;
541  char *path = getenv("PWD");
542 
543  /* Find the directory part of the (fully qualified) pidfile */
544  if (*config->pidfile != '/') {
545  StrAppend(&directory, path);
546  StrAppend(&directory, "/");
547  StrAppend(&directory, config->pidfile);
548  } else {
549  directory = StrStrdup(config->pidfile);
550  }
551  slash = strrchr(directory, '/');
552  *slash = 0;
553 
554  /* Check that it exists */
555  if (stat(directory, &stat_ret) != 0) {
556 
557  if (errno != ENOENT) {
558  log_msg(config, LOG_ERR, "cannot stat directory %s: %s",
559  directory, strerror(errno));
560  return -1;
561  }
562  }
563 
564  if (S_ISDIR(stat_ret.st_mode)) {
565  /* Do nothing, the directory exists already */
566  } else {
567  /* try to create it */
568  if (make_directory(config, directory) != 0) {
569  StrFree(directory);
570  return -1;
571  }
572  }
573  StrFree(directory);
574 
575  return 0;
576 }
577 
578 int make_directory(DAEMONCONFIG* config, const char* path) {
579 
580  char* parent;
581  char* slash;
582  struct stat stat_ret;
583 
584  parent = StrStrdup(path);
585  slash = strrchr(parent, '/');
586 
587  *slash = 0;
588 
589  if (stat(parent, &stat_ret) != 0) {
590  if (errno != ENOENT) {
591  log_msg(NULL, LOG_ERR, "cannot stat %s: %s\n",
592  parent, strerror(errno));
593  return 1;
594  }
595  }
596 
597  if (!S_ISDIR(stat_ret.st_mode)) {
598  make_directory(config, parent);
599  }
600 
601 
602  StrFree(parent);
603 
604  if (mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0) {
605  log_msg(NULL, LOG_ERR, "cannot create directory %s: %s\n",
606  path, strerror(errno));
607  return 1;
608  }
609 
610 
611  if (chown(path, config->uid, config->gid) == -1) {
612  log_msg(config, LOG_ERR, "cannot chown(%u,%u) %s: %s",
613  (unsigned) config->uid, (unsigned) config->gid,
614  path, strerror(errno));
615  return 1;
616  }
617 
618  return 0;
619 
620 }
621 
622  void
623 cmdlParse(DAEMONCONFIG* config, int *argc, char **argv)
624 {
625  int c;
626 
627  /*
628  * Read the command line
629  */
630  while ((c = getopt(*argc, argv, "1c:hdV?u:P:p:")) != -1) {
631  switch (c) {
632  case '1':
633  config->once = true;
634  break;
635  case 'c':
636  config->configfile = optarg;
637  break;
638  case 'd':
639  config->debug = true;
640  break;
641  case 'P':
642  config->pidfile = optarg;
643  config->pidfile_set = 1;
644  break;
645  case 'u':
646 #if 0 /* disable this feature */
647  config->username = optarg;
648  /* Parse the username into uid and gid */
649  config->gid = getgid();
650  config->uid = getuid();
651  if (*config->username) {
652  struct passwd *pwd;
653  if (isdigit(*config->username)) {
654  char *t;
655  config->uid = strtol(config->username, &t, 10);
656  if (*t != 0) {
657  if (*t != '.' || !isdigit(*++t)) {
658  log_msg(config, LOG_ERR, "-u user or -u uid or -u uid.gid. exiting...");
659  exit(1);
660  }
661  config->gid = strtol(t, &t, 10);
662  } else {
663  /* Lookup the group id in /etc/passwd */
664  if ((pwd = getpwuid(config->uid)) == NULL) {
665  log_msg(config, LOG_ERR, "user id %u does not exist. exiting...", (unsigned) config->uid);
666  exit(1);
667  } else {
668  config->gid = pwd->pw_gid;
669  }
670  endpwent();
671  }
672  } else {
673  /* Lookup the user id in /etc/passwd */
674  if ((pwd = getpwnam(config->username)) == NULL) {
675  log_msg(config, LOG_ERR, "user '%s' does not exist. exiting...", config->username);
676  exit(1);
677  } else {
678  config->uid = pwd->pw_uid;
679  config->gid = pwd->pw_gid;
680  }
681  endpwent();
682  }
683  }
684 #endif
685  break;
686  case 'p':
687  config->policy = optarg;
688  config->once = true;
689  fprintf(stdout, "Will only process policy \"%s\", will only run once. Check the logs for results. \n", config->policy);
690  break;
691  case 'h':
692  usage(config->program);
693  exit(0);
694  case '?':
695  usage(config->program);
696  exit(0);
697  case 'V':
698  version();
699  exit(0);
700  default:
701  usage(config->program);
702  exit(0);
703  }
704  }
705 }
706 
707 /*
708  * Returns 0 if the the config file could be read and non-zero if it could not.
709  *
710  * Any function calling this should exit on a non-zero return.
711  */
712 int
714 {
715  xmlDocPtr doc = NULL;
716  xmlDocPtr rngdoc = NULL;
717  xmlXPathContextPtr xpathCtx = NULL;
718  xmlXPathObjectPtr xpathObj = NULL;
719  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
720  xmlRelaxNGValidCtxtPtr rngctx = NULL;
721  xmlRelaxNGPtr schema = NULL;
722  xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval";
723  xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration";
724  xmlChar *rn_expr = (unsigned char*) "//Configuration/Enforcer/RolloverNotification";
725  xmlChar *ds_expr = (unsigned char*) "//Configuration/Enforcer/DelegationSignerSubmitCommand";
726  xmlChar *pid_expr = (unsigned char*) "//Configuration/Enforcer/PidFile";
727  xmlChar *litexpr = (unsigned char*) "//Configuration/Enforcer/Datastore/SQLite";
728  xmlChar *mysql_host = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host";
729  xmlChar *mysql_port = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host/@port";
730  xmlChar *mysql_db = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Database";
731  xmlChar *mysql_user = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Username";
732  xmlChar *mysql_pass = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Password";
733  xmlChar *log_user_expr = (unsigned char*) "//Configuration/Common/Logging/Syslog/Facility";
734 
735  int mysec = 0;
736  char *logFacilityName;
737  int my_log_user = DEFAULT_LOG_FACILITY;
738  int status;
739  int db_found = 0;
740  char* filename = NULL;
741  char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
742 
743  char* temp_char = NULL;
744  char* str = NULL; /* used to split DSSub command */
745 
746  FILE *file;
747 
748  /* Change the config file location if one was provided on the command line */
749  if (config->configfile != NULL) {
750  filename = StrStrdup(config->configfile);
751  } else {
752  filename = StrStrdup(OPENDNSSEC_CONFIG_FILE);
753  }
754 
755  if (verbose) {
756  log_msg(config, LOG_INFO, "Reading config \"%s\"", filename);
757  }
758 
759  /* Load XML document */
760  doc = xmlParseFile(filename);
761  if (doc == NULL) {
762  /* To get a better error message try to open the file */
763  file = fopen(filename, "r");
764  if (file == NULL) {
765  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", filename);
766  } else {
767  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", filename);
768  fclose(file);
769  }
770  return(-1);
771  }
772 
773  /* Load rng document */
774  if (verbose) {
775  log_msg(config, LOG_INFO, "Reading config schema \"%s\"", rngfilename);
776  }
777  rngdoc = xmlParseFile(rngfilename);
778  if (rngdoc == NULL) {
779  /* To get a better error message try to open the file */
780  file = fopen(rngfilename, "r");
781  if (file == NULL) {
782  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", rngfilename);
783  } else {
784  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", rngfilename);
785  fclose(file);
786  }
787  return(-1);
788  }
789 
790  /* Create an XML RelaxNGs parser context for the relax-ng document. */
791  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
792  if (rngpctx == NULL) {
793  log_msg(config, LOG_ERR, "Error: unable to create XML RelaxNGs parser context");
794  return(-1);
795  }
796 
797  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
798  schema = xmlRelaxNGParse(rngpctx);
799  if (schema == NULL) {
800  log_msg(config, LOG_ERR, "Error: unable to parse a schema definition resource");
801  return(-1);
802  }
803 
804  /* Create an XML RelaxNGs validation context based on the given schema */
805  rngctx = xmlRelaxNGNewValidCtxt(schema);
806  if (rngctx == NULL) {
807  log_msg(config, LOG_ERR, "Error: unable to create RelaxNGs validation context based on the schema");
808  return(-1);
809  }
810 
811  xmlRelaxNGSetValidErrors(rngctx,
812  (xmlRelaxNGValidityErrorFunc) log_xml_error,
813  (xmlRelaxNGValidityWarningFunc) log_xml_warn,
814  NULL);
815 
816  /* Validate a document tree in memory. */
817  status = xmlRelaxNGValidateDoc(rngctx,doc);
818  if (status != 0) {
819  log_msg(config, LOG_ERR, "Error validating file \"%s\"", filename);
820  return(-1);
821  }
822  xmlRelaxNGFreeValidCtxt(rngctx);
823  xmlRelaxNGFree(schema);
824  xmlRelaxNGFreeParserCtxt(rngpctx);
825  xmlFreeDoc(rngdoc);
826 
827  /* Now parse a value out of the conf */
828  /* Create xpath evaluation context */
829  xpathCtx = xmlXPathNewContext(doc);
830  if(xpathCtx == NULL) {
831  log_msg(config, LOG_ERR,"Error: unable to create new XPath context");
832  xmlFreeDoc(doc);
833  return(-1);
834  }
835 
836  /* Evaluate xpath expression for interval */
837  xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx);
838  if(xpathObj == NULL) {
839  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", iv_expr);
840  xmlXPathFreeContext(xpathCtx);
841  xmlFreeDoc(doc);
842  return(-1);
843  }
844 
845  temp_char = (char *)xmlXPathCastToString(xpathObj);
846  status = DtXMLIntervalSeconds(temp_char, &mysec);
847  if (status > 0) {
848  log_msg(config, LOG_ERR, "Error: unable to convert Interval %s to seconds, error: %i", temp_char, status);
849  StrFree(temp_char);
850  return status;
851  }
852  else if (status == -1) {
853  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
854  }
855  config->interval = mysec;
856  if (verbose) {
857  log_msg(config, LOG_INFO, "Communication Interval: %i", config->interval);
858  }
859  StrFree(temp_char);
860  xmlXPathFreeObject(xpathObj);
861 
862  /* Evaluate xpath expression for Manual key generation */
863  xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx);
864  if(xpathObj == NULL) {
865  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mk_expr);
866  xmlXPathFreeContext(xpathCtx);
867  xmlFreeDoc(doc);
868  return(-1);
869  }
870 
871  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
872  /* Manual key generation tag is present */
873  config->manualKeyGeneration = 1;
874  }
875  else {
876  /* Tag absent */
877  config->manualKeyGeneration = 0;
878  }
879  xmlXPathFreeObject(xpathObj);
880 
881  /* Evaluate xpath expression for rollover notification interval */
882  xpathObj = xmlXPathEvalExpression(rn_expr, xpathCtx);
883  if(xpathObj == NULL) {
884  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", rn_expr);
885  xmlXPathFreeContext(xpathCtx);
886  xmlFreeDoc(doc);
887  return(-1);
888  }
889 
890  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
891  /* Tag RolloverNotification is present; set rolloverNotify */
892  temp_char = (char *)xmlXPathCastToString(xpathObj);
893  status = DtXMLIntervalSeconds(temp_char, &mysec);
894  if (status > 0) {
895  log_msg(config, LOG_ERR, "Error: unable to convert RolloverNotification %s to seconds, error: %i", temp_char, status);
896  StrFree(temp_char);
897  xmlXPathFreeObject(xpathObj);
898  return status;
899  }
900  else if (status == -1) {
901  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
902  }
903  config->rolloverNotify = mysec;
904  if (verbose) {
905  log_msg(config, LOG_INFO, "Rollover Notification Interval: %i", config->rolloverNotify);
906  }
907  StrFree(temp_char);
908  }
909  else {
910  /* Tag RolloverNotification absent, set rolloverNotify to -1 */
911  config->rolloverNotify = -1;
912  }
913  xmlXPathFreeObject(xpathObj);
914 
915  /* Evaluate xpath expression for DelegationSignerSubmitCommand */
916  xpathObj = xmlXPathEvalExpression(ds_expr, xpathCtx);
917  if(xpathObj == NULL) {
918  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", ds_expr);
919  xmlXPathFreeContext(xpathCtx);
920  xmlFreeDoc(doc);
921  return(-1);
922  }
923  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
924  /* Tag DelegationSignerSubmitCommand is present; set DSSubmitCmd */
925  if (config->DSSubmitCmd != NULL) {
926  StrFree(config->DSSubmitCmd);
927  }
928  config->DSSubmitCmd = (char *)xmlXPathCastToString(xpathObj);
929 
930  /* If the string ends " --cka_id" strip that off and set flag */
931  str = strstr(config->DSSubmitCmd, " --cka_id");
932  if (str) {
933  config->DSSubCKA_ID = 1;
934  *str = 0;
935  } else {
936  config->DSSubCKA_ID = 0;
937  }
938 
939  if (verbose) {
940  log_msg(config, LOG_INFO, "Using command: %s to submit DS records", config->DSSubmitCmd);
941  }
942  } else {
943  if (verbose) {
944  log_msg(config, LOG_INFO, "No DS Submit command supplied");
945  }
946  config->DSSubmitCmd[0] = '\0';
947  }
948  xmlXPathFreeObject(xpathObj);
949 
950  /* Evaluate xpath expression for SQLite file location */
951 
952  xpathObj = xmlXPathEvalExpression(litexpr, xpathCtx);
953  if(xpathObj == NULL) {
954  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", litexpr);
955  xmlXPathFreeContext(xpathCtx);
956  xmlFreeDoc(doc);
957  return(-1);
958  }
959  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
960  db_found = SQLITE_DB;
961  if (config->schema != NULL) {
962  StrFree(config->schema);
963  }
964  config->schema = xmlXPathCastToString(xpathObj);
965  if (verbose) {
966  log_msg(config, LOG_INFO, "SQLite database set to: %s", config->schema);
967  }
968  }
969  xmlXPathFreeObject(xpathObj);
970 
971  if (db_found == 0) {
972  db_found = MYSQL_DB;
973 
974  /* Get all of the MySQL stuff read in too */
975  /* HOST */
976  xpathObj = xmlXPathEvalExpression(mysql_host, xpathCtx);
977  if(xpathObj == NULL) {
978  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_host);
979  xmlXPathFreeContext(xpathCtx);
980  xmlFreeDoc(doc);
981  return(-1);
982  }
983  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
984  if (config->host != NULL) {
985  StrFree(config->host);
986  }
987  config->host = xmlXPathCastToString(xpathObj);
988  if (verbose) {
989  log_msg(config, LOG_INFO, "MySQL database host set to: %s", config->host);
990  }
991  }
992  xmlXPathFreeObject(xpathObj);
993 
994  /* PORT */
995  xpathObj = xmlXPathEvalExpression(mysql_port, xpathCtx);
996  if(xpathObj == NULL) {
997  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_port);
998  xmlXPathFreeContext(xpathCtx);
999  xmlFreeDoc(doc);
1000  return(-1);
1001  }
1002  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1003  if (config->port != NULL) {
1004  StrFree(config->port);
1005  }
1006  config->port = xmlXPathCastToString(xpathObj);
1007  if (verbose) {
1008  log_msg(config, LOG_INFO, "MySQL database port set to: %s", config->port);
1009  }
1010  }
1011  xmlXPathFreeObject(xpathObj);
1012 
1013  /* SCHEMA */
1014  xpathObj = xmlXPathEvalExpression(mysql_db, xpathCtx);
1015  if(xpathObj == NULL) {
1016  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_db);
1017  xmlXPathFreeContext(xpathCtx);
1018  xmlFreeDoc(doc);
1019  return(-1);
1020  }
1021  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1022  if (config->schema != NULL) {
1023  StrFree(config->schema);
1024  }
1025  config->schema = xmlXPathCastToString(xpathObj);
1026  if (verbose) {
1027  log_msg(config, LOG_INFO, "MySQL database schema set to: %s", config->schema);
1028  }
1029  } else {
1030  db_found = 0;
1031  }
1032  xmlXPathFreeObject(xpathObj);
1033 
1034  /* DB USER */
1035  xpathObj = xmlXPathEvalExpression(mysql_user, xpathCtx);
1036  if(xpathObj == NULL) {
1037  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_user);
1038  xmlXPathFreeContext(xpathCtx);
1039  xmlFreeDoc(doc);
1040  return(-1);
1041  }
1042  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1043  if (config->user != NULL) {
1044  StrFree(config->user);
1045  }
1046  config->user = xmlXPathCastToString(xpathObj);
1047  if (verbose) {
1048  log_msg(config, LOG_INFO, "MySQL database user set to: %s", config->user);
1049  }
1050  } else {
1051  db_found = 0;
1052  }
1053  xmlXPathFreeObject(xpathObj);
1054 
1055  /* DB PASSWORD */
1056  xpathObj = xmlXPathEvalExpression(mysql_pass, xpathCtx);
1057  if(xpathObj == NULL) {
1058  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_pass);
1059  xmlXPathFreeContext(xpathCtx);
1060  xmlFreeDoc(doc);
1061  return(-1);
1062  }
1063  /* password may be blank */
1064 
1065  if (config->password != NULL) {
1066  StrFree(config->password);
1067  }
1068  config->password = xmlXPathCastToString(xpathObj);
1069  if (verbose) {
1070  log_msg(config, LOG_INFO, "MySQL database password set");
1071  }
1072  xmlXPathFreeObject(xpathObj);
1073 
1074  }
1075 
1076  /* Check that we found one or the other database */
1077  if(db_found == 0) {
1078  log_msg(config, LOG_ERR, "Error: unable to find complete database connection expression in %s", filename);
1079  xmlFreeDoc(doc);
1080  return(-1);
1081  }
1082 
1083  /* Check that we found the right database type */
1084  if (db_found != DbFlavour()) {
1085  log_msg(config, LOG_ERR, "Error: Config file %s specifies database type %s but system is compiled to use %s", filename, (db_found==1) ? "MySQL" : "sqlite3", (db_found==2) ? "MySQL" : "sqlite3");
1086  xmlFreeDoc(doc);
1087  return(-1);
1088  }
1089 
1090  /* Evaluate xpath expression for log facility (user) */
1091  xpathObj = xmlXPathEvalExpression(log_user_expr, xpathCtx);
1092  if(xpathObj == NULL) {
1093  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", log_user_expr);
1094  xmlXPathFreeContext(xpathCtx);
1095  xmlFreeDoc(doc);
1096  return(-1);
1097  }
1098 
1099  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1100  /* tag present */
1101  logFacilityName = (char *)xmlXPathCastToString(xpathObj);
1102 
1103  status = get_log_user(logFacilityName, &my_log_user);
1104  if (status > 0) {
1105  log_msg(config, LOG_ERR, "Error: unable to set log user: %s, error: %i", logFacilityName, status);
1106  StrFree(logFacilityName);
1107  xmlXPathFreeObject(xpathObj);
1108  xmlXPathFreeContext(xpathCtx);
1109  xmlFreeDoc(doc);
1110  return status;
1111  }
1112  config->log_user = my_log_user;
1113  if (verbose) {
1114  log_msg(config, LOG_INFO, "Log User set to: %s", logFacilityName);
1115  }
1116 
1117  } else {
1118  /* tag _not_ present, use default */
1119  logFacilityName = StrStrdup( (char *)DEFAULT_LOG_FACILITY_STRING );
1120  config->log_user = DEFAULT_LOG_FACILITY;
1121  if (verbose) {
1122  log_msg(config, LOG_INFO, "Using default log user: %s", logFacilityName);
1123  }
1124  }
1125 
1126  /* Evaluate xpath expression for pidfile */
1127  xpathObj = xmlXPathEvalExpression(pid_expr, xpathCtx);
1128  if(xpathObj == NULL) {
1129  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", pid_expr);
1130  xmlXPathFreeContext(xpathCtx);
1131  xmlFreeDoc(doc);
1132  return(-1);
1133  }
1134 
1135  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1136  /* tag present */
1137  if (!config->pidfile_set) {
1138  config->pidfile = (char *)xmlXPathCastToString(xpathObj);
1139  if (verbose) {
1140  log_msg(config, LOG_INFO, "Pidfile set to: %s", config->pidfile);
1141  }
1142  }
1143  }
1144 
1145  xmlXPathFreeObject(xpathObj);
1146 
1147  log_switch(my_log_user, logFacilityName, config->program, verbose);
1148 
1149  /* Cleanup */
1150  /* TODO: some other frees are needed */
1151  xmlFreeDoc(doc);
1152  StrFree(logFacilityName);
1153  StrFree(filename);
1154 
1155  return(0);
1156 
1157 }
1158 
1159 /* To overcome the potential differences in sqlite compile flags assume that it is not
1160  happy with multiple connections.
1161 
1162  The following 2 functions take out a lock and release it
1163 */
1164 
1165 int get_lite_lock(char *lock_filename, FILE* lock_fd)
1166 {
1167  struct flock fl;
1168  struct timeval tv;
1169 
1170  if (lock_fd == NULL) {
1171  log_msg(NULL, LOG_ERR, "%s could not be opened", lock_filename);
1172  return 1;
1173  }
1174 
1175  memset(&fl, 0, sizeof(struct flock));
1176  fl.l_type = F_WRLCK;
1177  fl.l_whence = SEEK_SET;
1178  fl.l_pid = getpid();
1179 
1180  while (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1181  if (errno == EACCES || errno == EAGAIN) {
1182  log_msg(NULL, LOG_INFO, "%s already locked, sleep", lock_filename);
1183 
1184  /* sleep for 10 seconds TODO make this configurable? */
1185  tv.tv_sec = 10;
1186  tv.tv_usec = 0;
1187  select(0, NULL, NULL, NULL, &tv);
1188 
1189  } else {
1190  log_msg(NULL, LOG_INFO, "couldn't get lock on %s, %s", lock_filename, strerror(errno));
1191  return 1;
1192  }
1193  }
1194 
1195  return 0;
1196 
1197 }
1198 
1199 int release_lite_lock(FILE* lock_fd)
1200 {
1201  struct flock fl;
1202 
1203  if (lock_fd == NULL) {
1204  return 1;
1205  }
1206 
1207  memset(&fl, 0, sizeof(struct flock));
1208  fl.l_type = F_UNLCK;
1209  fl.l_whence = SEEK_SET;
1210 
1211  if (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1212  return 1;
1213  }
1214 
1215  return 0;
1216 }
1217 
1218 /* convert the name of a log facility (user) into a number */
1219 int get_log_user(const char* username, int* usernumber)
1220 {
1221  char* case_username = NULL;
1222 
1223  if (username == NULL) {
1224  return 1;
1225  }
1226  /* Start with our default */
1227  *usernumber = DEFAULT_LOG_FACILITY;
1228 
1229  case_username = StrStrdup(username);
1230  (void) StrToUpper(case_username);
1231 
1232  /* POSIX only specifies LOG_USER and LOG_LOCAL[0 .. 7] */
1233  if (strncmp(case_username, "USER", 4) == 0) {
1234  *usernumber = LOG_USER;
1235  }
1236 #ifdef LOG_KERN
1237  else if (strncmp(case_username, "KERN", 4) == 0) {
1238  *usernumber = LOG_KERN;
1239  }
1240 #endif /* LOG_KERN */
1241 #ifdef LOG_MAIL
1242  else if (strncmp(case_username, "MAIL", 4) == 0) {
1243  *usernumber = LOG_MAIL;
1244  }
1245 #endif /* LOG_MAIL */
1246 #ifdef LOG_DAEMON
1247  else if (strncmp(case_username, "DAEMON", 6) == 0) {
1248  *usernumber = LOG_DAEMON;
1249  }
1250 #endif /* LOG_DAEMON */
1251 #ifdef LOG_AUTH
1252  else if (strncmp(case_username, "AUTH", 4) == 0) {
1253  *usernumber = LOG_AUTH;
1254  }
1255 #endif /* LOG_AUTH */
1256 #ifdef LOG_SYSLOG
1257  else if (strncmp(case_username, "SYSLOG", 6) == 0) {
1258  *usernumber = LOG_SYSLOG;
1259  }
1260 #endif /* LOG_SYSLOG */
1261 #ifdef LOG_LPR
1262  else if (strncmp(case_username, "LPR", 3) == 0) {
1263  *usernumber = LOG_LPR;
1264  }
1265 #endif /* LOG_LPR */
1266 #ifdef LOG_NEWS
1267  else if (strncmp(case_username, "NEWS", 4) == 0) {
1268  *usernumber = LOG_NEWS;
1269  }
1270 #endif /* LOG_NEWS */
1271 #ifdef LOG_UUCP
1272  else if (strncmp(case_username, "UUCP", 4) == 0) {
1273  *usernumber = LOG_UUCP;
1274  }
1275 #endif /* LOG_UUCP */
1276 #ifdef LOG_AUDIT /* Ubuntu at least doesn't want us to use LOG_AUDIT */
1277  else if (strncmp(case_username, "AUDIT", 5) == 0) {
1278  *usernumber = LOG_AUDIT;
1279  }
1280 #endif /* LOG_AUDIT */
1281 #ifdef LOG_CRON
1282  else if (strncmp(case_username, "CRON", 4) == 0) {
1283  *usernumber = LOG_CRON;
1284  }
1285 #endif /* LOG_CRON */
1286  else if (strncmp(case_username, "LOCAL0", 6) == 0) {
1287  *usernumber = LOG_LOCAL0;
1288  }
1289  else if (strncmp(case_username, "LOCAL1", 6) == 0) {
1290  *usernumber = LOG_LOCAL1;
1291  }
1292  else if (strncmp(case_username, "LOCAL2", 6) == 0) {
1293  *usernumber = LOG_LOCAL2;
1294  }
1295  else if (strncmp(case_username, "LOCAL3", 6) == 0) {
1296  *usernumber = LOG_LOCAL3;
1297  }
1298  else if (strncmp(case_username, "LOCAL4", 6) == 0) {
1299  *usernumber = LOG_LOCAL4;
1300  }
1301  else if (strncmp(case_username, "LOCAL5", 6) == 0) {
1302  *usernumber = LOG_LOCAL5;
1303  }
1304  else if (strncmp(case_username, "LOCAL6", 6) == 0) {
1305  *usernumber = LOG_LOCAL6;
1306  }
1307  else if (strncmp(case_username, "LOCAL7", 6) == 0) {
1308  *usernumber = LOG_LOCAL7;
1309  }
1310 
1311  StrFree(case_username);
1312 
1313  return 0;
1314 
1315 }
1316 
unsigned char * password
Definition: daemon.h:106
unsigned char * schema
Definition: daemon.h:107
bool once
Definition: daemon.h:89
#define DEFAULT_LOG_FACILITY
Definition: daemon.h:79
pid_t pid
Definition: daemon.h:90
#define StrFree(x)
Definition: string_util.h:66
int make_directory(DAEMONCONFIG *config, const char *path)
Definition: daemon_util.c:578
char * pidfile
Definition: daemon.h:91
char * DSSubmitCmd
Definition: daemon.h:114
int DbFlavour(void)
char * optarg
int daemon_our_pidfile
Definition: daemon.c:98
int log_user
Definition: daemon.h:118
#define DEFAULT_LOG_FACILITY_STRING
Definition: daemon.h:80
const char * program
Definition: daemon.h:87
uint16_t interval
Definition: daemon.h:109
char * username
Definition: daemon.h:94
int getPermsForDrop(DAEMONCONFIG *config)
Definition: daemon_util.c:91
#define COPYRIGHT_STR
Definition: daemon.h:126
uid_t uid
Definition: daemon.h:92
void log_xml_error(void *ignore, const char *format,...)
Definition: daemon_util.c:354
int rolloverNotify
Definition: daemon.h:113
void cmdlParse(DAEMONCONFIG *config, int *argc, char **argv)
Definition: daemon_util.c:623
int get_log_user(const char *username, int *usernumber)
Definition: daemon_util.c:1219
void log_init(int facility, const char *program_name)
Definition: daemon_util.c:265
char * configfile
Definition: daemon.h:103
char * StrStrdup(const char *string)
Definition: string_util.c:124
#define AUTHOR_NAME
Definition: daemon.h:125
unsigned char * host
Definition: daemon.h:105
int pidfile_set
Definition: daemon.h:119
int manualKeyGeneration
Definition: daemon.h:112
#define SQLITE_DB
Definition: database.h:46
int ReadConfig(DAEMONCONFIG *config, int verbose)
Definition: daemon_util.c:713
int write_data(DAEMONCONFIG *config, FILE *file, const void *data, size_t size)
Definition: daemon_util.c:416
int release_lite_lock(FILE *lock_fd)
Definition: daemon_util.c:1199
void ksm_log_msg(const char *format)
Definition: daemon_util.c:313
bool debug
Definition: daemon.h:88
void StrAppend(char **str1, const char *str2)
Definition: string_util2.c:76
void log_xml_warn(void *ignore, const char *format,...)
Definition: daemon_util.c:372
int createPidDir(DAEMONCONFIG *config)
Definition: daemon_util.c:536
#define MYSQL_DB
Definition: database.h:45
int verbose
Definition: kaspcheck.c:49
char * policy
Definition: daemon.h:116
gid_t gid
Definition: daemon.h:93
int get_lite_lock(char *lock_filename, FILE *lock_fd)
Definition: daemon_util.c:1165
DAEMONCONFIG config
Definition: daemon.c:71
int writepid(DAEMONCONFIG *config)
Definition: daemon_util.c:467
char * groupname
Definition: daemon.h:95
void log_msg(DAEMONCONFIG *config, int priority, const char *format,...)
Definition: daemon_util.c:294
int DtXMLIntervalSeconds(const char *text, int *interval)
Definition: datetime.c:925
size_t StrToUpper(char *text)
Definition: string_util.c:353
unsigned char * port
Definition: daemon.h:108
unsigned char * user
Definition: daemon.h:104
void log_switch(int facility, const char *facility_name, const char *program_name, int verbose)
Definition: daemon_util.c:275
int DSSubCKA_ID
Definition: daemon.h:115