📄 snort.c
字号:
#include <stdlib.h>#include <stdio.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <sys/unistd.h>#include <string.h>#include <firestorm.h>#include <args.h>#include <strtouint.h>#include <plugin.h>#include <cleanup.h>#include <packet.h>#include <alert.h>#include <signature.h>#include <parser.h>PLUGIN_STD_DEFS();/* Snort rulefile parser * Genrally the parsing is done with turing state machines, * It isn't _too_ hacky. * * TODO: * Full snort variable support * Multi-line support *//* Quick inline utility functions */static char wspace_map[256];#define terminator(x) (wspace_map[(unsigned char)x]==2)#define whitespace(x) (wspace_map[(unsigned char)x]==1)/* Maximum line length */#define SNORT_MAXLEN 8192/* Stuff we import */proc_sig_rule signature_rule;proc_sig_abort signature_abort;proc_sig_criteria signature_criteria;proc_sig_modifier signature_modifier;proc_sig_alert signature_alert;proc_sig_commit signature_commit;/* Snort variables */struct snort_var { struct snort_var *next; char *name; char *value; int negate;};struct snort_var *vars=NULL;struct snort_class { struct snort_class *next; char *name; u_int8_t prio;};struct snort_class *c_list=NULL;int snort_line(char *, int, char *);int snort_var(char *, int, char *);int snort_config(char *, int, char *);/* Snort keywords */struct skw{ char *name; int (*fn)(char *, int, char *);};struct skw snort_keywords[]={ {"alert", snort_line}, {"log", snort_line},#if 0 {"activate", NULL}, {"dynamic", NULL}, {"pass", NULL},#endif {"config", snort_config}, {"var", snort_var}, {NULL, NULL}};/* Snort parsing variables */#define SNORT_PROTO 0#define SNORT_SADDR 1#define SNORT_SPORT 2#define SNORT_DIR 3#define SNORT_DADDR 4#define SNORT_DPORT 5#define SNORT_MAX 6char *snort_head[SNORT_MAX];int snort_negate[SNORT_MAX];struct criteria *se_head;struct criteria *src_additional;struct criteria *dst_additional;char *snort_msg;unsigned long snort_rate;unsigned long snort_burst;u_int32_t snort_prio;u_int32_t snort_prio_set;u_int32_t snort_sid, snort_rev;/* These are modifiers */char *snort_modifiers[]={ "nocase", "offset", "depth", "regex", NULL};/* Not implemented hacks */char *snort_hacks[]={ "reference", "logto", NULL};int snort_commit_rule(int index);int snort_iplist(int index);struct { int var; int(*fn)(int);}steps[]={ {SNORT_SADDR, snort_iplist}, {SNORT_DADDR, snort_iplist}, {0, snort_commit_rule},};/* Error string */#define ELEN 128char estr[ELEN];void cleanup_additional(struct criteria *x){ struct criteria *s; for(s=x; s; ) { struct criteria *tmp=s; s=s->next; if ( tmp->args ) free(tmp->args); free(tmp); }}struct snort_var *snort_var_find(char *key){ struct snort_var *ret; for(ret=vars; ret; ret=ret->next) { if ( !strcmp(key, ret->name) ) return ret; } snprintf(estr, ELEN, "snort var not found: $%s", key); return NULL;}struct snort_class *snort_class_find(char *key){ struct snort_class *ret; for(ret=c_list; ret; ret=ret->next) { if ( !strcmp(key, ret->name) ) return ret; } return NULL;}int snort_parse_rate(char *str){ unsigned int num; unsigned int d; int i; if ( (i=strtouint(str,&num))<0 ) goto err; if ( i ) { str+=i; if ( *str++ != '/' ) goto err; switch ( *str ) { case 's': case 'S': d = RATE_SEC; break; case 'm': case 'M': d = RATE_MIN; break; case 'h': case 'H': d = RATE_HR; break; case 'd': case 'D': d = RATE_DAY; break; default: goto err; } }else{ /* Seconds is the default */ d = RATE_SEC; } if ( num>d ) { snprintf(estr,ELEN,"maximum granularity is 100/sec: %s", str); return 0; } snort_rate=d/num; return 1;err: snprintf(estr,ELEN,"rate parse error for '%s'", str); return 0;}int snort_addcrit(char *key, char *val, int negate){ int i; struct criteria *se; /* Snatch alert meta-data */ if ( !strcmp(key, "msg") ) { snort_msg=val; return 1; } if ( !strcmp(key, "sid") ) { if ( strtouint(val, &snort_sid) ) { snprintf(estr,ELEN,"invalid sid '%s'", val); return 0; } return 1; } if ( !strcmp(key, "rev") ) { if ( strtouint(val, &snort_rev) ) { snprintf(estr,ELEN,"invalid rev '%s'", val); return 0; } return 1; } if ( !strcmp(key, "priority") ) { if ( strtouint(val, &snort_prio) ) { snprintf(estr,ELEN,"invalid priority '%s'", val); return 0; } if ( snort_prio & ~0xffUL ) { snprintf(estr,ELEN,"priority is out of range (0-255)"); return 0; } snort_prio_set=1; return 1; } if ( !strcmp(key, "classtype") ) { struct snort_class *c; if ( !(c=snort_class_find(val)) ) { snprintf(estr,ELEN,"Unknown classtype '%s'", val); return 0; } if ( !snort_prio_set ) snort_prio=c->prio; return 1; } /* Rate limtiing */ if ( !strcmp(key, "rate") ) { return snort_parse_rate(val); } if ( !strcmp(key, "burst") ) { if ( strtouint(val, (unsigned int *)&snort_burst) ) { snprintf(estr,ELEN,"invalid burst '%s'", val); return 0; } return 1; } for(i=0; snort_hacks[i]; i++) { if ( !strcmp(key, snort_hacks[i]) ) return 1; } /* Modifier options */ for(i=0; snort_modifiers[i]; i++) { if ( !strcmp(key, snort_modifiers[i]) ) { if ( !se_head ) return 0; if ( !(se=calloc(1, sizeof(*se))) ) return 0; se->crit=key; se->args=val; se->negate=negate; se->next=se_head->modifier; se_head->modifier=se; return 1; } } if ( !(se=calloc(1, sizeof(*se))) ) { return 0; } se->next=NULL; se->crit=key; se->args=val; se->negate=negate; se->next=se_head; se_head=se; return 1;}/* Parse the body of a snort rule (the bit after the bracket) */#define zero_body() key=NULL; val=NULL; neg=0; state=0;int snort_parse_body(char *line){ char *key=NULL; char *val=NULL; int neg=0; char *cur; int state=0; int inq=0; int esc=0; /* Snort state machine parser */ for(cur=line; ; cur++) { if ( terminator(*cur) ) break; if ( state==0 ) { /* Anywhere */ if ( !whitespace(*cur) ) { key=cur; state=1; }else if ( *cur==')' ) { *cur='\0'; break; } }else if ( state==1 ) { /* Inside a key */ if ( *cur==':' ) { *cur='\0'; state=2; }else if ( *cur==';' && *(cur-1)!='\\' ) { *cur='\0'; val=NULL; if ( !snort_addcrit(key, val, neg) ) return 0; zero_body(); } }else if ( state==2 ) { /* Between key and value */ if ( *cur=='!' ) { neg=1; }else if ( !whitespace(*cur) ) { if ( *cur=='\"' ) { inq=1; } val=cur + inq; state=3; } }else if ( state==3 ) { /* In a value */ /* Enter quote marks */ if ( !inq && *cur=='\"' ) { inq=1; continue; } /* Allow missing end semicolon */ if ( !inq && *cur==')' ) { if ( *(cur-1)=='\"' ) *(cur-1)='\0'; *cur='\0'; if ( !snort_addcrit(key, val, neg) ) return 0; zero_body(); continue; } /* Check for escape chars */ if ( !esc && *cur=='\\' ) { esc=1; continue; } if ( inq && !esc && *cur=='\"' ) { /* End quotes */ inq=0; }else if ( !inq && !esc && *cur==';' ) { /* End */ if ( *(cur-1)=='\"' ) *(cur-1)='\0'; *cur='\0'; if ( !snort_addcrit(key, val, neg) ) return 0; zero_body(); }else{ esc=0; } } } return 1;}/* Actually commit a rule into the signature * subsystem */int snort_commit_rule(int index){ struct criteria *s, *m; struct rule *r; /* Create a new rule */ if ( !(r=signature_rule(snort_head[SNORT_PROTO])) ) { snprintf(estr, ELEN, "Unable to create new '%s' rule", snort_head[SNORT_PROTO]); return 0; } /* Alert stuff. Just use default alerting mechanism */ if ( !snort_sid ) mesg(M_WARN,"snort: rule has no sid: %s", snort_msg); if ( !signature_alert(r, snort_msg, snort_sid, snort_rev, snort_rate, snort_burst, (u_int8_t)snort_prio&0xff) ) { snprintf(estr, ELEN, "Unable to set rule target"); goto abort; } /* Source and destination addresses */ if ( strcmp(snort_head[SNORT_SADDR], "any") && !signature_criteria(r, snort_negate[SNORT_SADDR], "src", snort_head[SNORT_SADDR]) ){ snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } if ( strcmp(snort_head[SNORT_DADDR], "any") && !signature_criteria(r, snort_negate[SNORT_DADDR], "dst", snort_head[SNORT_DADDR]) ){ snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } /* Ports */ if ( strcmp(snort_head[SNORT_SPORT], "any") ) { if ( !signature_criteria(r, snort_negate[SNORT_SPORT], "sport", snort_head[SNORT_SPORT]) ) { snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } } if ( strcmp(snort_head[SNORT_DPORT], "any") ) { if ( !signature_criteria(r, snort_negate[SNORT_DPORT], "dport", snort_head[SNORT_DPORT]) ) { snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } } /* Additional source and destination addresses */ for(s=src_additional; s; s=s->next) { if ( !signature_criteria(r, s->negate, "src", s->args) ){ snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } } for(s=dst_additional; s; s=s->next) { if ( !signature_criteria(r, s->negate, "dst", s->args) ){ snprintf(estr, ELEN, "Unable add head criteria to rule"); goto abort; } } /* And all the options... */ for(s=se_head; s; s=s->next) { if ( !signature_criteria(r, s->negate, s->crit, s->args) ) { goto abort2; } for(m=s->modifier; m; m=m->next) { if ( !signature_modifier(r, m->negate, m->crit, m->args) ) { goto abort2; } } } /* lets go */ if ( !signature_commit(r) ) { snprintf(estr, ELEN, "Rule failed to commit: %s", snort_msg); goto abort; } return 1;abort2: snprintf(estr, ELEN, "Unable add '%s' to rule", s->crit);abort: signature_abort(r); return 0;}int snort_iplist(int index){ char buf[128]; char *cur, *ip, *tmp; size_t len=1; int ret=1; int i=steps[index++].var; struct criteria **additional; if ( snort_head[i][0]!='[' ) return steps[index].fn(index); if ( i==SNORT_SADDR ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -