[test suite] added tests/rijndael_hmac_fuzzing.pl file
[fwknop.git] / perl / legacy / fwknop / knopwatchd.c
1 /*
2 *****************************************************************************
3 *
4 *  File: knopwatchd.c
5 *
6 *  Purpose: knopwatchd checks on an interval of every five seconds to make
7 *           sure that both knopmd and fwknop are running on the box.  If
8 *           either daemon has died, knopwatchd will restart it and notify
9 *           each email address in EMAIL_ADDRESSES that the daemon has been
10 *           restarted.
11 *
12 *  Author: Michael Rash (mbr@cipherdyne.org)
13 *
14 *  Credits:  (see the CREDITS file)
15 *
16 *  Version: 1.9.12
17 *
18 *  Copyright (C) 2004-2009 Michael Rash (mbr@cipherdyne.org)
19 *
20 *  License (GNU Public License):
21 *
22 *     This program is distributed in the hope that it will be useful,
23 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
24 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 *     GNU General Public License for more details.
26 *
27 *     You should have received a copy of the GNU General Public License
28 *     along with this program; if not, write to the Free Software
29 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
30 *     USA
31 *
32 *****************************************************************************
33 *
34 *  $Id: knopwatchd.c 1533 2009-09-08 02:44:02Z mbr $
35 */
36
37 /* includes */
38 #include "fwknop.h"
39
40 /* Default configuration file to parse */
41 #define FWKNOP_CONF     "/etc/fwknop/fwknop.conf"
42
43 /* Maximum number of overwrite files allowed on the command line */
44 #define MAX_OVW_FILES   3
45
46 /* globals */
47 unsigned short int fwknopd_syscalls_ctr = 0;
48 unsigned short int knopmd_syscalls_ctr = 0;
49 unsigned short int no_email = 0;
50 unsigned short int check_knopmd;
51 char default_mail_sender[] = "root";
52 char hostname[MAX_GEN_LEN];
53 char mail_addrs[MAX_GEN_LEN];
54 char shCmd[MAX_GEN_LEN];
55 char mailCmd[MAX_GEN_LEN];
56 char sendmailCmd[MAX_GEN_LEN];
57 char fwknop_run_dir[MAX_PATH_LEN];
58 char alerting_methods[MAX_GEN_LEN];
59 char fwknopdCmd[MAX_PATH_LEN];
60 char fwknopd_pid_file[MAX_PATH_LEN];
61 char fwknopd_cmdline_file[MAX_PATH_LEN];
62 char knopmdCmd[MAX_PATH_LEN];
63 char knoptmCmd[MAX_PATH_LEN];
64 char knopmd_pid_file[MAX_PATH_LEN];
65 char knoptm_pid_file[MAX_PATH_LEN];
66 char knopwatchd_pid_file[MAX_PATH_LEN];
67 char char_knopwatchd_check_interval[MAX_NUM_LEN];
68 char char_knopwatchd_max_retries[MAX_NUM_LEN];
69 char enable_syslog_file[MAX_GEN_LEN];
70 char auth_mode[MAX_GEN_LEN];
71 unsigned int knopwatchd_check_interval = 0;
72 unsigned int knopwatchd_max_retries = 0;
73 unsigned char dump_cfg;
74
75 static volatile sig_atomic_t received_sighup = 0;
76
77 /* prototypes */
78 static void usage(void);
79 static void clean_settings(void);
80 static void parse_config(char *file);
81 static void check_config(void);
82 static void dump_config(void);
83 static void expand_config_vars(void);
84 static void find_sub_var_value(
85     char *value,
86     char *sub_var,
87     char *pre_str,
88     char *post_str
89 );
90
91 static void check_process(
92     const char *pid_name,
93     const char *pid_file,
94     const char *cmdline_file,
95     const char *binary_path,
96     unsigned int max_retries
97 );
98
99 static unsigned short int is_knopmd_required(void);
100 static void incr_syscall_ctr(const char *pid_name, unsigned int max_retries);
101 static void reset_syscall_ctr(const char *pid_name);
102 static void give_up(const char *pid_name);
103 static void exec_binary(const char *binary_path, const char *cmdline_file);
104 static void sighup_handler(int sig);
105
106 /* main */
107 int main(int argc, char *argv[]) {
108
109     int    cmdlopt;
110     char **ovw_file_ptr;
111     char  *overwrite_files[MAX_OVW_FILES+1];
112     char   overwrite_cmd[MAX_PATH_LEN];
113     char   config_file[MAX_PATH_LEN];
114
115 #ifdef DEBUG
116     fprintf(stderr, "[+] Entering DEBUG mode...\n");
117     sleep(1);
118 #endif
119
120     overwrite_files[0] = NULL;
121     strlcpy(config_file, FWKNOP_CONF, MAX_PATH_LEN);
122     dump_cfg = 0;
123
124     /* handle command line arguments */
125     while((cmdlopt = getopt(argc, argv, "c:O:Dh")) != -1) {
126         switch(cmdlopt) {
127             case 'c':
128                 strlcpy(config_file, optarg, MAX_PATH_LEN);
129                 break;
130             case 'O':
131                 strlcpy(overwrite_cmd, optarg, MAX_PATH_LEN);
132                 list_to_array(overwrite_cmd, ',', overwrite_files, MAX_OVW_FILES);
133                 break;
134             case 'D':
135                 dump_cfg = 1;
136                 break;
137             default:
138                 usage();
139         }
140     }
141
142     /* clean our settings */
143     clean_settings();
144
145     /* Parse both the overwrite and configuration file */
146     for (ovw_file_ptr=overwrite_files; *ovw_file_ptr!=NULL; ovw_file_ptr++)
147         parse_config(*ovw_file_ptr);
148     parse_config(config_file);
149
150     /* Check our settings */
151     check_config();
152
153     if (dump_cfg == 1)
154         dump_config();
155
156     /* see if we are supposed to disable all email alerts */
157     if (strncmp("noemail", alerting_methods, MAX_GEN_LEN) == 0)
158         no_email = 1;
159
160     /* first make sure there isn't another knopwatchd already running */
161     check_unique_pid(knopwatchd_pid_file, "knopwatchd");
162
163 #ifndef DEBUG
164     /* become a daemon */
165     daemonize_process(knopwatchd_pid_file);
166 #endif
167
168     /* install signal handler for HUP signals */
169     signal(SIGHUP, sighup_handler);
170
171     /* start doing the real work now that the daemon is running and
172      * the config file has been processed */
173
174     /* MAIN LOOP */
175     for (;;) {
176         /* restart processes as necessary */
177         check_process("fwknopd", fwknopd_pid_file, fwknopd_cmdline_file,
178             fwknopdCmd, knopwatchd_max_retries);
179
180         check_process("knoptm", knoptm_pid_file, NULL,
181             knoptmCmd, knopwatchd_max_retries);
182
183         if (check_knopmd)
184             check_process("knopmd", knopmd_pid_file, NULL,
185                 knopmdCmd, knopwatchd_max_retries);
186
187         /* sleep and then check to see if we received any signals */
188         sleep(knopwatchd_check_interval);
189
190         /* check for sighup */
191         if (received_sighup) {
192             received_sighup = 0;
193
194             /* clean our settings */
195             clean_settings();
196
197             /* reparse the config file since we received a HUP signal */
198             for (ovw_file_ptr=overwrite_files; *ovw_file_ptr!=NULL; ovw_file_ptr++)
199                 parse_config(*ovw_file_ptr);
200             parse_config(config_file);
201
202             check_config();
203
204             slogr("fwknopd(knopwatchd)",
205                     "received HUP signal, re-imported fwknop.conf");
206         }
207     }
208
209     /* this statement doesn't get executed, but for completeness... */
210     exit(EXIT_SUCCESS);
211 }
212 /******************** end main ********************/
213
214 static void check_process(
215     const char *pid_name,
216     const char *pid_file,
217     const char *cmdline_file,
218     const char *binary_path,
219     unsigned int max_retries)
220 {
221     FILE *pidfile_ptr;
222     pid_t pid;
223     unsigned short int restart = 0;
224     char syslog_str[MAX_MSG_LEN] = "";
225     char pid_line[MAX_PID_SIZE];
226     fwatch_email alert_email;
227
228     if ((pidfile_ptr = fopen(pid_file, "r")) == NULL) {
229 #ifdef DEBUG
230     fprintf(stderr, "[+] Could not open pid_file: %s\n", pid_file);
231 #endif
232         /* the pid file must not exist (or we can't read it), so
233          * setup to start the appropriate process */
234         restart = 1;
235     }
236
237     /* read the first line of the pid_file, which will contain the
238      * process id of any running pid_name process. */
239     if (! restart) {
240         if (fgets(pid_line, MAX_PID_SIZE, pidfile_ptr) == NULL) {
241 #ifdef DEBUG
242             fprintf(stderr, "[+] Could not read the pid_file: %s\n", pid_file);
243 #endif
244             /* see if we need to give up */
245             incr_syscall_ctr(pid_name, max_retries);
246             fclose(pidfile_ptr);
247             return;
248         }
249
250         /* convert the pid_line into an integer */
251         pid = atoi(pid_line);
252
253         /* close the pid_file now that we have read it */
254         fclose(pidfile_ptr);
255
256         if (kill(pid, 0) != 0) {
257             /* the process is not running so start it */
258             restart = 1;
259         }
260     }
261
262     if (restart) {
263
264         snprintf(syslog_str, MAX_MSG_LEN,
265             "restarting %s on %s", pid_name, hostname);
266         slogr("fwknopd(knopwatchd)", syslog_str);
267
268         /* send the email */
269         if (! no_email) {
270
271             alert_email.cmd = (*sendmailCmd != '\0') ? sendmailCmd : mailCmd;
272             alert_email.sender = default_mail_sender;
273             alert_email.recipient = mail_addrs;
274             snprintf(alert_email.subject, sizeof(alert_email.subject),
275                         "[*] knopwatchd: Restarting %s on %s",
276                         pid_name, hostname);
277             alert_email.subject[sizeof(alert_email.subject)-1] = '\0';
278
279             send_alert_email(shCmd, alert_email);
280         }
281
282         /* execute the binary_path fwknopd daemon */
283         exec_binary(binary_path, cmdline_file);
284
285         /* increment the number of times we have tried to restart the binary */
286         incr_syscall_ctr(pid_name, max_retries);
287     } else {
288 #ifdef DEBUG
289         fprintf(stderr, "[+] %s is running.\n", pid_name);
290 #endif
291         /* reset the syscall counter since the process is successfully
292          * running. */
293         reset_syscall_ctr(pid_name);
294     }
295     return;
296 }
297
298 static void incr_syscall_ctr(const char *pid_name, unsigned int max_retries)
299 {
300     if (strcmp("fwknopd", pid_name) == 0) {
301         fwknopd_syscalls_ctr++;
302 #ifdef DEBUG
303         fprintf(stderr,
304             "[+] %s not running.  Trying to restart (%d tries so far).\n",
305             pid_name, fwknopd_syscalls_ctr);
306 #endif
307         if (fwknopd_syscalls_ctr >= max_retries)
308             give_up(pid_name);
309     } else if (strcmp("knopmd", pid_name) == 0) {
310         knopmd_syscalls_ctr++;
311 #ifdef DEBUG
312         fprintf(stderr,
313             "[+] %s not running.  Trying to restart (%d tries so far).\n",
314             pid_name, knopmd_syscalls_ctr);
315 #endif
316         if (knopmd_syscalls_ctr >= max_retries)
317             give_up(pid_name);
318     }
319     return;
320 }
321
322 static void reset_syscall_ctr(const char *pid_name)
323 {
324     if (strcmp("fwknopd", pid_name) == 0) {
325         fwknopd_syscalls_ctr = 0;
326     } else if (strcmp("knopmd", pid_name) == 0) {
327         knopmd_syscalls_ctr = 0;
328     }
329     return;
330 }
331
332 static void give_up(const char *pid_name)
333 {
334     fwatch_email alert_email;
335
336 #ifdef DEBUG
337     fprintf(stderr, "[*] Could not restart %s process.  Exiting.\n", pid_name);
338 #endif
339
340     if (! no_email) {
341
342         alert_email.cmd = (*sendmailCmd != '\0') ? sendmailCmd : mailCmd;
343         alert_email.sender = default_mail_sender;
344         alert_email.recipient = mail_addrs;
345         snprintf(alert_email.subject, sizeof(alert_email.subject),
346                     "[*] knopwatchd: Could not restart %s on %s. Exiting.",
347                     pid_name, hostname);
348         alert_email.subject[sizeof(alert_email.subject)-1] = '\0';
349
350         send_alert_email(shCmd, alert_email);
351     }
352
353     exit(EXIT_FAILURE);
354 }
355
356 static void exec_binary(const char *binary, const char *cmdlinefile)
357 {
358     FILE *cmdline_ptr;
359     char *prog_argv[MAX_ARG_LEN];
360     char cmdline_buf[MAX_LINE_BUF];
361     char *index;
362     pid_t child_pid;
363     int arg_num=0, non_ws, i;
364
365 #ifdef DEBUG
366     fprintf(stderr, "[+] executing exec_binary(%s)\n", binary);
367 #endif
368
369     prog_argv[arg_num] = (char *) safe_malloc(strlen(binary)+1);
370     if (prog_argv[arg_num] == NULL) {
371         exit(EXIT_FAILURE);
372     }
373     strlcpy(prog_argv[arg_num], binary, strlen(binary)+1);
374     arg_num++;
375
376     if (cmdlinefile != NULL) {
377         /* restart binary with its command line arguments intact */
378         if ((cmdline_ptr = fopen(cmdlinefile, "r")) == NULL) {
379             exit(EXIT_FAILURE);
380         }
381         if ((fgets(cmdline_buf, MAX_LINE_BUF, cmdline_ptr)) == NULL) {
382             exit(EXIT_FAILURE);
383         }
384         fclose(cmdline_ptr);
385
386         /* initialize index to the beginning of the line */
387         index = cmdline_buf;
388
389         /* advance the index pointer through any whitespace
390          * at the beginning of the line */
391         while (isspace(*index)) index++;
392
393         while (*index != '\n' && *index != '\0') {
394             non_ws = 0;
395             while (!isspace(*index) && index != '\0' && *index != '\n') {
396                 index++;
397                 non_ws++;
398             }
399             prog_argv[arg_num] = (char *) safe_malloc(non_ws+1);
400             if (prog_argv[arg_num] == NULL) {
401                 exit(EXIT_FAILURE);
402             }
403             for (i=0; i<non_ws; i++)
404                 prog_argv[arg_num][i] = *(index - (non_ws - i));
405             prog_argv[arg_num][i] = '\0';
406
407             arg_num++;
408
409             /* get past any whitespace */
410             while (isspace(*index)) index++;
411         }
412     }
413
414     if (arg_num >= MAX_ARG_LEN)
415         exit(EXIT_FAILURE);
416     prog_argv[arg_num] = NULL;
417
418     if ((child_pid = fork()) < 0)
419         /* could not fork */
420         exit(EXIT_FAILURE);
421     else if (child_pid > 0) {
422         wait(NULL);
423         for (i=0; i<=arg_num; i++) {
424             free(prog_argv[i]);
425         }
426     } else {
427 #ifdef DEBUG
428         fprintf(stderr, "[+] restarting %s\n", binary);
429 #endif
430         exit(execve(binary, prog_argv, NULL));  /* don't use environment */
431     }
432     return;
433 }
434
435 static void parse_config(char * file)
436 {
437     FILE *config_ptr;         /* FILE pointer to the config file */
438     int linectr = 0;
439     char config_buf[MAX_LINE_BUF];
440     char *index;
441     int tmp;
442
443 #ifdef DEBUG
444     fprintf(stderr, "[+] Parsing file %s\n", file);
445 #endif
446
447     if ((config_ptr = fopen(file, "r")) == NULL) {
448         perror("[*] Could not open file");
449         exit(EXIT_FAILURE);
450     }
451
452     /* increment through each line of the config file */
453     while ((fgets(config_buf, MAX_LINE_BUF, config_ptr)) != NULL) {
454         linectr++;
455         index = config_buf;  /* set the index pointer to the
456                                 beginning of the line */
457         /* advance the index pointer through any whitespace
458          * at the beginning of the line */
459         while (isspace(*index)) index++;
460
461         /* skip comments and blank lines, etc. */
462         if ((*index != '#') && (*index != '\n') &&
463                 (*index != ';') && (index != NULL)) {
464
465             find_char_var("fwknopdCmd", fwknopdCmd, index);
466             find_char_var("HOSTNAME", hostname, index);
467             find_char_var("FWKNOP_RUN_DIR", fwknop_run_dir, index);
468             find_char_var("FWKNOP_PID_FILE", fwknopd_pid_file, index);
469             find_char_var("FWKNOP_CMDLINE_FILE", fwknopd_cmdline_file, index);
470             find_char_var("knopmdCmd", knopmdCmd, index);
471             find_char_var("knoptmCmd", knoptmCmd, index);
472             find_char_var("KNOPMD_PID_FILE", knopmd_pid_file, index);
473             find_char_var("KNOPTM_PID_FILE", knoptm_pid_file, index);
474             find_char_var("shCmd", shCmd, index);
475             find_char_var("mailCmd", mailCmd, index);
476             find_char_var("EMAIL_ADDRESSES", mail_addrs, index);
477             find_char_var("KNOPWATCHD_CHECK_INTERVAL",
478                 char_knopwatchd_check_interval, index);
479             find_char_var("KNOPWATCHD_MAX_RETRIES",
480                 char_knopwatchd_max_retries, index);
481             find_char_var("AUTH_MODE", auth_mode, index);
482             find_char_var("ENABLE_SYSLOG_FILE", enable_syslog_file, index);
483             find_char_var("KNOPWATCHD_PID_FILE", knopwatchd_pid_file, index);
484             find_char_var("ALERTING_METHODS", alerting_methods, index);
485             find_char_var("sendmailCmd", sendmailCmd, index);
486         }
487     }
488     fclose(config_ptr);
489
490     tmp = atoi(char_knopwatchd_check_interval);
491     if (tmp != 0)
492         knopwatchd_check_interval = tmp;
493
494     tmp = atoi(char_knopwatchd_max_retries);
495     if (tmp != 0)
496         knopwatchd_max_retries = tmp;
497
498     return;
499 }
500
501 static void check_config(void)
502 {
503     unsigned char err;
504
505 #ifdef DEBUG
506     fprintf(stderr, "[+] Checking configuration...\n");
507 #endif
508
509     err = 1;
510     if (fwknopdCmd[0] == '\0')
511         fprintf(stderr, "[*] Could not find fwknopdCmd\n");
512
513     else if (hostname[0] == '\0')
514         fprintf(stderr, "[*] Could not find HOSTNAME\n");
515
516     else if (fwknopd_pid_file[0] == '\0')
517         fprintf(stderr, "[*] Could not find FWKNOP_PID_FILE\n");
518
519     else if (fwknopd_cmdline_file[0] == '\0')
520         fprintf(stderr, "[*] Could not find FWKNOP_CMDLINE_FILE\n");
521
522     else if (knopmdCmd[0] == '\0')
523         fprintf(stderr, "[*] Could not find knopmdCmd\n");
524
525     else if (knoptmCmd[0] == '\0')
526         fprintf(stderr, "[*] Could not find knoptmCmd\n");
527
528     else if (knopmd_pid_file[0] == '\0')
529         fprintf(stderr, "[*] Could not find KNOPMD_PID_FILE\n");
530
531     else if (knoptm_pid_file[0] == '\0')
532         fprintf(stderr, "[*] Could not find KNOPTM_PID_FILE\n");
533
534     else if (shCmd[0] == '\0')
535         fprintf(stderr, "[*] Could not find shCmd\n");
536
537     else if ((mailCmd[0] == '\0') && (sendmailCmd[0] == '\0'))
538         fprintf(stderr, "[*] One of the sendmailCmd or mailCmd variables must \
539                                 be specified\n");
540
541     else if (mail_addrs[0] == '\0')
542         fprintf(stderr, "[*] Could not find EMAIL_ADDRESSES\n");
543
544     else if (knopwatchd_pid_file[0] == '\0')
545         fprintf(stderr, "[*] Could not find KNOPWATCHD_PID_FILE\n");
546
547     else if (auth_mode[0] == '\0')
548         fprintf(stderr, "[*] Could not find AUTH_MODE\n");
549
550     else if (enable_syslog_file[0] == '\0')
551         fprintf(stderr, "[*] Could not find ENABLE_SYSLOG_FILE\n");
552
553     else if (knopwatchd_check_interval <= 0)
554         fprintf(stderr, "[*] KNOPWATCHD_CHECK_INTERVAL must be > 0\n");
555
556     else if (knopwatchd_max_retries <= 0)
557         fprintf(stderr, "[*] KNOPWATCHD_MAX_RETRIES must be > 0\n");
558
559     else {
560
561         /* Resolve any embedded variables */
562         expand_config_vars();
563
564         /* Refresh the need to check knopmd */
565         check_knopmd = is_knopmd_required();
566
567         err = 0;
568     }
569
570     if (err == 1)
571         exit(EXIT_FAILURE);
572 }
573
574 /*
575  * Check to see if knopmd should not be running:
576  *
577  *   - first check if we are using the KNOCK mode
578  *   - then, in PK mode, see if ENABLE_SYSLOG_FILE is enabled, so
579  *     fwknopd is just parsing a file written to by syslog directly
580  *
581  * \return 0 if not required
582  *         1 otherwise
583  */
584 static unsigned short int is_knopmd_required(void)
585 {
586     unsigned short int required;
587
588     required = 0;
589
590     if (strncmp(auth_mode, "KNOCK", MAX_GEN_LEN) == 0)
591         required = 1;
592
593     if ( (check_knopmd) && (strncmp(enable_syslog_file, "Y", 1) == 0) )
594         required = 0;
595
596     return required;
597 }
598
599 static void expand_config_vars(void)
600 {
601     char sub_var[MAX_GEN_LEN]  = "";
602     char pre_str[MAX_GEN_LEN]  = "";
603     char post_str[MAX_GEN_LEN] = "";
604     int found_sub_var = 1, resolve_ctr = 0;
605
606     while (found_sub_var) {
607         resolve_ctr++;
608         if (resolve_ctr >= 20) {
609             fprintf(stderr, "[*] Exceeded maximum variable resolution attempts.\n");
610             exit(EXIT_FAILURE);
611         }
612         found_sub_var = 0;
613         if (has_sub_var("EMAIL_ADDRESSES", mail_addrs, sub_var,
614                 pre_str, post_str)) {
615             find_sub_var_value(mail_addrs, sub_var, pre_str, post_str);
616             found_sub_var = 1;
617         }
618
619         if (has_sub_var("HOSTNAME", hostname, sub_var,
620                 pre_str, post_str)) {
621             find_sub_var_value(hostname, sub_var, pre_str, post_str);
622             found_sub_var = 1;
623         }
624
625         if (has_sub_var("FWKNOP_RUN_DIR", fwknop_run_dir, sub_var,
626                 pre_str, post_str)) {
627             find_sub_var_value(fwknop_run_dir, sub_var, pre_str, post_str);
628             found_sub_var = 1;
629         }
630
631         if (has_sub_var("FWKNOP_PID_FILE", fwknopd_pid_file, sub_var,
632                 pre_str, post_str)) {
633             find_sub_var_value(fwknopd_pid_file, sub_var, pre_str, post_str);
634             found_sub_var = 1;
635         }
636
637         if (has_sub_var("FWKNOP_CMDLINE_FILE", fwknopd_cmdline_file, sub_var,
638                 pre_str, post_str)) {
639             find_sub_var_value(fwknopd_cmdline_file, sub_var, pre_str, post_str);
640             found_sub_var = 1;
641         }
642
643         if (has_sub_var("KNOPMD_PID_FILE", knopmd_pid_file, sub_var,
644                 pre_str, post_str)) {
645             find_sub_var_value(knopmd_pid_file, sub_var, pre_str, post_str);
646             found_sub_var = 1;
647         }
648
649         if (has_sub_var("KNOPTM_PID_FILE", knoptm_pid_file, sub_var,
650                 pre_str, post_str)) {
651             find_sub_var_value(knoptm_pid_file, sub_var, pre_str, post_str);
652             found_sub_var = 1;
653         }
654
655         if (has_sub_var("KNOPWATCHD_PID_FILE", knopwatchd_pid_file, sub_var,
656                 pre_str, post_str)) {
657             find_sub_var_value(knopwatchd_pid_file, sub_var, pre_str, post_str);
658             found_sub_var = 1;
659         }
660
661         if (has_sub_var("KNOPWATCHD_CHECK_INTERVAL",
662                 char_knopwatchd_check_interval, sub_var,
663                 pre_str, post_str)) {
664             find_sub_var_value(char_knopwatchd_check_interval,
665                 sub_var, pre_str, post_str);
666             found_sub_var = 1;
667         }
668
669         if (has_sub_var("KNOPWATCHD_MAX_RETRIES", char_knopwatchd_max_retries,
670                 sub_var, pre_str, post_str)) {
671             find_sub_var_value(char_knopwatchd_max_retries,
672                 sub_var, pre_str, post_str);
673             found_sub_var = 1;
674         }
675
676         if (has_sub_var("mailCmd", mailCmd, sub_var,
677                 pre_str, post_str)) {
678             find_sub_var_value(mailCmd, sub_var, pre_str, post_str);
679             found_sub_var = 1;
680         }
681
682         if (has_sub_var("sendmailCmd", sendmailCmd, sub_var,
683                 pre_str, post_str)) {
684             find_sub_var_value(sendmailCmd, sub_var, pre_str, post_str);
685             found_sub_var = 1;
686         }
687
688         if (has_sub_var("shCmd", shCmd, sub_var,
689                 pre_str, post_str)) {
690             find_sub_var_value(shCmd, sub_var, pre_str, post_str);
691             found_sub_var = 1;
692         }
693
694         if (has_sub_var("knopmdCmd", knopmdCmd, sub_var,
695                 pre_str, post_str)) {
696             find_sub_var_value(knopmdCmd, sub_var, pre_str, post_str);
697             found_sub_var = 1;
698         }
699
700         if (has_sub_var("fwknopdCmd", fwknopdCmd, sub_var,
701                 pre_str, post_str)) {
702             find_sub_var_value(fwknopdCmd, sub_var, pre_str, post_str);
703             found_sub_var = 1;
704         }
705     }
706
707     return;
708 }
709
710 static void find_sub_var_value(char *value, char *sub_var, char *pre_str,
711     char *post_str)
712 {
713     int found_var = 0;
714     if (strncmp(sub_var, "EMAIL_ADDRESSES", MAX_GEN_LEN) == 0) {
715         strlcpy(sub_var, mail_addrs, MAX_GEN_LEN);
716         found_var = 1;
717     } else if (strncmp(sub_var, "HOSTNAME", MAX_GEN_LEN) == 0) {
718         strlcpy(sub_var, hostname, MAX_GEN_LEN);
719         found_var = 1;
720     } else if (strncmp(sub_var, "FWKNOP_RUN_DIR", MAX_GEN_LEN) == 0) {
721         strlcpy(sub_var, fwknop_run_dir, MAX_GEN_LEN);
722         found_var = 1;
723     } else if (strncmp(sub_var, "FWKNOP_PID_FILE", MAX_GEN_LEN) == 0) {
724         strlcpy(sub_var, fwknopd_pid_file, MAX_GEN_LEN);
725         found_var = 1;
726     } else if (strncmp(sub_var, "FWKNOP_CMDLINE_FILE", MAX_GEN_LEN) == 0) {
727         strlcpy(sub_var, fwknopd_cmdline_file, MAX_GEN_LEN);
728         found_var = 1;
729     } else if (strncmp(sub_var, "KNOPMD_PID_FILE", MAX_GEN_LEN) == 0) {
730         strlcpy(sub_var, knopmd_pid_file, MAX_GEN_LEN);
731         found_var = 1;
732     } else if (strncmp(sub_var, "KNOPTM_PID_FILE", MAX_GEN_LEN) == 0) {
733         strlcpy(sub_var, knoptm_pid_file, MAX_GEN_LEN);
734         found_var = 1;
735     } else if (strncmp(sub_var, "KNOPWATCHD_PID_FILE", MAX_GEN_LEN) == 0) {
736         strlcpy(sub_var, knopwatchd_pid_file, MAX_GEN_LEN);
737         found_var = 1;
738     } else if (strncmp(sub_var, "KNOPWATCDHD_CHECK_INTERVAL", MAX_GEN_LEN) == 0) {
739         strlcpy(sub_var, char_knopwatchd_check_interval, MAX_GEN_LEN);
740         found_var = 1;
741     } else if (strncmp(sub_var, "KNOPWATCDHD_MAX_RETRIES", MAX_GEN_LEN) == 0) {
742         strlcpy(sub_var, char_knopwatchd_max_retries, MAX_GEN_LEN);
743         found_var = 1;
744     } else if (strncmp(sub_var, "mailCmd", MAX_GEN_LEN) == 0) {
745         strlcpy(sub_var, mailCmd, MAX_GEN_LEN);
746         found_var = 1;
747     } else if (strncmp(sub_var, "sendmailCmd", MAX_GEN_LEN) == 0) {
748         strlcpy(sub_var, sendmailCmd, MAX_GEN_LEN);
749         found_var = 1;
750     } else if (strncmp(sub_var, "shCmd", MAX_GEN_LEN) == 0) {
751         strlcpy(sub_var, shCmd, MAX_GEN_LEN);
752         found_var = 1;
753     } else if (strncmp(sub_var, "knopmdCmd", MAX_GEN_LEN) == 0) {
754         strlcpy(sub_var, knopmdCmd, MAX_GEN_LEN);
755         found_var = 1;
756     } else if (strncmp(sub_var, "fwknopdCmd", MAX_GEN_LEN) == 0) {
757         strlcpy(sub_var, fwknopdCmd, MAX_GEN_LEN);
758         found_var = 1;
759     }
760
761     if (found_var)
762
763         /* substitute the variable value */
764         expand_sub_var_value(value, sub_var, pre_str, post_str);
765
766     else {
767         fprintf(stderr, "[*] Could not resolve sub-var: %s to a value.\n",
768             sub_var);
769         exit(EXIT_FAILURE);
770     }
771     return;
772 }
773
774 static void sighup_handler(int sig)
775 {
776     received_sighup = 1;
777 }
778
779 static void clean_settings (void)
780 {
781 #ifdef DEBUG
782     fprintf(stderr, "[+] Cleaning settings\n");
783 #endif
784
785     /* Set the default values used by knopwatchd when trying to 
786      * restart the fwknopd, knoptm and knopmd daemons (5s /10 times) */
787     knopwatchd_check_interval = 5;
788     knopwatchd_max_retries    = 10;
789
790     *hostname                       = '\0';
791     *mail_addrs                     = '\0';
792     *shCmd                          = '\0';
793     *mailCmd                        = '\0';
794     *sendmailCmd                    = '\0';
795     *fwknop_run_dir                 = '\0';
796     *alerting_methods               = '\0';
797     *fwknopdCmd                     = '\0';
798     *fwknopd_pid_file               = '\0';
799     *fwknopd_cmdline_file           = '\0';
800     *knopmdCmd                      = '\0';
801     *knoptmCmd                      = '\0';
802     *knopmd_pid_file                = '\0';
803     *knoptm_pid_file                = '\0';
804     *knopwatchd_pid_file            = '\0';
805     *char_knopwatchd_check_interval = '\0';
806     *char_knopwatchd_max_retries    = '\0';
807     *enable_syslog_file             = '\0';
808     *auth_mode                      = '\0';
809 }
810
811 static void dump_config (void)
812 {
813     fprintf(stdout, "[+] Dumping settings...\n\n");
814
815     fprintf(stderr, "%30s\t%s\n", "fwknopdCmd", fwknopdCmd);
816     fprintf(stderr, "%30s\t%s\n", "hostname", hostname);
817     fprintf(stderr, "%30s\t%s\n", "fwknopd_pid_file", fwknopd_pid_file);
818     fprintf(stderr, "%30s\t%s\n", "fwknopd_cmdline_file", fwknopd_cmdline_file);
819     fprintf(stderr, "%30s\t%s\n", "knopmdCmd", knopmdCmd);
820     fprintf(stderr, "%30s\t%s\n", "knoptmCmd", knoptmCmd);
821     fprintf(stderr, "%30s\t%s\n", "knopmd_pid_file", knopmd_pid_file);
822     fprintf(stderr, "%30s\t%s\n", "knoptm_pid_file", knoptm_pid_file);
823     fprintf(stderr, "%30s\t%s\n", "knopwatchd_pid_file", knopwatchd_pid_file);
824     fprintf(stderr, "%30s\t%s\n", "shCmd", shCmd);
825     fprintf(stderr, "%30s\t%s\n", "mailCmd", mailCmd);
826     fprintf(stderr, "%30s\t%s\n", "sendmailCmd", sendmailCmd);
827     fprintf(stderr, "%30s\t%s\n", "mail_addrs", mail_addrs);
828     fprintf(stderr, "%30s\t%u\n", "knopwatchd_check_interval",
829                                 knopwatchd_check_interval);
830     fprintf(stderr, "%30s\t%u\n", "knopwatchd_max_retries",
831                                 knopwatchd_max_retries);
832     fprintf(stderr, "%30s\t%s\n", "alerting_methods", alerting_methods);
833     fprintf(stderr, "%30s\t%s\n", "ENABLE_SYSLOG_FILE", enable_syslog_file);
834     fprintf(stderr, "%30s\t%s\n", "AUTH_MODE", auth_mode);
835
836     exit(EXIT_SUCCESS);
837 }
838
839 static void usage (void)
840 {
841     fprintf(stderr, "knopwatchd - Fwknop watch daemon\n\n");
842
843     fprintf(stderr, "[+] Version: %s\n", FWKNOP_VERSION);
844     fprintf(stderr,
845 "    By Michael Rash (mbr@cipherdyne.org)\n"
846 "    URL: http://www.cipherdyne.org/fwknop/\n\n");
847
848     fprintf(stderr, "Usage: knopwatchd [options]\n\n");
849
850     fprintf(stderr,
851 "Options:\n"
852 "    -c <file>          - Specify path to config file instead of using the\n"
853 "                         default $config_file.\n"
854 "    -D                 - Dump  the  configuration values that fwknopd\n"
855 "                         derives from the /etc/fwknop/fwknop.conf (or other\n"
856 "                         override files) on STDERR\n"
857 "    -h                 - Display this usage message and exit\n"
858 "    -O <file>          - Override config variable values that are normally\n"
859 "                         read from the /etc/fwknop/fwknop.conf file with\n"
860 "                         values from the specified file\n");
861
862     exit(EXIT_FAILURE);
863 }