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