⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 conf.c

📁 Firestorm NIDS是一个性能非常高的网络入侵检测系统 (NIDS)。目前
💻 C
字号:
/* * This file is part of Firestorm NIDS * Copyright (c) 2002 Gianni Tedesco * This program is released under the terms of the GNU GPL version 2 * * This file reads in the configuration file and sets up all of * the enviroment for the firestorm NIDS sensor to run. Default * settings try to be as secure as possible, we are quite strict * if you want to configure firestorm in an obviously insecure * way, you can recompile with checks removed. * * TODO *  o preserve filename/line number for error messages */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include <firestorm.h>#include <args.h>#include <cleanup.h>#include <loader.h>#include <packet.h>#include <alert.h>#include <signature.h>#include <preproc.h>#include <decode.h>#include <capture.h>#include <target.h>#include <matcher.h>#include <parser.h>#include <conf.h>#ifndef _BSD_SOURCE#define _BSD_SOURCE#endif#include <grp.h>/* limited by AVAL_SIZE in most cases anyway */#define CONF_MAXLEN 1024struct conf {	struct conf *next;	char *data;};struct conf *cnf_plugins=NULL, *cnf_plugins_tail=NULL;struct conf *cnf_plugin=NULL, *cnf_plugin_tail=NULL;struct conf *cnf_preproc=NULL, *cnf_preproc_tail=NULL;struct conf *cnf_sig=NULL, *cnf_sig_tail=NULL;unsigned int f_uid=0;unsigned int f_gid=0;unsigned int do_chroot=1;char *root_dir=NULL;char *output_line=NULL;char *cap_line=NULL;char *logfile=NULL;/* Callbacks that can only be called once */int conf_rootfn(struct arg *a, void *u){	if ( root_dir ) return 0;	return ( (root_dir=strdup(a->val.v_str))!=NULL );}int conf_outputfn(struct arg *a, void *u){	if ( output_line ) return 0;	return ( (output_line=strdup(a->val.v_str))!=NULL );}int conf_capfn(struct arg *a, void *u){	if ( cap_line ) return 0;	return ( (cap_line=strdup(a->val.v_str))!=NULL );}int conf_logfile(struct arg *a, void *u){	if ( logfile ) return 0;	return ( (logfile=strdup(a->val.v_str))!=NULL );}/* Add a line to a list of lines */int conf_addline(struct conf **head, struct conf **tail, char *str){	struct conf *c;	if ( !(c=calloc(1, sizeof(*c))) )		cperror("calloc");	if ( !(c->data=strdup(str)) )		cperror("strdup");	if ( !(*head) )  {		(*head)=c;		(*tail)=c;	}else{		(*tail)->next=c;		(*tail)=c;	}	return 1;}/* Callbacks that can be called multiple times */int conf_plugins(struct arg *a, void *u){	return conf_addline(&cnf_plugins, &cnf_plugins_tail, a->val.v_str);}int conf_plugin(struct arg *a, void *u){	return conf_addline(&cnf_plugin, &cnf_plugin_tail, a->val.v_str);}int conf_preproc(struct arg *a, void *u){	return conf_addline(&cnf_preproc, &cnf_preproc_tail, a->val.v_str);}int conf_sig(struct arg *a, void *u){	return conf_addline(&cnf_sig, &cnf_sig_tail, a->val.v_str);}struct arg firestorm_args[]={	{"effective_uid", ARGTYPE_PUINT, NULL, {.vp_uint=&f_uid}},	{"effective_gid", ARGTYPE_PUINT, NULL, {.vp_uint=&f_gid}},	{"chroot", ARGTYPE_PBOOL, NULL, {.vp_bool=&do_chroot}},	{"firestorm_root", ARGTYPE_STRING, conf_rootfn},	{"capture", ARGTYPE_STRING, conf_capfn},	{"output", ARGTYPE_STRING, conf_outputfn},	{"logfile", ARGTYPE_STRING, conf_logfile},	{"load_plugins", ARGTYPE_STRING, conf_plugins},	{"load_plugin", ARGTYPE_STRING, conf_plugin},	{"preprocessor", ARGTYPE_STRING, conf_preproc},	{"signatures", ARGTYPE_STRING, conf_sig},	{NULL,ARGTYPE_NOP,NULL}};/* Perform initial file descriptor tweaks */void conf_tweak_fds(){	int fds=sysconf(_SC_OPEN_MAX);	while(fds>2) close(fds--);	if ( (fds=open("/dev/null", O_RDWR))<0 ) {		cleanup(EXIT_ERR, "/dev/null: open(): %s", get_err());	}	/* Make stdin and stderr be /dev/null */	if ( fds!=0 && dup2(fds,0)<0 )		cleanup(EXIT_ERR, "stdin: dup2(): %s", get_err());	if ( fds!=2 && dup2(fds,2)<0 )		cleanup(EXIT_ERR, "stderr: dup2(): %s", get_err());	if ( fds>2 ) close(fds);}/* Open the config file, we need to do some funky stuff */FILE *conf_open(char *fn){	int fd;	FILE *ret;	if ( (fd=open(fn, O_RDONLY))<0 ) {		cleanup(EXIT_ERR, "%s: open(): %s", fn, get_err());	}	/* If we were opened with stdout closed the config	 * could end up as fd1, that kinda sucks because when	 * we close it, some other bit of code may open fd1 as	 * writable! printing to stdout would then corrupt the	 * file - I know we are never setuid but better to be safe */	if ( fd==1 ) {		/* We know fd3 is closed already */		if ( dup2(fd, 3)<0 )			cleanup(EXIT_ERR, "%s: dup2(): %s", fn, get_err());		/* We know stdin is /dev/null, make it stdout too */		if ( dup2(0, 1)<0 )			cleanup(EXIT_ERR, "stdout: dup2(): %s", get_err());	}	/* Open for stdio */	if ( !(ret=fdopen(fd, "r")) ) {		cleanup(EXIT_ERR, "%s: fdopen(): %s", fn, get_err());	}	return ret;}/* Go in to the background (properly damnit) */void conf_background(void){	switch(fork()) {		case 0: break;		case -1:			cleanup(EXIT_ERR, "fork(): %s", get_err());		default: _exit(0);	}	/* This is so that we can't re-aquire a controlling terminal */	if (setsid()<0) {		cleanup(EXIT_ERR, "setsid(): %s", get_err());	}	switch(fork()) {		case 0: break;		case -1:			cleanup(EXIT_ERR, "fork(): %s", get_err());		default: _exit(0);	}}/* Parse a line */int conf_line(char *buf, char *fn, int line){	char *cur;	int state=0;	char *val=NULL;	for(cur=buf; *cur!=0 && *cur!='\r' && *cur!='\n'; cur++) {		switch(state) {		case 2:			continue;		case 0:			if ( isspace(*cur) ) {				state=1;				*cur=0;			}			break;		case 1:			if ( !isspace(*cur) ) {				val=cur;				state=2;			}			break;		}	}	if ( *cur==0 ) {		cleanup(EXIT_ERR, "%s:%i: line limit is %u characters",			fn, line, CONF_MAXLEN);	}else *cur=0;	if ( arg_found(firestorm_args, buf,		strlen(buf), val, strlen(val), NULL)<=0 ) {		return -1;	}	return 0;}/* Parse the whole file */void conf_read(char *fn, FILE *f){	char buf[CONF_MAXLEN];	int line=0;	while(fgets(buf, sizeof(buf), f)) {		char *p=buf;		line++;		while( *p && isspace(*p) ) p++;		if ( *p==0 || *p=='#' ) continue;		if ( conf_line(buf, fn, line) ) {			fclose(f);			cleanup(EXIT_ERR, "%s:%i: parse error", fn, line);		}	}	fclose(f);	return;}/* Split a string in two by whitespace */char *conf_split_once(char *l){	int state=0;	char *a;	for(a=l; *a; a++) {		switch (state) {		case 0:			if ( isspace(*a) ) {				*a=0;				state=1;			}			break;		case 1:			if ( !isspace(*a) ) goto done;			break;		}	}done:	return a;}/* parse a preproc line and add it */void conf_do_preproc(char *d){	char *a;	a=conf_split_once(d);	if ( !preproc_setup(d, a) ) {		cleanup(EXIT_ERR, "cannot find preproc: %s", d);	}}/* parse a signature line and add it */void conf_do_sig(char *d){	char *a;	a=conf_split_once(d);	if ( !parser_setup(d, a) ) {		cleanup(EXIT_ERR, "%s: error loading %s signatures", a, d);	}}/* parse the capture line, and set it all up */void conf_capture(void){	char *a;	a=conf_split_once(cap_line);	/* this will call cleanup() if it fails */	capture_setup(cap_line, a);	free(cap_line);}/* Perform firestorm sensor configuration */void conf_go(char *fn){	struct conf *c;	uid_t init_uid=geteuid(); /* cant fail */	/* If you want to do something this stupid then you	 * will have to recompile the code - i wont help you	 */	if ( init_uid != getuid() )		cleanup(EXIT_ERR, "SUID is for dumb ass motherfuckers");	conf_tweak_fds();	conf_read(fn, conf_open(fn));	/* Check there actually was even a capture line in the config */	if ( !cap_line )		cleanup(EXIT_ERR, "no captures specified!");	/* Change to root directory */	if ( root_dir ) {	       	if ( chdir(root_dir) )			cleanup(EXIT_ERR, "%s: chdir(): %s",				root_dir, get_err());		free(root_dir);	}else{		/* by default change to root, that way firestorm		 * wont stop the administrator unmounting whatever		 * filesystem we were run inside of */		if ( chdir("/") )			cleanup(EXIT_ERR, "/: chdir(): %s", get_err());	}	/* load plugins from directories */	while(cnf_plugins) {		c=cnf_plugins;		cnf_plugins=c->next;		loader_load_dir(c->data);		free(c->data);		free(c);	}	/* load individual plugin files */	while(cnf_plugin) {		c=cnf_plugin;		cnf_plugin=c->next;		if ( !loader_load(c->data) ) {			cleanup(EXIT_ERR, "unable to load a plugin", c->data);		}		free(c->data);		free(c);	}	/* Load in the actual objects that we want */	decode_load();	capdev_load();	matcher_load();	preproc_load();	parser_load();	/* chroot (properly damnit) */	if ( do_chroot && init_uid ) {		mesg(M_WARN, "cannot chroot, no privileges");	}else if ( do_chroot && chroot(".") ) {		cleanup(EXIT_ERR, "chroot(): %s", get_err());	}	/* Initialise capture */	conf_capture();	/* Drop privileges (properly damnit) */	if ( !init_uid ) {		if ( !f_gid || !f_uid ) 			cleanup(EXIT_ERR,				"running as root is seriously stupid");		if ( setgroups(1,&f_gid) || setgid(f_gid) ) {			cleanup(EXIT_ERR, "unable to drop gid to %u: %s",				f_gid, get_err());		}		if ( setuid(f_uid) ) {			cleanup(EXIT_ERR, "unable to drop uid to %u: %s",				f_uid, get_err());		}	}	/* open alert output file */	if ( !output_line )		cleanup(EXIT_ERR, "no output options specified");	alert_conf_hook(output_line);	free(output_line);	/* initialise preprocessors */	while(cnf_preproc) {		c=cnf_preproc;		cnf_preproc=c->next;		conf_do_preproc(c->data);		free(c->data);		free(c);	}	/* load signatures */	while(cnf_sig) {		c=cnf_sig;		cnf_sig=c->next;		conf_do_sig(c->data);		free(c->data);		free(c);	}	/* sort out mesg() output */	mesg_logfile(logfile);	if ( logfile ) {		/* Daemonize (properly damnit) */		conf_background();	}	/* Actually open alert log etc.. */	alert_conf_go();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -