1 /*
2  * Argus Software
3  * Copyright (c) 2000-2016 QoSient, LLC
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  */
21 
22 /*
23  * $Id: //depot/argus/clients/clients/radium.c#16 $
24  * $DateTime: 2016/06/01 15:17:28 $
25  * $Change: 3148 $
26  */
27 
28 /*
29  * radium.c  - this is the argus record distribtion node.
30  *    Acting just like a ra* program, supporting all the options
31  *    and functions of ra(), and providing access to data, like
32  *    argus, supporting remote filtering, and MAR record generation.
33  *    This is an important workhorse for the argus architecture.
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #include "argus_config.h"
38 #endif
39 
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <grp.h>
43 #include <pwd.h>
44 
45 #if defined(HAVE_SYS_VFS_H)
46 #include <sys/vfs.h>
47 #else
48 #include <sys/param.h>
49 #include <sys/mount.h>
50 #endif
51 
52 #include <argus_compat.h>
53 #include <argus_output.h>
54 
55 #include <rabins.h>
56 
57 int RaRealTime = 0;
58 float RaUpdateRate = 1.0;
59 
60 struct timeval ArgusLastRealTime = {0, 0};
61 struct timeval ArgusLastTime     = {0, 0};
62 struct timeval ArgusThisTime     = {0, 0};
63 
64 struct timeval dLastTime = {0, 0};
65 struct timeval dRealTime = {0, 0};
66 struct timeval dThisTime = {0, 0};
67 struct timeval dTime     = {0, 0};
68 
69 long long thisUsec = 0;
70 
71 void RadiumSendFile (struct ArgusOutputStruct *, struct ArgusClientData *, char *, int);
72 
73 extern char *chroot_dir;
74 extern uid_t new_uid;
75 extern gid_t new_gid;
76 
77 void ArgusSetChroot(char *);
78 
79 void
ArgusClientInit(struct ArgusParserStruct * parser)80 ArgusClientInit (struct ArgusParserStruct *parser)
81 {
82    struct ArgusModeStruct *mode;
83    FILE *tmpfile = NULL;
84    struct timeval *tvp;
85    int pid, dflag;
86 #if defined(ARGUS_THREADS)
87    sigset_t blocked_signals;
88    int thread = 0;
89 
90    thread++;
91 #endif /* ARGUS_THREADS */
92 
93 /*
94    if (thread == 0)
95       ArgusLog (LOG_ERR, "not compiled with pthread support.  exiting");
96 */
97    parser->RaWriteOut = 1;
98    parser->ArgusReverse = 1;
99 
100    if (!(parser->RaInitialized)) {
101       if ((mode = parser->ArgusModeList) != NULL) {
102          while (mode) {
103             if (!(strncasecmp (mode->mode, "rtime", 5)) ||
104                (!(strncasecmp (mode->mode, "realtime", 8)))) {
105                char *ptr = NULL;
106                RaRealTime++;
107                if ((ptr = strchr(mode->mode, ':')) != NULL) {
108                   double value = 0.0;
109                   char *endptr = NULL;
110                   ptr++;
111                   value = strtod(ptr, &endptr);
112                   if (ptr != endptr) {
113                      RaUpdateRate = value;
114                   }
115                }
116             } else
117                if (isdigit(*optarg))
118                   setArgusMarReportInterval (ArgusParser, optarg);
119 
120             mode = mode->nxt;
121          }
122       }
123 
124       dflag = parser->dflag;
125       parser->dflag = 0;
126 
127       if ((parser->ArgusAggregator = ArgusNewAggregator(parser, NULL, ARGUS_RECORD_AGGREGATOR)) == NULL)
128          ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewAggregator error");
129 
130       if (parser->ArgusFlowModelFile != NULL) {
131          RadiumParseResourceFile (parser, parser->ArgusFlowModelFile);
132       } else {
133          if (!(parser->Xflag)) {
134             RadiumParseResourceFile (parser, "/usr/local/etc/radium.conf");
135          }
136       }
137 
138       parser->dflag = (parser->dflag) ? (dflag ? 0 : 1) : dflag;
139 
140       if (parser->dflag) {
141          pid_t parent = getppid();
142 
143          if (parent != 1) {
144             if ((pid = fork ()) < 0) {
145                ArgusLog (LOG_ERR, "Can't fork daemon %s", strerror(errno));
146             } else {
147                if (pid) {
148                   struct timespec ts = {0, 500000000};
149                   int status;
150 
151                   nanosleep(&ts, NULL);
152                   waitpid(pid, &status, WNOHANG);
153                   if (kill(pid, 0) < 0) {
154                      exit (1);
155                   } else
156                      exit (0);
157 
158                } else {
159                   if (chdir ("/") < 0)
160                      ArgusLog (LOG_ERR, "Can't chdir to / %s", strerror(errno));
161 
162                   if ((parser->ArgusSessionId = setsid()) < 0)
163                      ArgusLog (LOG_ERR, "setsid error %s", strerror(errno));
164 
165                   umask(0);
166 
167                   ArgusLog(LOG_WARNING, "started");
168 
169                   if ((tmpfile = freopen ("/dev/null", "r", stdin)) == NULL)
170                      ArgusLog (LOG_ERR, "Cannot map stdout to /dev/null");
171 
172                   if ((tmpfile = freopen ("/dev/null", "a+", stdout)) == NULL)
173                      ArgusLog (LOG_ERR, "Cannot map stdout to /dev/null");
174 
175                   if ((tmpfile = freopen ("/dev/null", "a+", stderr)) == NULL)
176                      ArgusLog (LOG_ERR, "Cannot map stderr to /dev/null");
177                }
178             }
179          }
180       }
181 
182       if (parser->ArgusPortNum != 0) {
183          if (ArgusEstablishListen (parser, parser->ArgusPortNum, parser->ArgusBindAddr) < 0)
184             ArgusLog (LOG_ERR, "setArgusPortNum: ArgusEstablishListen returned %s", strerror(errno));
185       }
186 
187       if (chroot_dir != NULL)
188          ArgusSetChroot(chroot_dir);
189 
190       if (new_gid > 0) {
191          if (setgid(new_gid) < 0)
192             ArgusLog (LOG_ERR, "ArgusInitOutput: setgid error %s", strerror(errno));
193       }
194 
195       if (new_uid > 0) {
196          if (setuid(new_uid) < 0)
197             ArgusLog (LOG_ERR, "ArgusInitOutput: setuid error %s", strerror(errno));
198       }
199 /*
200    This is the basic new argus() strategy for processing output
201    records.  The thread will do two basic things:
202       1) it will grab stuff off the queue, and then do the basic
203          processing that this radium will do, such as time
204          adjustment, aggregation, correction, and anonymization, etc...
205 
206       2) it will manage the listen, to deal without remote client
207          requests.  radium() can write its records to a file, and
208          any number of remote clients, so ......
209 
210    The ArgusClientTimeout() routine will drive all the maintenance
211    and so it should be run, probably 4x a second, just for good
212    measure.
213 */
214 
215       parser->ArgusReliableConnection++;
216       parser->RaInitialized++;
217 
218       parser->ArgusOutput = ArgusNewOutput (parser);
219       ArgusInitOutput (parser->ArgusOutput);
220 
221       tvp = getArgusMarReportInterval(ArgusParser);
222       if ((tvp->tv_sec == 0) && (tvp->tv_usec == 0)) {
223          setArgusMarReportInterval (ArgusParser, "60s");
224       }
225 
226 #if defined(ARGUS_THREADS)
227       sigemptyset(&blocked_signals);
228       pthread_sigmask(SIG_BLOCK, &blocked_signals, NULL);
229 #endif
230       (void) signal (SIGHUP,  (void (*)(int)) ArgusShutDown);
231       (void) signal (SIGTERM, (void (*)(int)) ArgusShutDown);
232       (void) signal (SIGQUIT, (void (*)(int)) ArgusShutDown);
233       (void) signal (SIGINT,  (void (*)(int)) ArgusShutDown);
234 
235       (void) signal (SIGPIPE, SIG_IGN);
236       (void) signal (SIGTSTP, SIG_IGN);
237       (void) signal (SIGTTOU, SIG_IGN);
238       (void) signal (SIGTTIN, SIG_IGN);
239    }
240 }
241 
RaArgusInputComplete(struct ArgusInput * input)242 void RaArgusInputComplete (struct ArgusInput *input)
243 {
244 
245 };
246 
247 void
RaParseComplete(int sig)248 RaParseComplete (int sig)
249 {
250    struct ArgusRecordStruct *rec = NULL;
251 
252 #ifdef ARGUSDEBUG
253    ArgusDebug (2, "RaParseComplete(%d) Starting\n", sig);
254 #endif
255 
256    if (!ArgusParser->RaParseCompleting) {
257       ArgusParser->RaParseCompleting++;
258       ArgusParser->RaParseDone++;
259 
260       if (ArgusParser->ArgusActiveHosts != NULL) {
261          struct ArgusQueueStruct *queue =  ArgusParser->ArgusActiveHosts;
262          struct ArgusInput *input = NULL;
263 
264          while (queue->count > 0) {
265             if ((input = (struct ArgusInput *) ArgusPopQueue(queue, ARGUS_LOCK)) != NULL) {
266                ArgusCloseInput(ArgusParser, input);
267                if (input->hostname != NULL)
268                   free (input->hostname);
269                if (input->filename != NULL)
270                   free (input->filename);
271 #if defined(HAVE_GETADDRINFO)
272                if (input->host != NULL)
273                   freeaddrinfo (input->host);
274 #endif
275                ArgusFree(input);
276             }
277          }
278          ArgusDeleteQueue(queue);
279          ArgusParser->ArgusActiveHosts = NULL;
280       }
281 
282       if (ArgusParser->ArgusOutput) {
283          if ((rec = ArgusGenerateStatusMarRecord(ArgusParser->ArgusOutput, ARGUS_SHUTDOWN)) != NULL)
284             ArgusPushBackList(ArgusParser->ArgusOutput->ArgusOutputList, (struct ArgusListRecord *)rec, ARGUS_LOCK);
285 
286          ArgusCloseOutput(ArgusParser->ArgusOutput);
287          ArgusDeleteOutput(ArgusParser, ArgusParser->ArgusOutput);
288          ArgusParser->ArgusOutput = NULL;
289       }
290 
291       if (sig >= 0) {
292 #ifdef ARGUSDEBUG
293          ArgusDebug (2, "RaParseComplete(caught signal $d)\n", sig);
294 #endif
295 
296          switch (sig) {
297             case SIGHUP:
298             case SIGINT:
299             case SIGTERM:
300             case SIGQUIT: {
301                struct ArgusWfileStruct *wfile = NULL;
302 
303                ArgusShutDown(sig);
304 
305                if (ArgusParser->ArgusWfileList != NULL) {
306                   struct ArgusListObjectStruct *lobj = NULL;
307                   int i, count = ArgusParser->ArgusWfileList->count;
308 
309                   if ((lobj = ArgusParser->ArgusWfileList->start) != NULL) {
310                      for (i = 0; i < count; i++) {
311                         if ((wfile = (struct ArgusWfileStruct *) lobj) != NULL) {
312                            if (wfile->fd != NULL) {
313 #ifdef ARGUSDEBUG
314                               ArgusDebug (2, "RaParseComplete: closing %s\n", wfile->filename);
315 #endif
316                               fflush (wfile->fd);
317                               fclose (wfile->fd);
318                               wfile->fd = NULL;
319                            }
320                         }
321                         lobj = lobj->nxt;
322                      }
323                   }
324                }
325 #if defined(ARGUS_THREADS)
326                pthread_exit(0);
327 #else
328                exit(0);
329 #endif /* ARGUS_THREADS */
330                break;
331             }
332          }
333       }
334    }
335 
336 #ifdef ARGUSDEBUG
337    ArgusDebug (2, "RaParseComplete(%d) returning\n", sig);
338 #endif
339 }
340 
341 
342 void
ArgusClientTimeout()343 ArgusClientTimeout ()
344 {
345    gettimeofday(&ArgusParser->ArgusRealTime, 0);
346 
347    if (RaRealTime) {  /* establish value for time comparison */
348       if (ArgusLastTime.tv_sec != 0) {
349          if (ArgusLastRealTime.tv_sec > 0) {
350             RaDiffTime(&ArgusParser->ArgusRealTime, &ArgusLastRealTime, &dRealTime);
351             thisUsec = ((dRealTime.tv_sec * 1000000) + dRealTime.tv_usec) * RaUpdateRate;
352             dRealTime.tv_sec  = thisUsec / 1000000;
353             dRealTime.tv_usec = thisUsec % 1000000;
354 
355             ArgusLastTime.tv_sec  += dRealTime.tv_sec;
356             ArgusLastTime.tv_usec += dRealTime.tv_usec;
357 
358             if (ArgusLastTime.tv_usec > 1000000) {
359                ArgusLastTime.tv_sec++;
360                ArgusLastTime.tv_usec -= 1000000;
361             }
362          }
363 
364          ArgusLastRealTime = ArgusParser->ArgusRealTime;
365       }
366    }
367 
368 #ifdef ARGUSDEBUG
369    ArgusDebug (6, "ArgusClientTimeout()\n");
370 #endif
371 }
372 
373 void
parse_arg(int argc,char ** argv)374 parse_arg (int argc, char**argv)
375 {}
376 
377 void
usage()378 usage ()
379 {
380    extern char version[];
381 
382    fprintf (stdout, "Radium Version %s\n", version);
383    fprintf (stdout, "usage: %s [radiumoptions] [raoptions]\n", ArgusParser->ArgusProgramName);
384 
385    fprintf (stdout, "options: -c <dir>       daemon chroot directory.\n");
386    fprintf (stdout, "         -d             run as a daemon.\n");
387    fprintf (stdout, "         -f conf.file   read %s configure file.\n", ArgusParser->ArgusProgramName);
388    fprintf (stdout, "         -u <userid>    specify user id for daemon.\n");
389    fprintf (stdout, "         -g <groupid>   specify group id for daemon.\n");
390 #if defined (ARGUSDEBUG)
391    fprintf (stdout, "         -D <level>     specify debug level\n");
392 #endif
393 #ifdef ARGUS_SASL
394    fprintf (stdout, "         -U <user/auth> specify <user/auth> authentication information.\n");
395 #endif
396    fflush (stdout);
397    exit(1);
398 }
399 
400 
401 #define RADIUM_MAX_ANALYTICS	128
402 struct ArgusRecordStruct *(*RadiumAnalyticAlgorithmTable[RADIUM_MAX_ANALYTICS])(struct ArgusParserStruct *, struct ArgusRecordStruct *) = {
403    NULL, NULL, NULL
404 };
405 
406 
407 
408 void
RaProcessRecord(struct ArgusParserStruct * parser,struct ArgusRecordStruct * argus)409 RaProcessRecord (struct ArgusParserStruct *parser, struct ArgusRecordStruct *argus)
410 {
411    struct ArgusRecordStruct *ns;
412 
413    switch (argus->hdr.type & 0xF0) {
414       case ARGUS_MAR: {
415          struct ArgusRecord *rec = (struct ArgusRecord *)argus->dsrs[0];
416          if (rec && parser->ArgusAdjustTime) {
417             struct timeval drift;
418 
419             drift.tv_sec  = parser->ArgusRealTime.tv_sec  - ntohl(rec->argus_mar.now.tv_sec);
420             drift.tv_usec = parser->ArgusRealTime.tv_usec - ntohl(rec->argus_mar.now.tv_usec);
421             argus->input->ArgusTimeDrift  = drift.tv_sec * 1000000;
422             argus->input->ArgusTimeDrift += drift.tv_usec;
423             rec->argus_mar.drift = argus->input->ArgusTimeDrift;
424 #ifdef ARGUSDEBUG
425 #if defined(__APPLE_CC__) || defined(__APPLE__)
426             ArgusDebug (3, "RaProcessRecord: ArgusInput 0x%x drift %lld\n",
427                              argus->input, argus->input->ArgusTimeDrift);
428 #else
429             ArgusDebug (3, "RaProcessRecord: ArgusInput 0x%x drift %Ld\n",
430                              argus->input, argus->input->ArgusTimeDrift);
431 #endif
432 #endif
433          }
434          break;
435       }
436 
437       case ARGUS_EVENT:
438       case ARGUS_NETFLOW:
439       case ARGUS_FAR: {
440          struct ArgusTimeObject *time = (void *)argus->dsrs[ARGUS_TIME_INDEX];
441 
442          if (time != NULL) {
443             if (parser->ArgusAdjustTime) {
444                long long ArgusDriftLevel = parser->ArgusAdjustTime * 1000000;
445 
446                if (time && ((argus->input->ArgusTimeDrift >  ArgusDriftLevel) ||
447                             (argus->input->ArgusTimeDrift < -ArgusDriftLevel))) {
448                   int secs  = argus->input->ArgusTimeDrift / 1000000;
449                   int usecs = argus->input->ArgusTimeDrift % 1000000;
450 
451                   struct timeval startbuf, *start = &startbuf;
452                   struct timeval endbuf, *end = &endbuf;
453 
454                   start->tv_sec  = time->src.start.tv_sec;
455                   start->tv_usec = time->src.start.tv_usec;
456 
457                   end->tv_sec    = time->src.end.tv_sec;
458                   end->tv_usec   = time->src.end.tv_usec;
459 
460 #ifdef ARGUSDEBUG
461                   ArgusDebug (4, "RaProcessRecord() ArgusInput 0x%x adjusting timestamps by %d secs and %d usecs\n", argus->input, secs, usecs);
462 #endif
463                   time->hdr.argus_dsrvl8.qual |= ARGUS_TIMEADJUST;
464                   start->tv_sec  +=  secs;
465                   start->tv_usec += usecs;
466                   if (start->tv_usec < 0) {
467                      start->tv_sec--; start->tv_usec += 1000000;
468                   }
469                   if (start->tv_usec > 1000000) {
470                      start->tv_sec++; start->tv_usec -= 1000000;
471                   }
472 
473                   end->tv_sec  +=  secs;
474                   end->tv_usec += usecs;
475                   if (end->tv_usec < 0) {
476                      end->tv_sec--; end->tv_usec += 1000000;
477                   }
478                   if (end->tv_usec > 1000000) {
479                      end->tv_sec++; end->tv_usec -= 1000000;
480                   }
481                }
482             }
483 
484             ArgusThisTime.tv_sec  = time->src.start.tv_sec;
485             ArgusThisTime.tv_usec = time->src.start.tv_usec;
486 
487             if (RaRealTime) {
488                if (ArgusLastTime.tv_sec == 0)
489                   ArgusLastTime = ArgusThisTime;
490 
491                if (!((ArgusLastTime.tv_sec  > ArgusThisTime.tv_sec) ||
492                   ((ArgusLastTime.tv_sec == ArgusThisTime.tv_sec) &&
493                    (ArgusLastTime.tv_usec > ArgusThisTime.tv_usec)))) {
494 
495                   while ((ArgusThisTime.tv_sec  > ArgusLastTime.tv_sec) ||
496                         ((ArgusThisTime.tv_sec == ArgusLastTime.tv_sec) &&
497                          (ArgusThisTime.tv_usec > ArgusLastTime.tv_usec))) {
498                      struct timespec ts = {0, 0};
499                      int thisRate;
500 
501                      RaDiffTime(&ArgusThisTime, &ArgusLastTime, &dThisTime);
502                      thisRate = ((dThisTime.tv_sec * 1000000) + dThisTime.tv_usec)/RaUpdateRate;
503                      thisRate = (thisRate > 100000) ? 100000 : thisRate;
504 
505                      ts.tv_nsec = thisRate * 1000;
506                      nanosleep (&ts, NULL);
507                      ArgusClientTimeout ();
508 
509                      gettimeofday(&parser->ArgusRealTime, 0);
510 
511                      if (ArgusLastRealTime.tv_sec > 0) {
512                         RaDiffTime(&parser->ArgusRealTime, &ArgusLastRealTime, &dRealTime);
513                         thisUsec = ((dRealTime.tv_sec * 1000000) + dRealTime.tv_usec) * RaUpdateRate;
514                         dRealTime.tv_sec  = thisUsec / 1000000;
515                         dRealTime.tv_usec = thisUsec % 1000000;
516 
517                         ArgusLastTime.tv_sec  += dRealTime.tv_sec;
518                         ArgusLastTime.tv_usec += dRealTime.tv_usec;
519                         if (ArgusLastTime.tv_usec > 1000000) {
520                            ArgusLastTime.tv_sec++;
521                            ArgusLastTime.tv_usec -= 1000000;
522                         }
523                      }
524 
525                      ArgusLastRealTime = parser->ArgusRealTime;
526                   }
527                }
528 
529             } else
530                ArgusLastTime = parser->ArgusRealTime;
531 
532          }
533          break;
534       }
535    }
536 
537    if ((ns = ArgusCopyRecordStruct(argus)) != NULL) {
538       int i;
539       for (i = 0; i < RADIUM_MAX_ANALYTICS; i++) {
540          if (RadiumAnalyticAlgorithmTable[i] != NULL) {
541             if ((ns = RadiumAnalyticAlgorithmTable[i](parser, ns)) == NULL)
542                break;
543 
544          } else
545             break;
546       }
547 
548       if (ns != NULL)
549          ArgusPushBackList(parser->ArgusOutput->ArgusOutputList, (struct ArgusListRecord *) ns, ARGUS_LOCK);
550    }
551 
552 #if defined(ARGUS_THREADS)
553    pthread_cond_signal(&parser->ArgusOutput->ArgusOutputList->cond);
554 
555    if (parser->ArgusOutput->ArgusOutputList->count > 10000) {
556       struct timespec tsbuf = {0, 10000000}, *ts = &tsbuf;
557       nanosleep (ts, NULL);
558    }
559 
560 #else
561    ArgusOutputProcess(parser->ArgusOutput);
562 #endif
563 
564 #ifdef ARGUSDEBUG
565    ArgusDebug (4, "RaProcessRecord (0x%x, 0x%x) returning", parser, argus);
566 #endif
567 }
568 
RaSendArgusRecord(struct ArgusRecordStruct * argus)569 int RaSendArgusRecord(struct ArgusRecordStruct *argus) {return 0;}
570 
571 void ArgusWindowClose(void);
572 
ArgusWindowClose(void)573 void ArgusWindowClose(void) {
574 #ifdef ARGUSDEBUG
575    ArgusDebug (6, "ArgusWindowClose () returning\n");
576 #endif
577 }
578 
579 #define RADIUM_RCITEMS                          22
580 
581 #define RADIUM_DAEMON                           0
582 #define RADIUM_MONITOR_ID                       1
583 #define RADIUM_ARGUS_SERVER                     2
584 #define RADIUM_CISCONETFLOW_PORT                3
585 #define RADIUM_ACCESS_PORT                      4
586 #define RADIUM_INPUT_FILE                       5
587 #define RADIUM_USER_AUTH                        6
588 #define RADIUM_AUTH_PASS                        7
589 #define RADIUM_OUTPUT_FILE                      8
590 #define RADIUM_OUTPUT_STREAM                    9
591 #define RADIUM_MAR_STATUS_INTERVAL              10
592 #define RADIUM_DEBUG_LEVEL                      11
593 #define RADIUM_FILTER_OPTIMIZER                 12
594 #define RADIUM_FILTER_TAG                       13
595 #define RADIUM_BIND_IP                          14
596 #define RADIUM_MIN_SSF                          15
597 #define RADIUM_MAX_SSF                          16
598 #define RADIUM_ADJUST_TIME                      17
599 #define RADIUM_CHROOT_DIR                       18
600 #define RADIUM_SETUSER_ID                       19
601 #define RADIUM_SETGROUP_ID                      20
602 #define RADIUM_CLASSIFIER_FILE                  21
603 
604 char *RadiumResourceFileStr [] = {
605    "RADIUM_DAEMON=",
606    "RADIUM_MONITOR_ID=",
607    "RADIUM_ARGUS_SERVER=",
608    "RADIUM_CISCONETFLOW_PORT=",
609    "RADIUM_ACCESS_PORT=",
610    "RADIUM_INPUT_FILE=",
611    "RADIUM_USER_AUTH=",
612    "RADIUM_AUTH_PASS=",
613    "RADIUM_OUTPUT_FILE=",
614    "RADIUM_OUTPUT_STREAM=",
615    "RADIUM_MAR_STATUS_INTERVAL=",
616    "RADIUM_DEBUG_LEVEL=",
617    "RADIUM_FILTER_OPTIMIZER=",
618    "RADIUM_FILTER=",
619    "RADIUM_BIND_IP=",
620    "RADIUM_MIN_SSF=",
621    "RADIUM_MAX_SSF=",
622    "RADIUM_ADJUST_TIME=",
623    "RADIUM_CHROOT_DIR=",
624    "RADIUM_SETUSER_ID=",
625    "RADIUM_SETGROUP_ID=",
626    "RADIUM_CLASSIFIER_FILE=",
627 };
628 
629 int
RadiumParseResourceFile(struct ArgusParserStruct * parser,char * file)630 RadiumParseResourceFile (struct ArgusParserStruct *parser, char *file)
631 {
632    int retn = 0;
633    int i, len, done = 0, linenum = 0, Soption = 0, roption = 0, quoted = 0;
634    char strbuf[MAXSTRLEN], *str = strbuf, *optarg;
635    char result[MAXSTRLEN], *ptr;
636    FILE *fd;
637 
638    if (file) {
639       if ((fd = fopen (file, "r")) != NULL) {
640          while ((fgets(str, MAXSTRLEN, fd)) != NULL)  {
641             done = 0; quoted = 0; linenum++;
642             while (*str && isspace((int)*str))
643                 str++;
644 
645             if (*str && (*str != '#') && (*str != '\n') && (*str != '!')) {
646                for (i = 0; i < RADIUM_RCITEMS && !done; i++) {
647                   len = strlen(RadiumResourceFileStr[i]);
648                   if (!(strncmp (str, RadiumResourceFileStr[i], len))) {
649                      optarg = &str[len];
650                      if (*optarg == '\"') { optarg++; quoted = 1; }
651                      if (optarg[strlen(optarg) - 1] == '\n')
652                         optarg[strlen(optarg) - 1] = '\0';
653                      if (optarg[strlen(optarg) - 1] == '\"')
654                         optarg[strlen(optarg) - 1] = '\0';
655 
656                      switch (i) {
657                         case RADIUM_DAEMON: {
658                            if (!(strncasecmp(optarg, "yes", 3)))
659                               parser->dflag = 1;
660                            else
661                            if (!(strncasecmp(optarg, "no", 2)))
662                               parser->dflag = 0;
663 
664                            break;
665                         }
666 
667                         case RADIUM_MONITOR_ID:
668                            if (optarg && quoted) {   // Argus ID is a string.  Limit to date is 4 characters.
669                               int slen = strlen(optarg);
670                               if (slen > 4) optarg[4] = '\0';
671                               setArgusID (parser, optarg, ARGUS_IDIS_STRING);
672 
673                            } else {
674                            if (optarg && (*optarg == '`')) {
675                               if (optarg[strlen(optarg) - 1] == '`') {
676                                  FILE *tfd;
677 
678                                  optarg++;
679                                  optarg[strlen(optarg) - 1] = '\0';
680                                  if (!(strcmp (optarg, "hostname"))) {
681                                     if ((tfd = popen("hostname", "r")) != NULL) {
682                                        if ((ptr = fgets(result, MAXSTRLEN, tfd)) != NULL) {
683                                           optarg = ptr;
684                                           optarg[strlen(optarg) - 1] = '\0';
685 
686                                           if ((ptr = strstr(optarg, ".local")) != NULL) {
687                                              if (strlen(ptr) == strlen(".local"))
688                                                 *ptr = '\0';
689                                           }
690 
691                                        } else
692                                           ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) `hostname` failed %s.\n", file, strerror(errno));
693 
694                                        pclose(tfd);
695                                     } else
696                                        ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) System error: popen() %s\n", file, strerror(errno));
697                                  } else
698                                     ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) unsupported command `%s` at line %d.\n", file, optarg, linenum);
699                               } else
700                                  ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) syntax error line %d\n", file, linenum);
701                            }
702                            if (optarg && isalnum((int)*optarg)) {
703 #if defined(HAVE_GETADDRINFO)
704                               struct addrinfo *host;
705                               int retn;
706 
707                               if ((retn = getaddrinfo(optarg, NULL, NULL, &host)) == 0) {
708                                  struct addrinfo *hptr = host;
709                                  switch (host->ai_family) {
710                                     case AF_INET:  {
711                                        struct sockaddr_in *sa = (struct sockaddr_in *) host->ai_addr;
712                                        unsigned int addr;
713                                        bcopy ((char *)&sa->sin_addr, (char *)&addr, 4);
714                                        setArgusID (ArgusParser, &addr, ARGUS_IDIS_IPV4);
715                                        break;
716                                     }
717                                     default:
718                                        ArgusLog (LOG_ERR, "Probe ID %s not in address family\n", optarg);
719                                        break;
720                                  }
721                                  freeaddrinfo(hptr);
722 
723                               } else {
724                                  switch (retn) {
725                                     case EAI_AGAIN:
726                                        ArgusLog(LOG_ERR, "dns server not available");
727                                        break;
728                                     case EAI_NONAME:
729                                        ArgusLog(LOG_ERR, "srcid %s unknown", optarg);
730                                        break;
731 #if defined(EAI_ADDRFAMILY)
732                                     case EAI_ADDRFAMILY:
733                                        ArgusLog(LOG_ERR, "srcid %s has no IP address", optarg);
734                                        break;
735 #endif
736                                     case EAI_SYSTEM:
737                                        ArgusLog(LOG_ERR, "srcid %s name server error %s", optarg, strerror(errno));
738                                        break;
739                                  }
740                               }
741 #else
742                               struct hostent *host;
743 
744                               if ((host = gethostbyname(optarg)) != NULL) {
745                                  if ((host->h_addrtype == 2) && (host->h_length == 4)) {
746                                     unsigned int addr;
747                                     bcopy ((char *) *host->h_addr_list, (char *)&addr, host->h_length);
748                                     setArgusID (parser, &addr, ARGUS_IDIS_IPV4);
749                                  } else
750                                     ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) host '%s' error %s\n", file, optarg, strerror(errno));
751                               } else
752                                  if (optarg && isdigit((int)*optarg)) {
753                                     setArgusID (parser, optarg, ARGUS_IDIS_INT);
754                                  } else
755                                     ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) syntax error line %d\n", file, linenum);
756 
757 #endif
758                            } else
759                               ArgusLog (LOG_ERR, "RadiumParseResourceFile(%s) syntax error line %d\n", file, linenum);
760                            }
761 
762                            break;
763 
764                         case RADIUM_ARGUS_SERVER:
765                            ++parser->Sflag;
766                            if (!Soption++ && (parser->ArgusRemoteHostList != NULL))
767                               ArgusDeleteHostList(parser);
768 
769                            if (!(ArgusAddHostList (parser, optarg, ARGUS_DATA_SOURCE, IPPROTO_TCP)))
770                               ArgusLog (LOG_ERR, "%s: host %s unknown\n", optarg);
771                            break;
772 
773                         case RADIUM_CISCONETFLOW_PORT: {
774                            ++parser->Sflag; ++parser->Cflag;
775                            if (!Soption++ && (parser->ArgusRemoteHostList != NULL))
776                               ArgusDeleteHostList(parser);
777 
778                            if (!(ArgusAddHostList (parser, optarg, ARGUS_CISCO_DATA_SOURCE, IPPROTO_UDP)))
779                               ArgusLog (LOG_ERR, "%s: host %s unknown\n", optarg);
780 
781                            break;
782                         }
783 
784                         case RADIUM_INPUT_FILE:
785                            if ((!roption++) && (parser->ArgusInputFileList != NULL))
786                               ArgusDeleteFileList(parser);
787 
788                            if (!(ArgusAddFileList (parser, optarg, (parser->Cflag ? ARGUS_CISCO_DATA_SOURCE : ARGUS_DATA_SOURCE), -1, -1))) {
789                               ArgusLog (LOG_ERR, "%s: error: file arg %s\n", optarg);
790                            }
791                            break;
792 
793                         case RADIUM_ACCESS_PORT:
794                            parser->ArgusPortNum = atoi(optarg);
795                            break;
796 /*
797                         case RADIUM_USER_AUTH:
798                            ustr = strdup(optarg);
799                            break;
800 
801                         case RADIUM_AUTH_PASS:
802                            pstr = strdup(optarg);
803                            break;
804 */
805                         case RADIUM_OUTPUT_FILE:
806                         case RADIUM_OUTPUT_STREAM: {
807                            char *filter = NULL, *fptr;
808 
809                            if ((filter = strchr (optarg, ' ')) != NULL) {
810                               *filter++ = '\0';
811 
812                               if ((fptr = strchr (filter, '"')) != NULL) {
813                                  *fptr++ = '\0';
814                                  filter = fptr;
815                               }
816                            }
817 
818                            setArgusWfile (parser, optarg, filter);
819                            break;
820                         }
821 
822                         case RADIUM_MAR_STATUS_INTERVAL:
823                            setArgusMarReportInterval (parser, optarg);
824                            break;
825 
826                         case RADIUM_DEBUG_LEVEL:
827                            parser->debugflag = atoi(optarg);
828                            break;
829 
830                         case RADIUM_FILTER_OPTIMIZER:
831                            if ((strncasecmp(optarg, "yes", 3)))
832                               setArgusOflag  (parser, 1);
833                            else
834                               setArgusOflag  (parser, 0);
835                            break;
836 
837                         case RADIUM_FILTER_TAG:
838                            if ((parser->ArgusRemoteFilter = ArgusCalloc (1, MAXSTRLEN)) != NULL) {
839                               struct nff_program filter;
840 
841                               ptr = parser->ArgusRemoteFilter;
842                               str = optarg;
843                               while (*str) {
844                                  if ((*str == '\\') && (str[1] == '\n')) {
845                                     if (fgets(str, MAXSTRLEN, fd) != NULL)
846                                     while (*str && (isspace((int)*str) && (str[1] && isspace((int)str[1]))))
847                                        str++;
848                                  }
849 
850                                  if ((*str != '\n') && (*str != '"'))
851                                     *ptr++ = *str++;
852                                  else
853                                     str++;
854                               }
855 
856                               if (ArgusFilterCompile (&filter, parser->ArgusRemoteFilter, 0) < 0)
857                                  ArgusLog (LOG_ERR, "RaParseResourceFile: remote filter syntax error");
858 #ifdef ARGUSDEBUG
859                               ArgusDebug (1, "RadiumParseResourceFile: ArgusFilter \"%s\" \n", parser->ArgusRemoteFilter);
860 #endif
861                            }
862                            break;
863 
864                         case RADIUM_BIND_IP:
865                            if (*optarg != '\0')
866                               setArgusBindAddr (parser, optarg);
867 #ifdef ARGUSDEBUG
868                            ArgusDebug (1, "RadiumParseResourceFile: ArgusBindAddr \"%s\" \n", parser->ArgusBindAddr);
869 #endif
870                            break;
871 
872                         case RADIUM_MIN_SSF:
873                            if (*optarg != '\0') {
874 #ifdef ARGUS_SASL
875                               ArgusMinSsf = atoi(optarg);
876 #ifdef ARGUSDEBUG
877                            ArgusDebug (1, "RadiumParseResourceFile: ArgusMinSsf \"%s\" \n", ArgusMinSsf);
878 #endif
879 #endif
880                            }
881                            break;
882 
883                         case RADIUM_MAX_SSF:
884                            if (*optarg != '\0') {
885 #ifdef ARGUS_SASL
886                               ArgusMaxSsf = atoi(optarg);
887 #ifdef ARGUSDEBUG
888                               ArgusDebug (1, "RadiumParseResourceFile: ArgusMaxSsf \"%s\" \n", ArgusMaxSsf);
889 #endif
890 #endif
891                            }
892                            break;
893 
894                         case RADIUM_ADJUST_TIME: {
895                            char *ptr;
896                            parser->ArgusAdjustTime = strtol(optarg, (char **)&ptr, 10);
897                            if (ptr == optarg)
898                               ArgusLog (LOG_ERR, "%s syntax error: line %d", file, linenum);
899 
900                            if (isalpha((int) *ptr)) {
901                               switch (*ptr) {
902                                  case 's': break;
903                                  case 'm': parser->ArgusAdjustTime *= 60; break;
904                                  case 'h': parser->ArgusAdjustTime *= 3600; break;
905                               }
906                            }
907 #ifdef ARGUSDEBUG
908                            ArgusDebug (1, "RadiumParseResourceFile: ArgusAdjustTime is %d secs\n", parser->ArgusAdjustTime);
909 #endif
910                            break;
911                         }
912 
913                         case RADIUM_CHROOT_DIR: {
914                            if (chroot_dir != NULL)
915                               free(chroot_dir);
916                            chroot_dir = strdup(optarg);
917                            break;
918                         }
919                         case RADIUM_SETUSER_ID: {
920                            struct passwd *pw;
921                            if ((pw = getpwnam(optarg)) == NULL)
922                               ArgusLog (LOG_ERR, "unknown user \"%s\"\n", optarg);
923                            new_uid = pw->pw_uid;
924                            endpwent();
925                            break;
926                         }
927                         case RADIUM_SETGROUP_ID: {
928                            struct group *gr;
929                            if ((gr = getgrnam(optarg)) == NULL)
930                                ArgusLog (LOG_ERR, "unknown group \"%s\"\n", optarg);
931                            new_gid = gr->gr_gid;
932                            endgrent();
933                            break;
934                         }
935 
936 
937                         case RADIUM_CLASSIFIER_FILE: {
938                            if (parser->ArgusLabeler == NULL) {
939                               if ((parser->ArgusLabeler = ArgusNewLabeler(parser, 0L)) == NULL)
940                                  ArgusLog (LOG_ERR, "ArgusClientInit: ArgusNewLabeler error");
941                            }
942 
943                            if (RaLabelParseResourceFile (parser, parser->ArgusLabeler, optarg) != 0)
944                               ArgusLog (LOG_ERR, "ArgusClientInit: label conf file error %s", strerror(errno));
945 
946                            RadiumAnalyticAlgorithmTable[0] = ArgusLabelRecord;
947                            break;
948                         }
949                      }
950 
951                      done = 1;
952                      break;
953                   }
954                }
955             }
956          }
957 
958          fclose(fd);
959 
960       } else {
961          retn++;
962 #ifdef ARGUSDEBUG
963          ArgusDebug (1, "RadiumParseResourceFile: open %s %s\n", file, strerror(errno));
964 #endif
965       }
966    }
967 
968 #ifdef ARGUSDEBUG
969    ArgusDebug (1, "RadiumParseResourceFile (%s) returning %d\n", file, retn);
970 #endif
971 
972    return (retn);
973 }
974 
975 void
clearRadiumConfiguration(void)976 clearRadiumConfiguration (void)
977 {
978    ArgusParser->dflag = 0;
979    setArgusID (ArgusParser, 0, 0);
980 
981    ArgusParser->ArgusPortNum = 0;
982 
983    clearArgusWfile (ArgusParser);
984    setArgusBindAddr (ArgusParser, NULL);
985    setArgusOflag (ArgusParser, 1);
986 
987    ArgusParser->dflag = 0;
988 
989    if (ArgusParser->ArgusRemoteHostList != NULL)
990       ArgusDeleteHostList(ArgusParser);
991 
992    if (ArgusParser->ArgusInputFileList) {
993       ArgusDeleteFileList(ArgusParser);
994    }
995 
996    if (ArgusParser->ArgusRemoteFilter) {
997       ArgusFree(ArgusParser->ArgusRemoteFilter);
998       ArgusParser->ArgusRemoteFilter = NULL;
999    }
1000 
1001 #ifdef ARGUSDEBUG
1002    ArgusDebug (1, "clearRadiumConfiguration () returning\n");
1003 #endif
1004 }
1005