root/fwknop/tags/fwknop-0.9.7-pre1/knopmd.c

Revision 430, 11.7 kB (checked in by mbr, 3 years ago)

debug mode bugfix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2 ******************************************************************************
3 *
4 *  File: knopmd.c
5 *
6 *  Purpose: knopmd separates iptables messages from all other
7 *           kernel messages.
8 *
9 *  Strategy: read messages from the /var/log/knopmdfifo named pipe and
10 *            print any firewall related messages to the fwknop data file
11 *            "/var/log/fwknop/fwdata".
12 *
13 *  Author: Michael Rash (mbr@cipherdyne.org)
14 *
15 *  Version: 0.9.5
16 *
17 *  Copyright (C) 1999-2001 Michael Rash (mbr@cipherdyne.org)
18 *
19 *  License (GNU Public License):
20 *
21 *     This program is distributed in the hope that it will be useful,
22 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
23 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 *     GNU General Public License for more details.
25 *
26 *     You should have received a copy of the GNU General Public License
27 *     along with this program; if not, write to the Free Software
28 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
29 *     USA
30 *
31 *  NOTE: This code is essentially borrowed from kmsgsd.c that is bundled
32 *        psad: http://www.cipherdyne.org/psad/
33 *
34 ******************************************************************************
35 *
36 *  $Id$
37 */
38
39 /* includes */
40 #include "fwknop.h"
41 #include <getopt.h>
42
43 /* defines */
44 #define KNOPMD_CONF "/etc/fwknop/knopmd.conf"
45
46 /* to check for a pcap-based data method */
47 #define FWKNOP_CONF "/etc/fwknop/fwknop.conf"
48
49 /* globals */
50 static volatile sig_atomic_t received_sighup = 0;
51 extern char *optarg; /* for getopt */
52 extern int   optind; /* for getopt */
53 char *fw_msg_search[MAX_GEN_LEN];
54 int num_fw_search_strings = 0;
55 int fw_search_all_flag = 1;  /* default to parse all iptables messages */
56
57 /* prototypes */
58 static void parse_config(
59     char *config_file,
60     char *fwknopfifo_file,
61     char *fwdata_file,
62     char *knopmd_pid_file
63 );
64
65 static void check_auth_mode(void);
66 static int match_fw_msg(char *fw_mgs);
67 static void sighup_handler(int sig);
68
69 /* main */
70 int main(int argc, char *argv[]) {
71     char fwknopfifo_file[MAX_PATH_LEN];
72     char fwdata_file[MAX_PATH_LEN];
73     char config_file[MAX_PATH_LEN];
74     char fw_search_file[MAX_PATH_LEN];
75     char knopmd_pid_file[MAX_PATH_LEN];
76     char buf[MAX_LINE_BUF];
77     int fifo_fd, fwdata_fd;  /* file descriptors */
78     int cmdlopt, numbytes;
79 #ifdef DEBUG
80     int matched_ipt_log_msg = 0;
81     int fwlinectr = 0;
82 #endif
83
84 #ifdef DEBUG
85     fprintf(stderr, "[+] Entering DEBUG mode\n");
86     fprintf(stderr, "[+] Firewall messages will be written to both ");
87     fprintf(stderr, "STDOUT _and_ to fwdata.\n\n");
88 #endif
89
90     /* establish default paths to config and fw_search file (may be
91      * overriden with command line args below */
92     strlcpy(config_file, KNOPMD_CONF, MAX_PATH_LEN);
93
94     while((cmdlopt = getopt(argc, argv, "c:k:")) != -1) {
95         switch(cmdlopt) {
96             case 'c':
97                 strlcpy(config_file, optarg, MAX_PATH_LEN);
98                 break;
99             case 'k':
100                 strlcpy(fw_search_file, optarg, MAX_PATH_LEN);
101                 break;
102             default:
103                 printf("[+] Usage:  knopmd [-c <config file>] ");
104                 printf("[-k <fw_search file>]\n");
105                 exit(EXIT_FAILURE);
106         }
107     }
108
109 #ifdef DEBUG
110     fprintf(stderr, "[+] parsing config_file: %s\n", config_file);
111 #endif
112     /* parse config file (knopmd.conf) */
113     parse_config(config_file, fwknopfifo_file,
114         fwdata_file, knopmd_pid_file);
115
116     /* make sure there isn't another knopmd already running */
117     check_unique_pid(knopmd_pid_file, "knopmd");
118
119 #ifndef DEBUG
120     /* become a daemon */
121     daemonize_process(knopmd_pid_file);
122 #endif
123
124     /* install signal handler for HUP signals */
125     signal(SIGHUP, sighup_handler);
126
127     /* start doing the real work now that the daemon is running and
128      * the config file has been processed */
129
130     /* open the fwknopfifo named pipe.  Note that we are opening the pipe
131      * _without_ the O_NONBLOCK flag since we want the read on the file
132      * descriptor to block until there is something new in the pipe.
133      * Also, not that we are opening with O_RDWR, since this seems to
134      * fix the problem with knopmd not blocking on the read() if the
135      * system logger dies (and hence closes its file descriptor for the
136      * fwknopfifo). */
137     if ((fifo_fd = open(fwknopfifo_file, O_RDWR)) < 0) {
138         fprintf(stderr, "[-] Could not open %s for reading.\n",
139             fwknopfifo_file);
140         exit(EXIT_FAILURE);  /* could not open fwknopfifo named pipe */
141     }
142
143     /* open the fwdata file in append mode so we can write messages from
144      * the pipe into this file. */
145     if ((fwdata_fd = open(fwdata_file,
146             O_CREAT|O_WRONLY|O_APPEND, 0600)) < 0) {
147         fprintf(stderr, "[-] Could not open %s for writing.\n", fwdata_file);
148         exit(EXIT_FAILURE);  /* could not open fwdata file */
149     }
150
151     /* MAIN LOOP;
152      * Read data from the pipe indefinitely (we opened it _without_
153      * O_NONBLOCK) and write it to the fwdata file if it is a firewall message
154      */
155     while ((numbytes = read(fifo_fd, buf, MAX_LINE_BUF-1)) >= 0) {
156
157 #ifdef DEBUG
158         fprintf(stderr,
159             "read %d bytes from %s fifo.\n", numbytes, fwknopfifo_file);
160 #endif
161
162         /* make sure the buf contents qualifies as a string */
163         buf[numbytes] = '\0';
164
165         if (received_sighup) {
166             /* clear the signal flag */
167             received_sighup = 0;
168
169             /* re-parse the config file after receiving HUP signal */
170             parse_config(config_file, fwknopfifo_file,
171                 fwdata_file, knopmd_pid_file);
172
173             /* close file descriptors and re-open them after
174              * re-reading config file */
175             close(fifo_fd);
176             close(fwdata_fd);
177
178             /* re-open fwknopfifo and fwdata files */
179             if ((fifo_fd = open(fwknopfifo_file, O_RDONLY)) < 0) {
180                 fprintf(stderr, "[-] Could not open %s for reading.\n",
181                     fwknopfifo_file);
182                 exit(EXIT_FAILURE);  /* could not open fwknopfifo named pipe */
183             }
184
185             if ((fwdata_fd = open(fwdata_file, O_CREAT|O_WRONLY|O_APPEND,
186                     0600)) < 0) {
187                 fprintf(stderr, "[-] Could not open %s for writing.\n",
188                     fwdata_file);
189                 exit(EXIT_FAILURE);  /* could not open fwdata file */
190             }
191             slogr("fwknop(knopmd)",
192                     "[+] received HUP signal, re-imported knopmd.conf");
193         }
194
195         /* see if we matched a firewall message and write it to the
196          * fwdata file */
197         if ((strstr(buf, "OUT") != NULL
198                 && strstr(buf, "IN") != NULL)) {
199             if (! fw_search_all_flag) {  /* we are looking for specific log prefixes */
200                 if (match_fw_msg(buf)) {
201                     if (write(fwdata_fd, buf, numbytes) < 0) {
202                         exit(EXIT_FAILURE);  /* could not write to the fwdata file */
203                     }
204 #ifdef DEBUG
205                     matched_ipt_log_msg = 1;
206 #endif
207                 }
208             } else {
209                 if (write(fwdata_fd, buf, numbytes) < 0)
210                     exit(EXIT_FAILURE);  /* could not write to the fwdata file */
211 #ifdef DEBUG
212                 matched_ipt_log_msg = 1;
213 #endif
214             }
215 #ifdef DEBUG
216             if (matched_ipt_log_msg) {
217                 puts(buf);
218                 fprintf(stderr, "[-] Line matched search strings.\n");
219                 fwlinectr++;
220                 if (fwlinectr % 50 == 0)
221                     fprintf(stderr,
222                         "[+] Processed %d firewall lines.\n", fwlinectr);
223                 matched_ipt_log_msg = 0;
224             } else {
225                 puts(buf);
226                 printf("[-] Line did not match search strings.\n");
227             }
228 #endif
229         }
230     }
231
232     /* these statements don't get executed, but for completeness... */
233     close(fifo_fd);
234     close(fwdata_fd);
235
236     exit(EXIT_SUCCESS);
237 }
238 /******************** end main ********************/
239
240 static int match_fw_msg(char *fw_msg)
241 {
242     int i;
243     for (i=0; i < num_fw_search_strings; i++)
244         if (strstr(fw_msg, fw_msg_search[i]) != NULL)
245             return 1;
246     return 0;
247 }
248
249 static void parse_config(char *config_file, char *fwknopfifo_file,
250     char *fwdata_file, char *knopmd_pid_file)
251 {
252     FILE *config_ptr;   /* FILE pointer to the config file */
253     unsigned int linectr = 0, i;
254     char config_buf[MAX_LINE_BUF], tmp_fw_search_buf[MAX_GEN_LEN];
255     char *index;
256
257     /* first check to see if knopmd should not be running (i.e.
258      * AUTH_MODE in the fwknop.conf file is set to a pcap-based
259      * method). */
260     check_auth_mode();
261
262     for (i=0; i < num_fw_search_strings; i++)
263         free(fw_msg_search[i]);
264
265     num_fw_search_strings = 0;
266     fw_msg_search[num_fw_search_strings] = NULL;
267
268     if ((config_ptr = fopen(config_file, "r")) == NULL) {
269         fprintf(stderr, "[-] Could not open %s for reading.\n",
270             config_file);
271         exit(EXIT_FAILURE);
272     }
273
274     /* increment through each line of the config file */
275     while ((fgets(config_buf, MAX_LINE_BUF, config_ptr)) != NULL) {
276         linectr++;
277         /* set the index pointer to the beginning of the line */
278         index = config_buf;
279
280         /* advance the index pointer through any whitespace
281          * at the beginning of the line */
282         while (*index == ' ' || *index == '\t') index++;
283
284         /* skip comments and blank lines, etc. */
285         if ((*index != '#') && (*index != '\n') &&
286                 (*index != ';') && (index != NULL)) {
287
288             find_char_var("FWKNOP_FIFO ", fwknopfifo_file, index);
289             find_char_var("FW_DATA_FILE ", fwdata_file, index);
290             find_char_var("KNOPMD_PID_FILE ", knopmd_pid_file, index);
291
292             if (find_char_var("FW_MSG_SEARCH", tmp_fw_search_buf, index)) {
293                 fw_msg_search[num_fw_search_strings]
294                     = (char *) malloc(strlen(tmp_fw_search_buf));
295                 strlcpy(fw_msg_search[num_fw_search_strings],
296                     tmp_fw_search_buf, MAX_GEN_LEN);
297                 num_fw_search_strings++;
298             }
299             if (find_char_var("FW_SEARCH_ALL", tmp_fw_search_buf, index)) {
300                 if (tmp_fw_search_buf[0] == 'N')
301                     fw_search_all_flag = 0;
302             }
303         }
304     }
305     fclose(config_ptr);
306 #ifdef DEBUG
307     fprintf(stderr, "[+] FWKNOP_FIFO: %s\n", fwknopfifo_file);
308     fprintf(stderr, "[+] FW_DATA_FILE: %s\n", fwdata_file);
309     fprintf(stderr, "[+] KNOPMD_PID_FILE: %s\n", knopmd_pid_file);
310 #endif
311     return;
312 }
313
314 static void check_auth_mode(void)
315 {
316     FILE *config_ptr;   /* FILE pointer to the config file */
317     char config_buf[MAX_LINE_BUF];
318     char auth_mode[MAX_GEN_LEN];
319     char *index;
320
321     if ((config_ptr = fopen(FWKNOP_CONF, "r")) == NULL) {
322         fprintf(stderr, "[-] Could not open %s for reading.\n",
323             FWKNOP_CONF);
324         exit(EXIT_FAILURE);
325     }
326
327     auth_mode[0] = '\0';
328
329     /* increment through each line of the config file */
330     while ((fgets(config_buf, MAX_LINE_BUF, config_ptr)) != NULL) {
331         /* set the index pointer to the beginning of the line */
332         index = config_buf;
333
334         /* advance the index pointer through any whitespace
335          * at the beginning of the line */
336         while (*index == ' ' || *index == '\t') index++;
337
338         /* skip comments and blank lines, etc. */
339         if ((*index != '#') && (*index != '\n') &&
340                 (*index != ';') && (index != NULL)) {
341
342             find_char_var("AUTH_MODE ", auth_mode, index);
343         }
344     }
345     fclose(config_ptr);
346
347     /* see if we are using the ULOG_PCAP mode */
348     if (strncmp(auth_mode, "ULOG_PCAP", MAX_GEN_LEN) == 0)
349         exit(EXIT_FAILURE);
350
351     /* see if we are using the PCAP mode */
352     if (strncmp(auth_mode, "PCAP", MAX_GEN_LEN) == 0)
353         exit(EXIT_FAILURE);
354
355     return;
356 }
357
358 static void sighup_handler(int sig)
359 {
360     received_sighup = 1;
361 }
Note: See TracBrowser for help on using the browser.