diff --git a/base/network.c b/base/network.c index b44b8a2..fbbbbf0 100644 --- a/base/network.c +++ b/base/network.c @@ -86,17 +86,22 @@ int network_handler_create(mod,handlerp) _status=0; abort: if(_status){ - network_handler_destroy(&handler); + network_handler_destroy(mod, &handler); } return(_status); } -int network_handler_destroy(handlerp) +int network_handler_destroy(mod,handlerp) + proto_mod *mod; n_handler **handlerp; { + n_handler *handler=0; if(!handlerp || !*handlerp) return(0); + handler = *handlerp; + + mod->vtbl->destroy_ctx(mod->handle,&handler->ctx); free(*handlerp); *handlerp=0; return(0); @@ -121,6 +126,12 @@ int network_process_packet(handler,timestamp,data,length) p.len=length; p.ip=(struct ip *)data; + if(p.len < 20) { + if(!(NET_print_flags & NET_PRINT_JSON)) + printf("Malformed packet, packet too small to contain IP header, skipping ...\n"); + return(0); + } + /*Handle, or rather mishandle, fragmentation*/ off=ntohs(p.ip->ip_off); diff --git a/base/network.h b/base/network.h index 2a21635..65cbb1c 100644 --- a/base/network.h +++ b/base/network.h @@ -75,7 +75,7 @@ typedef struct packet_ packet; int network_handler_create PROTO_LIST((proto_mod *mod, n_handler **handlerp)); -int network_handler_destroy PROTO_LIST((n_handler **handlerp)); +int network_handler_destroy PROTO_LIST((proto_mod *mod,n_handler **handlerp)); int network_process_packet PROTO_LIST((n_handler *handler, struct timeval *timestamp,UCHAR *data,int length)); int packet_copy PROTO_LIST((packet *in,packet **out)); diff --git a/base/pcap-snoop.c b/base/pcap-snoop.c index 804b93c..5901e8b 100644 --- a/base/pcap-snoop.c +++ b/base/pcap-snoop.c @@ -127,6 +127,9 @@ int print_version() } pcap_t *p; +proto_mod *mod=&ssl_mod; +n_handler *n; +char *interface_name=0; void sig_handler(int sig) { int freed_conn = 0; @@ -138,8 +141,13 @@ void sig_handler(int sig) if(freed_conn && !(NET_print_flags & NET_PRINT_JSON)) printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn); + network_handler_destroy(mod, &n); + if(p) pcap_close(p); + if(interface_name) + free(interface_name); + exit(0); } @@ -168,6 +176,12 @@ void pcap_cb(ptr,hdr,data) len-=4; break; case DLT_EN10MB: + if(len < sizeof(struct ether_header)) { + if(!(NET_print_flags & NET_PRINT_JSON)) + printf("Frame size too small to contain Ethernet header, skipping ...\n"); + return; + } + type=ntohs(e_hdr->ether_type); data+=sizeof(struct ether_header); @@ -287,7 +301,6 @@ int main(argc,argv) char **argv; { int r; - n_handler *n; #ifdef _WIN32 __declspec(dllimport) char *optarg; __declspec(dllimport) int optind; @@ -296,10 +309,8 @@ int main(argc,argv) extern int optind; #endif pcap_if_t *interfaces; - char *interface_name=0; char *file=0; char *filter=0; - proto_mod *mod=&ssl_mod; bpf_u_int32 localnet,netmask; int c; module_def *m=0; @@ -493,6 +504,7 @@ int main(argc,argv) if(freed_conn && !(NET_print_flags & NET_PRINT_JSON)) printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn); + network_handler_destroy(mod, &n); pcap_close(p); free(n); diff --git a/base/proto_mod.h b/base/proto_mod.h index 8dddaaf..db5502a 100644 --- a/base/proto_mod.h +++ b/base/proto_mod.h @@ -62,6 +62,7 @@ struct proto_mod_vtbl_ { proto_obj **objp, struct in_addr *i_addr,u_short i_port, struct in_addr *r_addr,u_short r_port,struct timeval *time_base)); + int (*destroy_ctx) PROTO_LIST((void *handle,proto_ctx **ctxp)); int (*destroy) PROTO_LIST((proto_obj **objp)); int (*data) PROTO_LIST((proto_obj *obj,segment *data,int direction)); int (*close) PROTO_LIST((proto_obj *obj,packet *p,int direction)); diff --git a/base/tcppack.c b/base/tcppack.c index 330d366..f44777f 100644 --- a/base/tcppack.c +++ b/base/tcppack.c @@ -241,8 +241,7 @@ static int process_data_segment(conn,handler,p,stream,direction) l=p->len - p->tcp->th_off * 4; if(l < 0) { - if(!(NET_print_flags & NET_PRINT_JSON)) - printf("Malformed packet, computed TCP segment size is negative, skipping ...\n"); + fprintf(stderr,"Malformed packet, computed TCP segment size is negative, skipping ...\n"); return(0); } diff --git a/common/lib/r_assoc.c b/common/lib/r_assoc.c index 6a2393d..0e9e16e 100644 --- a/common/lib/r_assoc.c +++ b/common/lib/r_assoc.c @@ -121,6 +121,9 @@ int r_assoc_destroy(assocp) for(i=0;isize;i++) destroy_assoc_chain(assoc->chains[i]); + free(assoc->chains); + free(assoc); + return(0); } diff --git a/configure.ac b/configure.ac index 2101fdb..9321d8f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([ssldump], [1.1]) +AC_INIT([ssldump], [1.3]) AM_INIT_AUTOMAKE([subdir-objects]) AC_CONFIG_SRCDIR([base/pcap-snoop.c]) AC_CONFIG_HEADERS([config.h]) diff --git a/ssl/ssl.enums.c b/ssl/ssl.enums.c index 4a76035..f3f4dea 100644 --- a/ssl/ssl.enums.c +++ b/ssl/ssl.enums.c @@ -2969,6 +2969,7 @@ static int decode_server_name_type_host_name(ssl,dir,seg,data) if (server_name != NULL) { if (ssl->server_name) free(ssl->server_name); + if (l > data->len) l = data->len; memcpy(server_name,data->data,l); ssl->server_name = server_name; } diff --git a/ssl/ssl_analyze.c b/ssl/ssl_analyze.c index 2dda2ab..7184736 100644 --- a/ssl/ssl_analyze.c +++ b/ssl/ssl_analyze.c @@ -61,6 +61,7 @@ static int create_ssl_analyzer PROTO_LIST((void *handle, proto_ctx *ctx,tcp_conn *conn,proto_obj **objp, struct in_addr *i_addr,u_short i_port, struct in_addr *r_addr,u_short r_port, struct timeval *base_time)); +static int destroy_ssl_ctx PROTO_LIST((void *handle,proto_ctx **ctxp)); static int destroy_ssl_analyzer PROTO_LIST((proto_obj **objp)); static int read_ssl_record PROTO_LIST((ssl_obj *obj,r_queue *q,segment *seg, int offset,segment **lastp,int *offsetp)); @@ -228,6 +229,16 @@ static int create_ssl_ctx(handle,ctxp) return(_status); } +static int destroy_ssl_ctx(handle,ctxp) + void *handle; + proto_ctx **ctxp; + { + ssl_decode_ctx *ctx=0; + ctx=(ssl_decode_ctx *) *ctxp; + ssl_decode_ctx_destroy(&ctx); + return 0; + } + static int create_ssl_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn, proto_obj **objp, struct in_addr *i_addr, u_short i_port, struct in_addr *r_addr, u_short r_port, struct timeval *base_time) @@ -635,6 +646,7 @@ static struct proto_mod_vtbl_ ssl_vtbl ={ parse_ssl_flag, create_ssl_ctx, create_ssl_analyzer, + destroy_ssl_ctx, destroy_ssl_analyzer, data_ssl_analyzer, close_ssl_analyzer, diff --git a/ssl/ssldecode.c b/ssl/ssldecode.c index 14c9e2f..162a3f3 100644 --- a/ssl/ssldecode.c +++ b/ssl/ssldecode.c @@ -191,6 +191,25 @@ int ssl_decode_ctx_create(dp,keyfile,pass,keylogfile) #endif } +int ssl_decode_ctx_destroy(dp) + ssl_decode_ctx **dp; + { +#ifdef OPENSSL + ssl_decode_ctx *d = *dp; + if(d->ssl_key_log_file) { + fclose(d->ssl_key_log_file); + } + + r_assoc *x = d->session_cache; + r_assoc_destroy(&d->session_cache); + + SSL_CTX_free(d->ssl_ctx); + SSL_free(d->ssl); + free(d); +#endif + return(0); + } + int ssl_decoder_create(dp,ctx) ssl_decoder **dp; ssl_decode_ctx *ctx; diff --git a/ssl/ssldecode.h b/ssl/ssldecode.h index 74b8a6b..a878716 100644 --- a/ssl/ssldecode.h +++ b/ssl/ssldecode.h @@ -52,6 +52,7 @@ int ssl_decode_ctx_create PROTO_LIST((ssl_decode_ctx **ctx, char *keyfile,char *password,char *keylogfile)); +int ssl_decode_ctx_destroy(ssl_decode_ctx **dp); int ssl_decoder_destroy PROTO_LIST((ssl_decoder **dp)); int ssl_decoder_create PROTO_LIST((ssl_decoder **dp,ssl_decode_ctx *ctx)); int ssl_set_client_random PROTO_LIST((ssl_decoder *dp, diff --git a/ssl/sslprint.c b/ssl/sslprint.c index afbfa43..3864773 100644 --- a/ssl/sslprint.c +++ b/ssl/sslprint.c @@ -95,6 +95,7 @@ int process_v2_hello(ssl,seg) { int r; int rec_len; + int _status; UINT4 cs_len; UINT4 sid_len; UINT4 chall_len; @@ -104,36 +105,39 @@ int process_v2_hello(ssl,seg) UCHAR random[32]; if(seg->len==0) - return(SSL_NO_DATA); - + ABORT(SSL_NO_DATA); + d.data=seg->data; d.len=seg->len; /* First check the message length. */ if(d.len<4) - return(SSL_BAD_CONTENT_TYPE); + ABORT(SSL_BAD_CONTENT_TYPE); rec_len=((d.data[0] & 0x7f)<<8) | (d.data[1]); d.data+=2; d.len-=2; if(d.len!=rec_len) /* Whatever this is it isn't valid SSLv2*/ - return(SSL_BAD_CONTENT_TYPE); + ABORT(SSL_BAD_CONTENT_TYPE); /* If msg_type==1 then we've got a v2 message (or trash)*/ if(*d.data++!=1) - return(SSL_BAD_CONTENT_TYPE); + ABORT(SSL_BAD_CONTENT_TYPE); d.len--; SSL_DECODE_UINT16(ssl,"Version number",P_DC,&d,&ver); /* We can't handle real v2 clients*/ if(ver<=2){ explain(ssl,"Version 2 Client.\n"); - return(SSL_BAD_DATA); + ABORT(SSL_BAD_DATA); } + ssl->cur_json_st = json_object_new_object(); ssl_print_record_num(ssl); ssl_print_timestamp(ssl,&seg->p->ts); ssl_print_direction_indicator(ssl,DIR_I2R); explain(ssl," SSLv2 compatible client hello\n"); + json_object_object_add(ssl->cur_json_st, "msg_type", json_object_new_string("Handshake")); + json_object_object_add(ssl->cur_json_st, "handshake_type", json_object_new_string("ClientHello_v2_compat")); INDENT_INCR; @@ -148,7 +152,7 @@ int process_v2_hello(ssl,seg) if(cs_len%3){ fprintf(stderr,"Bad cipher spec length %d\n",cs_len); - return(SSL_BAD_DATA); + ABORT(SSL_BAD_DATA); } P_(P_HL){ explain(ssl,"cipher suites\n"); @@ -166,12 +170,12 @@ int process_v2_hello(ssl,seg) if(sid_len!=0){ fprintf(stderr,"Session ID field should be zero length\n"); - return(SSL_BAD_DATA); + ABORT(SSL_BAD_DATA); } if(chall_len<16 || chall_len>32){ fprintf(stderr,"Invalid challenge length %d\n",chall_len); - return(SSL_BAD_DATA); + ABORT(SSL_BAD_DATA); } SSL_DECODE_OPAQUE_ARRAY(ssl,0,chall_len, @@ -195,7 +199,18 @@ int process_v2_hello(ssl,seg) } INDENT_POP; - return(0); + + _status=0; + + abort: + if(ssl->cur_json_st) { + if(SSL_print_flags & SSL_PRINT_JSON) + printf("%s\n", json_object_to_json_string(ssl->cur_json_st)); + json_object_put(ssl->cur_json_st); + ssl->cur_json_st = NULL; + } + + return(_status); } int ssl_decode_switch(ssl,dtable,value,dir,seg,data) @@ -276,7 +291,10 @@ int ssl_expand_record(ssl,q,direction,data,len) printf(" unknown record type: %d\n", ct); ERETURN(r); } - ssl_get_enum_str(ssl,enumstr,ContentType_decoder,ct); + if((r=ssl_get_enum_str(ssl,enumstr,ContentType_decoder,ct))) { + strncpy(enumstr, "Unknown", 20); + } + json_object_object_add(jobj, "msg_type", json_object_new_string(enumstr)); if(!(SSL_print_flags & SSL_PRINT_JSON))