OpenDNSSEC-enforcer  1.4.5
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  break;
644  case 'u':
645  break; /* disable this feature */
646  config->username = optarg;
647  /* Parse the username into uid and gid */
648  config->gid = getgid();
649  config->uid = getuid();
650  if (*config->username) {
651  struct passwd *pwd;
652  if (isdigit(*config->username)) {
653  char *t;
654  config->uid = strtol(config->username, &t, 10);
655  if (*t != 0) {
656  if (*t != '.' || !isdigit(*++t)) {
657  log_msg(config, LOG_ERR, "-u user or -u uid or -u uid.gid. exiting...");
658  exit(1);
659  }
660  config->gid = strtol(t, &t, 10);
661  } else {
662  /* Lookup the group id in /etc/passwd */
663  if ((pwd = getpwuid(config->uid)) == NULL) {
664  log_msg(config, LOG_ERR, "user id %u does not exist. exiting...", (unsigned) config->uid);
665  exit(1);
666  } else {
667  config->gid = pwd->pw_gid;
668  }
669  endpwent();
670  }
671  } else {
672  /* Lookup the user id in /etc/passwd */
673  if ((pwd = getpwnam(config->username)) == NULL) {
674  log_msg(config, LOG_ERR, "user '%s' does not exist. exiting...", config->username);
675  exit(1);
676  } else {
677  config->uid = pwd->pw_uid;
678  config->gid = pwd->pw_gid;
679  }
680  endpwent();
681  }
682  }
683  break;
684  case 'p':
685  config->policy = optarg;
686  config->once = true;
687  fprintf(stdout, "Will only process policy \"%s\", will only run once. Check the logs for results. \n", config->policy);
688  break;
689  case 'h':
690  usage(config->program);
691  exit(0);
692  case '?':
693  usage(config->program);
694  exit(0);
695  case 'V':
696  version();
697  exit(0);
698  default:
699  usage(config->program);
700  exit(0);
701  }
702  }
703 }
704 
705 /*
706  * Returns 0 if the the config file could be read and non-zero if it could not.
707  *
708  * Any function calling this should exit on a non-zero return.
709  */
710 int
712 {
713  xmlDocPtr doc = NULL;
714  xmlDocPtr rngdoc = NULL;
715  xmlXPathContextPtr xpathCtx = NULL;
716  xmlXPathObjectPtr xpathObj = NULL;
717  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
718  xmlRelaxNGValidCtxtPtr rngctx = NULL;
719  xmlRelaxNGPtr schema = NULL;
720  xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval";
721  xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration";
722  xmlChar *rn_expr = (unsigned char*) "//Configuration/Enforcer/RolloverNotification";
723  xmlChar *ds_expr = (unsigned char*) "//Configuration/Enforcer/DelegationSignerSubmitCommand";
724  xmlChar *litexpr = (unsigned char*) "//Configuration/Enforcer/Datastore/SQLite";
725  xmlChar *mysql_host = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host";
726  xmlChar *mysql_port = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Host/@port";
727  xmlChar *mysql_db = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Database";
728  xmlChar *mysql_user = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Username";
729  xmlChar *mysql_pass = (unsigned char*) "//Configuration/Enforcer/Datastore/MySQL/Password";
730  xmlChar *log_user_expr = (unsigned char*) "//Configuration/Common/Logging/Syslog/Facility";
731 
732  int mysec = 0;
733  char *logFacilityName;
734  int my_log_user = DEFAULT_LOG_FACILITY;
735  int status;
736  int db_found = 0;
737  char* filename = NULL;
738  char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng";
739 
740  char* temp_char = NULL;
741  char* str = NULL; /* used to split DSSub command */
742 
743  FILE *file;
744 
745  /* Change the config file location if one was provided on the command line */
746  if (config->configfile != NULL) {
747  filename = StrStrdup(config->configfile);
748  } else {
749  filename = StrStrdup(OPENDNSSEC_CONFIG_FILE);
750  }
751 
752  if (verbose) {
753  log_msg(config, LOG_INFO, "Reading config \"%s\"", filename);
754  }
755 
756  /* Load XML document */
757  doc = xmlParseFile(filename);
758  if (doc == NULL) {
759  /* To get a better error message try to open the file */
760  file = fopen(filename, "r");
761  if (file == NULL) {
762  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", filename);
763  } else {
764  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", filename);
765  fclose(file);
766  }
767  return(-1);
768  }
769 
770  /* Load rng document */
771  if (verbose) {
772  log_msg(config, LOG_INFO, "Reading config schema \"%s\"", rngfilename);
773  }
774  rngdoc = xmlParseFile(rngfilename);
775  if (rngdoc == NULL) {
776  /* To get a better error message try to open the file */
777  file = fopen(rngfilename, "r");
778  if (file == NULL) {
779  log_msg(config, LOG_ERR, "Error: unable to open file \"%s\"", rngfilename);
780  } else {
781  log_msg(config, LOG_ERR, "Error: unable to parse file \"%s\"", rngfilename);
782  fclose(file);
783  }
784  return(-1);
785  }
786 
787  /* Create an XML RelaxNGs parser context for the relax-ng document. */
788  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
789  if (rngpctx == NULL) {
790  log_msg(config, LOG_ERR, "Error: unable to create XML RelaxNGs parser context");
791  return(-1);
792  }
793 
794  /* parse a schema definition resource and build an internal XML Shema struture which can be used to validate instances. */
795  schema = xmlRelaxNGParse(rngpctx);
796  if (schema == NULL) {
797  log_msg(config, LOG_ERR, "Error: unable to parse a schema definition resource");
798  return(-1);
799  }
800 
801  /* Create an XML RelaxNGs validation context based on the given schema */
802  rngctx = xmlRelaxNGNewValidCtxt(schema);
803  if (rngctx == NULL) {
804  log_msg(config, LOG_ERR, "Error: unable to create RelaxNGs validation context based on the schema");
805  return(-1);
806  }
807 
808  xmlRelaxNGSetValidErrors(rngctx,
809  (xmlRelaxNGValidityErrorFunc) log_xml_error,
810  (xmlRelaxNGValidityWarningFunc) log_xml_warn,
811  NULL);
812 
813  /* Validate a document tree in memory. */
814  status = xmlRelaxNGValidateDoc(rngctx,doc);
815  if (status != 0) {
816  log_msg(config, LOG_ERR, "Error validating file \"%s\"", filename);
817  return(-1);
818  }
819  xmlRelaxNGFreeValidCtxt(rngctx);
820  xmlRelaxNGFree(schema);
821  xmlRelaxNGFreeParserCtxt(rngpctx);
822  xmlFreeDoc(rngdoc);
823 
824  /* Now parse a value out of the conf */
825  /* Create xpath evaluation context */
826  xpathCtx = xmlXPathNewContext(doc);
827  if(xpathCtx == NULL) {
828  log_msg(config, LOG_ERR,"Error: unable to create new XPath context");
829  xmlFreeDoc(doc);
830  return(-1);
831  }
832 
833  /* Evaluate xpath expression for interval */
834  xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx);
835  if(xpathObj == NULL) {
836  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", iv_expr);
837  xmlXPathFreeContext(xpathCtx);
838  xmlFreeDoc(doc);
839  return(-1);
840  }
841 
842  temp_char = (char *)xmlXPathCastToString(xpathObj);
843  status = DtXMLIntervalSeconds(temp_char, &mysec);
844  if (status > 0) {
845  log_msg(config, LOG_ERR, "Error: unable to convert Interval %s to seconds, error: %i", temp_char, status);
846  StrFree(temp_char);
847  return status;
848  }
849  else if (status == -1) {
850  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
851  }
852  config->interval = mysec;
853  if (verbose) {
854  log_msg(config, LOG_INFO, "Communication Interval: %i", config->interval);
855  }
856  StrFree(temp_char);
857  xmlXPathFreeObject(xpathObj);
858 
859  /* Evaluate xpath expression for Manual key generation */
860  xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx);
861  if(xpathObj == NULL) {
862  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mk_expr);
863  xmlXPathFreeContext(xpathCtx);
864  xmlFreeDoc(doc);
865  return(-1);
866  }
867 
868  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
869  /* Manual key generation tag is present */
870  config->manualKeyGeneration = 1;
871  }
872  else {
873  /* Tag absent */
874  config->manualKeyGeneration = 0;
875  }
876  xmlXPathFreeObject(xpathObj);
877 
878  /* Evaluate xpath expression for rollover notification interval */
879  xpathObj = xmlXPathEvalExpression(rn_expr, xpathCtx);
880  if(xpathObj == NULL) {
881  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", rn_expr);
882  xmlXPathFreeContext(xpathCtx);
883  xmlFreeDoc(doc);
884  return(-1);
885  }
886 
887  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
888  /* Tag RolloverNotification is present; set rolloverNotify */
889  temp_char = (char *)xmlXPathCastToString(xpathObj);
890  status = DtXMLIntervalSeconds(temp_char, &mysec);
891  if (status > 0) {
892  log_msg(config, LOG_ERR, "Error: unable to convert RolloverNotification %s to seconds, error: %i", temp_char, status);
893  StrFree(temp_char);
894  xmlXPathFreeObject(xpathObj);
895  return status;
896  }
897  else if (status == -1) {
898  log_msg(config, LOG_INFO, "Info: converting %s to seconds; M interpreted as 31 days, Y interpreted as 365 days", temp_char);
899  }
900  config->rolloverNotify = mysec;
901  if (verbose) {
902  log_msg(config, LOG_INFO, "Rollover Notification Interval: %i", config->rolloverNotify);
903  }
904  StrFree(temp_char);
905  }
906  else {
907  /* Tag RolloverNotification absent, set rolloverNotify to -1 */
908  config->rolloverNotify = -1;
909  }
910  xmlXPathFreeObject(xpathObj);
911 
912  /* Evaluate xpath expression for DelegationSignerSubmitCommand */
913  xpathObj = xmlXPathEvalExpression(ds_expr, xpathCtx);
914  if(xpathObj == NULL) {
915  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", ds_expr);
916  xmlXPathFreeContext(xpathCtx);
917  xmlFreeDoc(doc);
918  return(-1);
919  }
920  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
921  /* Tag DelegationSignerSubmitCommand is present; set DSSubmitCmd */
922  if (config->DSSubmitCmd != NULL) {
923  StrFree(config->DSSubmitCmd);
924  }
925  config->DSSubmitCmd = (char *)xmlXPathCastToString(xpathObj);
926 
927  /* If the string ends " --cka_id" strip that off and set flag */
928  str = strstr(config->DSSubmitCmd, " --cka_id");
929  if (str) {
930  config->DSSubCKA_ID = 1;
931  *str = 0;
932  } else {
933  config->DSSubCKA_ID = 0;
934  }
935 
936  if (verbose) {
937  log_msg(config, LOG_INFO, "Using command: %s to submit DS records", config->DSSubmitCmd);
938  }
939  } else {
940  if (verbose) {
941  log_msg(config, LOG_INFO, "No DS Submit command supplied");
942  }
943  config->DSSubmitCmd[0] = '\0';
944  }
945  xmlXPathFreeObject(xpathObj);
946 
947  /* Evaluate xpath expression for SQLite file location */
948 
949  xpathObj = xmlXPathEvalExpression(litexpr, xpathCtx);
950  if(xpathObj == NULL) {
951  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", litexpr);
952  xmlXPathFreeContext(xpathCtx);
953  xmlFreeDoc(doc);
954  return(-1);
955  }
956  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
957  db_found = SQLITE_DB;
958  if (config->schema != NULL) {
959  StrFree(config->schema);
960  }
961  config->schema = xmlXPathCastToString(xpathObj);
962  if (verbose) {
963  log_msg(config, LOG_INFO, "SQLite database set to: %s", config->schema);
964  }
965  }
966  xmlXPathFreeObject(xpathObj);
967 
968  if (db_found == 0) {
969  db_found = MYSQL_DB;
970 
971  /* Get all of the MySQL stuff read in too */
972  /* HOST */
973  xpathObj = xmlXPathEvalExpression(mysql_host, xpathCtx);
974  if(xpathObj == NULL) {
975  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_host);
976  xmlXPathFreeContext(xpathCtx);
977  xmlFreeDoc(doc);
978  return(-1);
979  }
980  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
981  if (config->host != NULL) {
982  StrFree(config->host);
983  }
984  config->host = xmlXPathCastToString(xpathObj);
985  if (verbose) {
986  log_msg(config, LOG_INFO, "MySQL database host set to: %s", config->host);
987  }
988  }
989  xmlXPathFreeObject(xpathObj);
990 
991  /* PORT */
992  xpathObj = xmlXPathEvalExpression(mysql_port, xpathCtx);
993  if(xpathObj == NULL) {
994  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_port);
995  xmlXPathFreeContext(xpathCtx);
996  xmlFreeDoc(doc);
997  return(-1);
998  }
999  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1000  if (config->port != NULL) {
1001  StrFree(config->port);
1002  }
1003  config->port = xmlXPathCastToString(xpathObj);
1004  if (verbose) {
1005  log_msg(config, LOG_INFO, "MySQL database port set to: %s", config->port);
1006  }
1007  }
1008  xmlXPathFreeObject(xpathObj);
1009 
1010  /* SCHEMA */
1011  xpathObj = xmlXPathEvalExpression(mysql_db, xpathCtx);
1012  if(xpathObj == NULL) {
1013  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_db);
1014  xmlXPathFreeContext(xpathCtx);
1015  xmlFreeDoc(doc);
1016  return(-1);
1017  }
1018  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1019  if (config->schema != NULL) {
1020  StrFree(config->schema);
1021  }
1022  config->schema = xmlXPathCastToString(xpathObj);
1023  if (verbose) {
1024  log_msg(config, LOG_INFO, "MySQL database schema set to: %s", config->schema);
1025  }
1026  } else {
1027  db_found = 0;
1028  }
1029  xmlXPathFreeObject(xpathObj);
1030 
1031  /* DB USER */
1032  xpathObj = xmlXPathEvalExpression(mysql_user, xpathCtx);
1033  if(xpathObj == NULL) {
1034  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_user);
1035  xmlXPathFreeContext(xpathCtx);
1036  xmlFreeDoc(doc);
1037  return(-1);
1038  }
1039  if(xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1040  if (config->user != NULL) {
1041  StrFree(config->user);
1042  }
1043  config->user = xmlXPathCastToString(xpathObj);
1044  if (verbose) {
1045  log_msg(config, LOG_INFO, "MySQL database user set to: %s", config->user);
1046  }
1047  } else {
1048  db_found = 0;
1049  }
1050  xmlXPathFreeObject(xpathObj);
1051 
1052  /* DB PASSWORD */
1053  xpathObj = xmlXPathEvalExpression(mysql_pass, xpathCtx);
1054  if(xpathObj == NULL) {
1055  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", mysql_pass);
1056  xmlXPathFreeContext(xpathCtx);
1057  xmlFreeDoc(doc);
1058  return(-1);
1059  }
1060  /* password may be blank */
1061 
1062  if (config->password != NULL) {
1063  StrFree(config->password);
1064  }
1065  config->password = xmlXPathCastToString(xpathObj);
1066  if (verbose) {
1067  log_msg(config, LOG_INFO, "MySQL database password set");
1068  }
1069  xmlXPathFreeObject(xpathObj);
1070 
1071  }
1072 
1073  /* Check that we found one or the other database */
1074  if(db_found == 0) {
1075  log_msg(config, LOG_ERR, "Error: unable to find complete database connection expression in %s", filename);
1076  xmlFreeDoc(doc);
1077  return(-1);
1078  }
1079 
1080  /* Check that we found the right database type */
1081  if (db_found != DbFlavour()) {
1082  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");
1083  xmlFreeDoc(doc);
1084  return(-1);
1085  }
1086 
1087  /* Evaluate xpath expression for log facility (user) */
1088  xpathObj = xmlXPathEvalExpression(log_user_expr, xpathCtx);
1089  if(xpathObj == NULL) {
1090  log_msg(config, LOG_ERR, "Error: unable to evaluate xpath expression: %s", log_user_expr);
1091  xmlXPathFreeContext(xpathCtx);
1092  xmlFreeDoc(doc);
1093  return(-1);
1094  }
1095 
1096  if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
1097  /* tag present */
1098  logFacilityName = (char *)xmlXPathCastToString(xpathObj);
1099 
1100  status = get_log_user(logFacilityName, &my_log_user);
1101  if (status > 0) {
1102  log_msg(config, LOG_ERR, "Error: unable to set log user: %s, error: %i", logFacilityName, status);
1103  StrFree(logFacilityName);
1104  xmlXPathFreeObject(xpathObj);
1105  xmlXPathFreeContext(xpathCtx);
1106  xmlFreeDoc(doc);
1107  return status;
1108  }
1109  config->log_user = my_log_user;
1110  if (verbose) {
1111  log_msg(config, LOG_INFO, "Log User set to: %s", logFacilityName);
1112  }
1113 
1114  } else {
1115  /* tag _not_ present, use default */
1116  logFacilityName = StrStrdup( (char *)DEFAULT_LOG_FACILITY_STRING );
1117  config->log_user = DEFAULT_LOG_FACILITY;
1118  if (verbose) {
1119  log_msg(config, LOG_INFO, "Using default log user: %s", logFacilityName);
1120  }
1121  }
1122  xmlXPathFreeObject(xpathObj);
1123 
1124  log_switch(my_log_user, logFacilityName, config->program, verbose);
1125 
1126  /* Cleanup */
1127  /* TODO: some other frees are needed */
1128  xmlFreeDoc(doc);
1129  StrFree(logFacilityName);
1130  StrFree(filename);
1131 
1132  return(0);
1133 
1134 }
1135 
1136 /* To overcome the potential differences in sqlite compile flags assume that it is not
1137  happy with multiple connections.
1138 
1139  The following 2 functions take out a lock and release it
1140 */
1141 
1142 int get_lite_lock(char *lock_filename, FILE* lock_fd)
1143 {
1144  struct flock fl;
1145  struct timeval tv;
1146 
1147  if (lock_fd == NULL) {
1148  log_msg(NULL, LOG_ERR, "%s could not be opened", lock_filename);
1149  return 1;
1150  }
1151 
1152  memset(&fl, 0, sizeof(struct flock));
1153  fl.l_type = F_WRLCK;
1154  fl.l_whence = SEEK_SET;
1155  fl.l_pid = getpid();
1156 
1157  while (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1158  if (errno == EACCES || errno == EAGAIN) {
1159  log_msg(NULL, LOG_INFO, "%s already locked, sleep", lock_filename);
1160 
1161  /* sleep for 10 seconds TODO make this configurable? */
1162  tv.tv_sec = 10;
1163  tv.tv_usec = 0;
1164  select(0, NULL, NULL, NULL, &tv);
1165 
1166  } else {
1167  log_msg(NULL, LOG_INFO, "couldn't get lock on %s, %s", lock_filename, strerror(errno));
1168  return 1;
1169  }
1170  }
1171 
1172  return 0;
1173 
1174 }
1175 
1176 int release_lite_lock(FILE* lock_fd)
1177 {
1178  struct flock fl;
1179 
1180  if (lock_fd == NULL) {
1181  return 1;
1182  }
1183 
1184  memset(&fl, 0, sizeof(struct flock));
1185  fl.l_type = F_UNLCK;
1186  fl.l_whence = SEEK_SET;
1187 
1188  if (fcntl(fileno(lock_fd), F_SETLK, &fl) == -1) {
1189  return 1;
1190  }
1191 
1192  return 0;
1193 }
1194 
1195 /* convert the name of a log facility (user) into a number */
1196 int get_log_user(const char* username, int* usernumber)
1197 {
1198  char* case_username = NULL;
1199 
1200  if (username == NULL) {
1201  return 1;
1202  }
1203  /* Start with our default */
1204  *usernumber = DEFAULT_LOG_FACILITY;
1205 
1206  case_username = StrStrdup(username);
1207  (void) StrToUpper(case_username);
1208 
1209  /* POSIX only specifies LOG_USER and LOG_LOCAL[0 .. 7] */
1210  if (strncmp(case_username, "USER", 4) == 0) {
1211  *usernumber = LOG_USER;
1212  }
1213 #ifdef LOG_KERN
1214  else if (strncmp(case_username, "KERN", 4) == 0) {
1215  *usernumber = LOG_KERN;
1216  }
1217 #endif /* LOG_KERN */
1218 #ifdef LOG_MAIL
1219  else if (strncmp(case_username, "MAIL", 4) == 0) {
1220  *usernumber = LOG_MAIL;
1221  }
1222 #endif /* LOG_MAIL */
1223 #ifdef LOG_DAEMON
1224  else if (strncmp(case_username, "DAEMON", 6) == 0) {
1225  *usernumber = LOG_DAEMON;
1226  }
1227 #endif /* LOG_DAEMON */
1228 #ifdef LOG_AUTH
1229  else if (strncmp(case_username, "AUTH", 4) == 0) {
1230  *usernumber = LOG_AUTH;
1231  }
1232 #endif /* LOG_AUTH */
1233 #ifdef LOG_SYSLOG
1234  else if (strncmp(case_username, "SYSLOG", 6) == 0) {
1235  *usernumber = LOG_SYSLOG;
1236  }
1237 #endif /* LOG_SYSLOG */
1238 #ifdef LOG_LPR
1239  else if (strncmp(case_username, "LPR", 3) == 0) {
1240  *usernumber = LOG_LPR;
1241  }
1242 #endif /* LOG_LPR */
1243 #ifdef LOG_NEWS
1244  else if (strncmp(case_username, "NEWS", 4) == 0) {
1245  *usernumber = LOG_NEWS;
1246  }
1247 #endif /* LOG_NEWS */
1248 #ifdef LOG_UUCP
1249  else if (strncmp(case_username, "UUCP", 4) == 0) {
1250  *usernumber = LOG_UUCP;
1251  }
1252 #endif /* LOG_UUCP */
1253 #ifdef LOG_AUDIT /* Ubuntu at least doesn't want us to use LOG_AUDIT */
1254  else if (strncmp(case_username, "AUDIT", 5) == 0) {
1255  *usernumber = LOG_AUDIT;
1256  }
1257 #endif /* LOG_AUDIT */
1258 #ifdef LOG_CRON
1259  else if (strncmp(case_username, "CRON", 4) == 0) {
1260  *usernumber = LOG_CRON;
1261  }
1262 #endif /* LOG_CRON */
1263  else if (strncmp(case_username, "LOCAL0", 6) == 0) {
1264  *usernumber = LOG_LOCAL0;
1265  }
1266  else if (strncmp(case_username, "LOCAL1", 6) == 0) {
1267  *usernumber = LOG_LOCAL1;
1268  }
1269  else if (strncmp(case_username, "LOCAL2", 6) == 0) {
1270  *usernumber = LOG_LOCAL2;
1271  }
1272  else if (strncmp(case_username, "LOCAL3", 6) == 0) {
1273  *usernumber = LOG_LOCAL3;
1274  }
1275  else if (strncmp(case_username, "LOCAL4", 6) == 0) {
1276  *usernumber = LOG_LOCAL4;
1277  }
1278  else if (strncmp(case_username, "LOCAL5", 6) == 0) {
1279  *usernumber = LOG_LOCAL5;
1280  }
1281  else if (strncmp(case_username, "LOCAL6", 6) == 0) {
1282  *usernumber = LOG_LOCAL6;
1283  }
1284  else if (strncmp(case_username, "LOCAL7", 6) == 0) {
1285  *usernumber = LOG_LOCAL7;
1286  }
1287 
1288  StrFree(case_username);
1289 
1290  return 0;
1291 
1292 }
1293 
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:125
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:1196
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:124
unsigned char * host
Definition: daemon.h:105
int manualKeyGeneration
Definition: daemon.h:112
#define SQLITE_DB
Definition: database.h:46
int ReadConfig(DAEMONCONFIG *config, int verbose)
Definition: daemon_util.c:711
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:1176
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:1142
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