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