1 /********************************************************************************
2 * Nepenthes
3 * - finest collection -
4 *
5 *
6 *
7 * Copyright (C) 2005 Paul Baecher & Markus Koetter
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *
24 * contact nepenthesdev@users.sourceforge.net
25 *
26 *******************************************************************************/
27
28 /* $Id: Nepenthes.cpp 1410 2007-10-12 13:07:23Z common $ */
29
30 #include <config.h>
31
32 #ifdef WIN32
33 #else
34 #include <unistd.h>
35 #include <getopt.h>
36 #endif /* WIN32 */
37
38 #include <cstdio>
39 #include <cstdlib>
40 #include <csignal>
41 #include <sys/types.h>
42 #include <pwd.h>
43 #include <grp.h>
44 #include <dirent.h>
45 #include <sys/utsname.h>
46 #include <cctype>
47 #include <cerrno>
48 #include <cstring>
49
50 #ifdef HAVE_LIBCAP
51 #undef _POSIX_SOURCE
52 #include <sys/capability.h>
53 #endif
54
55 #include "Nepenthes.hpp"
56 #include "SocketManager.hpp"
57 #include "EventManager.hpp"
58 #include "DownloadManager.hpp"
59 #include "LogManager.hpp"
60 #include "ConsoleLogger.hpp"
61 #include "FileLogger.hpp"
62 #include "RingFileLogger.hpp"
63 #include "ModuleManager.hpp"
64 #include "ShellcodeManager.hpp"
65 #include "SubmitManager.hpp"
66 #include "Config.hpp"
67 #include "Utilities.hpp"
68 #include "DialogueFactoryManager.hpp"
69 #include "DNSManager.hpp"
70
71 #include "SQLManager.hpp"
72
73 #include "Message.hpp"
74
75
76 #ifdef STDTAGS
77 #undef STDTAGS
78 #define STDTAGS l_mgr
79 #endif
80
81 using namespace nepenthes;
82
83
84
85 Nepenthes *g_Nepenthes;
86
87
Options()88 Options::Options()
89 {
90 m_runMode = runNormal;
91 m_daemonize = false;
92 m_verbose = false;
93 m_setCaps = false;
94 m_ringLogger = false;
95 m_color = colorAuto;
96
97 m_fileCheckArguments = NULL;
98 m_configPath = SYSCONFDIR "/nepenthes/nepenthes.conf";
99 m_workingDir = PREFIX;
100 m_changeUser = NULL;
101 m_changeGroup = NULL;
102 m_changeRoot = NULL;
103 m_diskTags = NULL;
104 m_consoleTags = NULL;
105 }
106
107
108 /**
109 * the constructor
110 * takes no argument
111 * instances all managers
112 * inits all managers
113 */
Nepenthes()114 Nepenthes::Nepenthes()
115 {
116 g_Nepenthes = this;
117 m_running = true;
118
119 m_Config = NULL;
120 m_DialogueFactoryManager = NULL;
121 m_DNSManager = NULL;
122 m_DownloadManager = NULL;
123 m_EventManager = NULL;
124 m_LogManager = new LogManager;
125 m_ModuleManager = NULL;
126 m_ShellcodeManager = NULL;
127 m_SocketManager = NULL;
128 m_SubmitManager = NULL;
129 m_Utilities = NULL;
130
131 m_SQLManager = NULL;
132
133 m_UID = 0;
134 m_GID = 0;
135 }
136
137 /**
138 * Nepenthes destuctor
139 */
~Nepenthes()140 Nepenthes::~Nepenthes()
141 {
142 logPF();
143
144 if ( m_SocketManager != NULL )
145 m_SocketManager->Exit();
146
147 if (m_DownloadManager != NULL )
148 delete m_DownloadManager;
149
150 if (m_EventManager != NULL)
151 delete m_EventManager;
152
153 if (m_SubmitManager != NULL)
154 {
155 m_SubmitManager->Exit();
156 delete m_SubmitManager;
157 }
158
159 if (m_ModuleManager != NULL)
160 delete m_ModuleManager;
161
162 if (m_ShellcodeManager != NULL)
163 delete m_ShellcodeManager;
164
165 if (m_Utilities != NULL)
166 delete m_Utilities;
167
168 if (m_DialogueFactoryManager != NULL)
169 delete m_DialogueFactoryManager;
170
171 if (m_DNSManager != NULL)
172 delete m_DNSManager;
173
174 if (m_LogManager != NULL)
175 delete m_LogManager;
176
177 if ( m_SocketManager != NULL )
178 delete m_SocketManager;
179
180 g_Nepenthes = NULL;
181
182 printf("Quit\n");
183 }
184
185 /**
186 * start nepenthes, using command line arguments.
187 *
188 * @param argc number of arguments.
189 * @param argv vector containing arguments.
190 *
191 * @return 0 if the application was shut down poperly, non-null if an error occured.
192 */
parseArguments(int32_t argc,char ** argv,Options * options)193 bool Nepenthes::parseArguments(int32_t argc, char **argv, Options *options)
194 {
195 while( 1 )
196 {
197 int32_t option_index = 0;
198 static struct option long_options[] = {
199 { "config", 1, 0, 'c' },
200 { "capabilities", 0, 0, 'C' },
201 { "disk-log", 1, 0, 'd' },
202 { "daemonize", 0, 0, 'D' },
203 { "file-check", 1, 0, 'f' },
204 { "group", 1, 0, 'g' },
205 { "help", 0, 0, 'h' },
206 { "large-help", 0, 0, 'H' },
207 { "info", 0, 0, 'i' },
208 { "check-config", 0, 0, 'k' },
209 { "log", 1, 0, 'l' },
210 { "logging-help", 0, 0, 'L' },
211 { "color", 1, 0, 'o' },
212 { "chroot", 1, 0, 'r' },
213 { "ringlog", 0, 0, 'R' },
214 { "user", 1, 0, 'u' },
215 { "version", 0, 0, 'V' },
216 { "verbose", 0, 0, 'v' },
217 { "workingdir", 1, 0, 'w' },
218 { 0, 0, 0, 0 }
219 };
220
221 int32_t c = getopt_long(argc, argv, "c:Cd:Df:g:hHikl:Lo:r:Ru:vVw:", long_options, (int *)&option_index);
222 if (c == -1)
223 break;
224
225 switch (c)
226 {
227
228 case 'C':
229
230 options->m_setCaps = true;
231 break;
232
233
234 case 'c':
235 options->m_configPath = optarg;
236 break;
237
238 case 'd':
239 options->m_diskTags = optarg;
240 break;
241
242 case 'D':
243 options->m_daemonize = true;
244 break;
245
246
247 case 'f':
248 options->m_fileCheckArguments = optarg;
249 options->m_runMode = runFileCheck;
250 break;
251
252
253 case 'g':
254 options->m_changeGroup = optarg;
255 break;
256
257 case 'h':
258 show_help(false);
259 return false;
260 break;
261
262 case 'H':
263 show_help(true);
264 return false;
265 break;
266
267 case 'i':
268 show_info();
269 return false;
270 break;
271
272 case 'l':
273 options->m_consoleTags = optarg;
274 break;
275
276 case 'L':
277 show_loghelp();
278 return false;
279 break;
280
281 case 'k':
282 options->m_runMode = runConfigCheck;
283 break;
284
285 case 'o':
286 if ( !strcmp(optarg, "never") )
287 options->m_color = colorNever;
288 else if ( !strcmp(optarg, "always") )
289 options->m_color = colorAlways;
290 else if ( !strcmp(optarg, "auto") )
291 options->m_color = colorAuto;
292 else
293 {
294 fprintf(stdout, "Invalid argument for --color; must be one of\n"
295 "`never', `always' or `auto'.\n");
296 return false;
297 }
298 break;
299
300 case 'r':
301 options->m_changeRoot = optarg;
302 break;
303
304 case 'R':
305 options->m_ringLogger = true;
306 break;
307
308 case 'u':
309 options->m_changeUser = optarg;
310 break;
311
312
313 case 'v':
314 options->m_verbose = true;
315 break;
316
317 case 'V':
318 show_version();
319 return false;
320 break;
321
322 case 'w':
323 options->m_workingDir = optarg;
324 break;
325
326 case '?':
327 case ':':
328 exit(0);
329 break;
330
331 default:
332 break;
333 }
334 }
335
336 return true;
337 }
338
339
340 /**
341 * start nepenthes, using command line arguments.
342 *
343 * @param argc number of arguments.
344 * @param argv vector containing arguments.
345 *
346 * @return 0 if the application was shut down poperly, non-null if an error occured.
347 */
348
run(int32_t argc,char ** argv)349 int32_t Nepenthes::run(int32_t argc, char **argv)
350 {
351 Options opt;
352
353
354 if( !parseArguments(argc, argv, &opt) )
355 return -1;
356
357
358 if( opt.m_workingDir != NULL && chdir(opt.m_workingDir) )
359 {
360 logCrit("Cannot change working diretory to %s: %s.\n", opt.m_workingDir, strerror(errno));
361 return -1;
362 }
363
364 if( opt.m_changeUser != NULL && !changeUser(opt.m_changeUser) )
365 return -1;
366
367 if( opt.m_changeGroup != NULL && !changeGroup(opt.m_changeGroup) )
368 return -1;
369
370
371 show_logo();
372 show_version();
373
374
375
376 m_LogManager->registerTag(l_crit, "crit");
377 m_LogManager->registerTag(l_warn, "warn");
378 m_LogManager->registerTag(l_debug, "debug");
379 m_LogManager->registerTag(l_info, "info");
380 m_LogManager->registerTag(l_spam, "spam");
381 m_LogManager->registerTag(l_net, "net");
382 m_LogManager->registerTag(l_script, "script");
383 m_LogManager->registerTag(l_shell, "shell");
384 m_LogManager->registerTag(l_mem, "mem");
385 m_LogManager->registerTag(l_sc, "sc");
386 m_LogManager->registerTag(l_dl, "down");
387 m_LogManager->registerTag(l_mgr, "mgr");
388 m_LogManager->registerTag(l_hlr, "handler");
389 m_LogManager->registerTag(l_dia, "dia");
390 m_LogManager->registerTag(l_sub, "submit");
391 m_LogManager->registerTag(l_ev, "event");
392 m_LogManager->registerTag(l_mod, "module");
393 m_LogManager->registerTag(l_stdtag, "fixme");
394
395 if ( opt.m_runMode != runFileCheck || opt.m_verbose )
396 {
397
398 if ( opt.m_consoleTags )
399 m_LogManager->addLogger(new ConsoleLogger(m_LogManager), m_LogManager->parseTagString(opt.m_consoleTags));
400 else
401 m_LogManager->addLogger(new ConsoleLogger(m_LogManager), l_all);
402 }
403
404
405 if ( opt.m_runMode == runNormal || opt.m_runMode == runFileCheck )
406 {
407 m_DialogueFactoryManager = new DialogueFactoryManager(this);
408
409 m_DownloadManager = new DownloadManager(this);
410 m_EventManager = new EventManager(this);
411
412 // m_Lua = new Lua
413 m_ModuleManager = new ModuleManager(this);
414 m_ShellcodeManager = new ShellcodeManager(this);
415 m_SocketManager = new SocketManager(this);
416 m_SubmitManager = new SubmitManager(this);
417 m_Utilities = new Utilities();
418 m_DNSManager = new DNSManager(this);
419 m_SQLManager = new SQLManager(this);
420 }
421
422
423
424 switch ( opt.m_color )
425 {
426 case colorAuto:
427 if ( isatty(STDOUT_FILENO) )
428 m_LogManager->setColor(true);
429 else
430 m_LogManager->setColor(false);
431 break;
432
433 case colorNever:
434 m_LogManager->setColor(false);
435 break;
436
437 case colorAlways:
438 m_LogManager->setColor(true);
439 break;
440 }
441
442
443
444 /* load configuration. */
445 m_Config = new Config;
446 logSpam("Trying to load Nepenthes Configuration from %s \n", opt.m_configPath);
447 try
448 {
449 m_Config->load(opt.m_configPath);
450 logInfo("Loaded Nepenthes Configuration from \"%s\".\n", opt.m_configPath);
451 }
452 catch ( LoadError e )
453 {
454 fprintf(stderr, "Unable to load configuration file \"%s\": %s\n", opt.m_configPath, e.getMessage());
455 return -1;
456 }
457 catch ( ParseError e )
458 {
459 fprintf(stderr, "Parse error in \"%s\" on line %d: %s\n", opt.m_configPath, e.getLine(), e.getMessage());
460 return -1;
461 }
462
463 if ( opt.m_runMode == runConfigCheck ) // passed if we reach this
464 return 0;
465
466
467 if ( opt.m_runMode != runFileCheck || opt.m_verbose )
468 {
469
470 if ( opt.m_ringLogger == true )
471 {
472 string rlpath;
473 try
474 {
475 rlpath = m_Config->getValString("nepenthes.logmanager.ring_logging_file");
476 } catch ( ... )
477 {
478 logCrit("Could not find nepenthes.logmanager.ring_logging_file in Config\n");
479 return (false);
480 }
481
482
483 RingFileLogger *fl = new RingFileLogger(m_LogManager);
484
485 fl->setLogFileFormat((char *)rlpath.c_str());
486 fl->setMaxFiles(5);
487 fl->setMaxSize(1024 * 1024);
488
489 if ( opt.m_diskTags )
490 m_LogManager->addLogger(fl, m_LogManager->parseTagString(opt.m_diskTags));
491 else
492 m_LogManager->addLogger(fl, l_all);
493
494 } else
495 {
496 string flpath;
497 try
498 {
499 flpath = m_Config->getValString("nepenthes.logmanager.file_logging_file");
500 } catch ( ... )
501 {
502 logCrit("Could not find nepenthes.logmanager.file_logging_file in Config\n");
503 return (false);
504 }
505
506 FileLogger *fl = new FileLogger(m_LogManager);
507 fl->setLogFile(flpath.c_str());
508 if ( opt.m_diskTags )
509 m_LogManager->addLogger(fl, m_LogManager->parseTagString(opt.m_diskTags));
510 else
511 m_LogManager->addLogger(fl, l_all);
512
513 }
514 }
515
516 if (opt.m_daemonize == true)
517 {
518 logInfo("running as daemon\n");
519 daemon(1,0);
520 logInfo("daemon process id is %i\n",getpid());
521 }
522
523
524 if (opt.m_runMode == runFileCheck || opt.m_runMode == runNormal )
525 {
526
527 // socketManager will call WASStartup()
528 if ( m_SocketManager->Init() == false)
529 return -1;
530
531
532
533 if ( m_ModuleManager->Init() == false )
534 return -1;
535
536 m_ModuleManager->doList();
537
538
539 if (m_DNSManager->Init() == false )
540 return -1;
541
542 m_DNSManager->doList();
543
544
545 if (m_DownloadManager->Init() == false )
546 return -1;
547
548 m_DownloadManager->doList();
549
550
551 m_EventManager->doList();
552
553 m_ShellcodeManager->doList();
554
555 m_SocketManager->doList();
556
557
558 if (m_SubmitManager->Init() == false)
559 return -1;
560
561 m_SubmitManager->doList();
562
563
564 m_DialogueFactoryManager->doList();
565 m_SQLManager->doList();
566 }
567
568 // if we drop priviliges, we have to take care of the logfiles user/group permission
569 // if we do not drop privs, make sure the files are ours
570 // --common
571
572
573 if( !m_LogManager->setOwnership(m_UID, m_GID) )
574 return -1;
575
576 if ( setCapabilties() == false && opt.m_setCaps == true)
577 {
578 logCrit("As you asked to force capabilities, this is a critical error and we will terminate right now\n");
579 return -1;
580 }
581
582 if (opt.m_changeRoot != NULL && changeRoot(opt.m_changeRoot) == false )
583 return -1;
584
585
586 // change process group id
587 if ( opt.m_changeGroup != NULL && changeGroup() == false )
588 return -1;
589
590 // change process user id
591 if ( opt.m_changeUser != NULL && changeUser() == false )
592 return -1;
593
594
595 if (opt.m_runMode == runFileCheck )
596 {
597 show_version();
598 fileCheckMain(opt.m_fileCheckArguments,argc,optind,argv);
599 }else
600 {
601 doLoop();
602 }
603
604
605 if (m_Config != NULL)
606 {
607 delete m_Config;
608 }
609 return 0;
610 }
611
612
613
614 /**
615 * the Nepenthes mainloop
616 *
617 * @return should never return ;)
618 */
doLoop()619 bool Nepenthes::doLoop()
620 {
621
622 while (m_running)
623 {
624 getSocketMgr()->doLoop(500);
625 getEventMgr()->doTimeoutLoop();
626 // getDNSMgr()->pollDNS();
627 }
628 return true;
629 }
630
631
632
633 #define FC_DO_NONOP 0x001
634 #define FC_RM_NONOP 0x002
635 #define FC_RM_KNOWN 0x004
636
637 #define FC_IS_KNOWN 0x008
638 #define FC_IS_NONOP 0x010
639
640
fileCheckMain(const char * optval,int32_t argc,int32_t opti,char ** argv)641 bool Nepenthes::fileCheckMain(const char *optval, int32_t argc, int32_t opti, char **argv)
642 {
643 if ( opti >= argc )
644 {
645 return true;
646 }
647
648
649 uint8_t options=0;
650 if (optval != NULL)
651 {
652 if (strstr(optval,"rmnonop") != NULL)
653 {
654 options |= FC_RM_NONOP;
655 }
656 if (strstr(optval,"rmknown") != NULL)
657 {
658 options |= FC_RM_KNOWN;
659 }
660 if (strstr(optval,"dononop") != NULL)
661 {
662 options |= FC_DO_NONOP;
663 }
664 }
665
666 printf ("Checking Files: \n");
667 for ( ; opti < argc && m_running == true; )
668 {
669
670 struct stat fileinfo;
671 if ( stat((const char*)argv[opti],&fileinfo) != 0 )
672 {
673 printf("Could not stat %s: %s", (const char*)argv[opti], strerror(errno));
674 return -1;
675 }
676
677 if ( S_ISREG(fileinfo.st_mode) )
678 {
679
680 uint8_t result = fileCheckPrinter(argv[opti],options);
681
682 if (
683 (options & FC_RM_KNOWN && result & FC_IS_KNOWN) ||
684 (options & FC_RM_NONOP && result & FC_IS_NONOP)
685 )
686
687 {
688 if (unlink(argv[opti]) != 0)
689 {
690 printf("could not remove file %s (%s)\n",argv[opti],strerror(errno));
691 }
692 }
693
694 }else
695 if ( S_ISDIR(fileinfo.st_mode) )
696 {
697 DIR *bindir = opendir(argv[opti]);
698 struct dirent *dirnode;
699 string basepath = argv[opti];
700
701 while ( (dirnode = readdir(bindir)) != NULL && m_running == true )
702 {
703
704 #if defined(d_type_IS_NOT_A_POSIX_SPEC)
705 if ( dirnode->d_type == 8 )
706 #else
707 if (1)
708 #endif
709 {
710 string filepath = basepath + "/" + dirnode->d_name;
711 uint8_t result = fileCheckPrinter(filepath.c_str(),options);
712
713 if (
714 (options & FC_RM_KNOWN && result & FC_IS_KNOWN) ||
715 (options & FC_RM_NONOP && result & FC_IS_NONOP)
716 )
717
718 {
719 if (unlink(filepath.c_str()) != 0)
720 {
721 printf("could not remove file %s (%s)\n",filepath.c_str(),strerror(errno));
722 }
723 }
724 }
725 }
726 closedir(bindir);
727 }
728
729 opti++;
730 }
731 return true;
732 }
733
fileCheckPrinter(const char * filename,uint8_t options)734 uint8_t Nepenthes::fileCheckPrinter(const char *filename, uint8_t options)
735 {
736 uint8_t result=0;
737
738 Message *Msg=NULL;
739
740 printf("\t %s\t",filename);
741 switch ( fileCheck(filename,&Msg) )
742 {
743 case -1:
744 printf("could not open file");
745 break;
746
747 case 0:
748 if ( m_ShellcodeManager->fileCheck(&Msg) == SCH_DONE )
749 {
750 result |= FC_IS_KNOWN;
751 printf("\033[32;1mKNOWN\033[0m");
752 } else
753 {
754 printf("\033[31;1mFAILED\033[0m");
755 }
756 delete Msg;
757 break;
758
759 case 1:
760
761 result |= FC_IS_NONOP;
762
763 if ( options & FC_DO_NONOP )
764 {
765 if ( m_ShellcodeManager->fileCheck(&Msg) == SCH_DONE )
766 {
767 result |= FC_IS_KNOWN;
768 printf("\033[32;1mKNOWN\033[0m");
769 } else
770 {
771 printf("\033[31;1mFAILED\033[0m");
772 }
773 } else
774 {
775 printf("NONOP");
776 }
777
778
779 delete Msg;
780 break;
781 }
782 printf("\n");
783 return result;
784 }
785
786
787 /**
788 *
789 * @param filename
790 * @param Msg
791 *
792 * @return -1 cound not open file
793 * 0 cool
794 * 1 no nop slide
795 */
fileCheck(const char * filename,Message ** Msg)796 int32_t Nepenthes::fileCheck(const char *filename, Message **Msg)
797 {
798 logPF();
799 uint32_t filesize=0;
800 unsigned char *buffer=NULL;
801 struct stat fileinfo;
802 int32_t retval = -1;
803
804 if (stat((const char*)filename,&fileinfo) != 0)
805 {
806 return -1;
807 }
808
809 filesize=fileinfo.st_size;
810 printf("%5i\t",filesize);
811 buffer = (unsigned char *)malloc(fileinfo.st_size);
812
813 FILE *f;
814 if ( (f = fopen((const char *)filename,"rb")) == NULL )
815 {
816 return -1;
817 } else
818 {
819 fread(buffer,1,filesize,f);
820 fclose(f);
821
822 uint32_t i;
823 bool nopslide=false;
824 for ( i=0;i<filesize;i++ )
825 {
826 if ( buffer[i] == 0x90 )
827 {
828 nopslide = true;
829 break;
830 }
831 }
832 if ( nopslide )
833 {
834 *Msg = new Message((char *)buffer, filesize, 0, 0, 0, 0, NULL, NULL);
835 retval = 0;
836 } else
837 {
838 *Msg = new Message((char *)buffer, filesize, 0, 0, 0, 0, NULL, NULL);
839 retval = 1;
840 }
841 }
842 free(buffer);
843 return retval;
844 }
845
846
847
848 /**
849 * get nepenthes Config
850 *
851 * @return returns pointer to nepenthes Config
852 */
getConfig()853 Config *Nepenthes::getConfig()
854 {
855 return m_Config;
856 }
857
858 /**
859 * get DownloadManager
860 *
861 * @return returns pointer to the DownloadManager
862 */
getDownloadMgr()863 DownloadManager *Nepenthes::getDownloadMgr()
864 {
865 return m_DownloadManager;
866 }
867
868 /**
869 * get EventManager
870 *
871 * @return returns EventManager
872 */
getEventMgr()873 EventManager *Nepenthes::getEventMgr()
874 {
875 return m_EventManager;
876 }
877
878 /**
879 * get LogManager
880 *
881 * @return returns LogManager
882 */
getLogMgr()883 LogManager *Nepenthes::getLogMgr()
884 {
885 return m_LogManager;
886 }
887
getLua()888 LuaInterface *Nepenthes::getLua()
889 {
890 return m_Lua;
891 }
892
893 /**
894 * get ModuleManager
895 *
896 * @return returns ModuleManager
897 */
getModuleMgr()898 ModuleManager *Nepenthes::getModuleMgr()
899 {
900 return m_ModuleManager;
901 }
902
903
904 /**
905 * get ShellcodeManager
906 *
907 * @return returns ShellcodeManager
908 */
getShellcodeMgr()909 ShellcodeManager *Nepenthes::getShellcodeMgr()
910 {
911 return m_ShellcodeManager;
912 }
913
914 /**
915 * get SocketManager
916 *
917 * @return returns SocketManager
918 */
getSocketMgr()919 SocketManager *Nepenthes::getSocketMgr()
920 {
921 return m_SocketManager;
922 }
923
924
925 /**
926 * get SubmitManager
927 *
928 * @return returns SubmitManager
929 */
getSubmitMgr()930 SubmitManager *Nepenthes::getSubmitMgr()
931 {
932 return m_SubmitManager;
933 }
934
935 /**
936 * get the famous Utilities
937 *
938 * @return returns the Utilities
939 */
getUtilities()940 Utilities *Nepenthes::getUtilities()
941 {
942 return m_Utilities;
943 }
944
945 /**
946 * get the DialogueFactoryManager
947 *
948 * @return returns the DialogueFactoryManager
949 */
getFactoryMgr()950 DialogueFactoryManager *Nepenthes::getFactoryMgr()
951 {
952 return m_DialogueFactoryManager;
953 }
954
955 /**
956 * get the DNSManager
957 *
958 * @return returns the DNSManager
959 */
getDNSMgr()960 DNSManager *Nepenthes::getDNSMgr()
961 {
962 return m_DNSManager;
963 }
964
965
966 /**
967 * get the SQLManager
968 *
969 * @return returns the SQLManager
970 */
getSQLMgr()971 SQLManager *Nepenthes::getSQLMgr()
972 {
973 return m_SQLManager;
974 }
975
976 /**
977 * stop the nepenthes
978 *
979 * @return returns true if running, else false
980 */
stop()981 bool Nepenthes::stop()
982 {
983 if(m_running)
984 {
985 m_running = false;
986 return true;
987 }
988 return false;
989 }
990
991 /**
992 * reload the config
993 *
994 * FIXME does not work
995 * exits nepenthes
996 *
997 * @return returns false
998 */
reloadConfig()999 bool Nepenthes::reloadConfig()
1000 {
1001 bool retval=true;
1002 while(retval)
1003 {
1004 retval = false;
1005 printf("no config yet\n");
1006 stop();
1007 return false;
1008 }
1009 return false;
1010 }
1011
1012
1013 /**
1014 * resolve a user to a uid_t
1015 *
1016 * @param user the username to resolve
1017 *
1018 * @return returns true on success,
1019 * else false
1020 */
changeUser(const char * user)1021 bool Nepenthes::changeUser(const char *user)
1022 {
1023 passwd * pass;
1024
1025 if (isdigit(*user) != 0)
1026 {
1027 m_UID = atoi(user);
1028 printf("User %s has uid %i\n",user,m_UID);
1029 return true;
1030 }else
1031 if ( (pass = getpwnam(user)) == NULL )
1032 {
1033 printf("Could not get userid for user '%s'\n",user);
1034 return false;
1035 }else
1036 {
1037 printf("User %s has uid %i\n",user,pass->pw_uid);
1038 m_UID = pass->pw_uid;
1039 return true;
1040 }
1041
1042 }
1043
1044
1045
1046 /**
1047 * this was intended to change the process userid
1048 *
1049 * to be *crossplattform* compatible, we had to add this shiny ifdef jungle
1050 * md said its taken from honeyd, so i guess its true
1051 *
1052 * @return true if the userid was changed successfully, else false
1053 */
changeUser()1054 bool Nepenthes::changeUser()
1055 {
1056 #ifdef HAVE_SETRESUID
1057 if ( setresuid(m_UID, m_UID, m_UID) < 0 )
1058 {
1059 logCrit("Could not set User id %i for process \n%s\n",m_UID,strerror(errno));
1060 return false;
1061 } else
1062 {
1063 logInfo("Process userid %i\n",getuid());
1064 return true;
1065 }
1066 #else
1067
1068 #ifdef HAVE_SETREUID
1069 if (setrugid(m_UID, m_UID) == -1)
1070 {
1071 logCrit("setreuid(%d) failed\n%s\n", m_UID, strerror(errno));
1072 return false;
1073 }else
1074 {
1075 logInfo("Process setreuid(%d) success\n", m_UID);
1076 }
1077 #endif
1078
1079 #ifdef HAVE_SETEUID
1080 if (seteuid(m_UID) == -1)
1081 {
1082 logCrit("seteuid(%d) failed\n%s\n", m_UID, strerror(errno));
1083 return false;
1084 }else
1085 {
1086 logInfo("Process seteuid(%d) success\n", m_UID);
1087 }
1088 #endif
1089
1090 if (setuid(m_UID) == -1)
1091 {
1092 logCrit("setuid(%d) failed\n%s\n", m_UID, strerror(errno));
1093 return false;
1094 }else
1095 {
1096 logInfo("Process setuid(%d) success\n", m_UID);
1097 }
1098 #endif // HAVE_SETRESUID
1099
1100 return true;
1101 }
1102
1103
1104 /**
1105 * resolve a groupnames gid_t
1106 *
1107 * @param gruppe the group tp resolve
1108 *
1109 * @return returns true on success, else false
1110 */
changeGroup(const char * gruppe)1111 bool Nepenthes::changeGroup(const char *gruppe)
1112 {
1113 struct group *grp;
1114
1115 if (isdigit(*gruppe) != 0)
1116 {
1117 m_GID = atoi(gruppe);
1118 printf("Group %s has gid %i\n",gruppe,m_GID);
1119 return true;
1120 }else
1121 if ( (grp = getgrnam(gruppe)) == NULL )
1122 {
1123 printf("Could not get groupid for group '%s' (%s)\n",gruppe,strerror(errno));
1124 return false;
1125 }else
1126 {
1127 printf("Group %s has gid %u\n",gruppe,grp->gr_gid);
1128 m_GID = grp->gr_gid;
1129 return true;
1130 }
1131
1132 }
1133
1134 /**
1135 * changes the process group id
1136 *
1137 * md said the ifdef jungle is taken from honeyd
1138 * maybe somebody can tell me which operatingsystem lacks setresgid()
1139 * so i can blame it for the unreadable code
1140 *
1141 * @return true if change worked, else false
1142 */
changeGroup()1143 bool Nepenthes::changeGroup()
1144 {
1145
1146
1147 #ifdef HAVE_SETRESGID
1148 if ( setresgid(m_GID, m_GID, m_GID) < 0 )
1149 {
1150 logCrit("Could not set Group id %i for process \n%s\n",m_GID,strerror(errno));
1151 return false;
1152 } else
1153 {
1154 logInfo("Process groupid %i\n",getgid());
1155 return true;
1156 }
1157 #else /* HAVE_SETRESGID */
1158
1159 #ifdef HAVE_SETGROUPS
1160 if ( setgroups(1, &m_GID) == -1 )
1161 {
1162 logCrit("setgroups(%d) failed\n%s\n", m_GID, strerror(errno));
1163 return false;
1164 }else
1165 {
1166 logInfo("Process setgroups(%d) success\n", m_GID);
1167 }
1168 #endif /* HAVE_SETGROUPS */
1169
1170 #ifdef HAVE_SETREGID
1171 if ( setregid(m_GID, m_GID) == -1 )
1172 {
1173 logCrit("setregid(%d) failed\n%s\n", m_GID, strerror(errno));
1174 return false;
1175 }else
1176 {
1177 logInfo("Process setgroups(%d) success\n", m_GID);
1178 }
1179 #endif /* HAVE_SETREGID */
1180
1181 if ( setegid(m_GID) == -1 )
1182 {
1183 logCrit("setegid(%d) failed\n%s\n", m_GID, strerror(errno));
1184 return false;
1185 }else
1186 {
1187 logInfo("Process setegid(%d) success\n", m_GID);
1188 }
1189
1190 if ( setgid(m_GID) == -1 )
1191 {
1192 logCrit("setgid(%d) failed\n%s\n", m_GID), strerror(errno);
1193 return false;
1194 }else
1195 {
1196 logInfo("Process setgid(%d) success\n", m_GID);
1197 }
1198
1199 #endif /* HAVE_SETRESGID */
1200 return true;
1201 }
1202
1203 /**
1204 * change the process root
1205 *
1206 * @param path the path to chroot() to
1207 *
1208 * @return return true on success,
1209 * else false
1210 */
changeRoot(const char * path)1211 bool Nepenthes::changeRoot(const char *path)
1212 {
1213 if ( chroot(path) < 0)
1214 {
1215 logCrit("Could not changeroot to %s \n%s\n",path,strerror(errno));
1216 return false;
1217 }else
1218 {
1219 logInfo("Changed root to %s\n",path);
1220 return true;
1221 }
1222
1223 }
1224
1225
setCapabilties()1226 bool Nepenthes::setCapabilties()
1227 {
1228 logPF();
1229
1230 #ifdef HAVE_LIBCAP
1231 // set caps
1232 cap_t caps = cap_init();
1233 cap_value_t capList[6] =
1234 {
1235 CAP_SYS_CHROOT, // chroot()
1236 CAP_NET_BIND_SERVICE, // bind() ports < 1024
1237 CAP_SETUID, // setuid()
1238 CAP_SETGID, // setgid()
1239 CAP_NET_RAW, // pcap
1240 CAP_NET_ADMIN // route
1241 };
1242
1243 unsigned num_caps = 6;
1244
1245 cap_set_flag(caps, CAP_EFFECTIVE, num_caps, capList, CAP_SET);
1246 cap_set_flag(caps, CAP_INHERITABLE, num_caps, capList, CAP_SET);
1247 cap_set_flag(caps, CAP_PERMITTED, num_caps, capList, CAP_SET);
1248
1249 if ( cap_set_proc(caps) )
1250 {
1251 cap_free(caps);
1252 logCrit("Could not set capabilities '%s'\n",strerror(errno));
1253 logCrit("Maybe you did not load the kernel module 'capability' ?\n");
1254 logCrit("Try 'modprobe capability' \n");
1255 return false;
1256 }
1257 cap_free(caps);
1258
1259 // print caps
1260 caps = cap_get_proc();
1261 ssize_t y = 0;
1262 logInfo("The process %d was given capabilities %s\n",(int) getpid(), cap_to_text(caps, &y));
1263 fflush(0);
1264 cap_free(caps);
1265
1266 return true;
1267 #else
1268 logCrit("Compiled without support for capabilities, no way to run capabilities\n");
1269 return false;
1270 #endif // HAVE_LIBCAP
1271
1272 }
1273
1274
1275
1276 /**
1277 * the signalhandler
1278 *
1279 * @param iSignal the signal we get
1280 */
SignalHandler(int32_t iSignal)1281 void SignalHandler(int32_t iSignal)
1282 {
1283 if ( g_Nepenthes != NULL )
1284 logWarn("Got signal %i ('%s')\n", iSignal,strsignal(iSignal));
1285
1286 switch ( iSignal )
1287 {
1288 case SIGHUP:
1289 if ( g_Nepenthes != NULL )
1290 {
1291 logCrit("Got SIGHUP\nRereading Config File!\n\n");
1292 g_Nepenthes->reloadConfig();
1293 }
1294 break;
1295
1296 case SIGINT:
1297 if ( g_Nepenthes != NULL )
1298 {
1299 logCrit("Got SIGINT\nStopping NOW!\n\n");
1300 g_Nepenthes->stop();
1301 }
1302 break;
1303
1304 case SIGABRT:
1305 if ( g_Nepenthes != NULL )
1306 logCrit("Unhandled Exception\n");
1307 exit(-1);
1308 break;
1309
1310 case SIGSEGV:
1311 if ( g_Nepenthes != NULL )
1312 logCrit("Segmentation Fault\n");
1313 exit(-1);
1314 break;
1315
1316 case SIGBUS:
1317 if ( g_Nepenthes != NULL )
1318 logCrit("Bus Error\n");
1319 exit(-1);
1320 break;
1321
1322 case SIGPIPE:
1323 break;
1324
1325 case SIGCHLD:
1326 break;
1327
1328
1329 default:
1330 if ( g_Nepenthes != NULL )
1331 {
1332 logCrit("Exit 'cause of %i\n", iSignal);
1333 g_Nepenthes->stop();
1334 }
1335 }
1336 }
1337
1338 /**
1339 * show the nepenthes logo
1340 */
1341 void show_logo();
1342
1343 /**
1344 * the main
1345 *
1346 * @param argc argument count
1347 * @param argv argument vector
1348 *
1349 * @return returns 0 on success
1350 */
1351 #if defined(CYGWIN) || defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(WIN32)
main(int32_t argc,char ** argv)1352 int main(int32_t argc, char **argv)
1353 {
1354
1355 // win32 signals here
1356 #else
1357 int main(int32_t argc, char **argv)
1358 {
1359
1360 /* Signal Handler Value Action Comment
1361 * -------------------------------------------------------------------------
1362 * First the signals described in the original POSIX.1 standard.
1363 */
1364 signal(SIGHUP, SignalHandler); // 1 Term Hangup detected on controlling terminal or death of controlling process
1365 signal(SIGINT, SignalHandler); // 2 Term Interrupt from keyboard
1366 signal(SIGQUIT, SignalHandler); // 3 Core Quit from keyboard
1367 signal(SIGILL, SignalHandler); // 4 Core Illegal Instruction
1368 signal(SIGABRT, SignalHandler); // 6 Core Abort signal from abort(3)
1369 signal(SIGFPE, SignalHandler); // 8 Core Floating point exception
1370 // signal(SIGKILL, SignalHandler); // 9 Term Kill signal
1371 signal(SIGSEGV, SignalHandler); // 11 Core Invalid memory reference
1372
1373 /* I hate breaking this well formatted list,
1374 * but some systems lack
1375 * MSG_NOSIGNAL as send() option and
1376 * SO_NOSIGPIPE as setsockopt() feature
1377 * So we would get sigpipe when sending data on a closed connection ...
1378 * it sucks, but we have to ignore sigpipe on such systems (f.e. OpenBSD 3.8)
1379 */
1380 #if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL)
1381 signal(SIGPIPE, SIG_IGN); // 13 Term Broken pipe: write to pipe with no readers
1382 #else
1383 signal(SIGPIPE, SignalHandler); // 13 Term Broken pipe: write to pipe with no readers
1384 #endif
1385 //
1386 signal(SIGALRM, SignalHandler); // 14 Term Timer signal from alarm(2)
1387 signal(SIGTERM, SignalHandler); // 15 Term Termination signal
1388 // signal(SIGUSR1, SignalHandler); // 30,10,16 Term User-defined signal 1
1389 // signal(SIGUSR2, SignalHandler); // 31,12,17 Term User-defined signal 2
1390 signal(SIGCHLD, SignalHandler); // 20,17,18 Ign Child stopped or terminated
1391 signal(SIGCONT, SignalHandler); // 19,18,25 Continue if stopped
1392 // signal(SIGSTOP, SIG_IGN ); // 17,19,23 Stop Stop process
1393 // signal(SIGTSTP, SIG_IGN ); // 18,20,24 Stop Stop typed at tty
1394 signal(SIGTTIN, SignalHandler); // 21,21,26 Stop tty input for background process
1395 signal(SIGTTOU, SignalHandler); // 22,22,27 Stop tty output for background process
1396
1397 /*
1398 * Next the signals not in the POSIX.1 standard but described in SUSv2 and SUSv3 / POSIX 1003.1-2001.
1399 */
1400
1401 signal(SIGBUS, SignalHandler); // 10,7,10 Core Bus error (bad memory access)
1402
1403 #ifdef HAVE_SIGPOLL
1404 signal(SIGPOLL, SignalHandler); // Term Pollable event (Sys V). Synonym of SIGIO
1405 #endif
1406 signal(SIGPROF, SignalHandler); // 27,27,29 Term Profiling timer expired
1407 signal(SIGSYS, SignalHandler); // 12,-,12 Core Bad argument to routine (SVID)
1408 signal(SIGTRAP, SignalHandler); // 5 Core Trace/breakpoint trap
1409
1410 signal(SIGURG, SignalHandler); // 16,23,21 Ign Urgent condition on socket (4.2 BSD)
1411 signal(SIGVTALRM,SignalHandler); // 26,26,28 Term Virtual alarm clock (4.2 BSD)
1412 signal(SIGXCPU, SignalHandler); // 24,24,30 Core CPU time limit exceeded (4.2 BSD)
1413 signal(SIGXFSZ, SignalHandler); // 25,25,31 Core File size limit exceeded (4.2 BSD)
1414 /*
1415 * Next various other signals.
1416 */
1417 signal(SIGIOT, SignalHandler); // 6 Core IOT trap. A synonym for SIGABRT
1418 // signal(SIGEMT, SignalHandler); // 7,-,7 Term
1419 #ifdef HAVE_SIGSTKFLT
1420 signal(SIGSTKFLT,SignalHandler); // -,16,- Term Stack fault on coprocessor (unused)
1421 #endif
1422 signal(SIGIO, SignalHandler); // 23,29,22 Term I/O now possible (4.2 BSD)
1423 #ifdef HAVE_SIGCLD
1424 signal(SIGCLD, SignalHandler); // -,-,18 Ign A synonym for SIGCHLD
1425 #endif
1426 #ifdef HAVE_SIGPWR
1427 signal(SIGPWR, SignalHandler); // 29,30,19 Term Power failure (System V)
1428 #endif
1429 #ifdef HAVE_SIGINFO
1430 signal(SIGINFO, SignalHandler); // 29,-,-
1431
1432 #endif
1433 // signal(SIGLOST, SignalHandler); // -,-,- Term File lock lost
1434 signal(SIGWINCH, SIG_IGN ); // 28,28,20 Ign Window resize signal (4.3 BSD, Sun)
1435 #ifdef HAVE_SIGUNUSED
1436 signal(SIGUNUSED,SignalHandler); // -,31,- Term Unused signal (will be SIGSYS)
1437 #endif
1438 #endif
1439
1440 Nepenthes *nepenthes = new Nepenthes();
1441 int retval = nepenthes->run(argc, argv);
1442 delete nepenthes;
1443 printf("run is done %i\n",retval);
1444 return retval;
1445 }
1446
1447 void show_logo()
1448 {
1449 puts("# #\n" \
1450 " \n" \
1451 " !�..,(' \n" \
1452 " !!..,�, \n" \
1453 " !*'.,!* \n" \
1454 " *!'.,!� \n" \
1455 " '!'.,!� \n" \
1456 " .�,',*�,,. \n" \
1457 " ,#=%(#%#%%#%%%C \n" \
1458 " .#%C=,:::::::,,5%#. \n" \
1459 " (#!!,,,,,,,,,,,J7#' \n" \
1460 " =#!(=,,,,,,,,:==(7! ,%###!##%'. \n" \
1461 " .=#(CJ3$#%C7==�((77 ,%##%%!#%%%#%* \n" \
1462 " .#(#J#A3#$==7=J=!�(=3' ,%##%%::::,,::%#%, '!(====((!,'. \n" \
1463 " ######$@53C=(����==(�=C7 %##(::::,,,,,::%##A$$3$CCJ3CJC(7C!\n" \
1464 " #(###3#'J�%J(�!!!*!!J(((=J' ,##(:::,,,,,:::%##5%C' . \n" \
1465 " .#3#3#$#. C5$C7�!=���!7=(�(7= ;##(:,,,,,,,::%###%. \n" \
1466 " '####*. 7AJC7�!7�(��!�((=7C. |###((,,,,,,,)%##%=C, .*�(7! \n" \
1467 " (%7C77!(==!�!��=7=C! ((%############%!(CC�.,�JAA%3C' \n" \
1468 " �$C7C7=�(=���((=(=J= ,:%%@M;%%;.77C7(=C!�!*!�=!�C(777J3$3=!,'. \n" \
1469 " ,%CJJ=C(7(((((=((=JC 7####::###CC=(CC=(=�(*!=!=�=7=77JJ, \n" \
1470 " .%J337J==(=7==C=C7C3,##J!::::77#%J=CJ==���=!=�===(7C7C* \n" \
1471 " C$33C3C7=7C777CJJJ%7##C:,,,,,:#$3CJC==(=7(���(=C(J$CJ* \n" \
1472 " '%$333CCC3CCCCCJ%3%#%#$C:,,,:3#AJJ3C7=JC=(((((7C7C3J3! \n" \
1473 " (#$$3JJJ%3J$J33$$AA33#5J:,,:A#$$$JC7CJCC7=(=(CJ$CJJ$, \n" \
1474 " J#%$$%33%$5$A#$%#%CJ3#A%:35#%J3$3JJCCC$C7J77JC$J33$' \n" \
1475 " .75AA%%%$AA%#A%5#%CJC#J###3#J$%3$JJCCJCC3J33$33$$A. \n" \
1476 " =5555A%AA5#5@%,%CJC3J###ACJJ$5$33JJJJJJJJ%%%3%%A% \n" \
1477 " .3@55##A5###='!AJCJJ3###ACJ3A#$$$%$$33333$%%%AA5! \n" \
1478 " %3J%5�5$J=' '533CC3###ACJ$#@A%%%AA$A%$$A%AA55� \n" \
1479 " A=(3$A'. 3A3J33###%CJ$�#AA55AA%5#AA%%5#5� \n" \
1480 " .AC=�$J 'A%$J$A##A33AA�555###55#5555#A! \n" \
1481 " *J7==A� '$%$%%##A3A=.JA###555%55##5(. \n" \
1482 " =JJJJ5' '(A5A#JA%! *=�@#%AA5553� \n" \
1483 " J$3J$$ .55A$#* .#A$A�%7* \n" \
1484 " .$33$%C %$JJ5. !3J(%�. \n" \
1485 " '%%%A$7 %CC75. C(J7( \n" \
1486 " *A%J$A= %==73 ,J7C$' \n" \
1487 " 7%$JJ@! 'A7=CC =C7CJ \n" \
1488 " $J3(3#. *$77C= %(CC( \n" \
1489 " .#33($J �7C73, '$JJC, \n" \
1490 " \n" \
1491 "# #\n" \
1492 " \n" \
1493 " Nepenthes Ampullaria \n" \
1494 " \n" \
1495 "# #\n");
1496 }
1497
1498 /**
1499 * show cli flags help
1500 *
1501 * @param defaults include default values
1502 */
1503 void show_help(bool defaults)
1504 {
1505 typedef struct
1506 {
1507 const char *m_shortOpt;
1508 const char *m_longOpt;
1509 const char *m_Description;
1510 const char *m_Default;
1511 } helpstruct;
1512
1513 helpstruct myopts[]=
1514 {
1515 {"c", "config=FILE", "use FILE as configuration file", SYSCONFDIR "/nepenthes.conf" },
1516 {"C", "capabilities", "force kernel 'security' capabilities", 0 },
1517 {"d", "disk-log", "disk logging tags, see -L", 0 },
1518 {"D", "daemonize", "run as daemon", 0 },
1519 {"f", "file-check=OPTS", "check file for known shellcode, OPTS can\n"
1520 " be any combination of `rmknown' and\n"
1521 " `rmnonop'; seperate by comma when needed", 0 },
1522 {"h", "help", "display help", 0 },
1523 {"H", "large-help", "display help with default values", 0 },
1524 {"i", "info", "how to contact us", 0 },
1525 {"k", "check-config", "check configuration file for syntax errors", 0 },
1526 {"l", "log", "console logging tags, see -L", 0 },
1527 {"L", "logging-help", "display help for -d and -l", 0 },
1528 {"o", "color=WHEN", "control color usage. WHEN may be `never',\n"
1529 " `always' or `auto'", "`auto'" },
1530 {"r", "chroot=DIR", "chroot to DIR after startup", "don't chroot" },
1531 {"R", "ringlog", "use ringlogger instead of filelogger", "filelogger" },
1532 {"u", "user=USER", "switch to USER after startup", "keep current user"},
1533 {"g", "group=GROUP", "switch to GROUP after startup (use with -u)", "keep current group"},
1534 {"V", "version", "show version", "" },
1535 {"w", "workingdir=DIR", "set the process' working dir to DIR", PREFIX },
1536 };
1537 show_version();
1538
1539 for ( uint32_t i=0;i<sizeof(myopts)/sizeof(helpstruct);i++ )
1540 {
1541 printf(" -%s, --%-19s %s\n", myopts[i].m_shortOpt,
1542 myopts[i].m_longOpt,
1543 myopts[i].m_Description);
1544
1545 if( defaults == true && myopts[i].m_Default )
1546 {
1547 printf(" Default value/behaviour: %s\n", myopts[i].m_Default);
1548 }
1549 }
1550 }
1551
1552
1553 #if defined(__GNUG__)
1554 #define MY_COMPILER "g++"
1555 /*
1556 #if ( __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ <= 2 ) // g++ 4 detection
1557 #error "MAKE SURE TO READ THIS"
1558 #error "g++ 4 has bugs, dont use it"
1559 #error "nepenthes would compile using g++4, but it will segfault while running"
1560 #error "refer to http://nepenthes.sourceforge.net/documentation:readme:faq:gcc_4 for more information"
1561 #error "if you got no other compiler feel free to remove this section by commenting it out"
1562 #error "but don't complain when it does not work"
1563 #error "you can find it in Nepenthes.cpp around line 1569, just search for 'g++ 4 detection'"
1564 #endif
1565 */
1566 #elif defined(__CYGWIN__)
1567 #define MY_COMPILER "cygwin"
1568 #else
1569 #define MY_COMPILER "unknown Compiler"
1570 #endif
1571
1572
1573 #if defined(__FreeBSD__)
1574 # define MY_OS "FreeBSD"
1575 #elif defined(linux) || defined (__linux)
1576 # define MY_OS "Linux"
1577 #elif defined (__MACOSX__) || defined (__APPLE__)
1578 # define MY_OS "Mac OS X"
1579 #elif defined(__NetBSD__)
1580 # define MY_OS "NetBSD"
1581 #elif defined(__OpenBSD__)
1582 # define MY_OS "OpenBSD"
1583 #elif defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
1584 # define MY_OS "Windows"
1585 #elif defined(CYGWIN)
1586 # define MY_OS "Cygwin\Windows"
1587 #else
1588 # define MY_OS "Unknown OS"
1589 #endif
1590
1591
1592 #if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
1593 # define MY_ARCH "Alpha"
1594 #elif defined(__arm__)
1595 # if defined(__ARMEB__)
1596 # define MY_ARCH "ARMeb"
1597 # else
1598 # define MY_ARCH "ARM"
1599 # endif
1600 #elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL)
1601 # define MY_ARCH "x86"
1602 #elif defined(__x86_64__) || defined(__amd64__)
1603 # define MY_ARCH "x86_64"
1604 #elif defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(_M_IA64)
1605 # define MY_ARCH "Intel Architecture-64"
1606 #elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
1607 # if defined(__mips32__) || defined(__mips32)
1608 # define MY_ARCH "MIPS32"
1609 # else
1610 # define MY_ARCH "MIPS"
1611 # endif
1612 #elif defined(__hppa__) || defined(__hppa)
1613 # define MY_ARCH "PA RISC"
1614 #elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || defined(__PPC) || defined(__PPC__)
1615 # define MY_ARCH "PowerPC"
1616 #elif defined(__THW_RS6000) || defined(_IBMR2) || defined(_POWER) || defined(_ARCH_PWR) || defined(_ARCH_PWR2)
1617 # define MY_ARCH "RS/6000"
1618 #elif defined(__sparc__) || defined(sparc) || defined(__sparc)
1619 # define MY_ARCH "SPARC"
1620 #else
1621 # define MY_ARCH "Unknown Architecture"
1622 #endif
1623
1624 void show_loghelp()
1625 {
1626 show_info();
1627 printf("\nAll Nepenthes log messages have certain tags.\n");
1628 printf("You can specify filter rules with -d and -l\n");
1629 printf("with a filter string. A filter string is a set of\n");
1630 printf("tags seperated by comma. A message needs to have at\n");
1631 printf("least one tag of the filter string you specify, i.e.\n");
1632 printf("bin/nepenthes -l \"foo,bar\" would require either `foo' or\n");
1633 printf("`bar' to appear within the log message. Messages\n");
1634 printf("which don't have one of these tags will be discarded.\n");
1635 }
1636
1637 /**
1638 * show version
1639 */
1640 void show_version()
1641 {
1642 struct utsname sysinfo;
1643 int i = uname(&sysinfo);
1644
1645 printf("\n");
1646 printf("Nepenthes Version %s \n",VERSION);
1647 printf("Compiled on %s/%s at %s %s with %s %s \n",MY_OS,MY_ARCH,__DATE__, __TIME__,MY_COMPILER,__VERSION__);
1648
1649 if (i == 0)
1650 {
1651 printf("Started on %s running %s/%s release %s\n",
1652 sysinfo.nodename,
1653 sysinfo.sysname,
1654 sysinfo.machine,
1655 sysinfo.release
1656 );
1657 }
1658
1659 printf("\n");
1660 }
1661
1662 /**
1663 * show compiling info
1664 */
1665 void show_info()
1666 {
1667 show_version();
1668 printf("Copyright (C) 2005 Paul Baecher & Markus Koetter\n");
1669 printf("Contact:\tnepenthesdev@users.sourceforge.net\n");
1670 printf("\t\thttp://nepenthes.sourceforge.net\n");
1671 }
1672
1673