OpenDNSSEC-enforcer  1.4.9
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, " -d no-daemonize.\n");
397  fprintf(stderr, " -1 Run once, then exit.\n");
398  fprintf(stderr, " -p <policy> Run once processing only the specified policy, then exit.\n");
399 /* fprintf(stderr, " -u user Change effective uid to the specified user.\n");*/
400  fprintf(stderr, " -P <pidfile> Specify the PID file to write.\n");
401 
402  fprintf(stderr, " -V Print version.\n");
403  fprintf(stderr, " -[?|h] This help.\n");
404 }
405 
406  static void
407 version(void)
408 {
409  fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
410  fprintf(stderr, "Written by %s.\n\n", AUTHOR_NAME);
411  fprintf(stderr, "%s. This is free software.\n", COPYRIGHT_STR);
412  fprintf(stderr, "See source files for more license information\n");
413  exit(0);
414 }
415 
416  int
417 write_data(DAEMONCONFIG *config, FILE *file, const void *data, size_t size)
418 {
419  size_t result;
420 
421  if (size == 0)
422  return 1;
423 
424  result = fwrite(data, 1, size, file);
425 
426  if (result == 0) {
427  log_msg(config, LOG_ERR, "write failed: %s", strerror(errno));
428  return 0;
429  } else if (result < size) {
430  log_msg(config, LOG_ERR, "short write (disk full?)");
431  return 0;
432  } else {
433  return 1;
434  }
435 }
436 
437  static pid_t
438 readpid(const char *file)
439 {
440  int fd;
441  pid_t pid;
442  char pidbuf[32];
443  char *t;
444  int l;
445 
446  if ((fd = open(file, O_RDONLY)) == -1) {
447  return -1;
448  }
449  if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) {
450  close(fd);
451  return -1;
452  }
453  close(fd);
454  /* Empty pidfile means no pidfile... */
455  if (l == 0) {
456  errno = ENOENT;
457  return -1;
458  }
459  pid = strtol(pidbuf, &t, 10);
460 
461  if (*t && *t != '\n') {
462  return -1;
463  }
464  return pid;
465 }
466 
467  int
469 {
470  FILE * fd;
471  char pidbuf[32];
472  struct stat stat_ret;
473  pid_t oldpid;
474 
475  /* If the file exists then either we didn't shutdown cleanly or an enforcer is
476  * already running; in either case shutdown */
477  if (stat(config->pidfile, &stat_ret) != 0) {
478 
479  if (errno != ENOENT) {
480  log_msg(config, LOG_ERR, "cannot stat pidfile %s: %s",
481  config->pidfile, strerror(errno));
482  return -1;
483  }
484  } else {
485  if (S_ISREG(stat_ret.st_mode)) {
486  /* The file exists already */
487  if ((oldpid = readpid(config->pidfile)) == -1) {
488  /* consider stale pidfile */
489  if (errno != ENOENT) {
490  log_msg(config, LOG_ERR, "cannot read pidfile %s: %s",
491  config->pidfile, strerror(errno));
492  }
493  } else {
494  if (kill(oldpid, 0) == 0 || errno == EPERM) {
495  log_msg(config, LOG_ERR, "pidfile %s already exists, "
496  "a process with pid %u is already running. "
497  "If no ods-enforcerd process is running, a previous "
498  "instance didn't shutdown cleanly, please remove this "
499  "file and try again.", config->pidfile, oldpid);
500  exit(1);
501  } else {
502  log_msg(config, LOG_WARNING, "pidfile %s already exists, "
503  "but no process with pid %u is running. "
504  "A previous instance didn't shutdown cleanly, this "
505  "pidfile is stale.", config->pidfile, oldpid);
506  }
507  }
508  }
509  }
510 
511  /* All good, carry on */
512  snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) config->pid);
513 
514  if ((fd = fopen(config->pidfile, "w")) == NULL ) {
515  return -1;
516  }
517 
518  if (!write_data(config, fd, pidbuf, strlen(pidbuf))) {
519  fclose(fd);
520  return -1;
521  }
522  fclose(fd);
523 
524  if (chown(config->pidfile, config->uid, config->gid) == -1) {
525  log_msg(config, LOG_ERR, "cannot chown(%u,%u) %s: %s",
526  (unsigned) config->uid, (unsigned) config->gid,
527  config->pidfile, strerror(errno));
528  return -1;
529  }
530 
531  /* Mark this our pidfile so exit_function unlink's it */
532  daemon_our_pidfile = 1;
533  return 0;
534 }
535 
536  int
538 {
539  char* directory = NULL;
540  char* slash;
541  struct stat stat_ret;
542  char *path = getenv("PWD");
543 
544  /* Find the directory part of the (fully qualified) pidfile */
545  if (*config->pidfile != '/') {
546  StrAppend(&directory, path);
547  StrAppend(&directory, "/");
548  StrAppend(&directory, config->pidfile);
549  } else {
550  directory = StrStrdup(config->pidfile);
551  }
552  slash = strrchr(directory, '/');
553  *slash = 0;
554 
555  /* Check that it exists */
556  if (stat(directory, &stat_ret) != 0) {
557 
558  if (errno != ENOENT) {
559  log_msg(config, LOG_ERR, "cannot stat directory %s: %s",
560  directory, strerror(errno));
561  return -1;
562  }
563  }
564 
565  if (S_ISDIR(stat_ret.st_mode)) {
566  /* Do nothing, the directory exists already */
567  } else {
568  /* try to create it */
569  if (make_directory(config, directory) != 0) {
570  StrFree(directory);
571  return -1;
572  }
573  }
574  StrFree(directory);
575 
576  return 0;
577 }
578 
579 int make_directory(DAEMONCONFIG* config, const char* path) {
580 
581  char* parent;
582  char* slash;
583  struct stat stat_ret;
584 
585  parent = StrStrdup(path);
586  slash = strrchr(parent, '/');
587 
588  *slash = 0;
589 
590  if (stat(parent, &stat_ret) != 0) {
591  if (errno != ENOENT) {
592  log_msg(NULL, LOG_ERR, "cannot stat %s: %s\n",
593  parent, strerror(errno));
594  return 1;
595  }
596  }
597 
598  if (!S_ISDIR(stat_ret.st_mode)) {
599  make_directory(config, parent);
600  }
601 
602 
603  StrFree(parent);
604 
605  if (mkdir(path, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0) {
606  log_msg(NULL, LOG_ERR, "cannot create directory %s: %s\n",
607  path, strerror(errno));
608  return 1;
609  }
610 
611 
612  if (chown(path, config->uid, config->gid) == -1) {
613  log_msg(config, LOG_ERR, "cannot chown(%u,%u) %s: %s",
614  (unsigned) config->uid, (unsigned) config->gid,
615  path, strerror(errno));
616  return 1;
617  }
618 
619  return 0;
620 
621 }
622 
623  void
624 cmdlParse(DAEMONCONFIG* config, int *argc, char **argv)
625 {
626  int c;
627 
628  /*
629  * Read the command line
630  */
631  while ((c = getopt(*argc, argv, "1c:hdDV?u:P:p:")) != -1) {
632  switch (c) {
633  case '1':
634  config->once = true;
635  break;
636  case 'c':
637  config->configfile = optarg;
638  break;
639  case 'D':
640  config->debug = true;
641  break;
642  case 'd':
643  config->fork = false;
644  break;
645  case 'P':
646  config->pidfile = optarg;
647  config->pidfile_set = 1;
648  break;
649  case 'u':
650 #if 0 /* disable this feature */
651  config->username = optarg;
652  /* Parse the username into uid and gid */
653  config->gid = getgid();
654  config->uid = getuid();
655  if (*config->username) {
656  struct passwd *pwd;
657  if (isdigit(*config->username)) {
658  char *t;
659  config->uid = strtol(config->username, &t, 10);
660  if (*t != 0) {
661  if (*t != '.' || !isdigit(*++t)) {
662  log_msg(config, LOG_ERR, "-u user or -u uid or -u uid.gid. exiting...");
663  exit(1);
664  }
665  config->gid = strtol(t, &t, 10);
666  } else {
667  /* Lookup the group id in /etc/passwd */
668  if ((pwd = getpwuid(config->uid)) == NULL) {
669  log_msg(config, LOG_ERR, "user id %u does not exist. exiting...", (unsigned) config->uid);
670  exit(1);
671  } else {
672  config->gid = pwd->pw_gid;
673  }
674  endpwent();
675  }
676  } else {
677  /* Lookup the user id in /etc/passwd */
678  if ((pwd = getpwnam(config->username)) == NULL) {
679  log_msg(config, LOG_ERR, "user '%s' does not exist. exiting...", config->username);
680  exit(1);
681  } else {
682  config->uid = pwd->pw_uid;
683  config->gid = pwd->pw_gid;
684  }
685  endpwent();
686  }
687  }
688 #endif
689  break;
690  case 'p':
691  config->policy = optarg;
692  config->once = true;
693  fprintf(stdout, "Will only process policy \"%s\", will only run once. Check the logs for results. \n", config->policy);
694  break;
695  case 'h':
696  usage(config->program);
697  exit(0);
698  case '?':
699  usage(config->program);
700  exit(0);
701  case 'V':
702  version();
703  exit(0);
704  default:
705  usage(config->program);
706  exit(0);
707  }
708  }
709 }
710 
711 /*
712  * Returns 0 if the the config file could be read and non-zero if it could not.
713  *
714  * Any function calling this should exit on a non-zero return.
715  */
716 int
718 {
719  xmlDocPtr doc = NULL;
720  xmlDocPtr rngdoc = NULL;
721  xmlXPathContextPtr xpathCtx = NULL;
722  xmlXPathObjectPtr xpathObj = NULL;
723  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
724  xmlRelaxNGValidCtxtPtr rngctx = NULL;
725  xmlRelaxNGPtr schema = NULL;
726  xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval";
727  xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration";
728  xmlChar *rn_expr = (unsigned char*) "//Configuration/Enforcer/RolloverNotification";
729  xmlChar *ds_expr = (unsigned char*) "//Configuration/Enforcer/DelegationSignerSubmitCommand";
730  xmlChar *pid_expr = (unsigned char*) "//Configuration/Enforcer/PidFile";
731  xmlChar *litexpr = (unsigned char*) "//Configuration/Enforcer/Datastore/SQLite";
732  xmlChar *mysql_host = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host";
733  xmlChar *mysql_port = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host/@port";
734  xmlChar *mysql_db = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Database";
735  xmlChar *mysql_user = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Username";
736  xmlChar *mysql_pass = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Password";
737  xmlChar *log_user_expr = (unsigned char*) "//Configuration/Common/Logging/Syslog/Facility";
738 
739  int mysec = 0;
740  char *logFacilityName;
741  int my_log_user = DEFAULT_LOG_FACILITY;
742  int status;
743  int db_found = 0;
744  char* filename = NULL;
745  char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
746 
747  char* temp_char = NULL;
748  char* str = NULL; /* used to split DSSub command */
749 
750  FILE *file;
751 
752  /* Change the config file location if one was provided on the command line */
753  if (config->configfile != NULL) {
754  filename = StrStrdup(config->configfile);
755  } else {
756  filename = StrStrdup(OPENDNSSEC_CONFIG_FILE);
757  }
758 
759  if (verbose) {
760  log_msg(config, LOG_INFO, "Reading config \"%s\"", filename);
761  }
762 
763  /* Load XML document */
764  doc = xmlParseFile(filename);
765  if (doc == NULL) {
766  /* To get a better error message try to open the file */
767  file = fopen(filename, "r");
768  if (file == NULL) {
769  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", filename);
770  } else {
771  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", filename);
772  fclose(file);
773  }
774  return(-1);
775  }
776 
777  /* Load rng document */
778  if (verbose) {
779  log_msg(config, LOG_INFO, "Reading config schema \"%s\"", rngfilename);
780  }
781  rngdoc = xmlParseFile(rngfilename);
782  if (rngdoc == NULL) {
783  /* To get a better error message try to open the file */
784  file = fopen(rngfilename, "r");
785  if (file == NULL) {
786  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", rngfilename);
787  } else {
788  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", rngfilename);
789  fclose(file);
790  }
791  return(-1);
792  }
793 
794  /* Create an XML RelaxNGs parser context for the relax-ng document. */
795  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
796  if (rngpctx == NULL) {
797  log_msg(config, LOG_ERR, "Error: unable to create XML RelaxNGs parser context");
798  return(-1);
799  }
800 
801  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
802  schema = xmlRelaxNGParse(rngpctx);
803  if (schema == NULL) {
804  log_msg(config, LOG_ERR, "Error: unable to parse a schema definition resource");
805  return(-1);
806  }
807 
808  /* Create an XML RelaxNGs validation context based on the given schema */
809  rngctx = xmlRelaxNGNewValidCtxt(schema);
810  if (rngctx == NULL) {
811  log_msg(config, LOG_ERR, "Error: unable to create RelaxNGs validation context based on the schema");
812  return(-1);
813  }
814 
815  xmlRelaxNGSetValidErrors(rngctx,
816  (xmlRelaxNGValidityErrorFunc) log_xml_error,
817  (xmlRelaxNGValidityWarningFunc) log_xml_warn,
818  NULL);
819 
820  /* Validate a document tree in memory. */
821  status = xmlRelaxNGValidateDoc(rngctx,doc);
822  if (status != 0) {
823  log_msg(config, LOG_ERR, "Error validating file \"%s\"", filename);
824  return(-1);
825  }
826  xmlRelaxNGFreeValidCtxt(rngctx);
827  xmlRelaxNGFree(schema);
828  xmlRelaxNGFreeParserCtxt(rngpctx);
829  xmlFreeDoc(rngdoc);
830 
831  /* Now parse a value out of the conf */
832  /* Create xpath evaluation context */
833  xpathCtx = xmlXPathNewContext(doc);
834  if(xpathCtx == NULL) {
835  log_msg(config, LOG_ERR,"Error: unable to create new XPath context");
836  xmlFreeDoc(doc);
837  return(-1);
838  }
839 
840  /* Evaluate xpath expression for interval */
841  xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx);
842  if(xpathObj == NULL) {
843  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", iv_expr);
844  xmlXPathFreeContext(xpathCtx);
845  xmlFreeDoc(doc);
846  return(-1);
847  }
848 
849  temp_char = (char *)xmlXPathCastToString(xpathObj);
850  status = DtXMLIntervalSeconds(temp_char, &mysec);
851  if (status > 0) {
852  log_msg(config, LOG_ERR, "Error: unable to convert Interval %s to seconds, error: %i", temp_char, status);
853  StrFree(temp_char);
854  return status;
855  }
856  else if (status == -1) {
857  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
858  }
859  config->interval = mysec;
860  if (verbose) {
861  log_msg(config, LOG_INFO, "Communication Interval: %i", config->interval);
862  }
863  StrFree(temp_char);
864  xmlXPathFreeObject(xpathObj);
865 
866  /* Evaluate xpath expression for Manual key generation */
867  xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx);
868  if(xpathObj == NULL) {
869  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mk_expr);
870  xmlXPathFreeContext(xpathCtx);
871  xmlFreeDoc(doc);
872  return(-1);
873  }
874 
875  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
876  /* Manual key generation tag is present */
877  config->manualKeyGeneration = 1;
878  }
879  else {
880  /* Tag absent */
881  config->manualKeyGeneration = 0;
882  }
883  xmlXPathFreeObject(xpathObj);
884 
885  /* Evaluate xpath expression for rollover notification interval */
886  xpathObj = xmlXPathEvalExpression(rn_expr, xpathCtx);
887  if(xpathObj == NULL) {
888  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", rn_expr);
889  xmlXPathFreeContext(xpathCtx);
890  xmlFreeDoc(doc);
891  return(-1);
892  }
893 
894  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
895  /* Tag RolloverNotification is present; set rolloverNotify */
896  temp_char = (char *)xmlXPathCastToString(xpathObj);
897  status = DtXMLIntervalSeconds(temp_char, &mysec);
898  if (status > 0) {
899  log_msg(config, LOG_ERR, "Error: unable to convert RolloverNotification %s to seconds, error: %i", temp_char, status);
900  StrFree(temp_char);
901  xmlXPathFreeObject(xpathObj);
902  return status;
903  }
904  else if (status == -1) {
905  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
906  }
907  config->rolloverNotify = mysec;
908  if (verbose) {
909  log_msg(config, LOG_INFO, "Rollover Notification Interval: %i", config->rolloverNotify);
910  }
911  StrFree(temp_char);
912  }
913  else {
914  /* Tag RolloverNotification absent, set rolloverNotify to -1 */
915  config->rolloverNotify = -1;
916  }
917  xmlXPathFreeObject(xpathObj);
918 
919  /* Evaluate xpath expression for DelegationSignerSubmitCommand */
920  xpathObj = xmlXPathEvalExpression(ds_expr, xpathCtx);
921  if(xpathObj == NULL) {
922  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", ds_expr);
923  xmlXPathFreeContext(xpathCtx);
924  xmlFreeDoc(doc);
925  return(-1);
926  }
927  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
928  /* Tag DelegationSignerSubmitCommand is present; set DSSubmitCmd */
929  if (config->DSSubmitCmd != NULL) {
930  StrFree(config->DSSubmitCmd);
931  }
932  config->DSSubmitCmd = (char *)xmlXPathCastToString(xpathObj);
933 
934  /* If the string ends " --cka_id" strip that off and set flag */
935  str = strstr(config->DSSubmitCmd, " --cka_id");
936  if (str) {
937  config->DSSubCKA_ID = 1;
938  *str = 0;
939  } else {
940  config->DSSubCKA_ID = 0;
941  }
942 
943  if (verbose) {
944  log_msg(config, LOG_INFO, "Using command: %s to submit DS records", config->DSSubmitCmd);
945  }
946  } else {
947  if (verbose) {
948  log_msg(config, LOG_INFO, "No DS Submit command supplied");
949  }
950  config->DSSubmitCmd[0] = '\0';
951  }
952  xmlXPathFreeObject(xpathObj);
953 
954  /* Evaluate xpath expression for SQLite file location */
955 
956  xpathObj = xmlXPathEvalExpression(litexpr, xpathCtx);
957  if(xpathObj == NULL) {
958  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", litexpr);
959  xmlXPathFreeContext(xpathCtx);
960  xmlFreeDoc(doc);
961  return(-1);
962  }
963  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
964  db_found = SQLITE_DB;
965  if (config->schema != NULL) {
966  StrFree(config->schema);
967  }
968  config->schema = xmlXPathCastToString(xpathObj);
969  if (verbose) {
970  log_msg(config, LOG_INFO, "SQLite database set to: %s", config->schema);
971  }
972  }
973  xmlXPathFreeObject(xpathObj);
974 
975  if (db_found == 0) {
976  db_found = MYSQL_DB;
977 
978  /* Get all of the MySQL stuff read in too */
979  /* HOST */
980  xpathObj = xmlXPathEvalExpression(mysql_host, xpathCtx);
981  if(xpathObj == NULL) {
982  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_host);
983  xmlXPathFreeContext(xpathCtx);
984  xmlFreeDoc(doc);
985  return(-1);
986  }
987  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
988  if (config->host != NULL) {
989  StrFree(config->host);
990  }
991  config->host = xmlXPathCastToString(xpathObj);
992  if (verbose) {
993  log_msg(config, LOG_INFO, "MySQL database host set to: %s", config->host);
994  }
995  }
996  xmlXPathFreeObject(xpathObj);
997 
998  /* PORT */
999  xpathObj = xmlXPathEvalExpression(mysql_port, xpathCtx);
1000  if(xpathObj == NULL) {
1001  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_port);
1002  xmlXPathFreeContext(xpathCtx);
1003  xmlFreeDoc(doc);
1004  return(-1);
1005  }
1006  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1007  if (config->port != NULL) {
1008  StrFree(config->port);
1009  }
1010  config->port = xmlXPathCastToString(xpathObj);
1011  if (verbose) {
1012  log_msg(config, LOG_INFO, "MySQL database port set to: %s", config->port);
1013  }
1014  }
1015  xmlXPathFreeObject(xpathObj);
1016 
1017  /* SCHEMA */
1018  xpathObj = xmlXPathEvalExpression(mysql_db, xpathCtx);
1019  if(xpathObj == NULL) {
1020  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_db);
1021  xmlXPathFreeContext(xpathCtx);
1022  xmlFreeDoc(doc);
1023  return(-1);
1024  }
1025  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1026  if (config->schema != NULL) {
1027  StrFree(config->schema);
1028  }
1029  config->schema = xmlXPathCastToString(xpathObj);
1030  if (verbose) {
1031  log_msg(config, LOG_INFO, "MySQL database schema set to: %s", config->schema);
1032  }
1033  } else {
1034  db_found = 0;
1035  }
1036  xmlXPathFreeObject(xpathObj);
1037 
1038  /* DB USER */
1039  xpathObj = xmlXPathEvalExpression(mysql_user, xpathCtx);
1040  if(xpathObj == NULL) {
1041  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_user);
1042  xmlXPathFreeContext(xpathCtx);
1043  xmlFreeDoc(doc);
1044  return(-1);
1045  }
1046  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1047  if (config->user != NULL) {
1048  StrFree(config->user);
1049  }
1050  config->user = xmlXPathCastToString(xpathObj);
1051  if (verbose) {
1052  log_msg(config, LOG_INFO, "MySQL database user set to: %s", config->user);
1053  }
1054  } else {
1055  db_found = 0;
1056  }
1057  xmlXPathFreeObject(xpathObj);
1058 
1059  /* DB PASSWORD */
1060  xpathObj = xmlXPathEvalExpression(mysql_pass, xpathCtx);
1061  if(xpathObj == NULL) {
1062  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_pass);
1063  xmlXPathFreeContext(xpathCtx);
1064  xmlFreeDoc(doc);
1065  return(-1);
1066  }
1067  /* password may be blank */
1068 
1069  if (config->password != NULL) {
1070  StrFree(config->password);
1071  }
1072  config->password = xmlXPathCastToString(xpathObj);
1073  if (verbose) {
1074  log_msg(config, LOG_INFO, "MySQL database password set");
1075  }
1076  xmlXPathFreeObject(xpathObj);
1077 
1078  }
1079 
1080  /* Check that we found one or the other database */
1081  if(db_found == 0) {
1082  log_msg(config, LOG_ERR, "Error: unable to find complete database connection expression in %s", filename);
1083  xmlFreeDoc(doc);
1084  return(-1);
1085  }
1086 
1087  /* Check that we found the right database type */
1088  if (db_found != DbFlavour()) {
1089  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");
1090  xmlFreeDoc(doc);
1091  return(-1);
1092  }
1093 
1094  /* Evaluate xpath expression for log facility (user) */
1095  xpathObj = xmlXPathEvalExpression(log_user_expr, xpathCtx);
1096  if(xpathObj == NULL) {
1097  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", log_user_expr);
1098  xmlXPathFreeContext(xpathCtx);
1099  xmlFreeDoc(doc);
1100  return(-1);
1101  }
1102 
1103  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1104  /* tag present */
1105  logFacilityName = (char *)xmlXPathCastToString(xpathObj);
1106 
1107  status = get_log_user(logFacilityName, &my_log_user);
1108  if (status > 0) {
1109  log_msg(config, LOG_ERR, "Error: unable to set log user: %s, error: %i", logFacilityName, status);
1110  StrFree(logFacilityName);
1111  xmlXPathFreeObject(xpathObj);
1112  xmlXPathFreeContext(xpathCtx);
1113  xmlFreeDoc(doc);
1114  return status;
1115  }
1116  config->log_user = my_log_user;
1117  if (verbose) {
1118  log_msg(config, LOG_INFO, "Log User set to: %s", logFacilityName);
1119  }
1120 
1121  } else {
1122  /* tag _not_ present, use default */
1123  logFacilityName = StrStrdup( (char *)DEFAULT_LOG_FACILITY_STRING );
1124  config->log_user = DEFAULT_LOG_FACILITY;
1125  if (verbose) {
1126  log_msg(config, LOG_INFO, "Using default log user: %s", logFacilityName);
1127  }
1128  }
1129 
1130  /* Evaluate xpath expression for pidfile */
1131  xpathObj = xmlXPathEvalExpression(pid_expr, xpathCtx);
1132  if(xpathObj == NULL) {
1133  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", pid_expr);
1134  xmlXPathFreeContext(xpathCtx);
1135  xmlFreeDoc(doc);
1136  return(-1);
1137  }
1138 
1139  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1140  /* tag present */
1141  if (!config->pidfile_set) {
1142  config->pidfile = (char *)xmlXPathCastToString(xpathObj);
1143  if (verbose) {
1144  log_msg(config, LOG_INFO, "Pidfile set to: %s", config->pidfile);
1145  }
1146  }
1147  }
1148 
1149  xmlXPathFreeObject(xpathObj);
1150 
1151  log_switch(my_log_user, logFacilityName, config->program, verbose);
1152 
1153  /* Cleanup */
1154  /* TODO: some other frees are needed */
1155  xmlFreeDoc(doc);
1156  StrFree(logFacilityName);
1157  StrFree(filename);
1158 
1159  return(0);
1160 
1161 }
1162 
1163 /* To overcome the potential differences in sqlite compile flags assume that it is not
1164  happy with multiple connections.
1165 
1166  The following 2 functions take out a lock and release it
1167 */
1168 
1169 int get_lite_lock(char *lock_filename, FILE* lock_fd)
1170 {
1171  struct flock fl;
1172  struct timeval tv;
1173 
1174  if (lock_fd == NULL) {
1175  log_msg(NULL, LOG_ERR, "%s could not be opened", lock_filename);
1176  return 1;
1177  }
1178 
1179  memset(&fl, 0, sizeof(struct flock));
1180  fl.l_type = F_WRLCK;
1181  fl.l_whence = SEEK_SET;
1182  fl.l_pid = getpid();
1183 
1184  while (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1185  if (errno == EACCES || errno == EAGAIN) {
1186  log_msg(NULL, LOG_INFO, "%s already locked, sleep", lock_filename);
1187 
1188  /* sleep for 10 seconds TODO make this configurable? */
1189  tv.tv_sec = 10;
1190  tv.tv_usec = 0;
1191  select(0, NULL, NULL, NULL, &tv);
1192 
1193  } else {
1194  log_msg(NULL, LOG_INFO, "couldn't get lock on %s, %s", lock_filename, strerror(errno));
1195  return 1;
1196  }
1197  }
1198 
1199  return 0;
1200 
1201 }
1202 
1203 int release_lite_lock(FILE* lock_fd)
1204 {
1205  struct flock fl;
1206 
1207  if (lock_fd == NULL) {
1208  return 1;
1209  }
1210 
1211  memset(&fl, 0, sizeof(struct flock));
1212  fl.l_type = F_UNLCK;
1213  fl.l_whence = SEEK_SET;
1214 
1215  if (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1216  return 1;
1217  }
1218 
1219  return 0;
1220 }
1221 
1222 /* convert the name of a log facility (user) into a number */
1223 int get_log_user(const char* username, int* usernumber)
1224 {
1225  char* case_username = NULL;
1226 
1227  if (username == NULL) {
1228  return 1;
1229  }
1230  /* Start with our default */
1231  *usernumber = DEFAULT_LOG_FACILITY;
1232 
1233  case_username = StrStrdup(username);
1234  (void) StrToUpper(case_username);
1235 
1236  /* POSIX only specifies LOG_USER and LOG_LOCAL[0 .. 7] */
1237  if (strncmp(case_username, "USER", 4) == 0) {
1238  *usernumber = LOG_USER;
1239  }
1240 #ifdef LOG_KERN
1241  else if (strncmp(case_username, "KERN", 4) == 0) {
1242  *usernumber = LOG_KERN;
1243  }
1244 #endif /* LOG_KERN */
1245 #ifdef LOG_MAIL
1246  else if (strncmp(case_username, "MAIL", 4) == 0) {
1247  *usernumber = LOG_MAIL;
1248  }
1249 #endif /* LOG_MAIL */
1250 #ifdef LOG_DAEMON
1251  else if (strncmp(case_username, "DAEMON", 6) == 0) {
1252  *usernumber = LOG_DAEMON;
1253  }
1254 #endif /* LOG_DAEMON */
1255 #ifdef LOG_AUTH
1256  else if (strncmp(case_username, "AUTH", 4) == 0) {
1257  *usernumber = LOG_AUTH;
1258  }
1259 #endif /* LOG_AUTH */
1260 #ifdef LOG_SYSLOG
1261  else if (strncmp(case_username, "SYSLOG", 6) == 0) {
1262  *usernumber = LOG_SYSLOG;
1263  }
1264 #endif /* LOG_SYSLOG */
1265 #ifdef LOG_LPR
1266  else if (strncmp(case_username, "LPR", 3) == 0) {
1267  *usernumber = LOG_LPR;
1268  }
1269 #endif /* LOG_LPR */
1270 #ifdef LOG_NEWS
1271  else if (strncmp(case_username, "NEWS", 4) == 0) {
1272  *usernumber = LOG_NEWS;
1273  }
1274 #endif /* LOG_NEWS */
1275 #ifdef LOG_UUCP
1276  else if (strncmp(case_username, "UUCP", 4) == 0) {
1277  *usernumber = LOG_UUCP;
1278  }
1279 #endif /* LOG_UUCP */
1280 #ifdef LOG_AUDIT /* Ubuntu at least doesn't want us to use LOG_AUDIT */
1281  else if (strncmp(case_username, "AUDIT", 5) == 0) {
1282  *usernumber = LOG_AUDIT;
1283  }
1284 #endif /* LOG_AUDIT */
1285 #ifdef LOG_CRON
1286  else if (strncmp(case_username, "CRON", 4) == 0) {
1287  *usernumber = LOG_CRON;
1288  }
1289 #endif /* LOG_CRON */
1290  else if (strncmp(case_username, "LOCAL0", 6) == 0) {
1291  *usernumber = LOG_LOCAL0;
1292  }
1293  else if (strncmp(case_username, "LOCAL1", 6) == 0) {
1294  *usernumber = LOG_LOCAL1;
1295  }
1296  else if (strncmp(case_username, "LOCAL2", 6) == 0) {
1297  *usernumber = LOG_LOCAL2;
1298  }
1299  else if (strncmp(case_username, "LOCAL3", 6) == 0) {
1300  *usernumber = LOG_LOCAL3;
1301  }
1302  else if (strncmp(case_username, "LOCAL4", 6) == 0) {
1303  *usernumber = LOG_LOCAL4;
1304  }
1305  else if (strncmp(case_username, "LOCAL5", 6) == 0) {
1306  *usernumber = LOG_LOCAL5;
1307  }
1308  else if (strncmp(case_username, "LOCAL6", 6) == 0) {
1309  *usernumber = LOG_LOCAL6;
1310  }
1311  else if (strncmp(case_username, "LOCAL7", 6) == 0) {
1312  *usernumber = LOG_LOCAL7;
1313  }
1314 
1315  StrFree(case_username);
1316 
1317  return 0;
1318 
1319 }
1320 
unsigned char * password
Definition: daemon.h:107
unsigned char * schema
Definition: daemon.h:108
bool once
Definition: daemon.h:90
#define DEFAULT_LOG_FACILITY
Definition: daemon.h:79
pid_t pid
Definition: daemon.h:91
#define StrFree(x)
Definition: string_util.h:66
int make_directory(DAEMONCONFIG *config, const char *path)
Definition: daemon_util.c:579
char * pidfile
Definition: daemon.h:92
char * DSSubmitCmd
Definition: daemon.h:115
int DbFlavour(void)
char * optarg
int daemon_our_pidfile
Definition: daemon.c:98
int log_user
Definition: daemon.h:119
#define DEFAULT_LOG_FACILITY_STRING
Definition: daemon.h:80
const char * program
Definition: daemon.h:87
uint16_t interval
Definition: daemon.h:110
char * username
Definition: daemon.h:95
int getPermsForDrop(DAEMONCONFIG *config)
Definition: daemon_util.c:91
#define COPYRIGHT_STR
Definition: daemon.h:127
uid_t uid
Definition: daemon.h:93
bool fork
Definition: daemon.h:89
void log_xml_error(void *ignore, const char *format,...)
Definition: daemon_util.c:354
int rolloverNotify
Definition: daemon.h:114
void cmdlParse(DAEMONCONFIG *config, int *argc, char **argv)
Definition: daemon_util.c:624
int get_log_user(const char *username, int *usernumber)
Definition: daemon_util.c:1223
void log_init(int facility, const char *program_name)
Definition: daemon_util.c:265
char * configfile
Definition: daemon.h:104
char * StrStrdup(const char *string)
Definition: string_util.c:124
#define AUTHOR_NAME
Definition: daemon.h:126
unsigned char * host
Definition: daemon.h:106
int pidfile_set
Definition: daemon.h:120
int manualKeyGeneration
Definition: daemon.h:113
#define SQLITE_DB
Definition: database.h:46
int ReadConfig(DAEMONCONFIG *config, int verbose)
Definition: daemon_util.c:717
int write_data(DAEMONCONFIG *config, FILE *file, const void *data, size_t size)
Definition: daemon_util.c:417
int release_lite_lock(FILE *lock_fd)
Definition: daemon_util.c:1203
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:537
#define MYSQL_DB
Definition: database.h:45
int verbose
Definition: kaspcheck.c:49
char * policy
Definition: daemon.h:117
gid_t gid
Definition: daemon.h:94
int get_lite_lock(char *lock_filename, FILE *lock_fd)
Definition: daemon_util.c:1169
DAEMONCONFIG config
Definition: daemon.c:71
int writepid(DAEMONCONFIG *config)
Definition: daemon_util.c:468
char * groupname
Definition: daemon.h:96
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:109
unsigned char * user
Definition: daemon.h:105
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:116