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