00001
00002
00003
00004
00005
00006 #ifdef HAVE_CONFIG_H
00007 #include "config.h"
00008 #endif
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <unistd.h>
00013 #include <getopt.h>
00014 #include <log.h>
00015 #include <strutil.h>
00016 #include <tail.h>
00017 #include <configfile.h>
00018
00019 char * proginfo = "secwatch " VERSION " built " __TIME__" " __DATE__ " Copyright (C) 2006 Nic Stevens.\nPlease see COPYING for licensing information.\n";
00020 char * dfltConfig = "/usr/local/etc/secwatch.conf";
00021 int maxage = -1;
00022 int fork_flag = 1;
00023 int dmpCfg = 0;
00024 int dmpPat = 0;
00025
00026 char * utxt[] = {
00027 "Dump configuration",
00028 "Dump patterns",
00029 "Configuration filename",
00030 "Show this list",
00031 "Show program version and exit.",
00032 "set the name of the patterns file",
00033 "set the name of the file holding the PID of the daemon",
00034 "set the name of the IP list",
00035 "set a comma delimited list of log files to scan",
00036 "set the maximum number of attemtps before firewalling",
00037 "set the maximum age, in minutes, of an IP ban",
00038 "set to true or false to have the daemon fork or stay in foreground",
00039 "set the address to send alerts to",
00040 "set the address to send alerts from",
00041 "set the location of the sendmail binary",
00042 "set the syslog priority to use",
00043 "set the syslog facility to use",
00044 "set the firewall reject selections",
00045 "set the inprej firewall rule",
00046 "set the outrej firewall rule",
00047 "set the fwdrej firewall rule",
00048 "set the firewall accept selections",
00049 "set the inpalw firewall rule",
00050 "set the outalw firewall rule",
00051 "set the fwdalw firewall rule",
00052 NULL
00053 };
00054
00055 static struct option _opts[] = {
00056 {"dump-cfg",no_argument,&dmpCfg,'d'},
00057 {"dump-pat",no_argument,&dmpPat,'p'},
00058 {"config", required_argument, 0, 'f'},
00059 {"help", no_argument, 0, 'h'},
00060 {"version",no_argument, 0, 'v'},
00061 {0,0,0,0}
00062 };
00063 #define BASEOPTS 5
00064 struct option *opts = NULL;
00065 int numopts = 0;
00066
00067 void makeopts(void) {
00068 int i, ip;
00069 char desc[100];
00070 struct option op;
00071 for(i = 0; i < BASEOPTS; i++) {
00072 numopts++;
00073 if((opts = realloc(opts,sizeof(struct option)*(numopts+1))) == NULL) {
00074 fprintf(stderr,"Fatal: Could not create option space\n");
00075 exit(-1);
00076 }
00077 opts[i] = _opts[i];
00078 opts[i+1].name = NULL;
00079 }
00080 for(i = 0; config[i].name != NULL; i++) {
00081 ip = numopts++;
00082 if((opts = realloc(opts,(sizeof(struct option )*(numopts+1)))) == NULL) {
00083 fprintf(stderr,"Fatal: Could not create option space\n");
00084 exit(-1);
00085 }
00086 sprintf(desc,"set-%s",config[i].name);
00087 op.has_arg = 1;
00088 op.name = strdup(desc);
00089 op.flag = NULL;
00090 op.val = BASEOPTS+i;
00091 opts[ip] = op;
00092 opts[numopts].name = NULL;
00093 }
00094 }
00095
00096 void showProgInfo(FILE *o) {
00097 fprintf(o,"%s\n",proginfo);
00098 }
00099 void usage(FILE *o) {
00100 int i, j;
00101 showProgInfo(o);
00102 for(i = 0; opts[i].val != 0; i++) {
00103 if(i < BASEOPTS)
00104 fprintf(o,"-%c, --%-12.12s %s\n",
00105 opts[i].val,opts[i].name,utxt[i]);
00106 else {
00107 cfgitem_t *c = &config[i-BASEOPTS];
00108 char **a, *p, buf[128];
00109 int x;
00110 p = &buf[0];
00111 switch(c->type) {
00112 case ci_pathname:
00113 p = confVarPath(c->name,&x);
00114 break;
00115 case ci_text:
00116 p = confVarText(c->name,&x);
00117 break;
00118 case ci_integer:
00119 sprintf(buf,"%d",confVarInt(c->name,&x));
00120 break;
00121 case ci_boolean:
00122 if(c->val.i)
00123 strcpy(p,"true");
00124 else
00125 strcpy(p,"false");
00126 break;
00127 case ci_logpri:
00128 case ci_logfac:
00129 p = (c->type == ci_logpri) ? sysLogPriId(c->val.i) : sysLogFacId(c->val.i);
00130 break;
00131 case ci_flist:
00132 bzero(buf,sizeof(buf));
00133 for(j = 0; c->val.a[j] != NULL; j++) {
00134 char *foo = ",";
00135 strcat(buf,c->val.a[j]);
00136 if(c->val.a[j+1] != NULL)
00137 strcat(buf,foo);
00138 }
00139 break;
00140 }
00141 fprintf(o," --%-12.12s %s [Default: %s]\n",
00142 opts[i].name,
00143 utxt[i],
00144 p);
00145 }
00146 }
00147 }
00148 char **argvw;
00149 int main(int argc, char *argv[]) {
00150 int c, i, x;
00151 int optind, error = 0;
00152 char _maxage[10];
00153 char ebuf[10240];
00154 char *s, * configFile = dfltConfig;
00155 char ** logs;
00156 argvw = argv;
00157 makeopts();
00158 while(1) {
00159 c = getopt_long(argc, argv, "nf:dphv",opts,&optind);
00160 if(c == -1)
00161 break;
00162 switch(c) {
00163 case 'd':
00164 case 0:
00165 case 'p':
00166 case '1':
00167 case '2':
00168 break;
00169 case 'f':
00170 configFile = optarg;
00171 break;
00172 case 'h':
00173 usage(stdout);
00174 return 0;
00175 break;
00176 case 'v':
00177 showProgInfo(stdout);
00178 return 0;
00179 break;
00180 default:
00181 if(c >= 6 && c < numopts) {
00182 i = c -6;
00183 switch(config[i].type) {
00184 case ci_pathname:
00185 config[i].val.s = strdup(optarg);
00186 break;
00187 case ci_text:
00188 config[i].val.s = strdup(optarg);
00189 break;
00190 case ci_logfac:
00191 config[i].val.i = sysLogFac(optarg);
00192 break;
00193 case ci_logpri:
00194 config[i].val.i = sysLogPri(optarg);
00195 break;
00196 case ci_boolean:
00197 getBooleanValue(optarg,&config[i].val.i);
00198 break;
00199 case ci_integer:
00200 config[i].val.i = atoi(optarg);
00201 break;
00202 case ci_flist:
00203 config[i].val.a = split(",",optarg);
00204 break;
00205 }
00206 } else {
00207 fprintf(stderr,"%s: invalid argument(%d)\n",*argv,c);
00208 error = 1;
00209 break;
00210 }
00211 }
00212 }
00213 if(error) {
00214 usage(stderr);
00215 return -1;
00216 }
00217 if(configFile != NULL) {
00218 if(readConfig(configFile,ebuf,sizeof(ebuf))) {
00219 fprintf(stderr,"%s: Configuration error %s\n",*argv,ebuf);
00220 return -1;
00221 }
00222 }
00223 if(dmpCfg || dmpPat)
00224 showProgInfo(stdout);
00225
00226 if(dmpCfg)
00227 dumpConfig();
00228
00229 if(loadPatterns(confVarPath("patterns",&x),&ebuf,sizeof(ebuf))) {
00230 fprintf(stderr,"%s: Pattern error: %s\n",*argv,ebuf);
00231 return -1;
00232 }
00233 if(dmpPat)
00234 dumpPats();
00235
00236 if((logs = split(",",confVarText("logfiles",&x))) == NULL) {
00237 fprintf(stderr,"%s: No logs defined.\n",*argv);
00238 return -1;
00239 }
00240 for(i = 0; logs[i] != 0; i++) {
00241 logs[i] = trim(logs[i]);
00242 if(addtailsource(logs[i])) {
00243 fprintf(stderr,"%s: Error adding log source \"%s\": %m\n",*argv,logs[i]);
00244 return -1;
00245 }
00246 }
00247 if(dmpPat | dmpCfg)
00248 return 0;
00249 if(fork_flag) {
00250 if((i = fork()) == -1) {
00251 fprintf(stderr,"%s: Cannot fork: %m\n",*argv);
00252 return -1;
00253 }
00254 if(i == 0)
00255 return 0;
00256 }
00257 setsid();
00258 secwatch();
00259 }