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