From ecacee7c364bc5b1cd1e426e157a721f7be89005 Mon Sep 17 00:00:00 2001 From: William Robinet Date: Mon, 14 Aug 2023 12:37:08 +0200 Subject: [PATCH] Lint ALL the things ! --- base/network.c | 424 +-- base/network.h | 94 +- base/pcap-snoop.c.in | 825 +++-- base/print_utils.c | 73 +- base/print_utils.h | 13 +- base/proto_mod.c | 64 +- base/proto_mod.h | 88 +- base/tcpconn.c | 314 +- base/tcpconn.h | 97 +- base/tcppack.c | 749 ++-- base/tcppack.h | 10 +- common/include/r_assoc.h | 49 +- common/include/r_bitfield.h | 16 +- common/include/r_common.h | 9 +- common/include/r_data.h | 37 +- common/include/r_defaults.h | 8 +- common/include/r_errors.h | 25 +- common/include/r_includes.h | 7 +- common/include/r_list.h | 34 +- common/include/r_macros.h | 66 +- common/include/r_thread.h | 16 +- common/include/r_time.h | 41 +- common/include/r_types.h | 35 +- common/lib/assoc.h | 7 +- common/lib/debug.c | 62 +- common/lib/debug.h | 12 +- common/lib/r_assoc.c | 598 ++- common/lib/r_assoc_test.c | 149 +- common/lib/r_bitfield.c | 150 +- common/lib/r_data.c | 170 +- common/lib/r_data.h | 8 +- common/lib/r_errors.c | 20 +- common/lib/r_list.c | 304 +- common/lib/r_replace.c | 32 +- common/lib/r_time.c | 161 +- common/lib/threads/pthreads/pthread.c | 225 +- null/null_analyze.c | 168 +- null/null_analyze.h | 7 +- pcap/attrib.h | 26 +- pcap/logpkt.c | 1122 +++--- pcap/logpkt.h | 46 +- pcap/pcap_logger.c | 213 +- pcap/pcap_logger.h | 1 - pcap/sys.c | 58 +- ssl/ciphersuites.c | 395 +- ssl/ssl.enums.c | 4825 +++++++++---------------- ssl/ssl_analyze.c | 1002 +++-- ssl/ssl_analyze.h | 65 +- ssl/ssl_h.h | 133 +- ssl/ssl_rec.c | 788 ++-- ssl/ssl_rec.h | 50 +- ssl/sslciphers.h | 84 +- ssl/ssldecode.c | 2337 ++++++------ ssl/ssldecode.h | 81 +- ssl/sslprint.c | 1270 ++++--- ssl/sslprint.h | 145 +- ssl/sslxprint.c | 350 +- ssl/sslxprint.h | 11 +- 58 files changed, 8234 insertions(+), 9935 deletions(-) diff --git a/base/network.c b/base/network.c index 074de52..8a9eec0 100644 --- a/base/network.c +++ b/base/network.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: network.c,v 1.10 2002/09/09 21:02:58 ekr Exp $ @@ -43,8 +44,6 @@ ekr@rtfm.com Tue Dec 29 09:52:54 1998 */ - - #include #include #include "network.h" @@ -64,248 +63,251 @@ UINT4 NET_print_flags; struct network_handler_ { - proto_mod *mod; - proto_ctx *ctx; + proto_mod *mod; + proto_ctx *ctx; }; -int -network_handler_create (proto_mod *mod, n_handler **handlerp) - { - int r,_status; - n_handler *handler=0; - - if(!(handler=(n_handler *)malloc(sizeof(n_handler)))) - ABORT(R_NO_MEMORY); - if(mod->vtbl->create_ctx){ - if((r=mod->vtbl->create_ctx(mod->handle,&handler->ctx))) - ABORT(r); - } - handler->mod=mod; - *handlerp=handler; - _status=0; - abort: - if(_status){ - network_handler_destroy(mod, &handler); - } - return(_status); +int network_handler_create(proto_mod *mod, n_handler **handlerp) { + int r, _status; + n_handler *handler = 0; + + if(!(handler = (n_handler *)malloc(sizeof(n_handler)))) + ABORT(R_NO_MEMORY); + if(mod->vtbl->create_ctx) { + if((r = mod->vtbl->create_ctx(mod->handle, &handler->ctx))) + ABORT(r); + } + handler->mod = mod; + *handlerp = handler; + _status = 0; +abort: + if(_status) { + network_handler_destroy(mod, &handler); + } + return (_status); +} + +int network_handler_destroy(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); +} + +int network_process_packet(n_handler *handler, + struct timeval *timestamp, + UCHAR *data, + int length, + int af) { + int r; + int hlen; + packet p; + u_short off; + int proto; + + /*We can pretty much ignore all the options*/ + memcpy(&p.ts, timestamp, sizeof(struct timeval)); + p.base = data; + p._len = length; + p.data = data; + p.len = length; + p.af = af; + + 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); } -int -network_handler_destroy (proto_mod *mod, n_handler **handlerp) - { - n_handler *handler=0; - if(!handlerp || !*handlerp) - return(0); + memset(&p.i_addr.so_st, 0x0, sizeof(struct sockaddr_storage)); + memset(&p.r_addr.so_st, 0x0, sizeof(struct sockaddr_storage)); - handler = *handlerp; + if(af == AF_INET) { + p.l3_hdr.ip = (struct ip *)data; + memcpy(&p.i_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_src, + sizeof(struct in_addr)); + p.i_addr.so_in.sin_family = AF_INET; + memcpy(&p.r_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_dst, + sizeof(struct in_addr)); + p.r_addr.so_in.sin_family = AF_INET; - mod->vtbl->destroy_ctx(mod->handle,&handler->ctx); - free(*handlerp); - *handlerp=0; - return(0); - } + /*Handle, or rather mishandle, fragmentation*/ + off = ntohs(p.l3_hdr.ip->ip_off); -int -network_process_packet (n_handler *handler, struct timeval *timestamp, UCHAR *data, int length, int af) - { - int r; - int hlen; - packet p; - u_short off; - int proto; - - /*We can pretty much ignore all the options*/ - memcpy(&p.ts,timestamp,sizeof(struct timeval)); - p.base=data; - p._len=length; - p.data=data; - p.len=length; - p.af=af; + if((off & 0x1fff) || /*Later fragment*/ + (off & 0x2000)) { /*More fragments*/ + /* fprintf(stderr,"Fragmented packet! rejecting\n"); */ + return (0); + } - if(p.len < 20) { + hlen = p.l3_hdr.ip->ip_hl * 4; + p.data += hlen; + p.len = ntohs(p.l3_hdr.ip->ip_len); + + if(p.len > length) { if(!(NET_print_flags & NET_PRINT_JSON)) - printf("Malformed packet, packet too small to contain IP header, skipping ...\n"); - return(0); + printf( + "Malformed packet, size from IP header is larger than size " + "reported by libpcap, skipping ...\n"); + return (0); } - memset(&p.i_addr.so_st, 0x0, sizeof(struct sockaddr_storage)); - memset(&p.r_addr.so_st, 0x0, sizeof(struct sockaddr_storage)); + if(p.len == 0) { + DBG((0, + "ip length reported as 0, presumed to be because of 'TCP " + "segmentation offload' (TSO)\n")); + p.len = p._len; + } + p.len -= hlen; - if(af == AF_INET) { - p.l3_hdr.ip=(struct ip *)data; - memcpy(&p.i_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_src, sizeof(struct in_addr)); - p.i_addr.so_in.sin_family = AF_INET; - memcpy(&p.r_addr.so_in.sin_addr, &p.l3_hdr.ip->ip_dst, sizeof(struct in_addr)); - p.r_addr.so_in.sin_family = AF_INET; - - /*Handle, or rather mishandle, fragmentation*/ - off=ntohs(p.l3_hdr.ip->ip_off); - - if((off & 0x1fff) || /*Later fragment*/ - (off & 0x2000)){ /*More fragments*/ - /* fprintf(stderr,"Fragmented packet! rejecting\n"); */ - return(0); - } - - hlen=p.l3_hdr.ip->ip_hl * 4; - p.data += hlen; - p.len = ntohs(p.l3_hdr.ip->ip_len); - - if(p.len > length) { - if(!(NET_print_flags & NET_PRINT_JSON)) - printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n"); - return(0); - } - - if (p.len == 0) { - DBG((0,"ip length reported as 0, presumed to be because of 'TCP segmentation offload' (TSO)\n")); - p.len = p._len; - } - p.len -= hlen; - - proto = p.l3_hdr.ip->ip_p; - } else { - p.l3_hdr.ip6=(struct ip6_hdr *)data; - memcpy(&p.i_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_src, sizeof(struct in6_addr)); - p.i_addr.so_in6.sin6_family = AF_INET6; - memcpy(&p.r_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_dst, sizeof(struct in6_addr)); - p.r_addr.so_in6.sin6_family = AF_INET6; - // Skip packets with header extensions - if(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) { - return 0; - } - - hlen=40; // Fixed header size with no extension - p.data += hlen; - p.len = ntohs(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); - if(p.len > length) { - if(!(NET_print_flags & NET_PRINT_JSON)) - printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n"); - return(0); - } - - if (p.len == 0) { - DBG((0,"ip length reported as 0, presumed to be because of 'TCP segmentation offload' (TSO)\n")); - p.len = p._len; - } - - proto = p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt; + proto = p.l3_hdr.ip->ip_p; + } else { + p.l3_hdr.ip6 = (struct ip6_hdr *)data; + memcpy(&p.i_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_src, + sizeof(struct in6_addr)); + p.i_addr.so_in6.sin6_family = AF_INET6; + memcpy(&p.r_addr.so_in6.sin6_addr, &p.l3_hdr.ip6->ip6_dst, + sizeof(struct in6_addr)); + p.r_addr.so_in6.sin6_family = AF_INET6; + // Skip packets with header extensions + if(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) { + return 0; } - switch(proto){ - case IPPROTO_TCP: - if((r=process_tcp_packet(handler->mod,handler->ctx,&p))) - ERETURN(r); - break; + hlen = 40; // Fixed header size with no extension + p.data += hlen; + p.len = ntohs(p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); + if(p.len > length) { + if(!(NET_print_flags & NET_PRINT_JSON)) + printf( + "Malformed packet, size from IP header is larger than size " + "reported by libpcap, skipping ...\n"); + return (0); } - return(0); + if(p.len == 0) { + DBG((0, + "ip length reported as 0, presumed to be because of 'TCP " + "segmentation offload' (TSO)\n")); + p.len = p._len; + } + + proto = p.l3_hdr.ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt; } -int -packet_copy (packet *in, packet **out) - { - int _status; - - packet *p=0; - - if(!(p=(packet *)calloc(1,sizeof(packet)))) - ABORT(R_NO_MEMORY); - - memcpy(&p->ts,&in->ts,sizeof(struct timeval)); - if(!(p->base=(UCHAR *)malloc(in->_len))) - ABORT(R_NO_MEMORY); - memcpy(p->base,in->base,p->_len=in->_len); - - p->data=p->base + (in->data - in->base); - p->len=in->len; - - p->ip=(struct ip *)(p->base + ((UCHAR *)in->ip - in->base)); - p->tcp=(struct tcphdr *)(p->base + ((UCHAR *)in->tcp - in->base)); - - *out=p; - - _status=0; - abort: - if(_status){ - packet_destroy(p); - } - return(_status); + switch(proto) { + case IPPROTO_TCP: + if((r = process_tcp_packet(handler->mod, handler->ctx, &p))) + ERETURN(r); + break; } -int -packet_destroy (packet *p) - { - if(!p) - return(0); + return (0); +} - FREE(p->base); - FREE(p); - return(0); +int packet_copy(packet *in, packet **out) { + int _status; + + packet *p = 0; + + if(!(p = (packet *)calloc(1, sizeof(packet)))) + ABORT(R_NO_MEMORY); + + memcpy(&p->ts, &in->ts, sizeof(struct timeval)); + if(!(p->base = (UCHAR *)malloc(in->_len))) + ABORT(R_NO_MEMORY); + memcpy(p->base, in->base, p->_len = in->_len); + + p->data = p->base + (in->data - in->base); + p->len = in->len; + + p->ip = (struct ip *)(p->base + ((UCHAR *)in->ip - in->base)); + p->tcp = (struct tcphdr *)(p->base + ((UCHAR *)in->tcp - in->base)); + + *out = p; + + _status = 0; +abort: + if(_status) { + packet_destroy(p); } - -int -timestamp_diff (struct timeval *t1, struct timeval *t0, struct timeval *diff) - { - long d; + return (_status); +} - if(t0->tv_sec > t1->tv_sec) - ERETURN(R_BAD_ARGS); +int packet_destroy(packet *p) { + if(!p) + return (0); - /*Easy case*/ - if(t0->tv_usec <= t1->tv_usec){ - diff->tv_sec=t1->tv_sec - t0->tv_sec; - diff->tv_usec=t1->tv_usec - t0->tv_usec; - return(0); - } + FREE(p->base); + FREE(p); + return (0); +} - /*Hard case*/ - d=t0->tv_usec - t1->tv_usec; - if(t1->tv_sec < (t0->tv_sec + 1)) - ERETURN(R_BAD_ARGS); - diff->tv_sec=t1->tv_sec - (t0->tv_sec + 1); - diff->tv_usec=1000000 - d; +int timestamp_diff(struct timeval *t1, + struct timeval *t0, + struct timeval *diff) { + long d; - return(0); + if(t0->tv_sec > t1->tv_sec) + ERETURN(R_BAD_ARGS); + + /*Easy case*/ + if(t0->tv_usec <= t1->tv_usec) { + diff->tv_sec = t1->tv_sec - t0->tv_sec; + diff->tv_usec = t1->tv_usec - t0->tv_usec; + return (0); } - + /*Hard case*/ + d = t0->tv_usec - t1->tv_usec; + if(t1->tv_sec < (t0->tv_sec + 1)) + ERETURN(R_BAD_ARGS); + diff->tv_sec = t1->tv_sec - (t0->tv_sec + 1); + diff->tv_usec = 1000000 - d; -int -lookuphostname (struct sockaddr_storage *so_st, char **namep) - { - int r = 1; - *namep = calloc(1, NI_MAXHOST); - void *addr = NULL; + return (0); +} - if(!(NET_print_flags & NET_PRINT_NO_RESOLVE)) { - r = getnameinfo((struct sockaddr *) so_st, sizeof(struct sockaddr_storage), *namep, NI_MAXHOST, NULL, 0, 0); - } +int lookuphostname(struct sockaddr_storage *so_st, char **namep) { + int r = 1; + *namep = calloc(1, NI_MAXHOST); + void *addr = NULL; - if(r) { - if(so_st->ss_family == AF_INET) { - addr = &((struct sockaddr_in *) so_st)->sin_addr; - } else { - addr = &((struct sockaddr_in6 *) so_st)->sin6_addr; - } - inet_ntop(so_st->ss_family, addr, *namep, INET6_ADDRSTRLEN); - } - - return(0); + if(!(NET_print_flags & NET_PRINT_NO_RESOLVE)) { + r = getnameinfo((struct sockaddr *)so_st, sizeof(struct sockaddr_storage), + *namep, NI_MAXHOST, NULL, 0, 0); } - -int -addrtotext (struct sockaddr_storage *so_st, char **namep) - { - *namep = calloc(1, NI_MAXHOST); - void *addr = NULL; + if(r) { if(so_st->ss_family == AF_INET) { - addr = &((struct sockaddr_in *) so_st)->sin_addr; + addr = &((struct sockaddr_in *)so_st)->sin_addr; } else { - addr = &((struct sockaddr_in6 *) so_st)->sin6_addr; + addr = &((struct sockaddr_in6 *)so_st)->sin6_addr; } inet_ntop(so_st->ss_family, addr, *namep, INET6_ADDRSTRLEN); - - return(0); } + + return (0); +} + +int addrtotext(struct sockaddr_storage *so_st, char **namep) { + *namep = calloc(1, NI_MAXHOST); + void *addr = NULL; + + if(so_st->ss_family == AF_INET) { + addr = &((struct sockaddr_in *)so_st)->sin_addr; + } else { + addr = &((struct sockaddr_in6 *)so_st)->sin6_addr; + } + inet_ntop(so_st->ss_family, addr, *namep, INET6_ADDRSTRLEN); + + return (0); +} diff --git a/base/network.h b/base/network.h index 1760157..952a544 100644 --- a/base/network.h +++ b/base/network.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: network.h,v 1.3 2001/09/14 22:29:14 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Dec 29 09:53:50 1998 */ - #ifndef _network_h #define _network_h @@ -74,44 +74,47 @@ typedef struct proto_mod_ proto_mod; typedef struct proto_handler_ proto_handler; typedef struct packet_ packet; -int network_handler_create PROTO_LIST((proto_mod *mod, - 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 af)); -int packet_copy PROTO_LIST((packet *in,packet **out)); -int packet_destroy PROTO_LIST((packet *p)); -int timestamp_diff PROTO_LIST(( struct timeval *t1,struct timeval *t0, - struct timeval *diff)); -int lookuphostname PROTO_LIST((struct sockaddr_storage *addr,char **name)); -int addrtotext PROTO_LIST((struct sockaddr_storage *addr,char **name)); +int network_handler_create PROTO_LIST((proto_mod * mod, 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 af)); +int packet_copy PROTO_LIST((packet * in, packet **out)); +int packet_destroy PROTO_LIST((packet * p)); +int timestamp_diff PROTO_LIST((struct timeval * t1, + struct timeval *t0, + struct timeval *diff)); +int lookuphostname PROTO_LIST((struct sockaddr_storage * addr, char **name)); +int addrtotext PROTO_LIST((struct sockaddr_storage * addr, char **name)); struct packet_ { - struct timeval ts; - UCHAR *base; /*The base of the packet*/ - int _len; - UCHAR *data; /*The data ptr appropriate to this layer*/ - int len; /*The length of the data segment*/ - - /*These just save us the effort of doing casts to the data - segments*/ - struct ip *ip; /*The IP header*/ - int af; - union { - struct ip *ip; /*The IP header*/ - struct ip6_hdr *ip6; /*The IP header*/ - } l3_hdr; - struct tcphdr *tcp; /*The TCP header*/ - union { - struct sockaddr_storage so_st; - struct sockaddr_in so_in; - struct sockaddr_in6 so_in6; - } i_addr; - union { - struct sockaddr_storage so_st; - struct sockaddr_in so_in; - struct sockaddr_in6 so_in6; - } r_addr; + struct timeval ts; + UCHAR *base; /*The base of the packet*/ + int _len; + UCHAR *data; /*The data ptr appropriate to this layer*/ + int len; /*The length of the data segment*/ + + /*These just save us the effort of doing casts to the data + segments*/ + struct ip *ip; /*The IP header*/ + int af; + union { + struct ip *ip; /*The IP header*/ + struct ip6_hdr *ip6; /*The IP header*/ + } l3_hdr; + struct tcphdr *tcp; /*The TCP header*/ + union { + struct sockaddr_storage so_st; + struct sockaddr_in so_in; + struct sockaddr_in6 so_in6; + } i_addr; + union { + struct sockaddr_storage so_st; + struct sockaddr_in so_in; + struct sockaddr_in6 so_in6; + } r_addr; }; #include "tcpconn.h" @@ -119,11 +122,10 @@ struct packet_ { extern UINT4 NET_print_flags; -#define NET_PRINT_TCP_HDR 1 -#define NET_PRINT_TYPESET 2 -#define NET_PRINT_ACKS 4 -#define NET_PRINT_NO_RESOLVE 8 -#define NET_PRINT_JSON 16 -#define NET_PRINT_TS 32 +#define NET_PRINT_TCP_HDR 1 +#define NET_PRINT_TYPESET 2 +#define NET_PRINT_ACKS 4 +#define NET_PRINT_NO_RESOLVE 8 +#define NET_PRINT_JSON 16 +#define NET_PRINT_TS 32 #endif - diff --git a/base/pcap-snoop.c.in b/base/pcap-snoop.c.in index 672cf19..909003a 100644 --- a/base/pcap-snoop.c.in +++ b/base/pcap-snoop.c.in @@ -19,7 +19,7 @@ with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -46,9 +46,6 @@ ekr@rtfm.com Tue Dec 29 10:17:41 1998 */ - - - #include #include #ifndef __OpenBSD__ @@ -80,493 +77,491 @@ #include "pcap_logger.h" #ifndef ETHERTYPE_8021Q -# define ETHERTYPE_8021Q 0x8100 +#define ETHERTYPE_8021Q 0x8100 #endif -char *collapse_args PROTO_LIST((int argc,char **argv)); -static int pcap_if_type=DLT_NULL; -int err_exit PROTO_LIST((char *str,int num)); +char *collapse_args PROTO_LIST((int argc, char **argv)); +static int pcap_if_type = DLT_NULL; +int err_exit PROTO_LIST((char *str, int num)); int usage PROTO_LIST((void)); int print_version PROTO_LIST((void)); void sig_handler PROTO_LIST((int sig)); -void pcap_cb PROTO_LIST((u_char *ptr,const struct pcap_pkthdr *hdr,const u_char *data)); -int main PROTO_LIST((int argc,char **argv)); +void pcap_cb PROTO_LIST((u_char * ptr, + const struct pcap_pkthdr *hdr, + const u_char *data)); +int main PROTO_LIST((int argc, char **argv)); -int packet_cnt = 0; // Packet counter used for connection pool cleaning -int conn_freq = 100; // Number of packets after which a connection pool - // cleaning is performed -int conn_ttl = 100; // TTL of inactive connections in connection pool -struct timeval last_packet_seen_time = // Timestamp of the last packet of the - (struct timeval) {0}; // last block of conn_freq packets seen +int packet_cnt = 0; // Packet counter used for connection pool cleaning +int conn_freq = 100; // Number of packets after which a connection pool + // cleaning is performed +int conn_ttl = 100; // TTL of inactive connections in connection pool +struct timeval last_packet_seen_time = // Timestamp of the last packet of the + (struct timeval){0}; // last block of conn_freq packets seen -logger_mod *logger=NULL; +logger_mod *logger = NULL; -int -err_exit (char *str, int num) - { - fprintf(stderr,"ERROR: %s\n",str); - sig_handler(SIGQUIT); - exit(num); - } +int err_exit(char *str, int num) { + fprintf(stderr, "ERROR: %s\n", str); + sig_handler(SIGQUIT); + exit(num); +} -int -usage (void) - { - fprintf(stderr,"Usage: ssldump [-r dumpfile] [-i interface] [-l sslkeylogfile] [-w outpcapfile]\n"); - fprintf(stderr," [-k keyfile] [-p password] [-vtaTznsAxVNde]\n"); - fprintf(stderr," [filter]\n"); - exit(0); - } +int usage(void) { + fprintf(stderr, + "Usage: ssldump [-r dumpfile] [-i interface] [-l sslkeylogfile] [-w " + "outpcapfile]\n"); + fprintf(stderr, + " [-k keyfile] [-p password] [-vtaTznsAxVNde]\n"); + fprintf(stderr, " [filter]\n"); + exit(0); +} -int -print_version (void) - { - printf("Version: @ssldump_VERSION@ (@ssldump_DESCRIPTION@)\n"); - printf("Maintained by a bunch of volunteers, see https://github.com/adulau/ssldump/blob/master/CREDITS\n"); - printf("Copyright (C) 2015-2023 the aforementioned volunteers\n"); - printf("Copyright (C) 1998-2001 RTFM, Inc.\n"); - printf("All rights reserved.\n"); -#ifdef OPENSSL - printf("Compiled with OpenSSL: decryption enabled\n"); -#endif - exit(0); - } +int print_version(void) { + printf("Version: @ssldump_VERSION@ (@ssldump_DESCRIPTION@)\n"); + printf( + "Maintained by a bunch of volunteers, see " + "https://github.com/adulau/ssldump/blob/master/CREDITS\n"); + printf("Copyright (C) 2015-2023 the aforementioned volunteers\n"); + printf("Copyright (C) 1998-2001 RTFM, Inc.\n"); + printf("All rights reserved.\n"); +#ifdef OPENSSL + printf("Compiled with OpenSSL: decryption enabled\n"); +#endif + exit(0); +} pcap_t *p; -proto_mod *mod=&ssl_mod; +proto_mod *mod = &ssl_mod; n_handler *n; -char *interface_name=0; -char *file=0; -char *filter=0; -void sig_handler(int sig) - { - int freed_conn = 0; - fflush(stdout); - if (logger) - logger->vtbl->deinit(); +char *interface_name = 0; +char *file = 0; +char *filter = 0; +void sig_handler(int sig) { + int freed_conn = 0; + fflush(stdout); + if(logger) + logger->vtbl->deinit(); - freed_conn = destroy_all_conn(); - if(freed_conn && !(NET_print_flags & NET_PRINT_JSON)) - printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn); + freed_conn = destroy_all_conn(); + 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); + network_handler_destroy(mod, &n); - if(p) - pcap_close(p); - if(interface_name) - free(interface_name); - if(filter) - free(filter); - if(file) - free(file); + if(p) + pcap_close(p); + if(interface_name) + free(interface_name); + if(filter) + free(filter); + if(file) + free(file); - exit(sig); - } - -void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) - { - n_handler *n; - int len; - struct ether_header *e_hdr=(struct ether_header *)data; - int type, cleaned_conn; - - n=(n_handler *)ptr; - if(hdr->caplen!=hdr->len) err_exit("Length mismatch",-1); + exit(sig); +} - len=hdr->len; - - switch(pcap_if_type){ - case DLT_RAW: +void pcap_cb(u_char *ptr, const struct pcap_pkthdr *hdr, const u_char *data) { + n_handler *n; + int len; + struct ether_header *e_hdr = (struct ether_header *)data; + int type, cleaned_conn; + + n = (n_handler *)ptr; + if(hdr->caplen != hdr->len) + err_exit("Length mismatch", -1); + + len = hdr->len; + + switch(pcap_if_type) { + case DLT_RAW: #ifdef DLT_LOOP - case DLT_LOOP: + case DLT_LOOP: #endif - case DLT_NULL: - data+=4; - 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; - } + case DLT_NULL: + data += 4; + 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); + type = ntohs(e_hdr->ether_type); - data+=sizeof(struct ether_header); - len-=sizeof(struct ether_header); + data += sizeof(struct ether_header); + len -= sizeof(struct ether_header); - /* if vlans, push past VLAN header (4 bytes) */ - if(type==ETHERTYPE_8021Q) { - type=ntohs(*(u_int16_t *)(data + 2)); + /* if vlans, push past VLAN header (4 bytes) */ + if(type == ETHERTYPE_8021Q) { + type = ntohs(*(u_int16_t *)(data + 2)); - data+=4; - len+=4; - } + data += 4; + len += 4; + } - if(type!=ETHERTYPE_IP && type!=ETHERTYPE_IPV6) - return; + if(type != ETHERTYPE_IP && type != ETHERTYPE_IPV6) + return; - break; - case DLT_IEEE802: - data+=22; - len-=22; - break; - case DLT_FDDI: - data+=21; - len-=21; - break; + break; + case DLT_IEEE802: + data += 22; + len -= 22; + break; + case DLT_FDDI: + data += 21; + len -= 21; + break; #ifdef __amigaos__ - case DLT_MIAMI: - data+=16; - len-=16; - break; + case DLT_MIAMI: + data += 16; + len -= 16; + break; #endif - case DLT_SLIP: + case DLT_SLIP: #ifdef DLT_SLIP_BSDOS - case DLT_SLIP_BSDOS: + case DLT_SLIP_BSDOS: #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__) - data+=16; - len-=16; +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__bsdi__) || defined(__APPLE__) + data += 16; + len -= 16; #else - data+=24; - len-=24; + data += 24; + len -= 24; #endif - break; - case DLT_PPP: + break; + case DLT_PPP: #ifdef DLT_PPP_BSDOS - case DLT_PPP_BSDOS: + case DLT_PPP_BSDOS: #endif #ifdef DLT_PPP_SERIAL - case DLT_PPP_SERIAL: + case DLT_PPP_SERIAL: #endif #ifdef DLT_PPP_ETHER - case DLT_PPP_ETHER: + case DLT_PPP_ETHER: #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) || defined(__APPLE__) - data+=4; - len-=4; +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__bsdi__) || defined(__APPLE__) + data += 4; + len -= 4; #else #if defined(sun) || defined(__sun) - data+=8; - len-=8; + data += 8; + len -= 8; #else - data+=24; - len-=24; + data += 24; + len -= 24; #endif #endif - break; + break; #ifdef DLT_ENC - case DLT_ENC: - data+=12; - len-=12; - break; + case DLT_ENC: + data += 12; + len -= 12; + break; #endif #ifdef DLT_LINUX_SLL - case DLT_LINUX_SLL: - data+=16; - len-=16; - break; + case DLT_LINUX_SLL: + data += 16; + len -= 16; + break; #endif #ifdef DLT_IPNET - case DLT_IPNET: - data+=24; - len-=24; - break; + case DLT_IPNET: + data += 24; + len -= 24; + break; #endif - } - - if(type == ETHERTYPE_IPV6) - network_process_packet(n,(struct timeval *) &hdr->ts,(u_char *)data,len, AF_INET6); - else - network_process_packet(n,(struct timeval *) &hdr->ts,(u_char *)data,len, AF_INET); - - if(packet_cnt == conn_freq) { - packet_cnt = 0; - memcpy(&last_packet_seen_time,&hdr->ts,sizeof(struct timeval)); - if((cleaned_conn = clean_old_conn()) && !(NET_print_flags & NET_PRINT_JSON)) - printf("%d inactive connection(s) cleaned from connection pool\n", cleaned_conn); - } else { - packet_cnt++; - } } + if(type == ETHERTYPE_IPV6) + network_process_packet(n, (struct timeval *)&hdr->ts, (u_char *)data, len, + AF_INET6); + else + network_process_packet(n, (struct timeval *)&hdr->ts, (u_char *)data, len, + AF_INET); + + if(packet_cnt == conn_freq) { + packet_cnt = 0; + memcpy(&last_packet_seen_time, &hdr->ts, sizeof(struct timeval)); + if((cleaned_conn = clean_old_conn()) && !(NET_print_flags & NET_PRINT_JSON)) + printf("%d inactive connection(s) cleaned from connection pool\n", + cleaned_conn); + } else { + packet_cnt++; + } +} + typedef struct module_def_ { - char *name; - proto_mod *mod; + char *name; + proto_mod *mod; } module_def; -static module_def modules[]={ - {"SSL",&ssl_mod}, - {"NULL",&null_mod}, +static module_def modules[] = {{"SSL", &ssl_mod}, + {"NULL", &null_mod}, #ifdef ENABLE_RECORD - {"RECORD",&record_mod}, + {"RECORD", &record_mod}, #endif - {0,0} -}; - + {0, 0}}; int parse_ssl_flag PROTO_LIST((int c)); -int -main (int argc, char **argv) - { - int r; +int main(int argc, char **argv) { + int r; #ifdef _WIN32 - __declspec(dllimport) char *optarg; - __declspec(dllimport) int optind; + __declspec(dllimport) char *optarg; + __declspec(dllimport) int optind; #else - extern char *optarg; - extern int optind; + extern char *optarg; + extern int optind; #endif - pcap_if_t *interfaces; - bpf_u_int32 localnet,netmask; - int c; - module_def *m=0; - int no_promiscuous=0; - int freed_conn=0; - - char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *interfaces; + bpf_u_int32 localnet, netmask; + int c; + module_def *m = 0; + int no_promiscuous = 0; + int freed_conn = 0; - signal(SIGINT,sig_handler); - - while((c=getopt(argc,argv,"vr:F:f:S:jyTt:ai:k:l:w:p:znsAxXhHVNdqem:P"))!=EOF){ - switch(c){ - case 'v': - print_version(); - break; - case 'f': - fprintf(stderr,"-f option replaced by -r. Use that in the future\n"); - case 'r': - file=strdup(optarg); - break; - case 'S': - ssl_mod.vtbl->parse_flags(optarg); - break; - case 'y': - NET_print_flags|=NET_PRINT_TYPESET; - /*Kludge*/ - SSL_print_flags |= SSL_PRINT_NROFF; - break; - case 'j': - NET_print_flags |= NET_PRINT_JSON; - SSL_print_flags |= SSL_PRINT_JSON; - break; - case 'z': - NET_print_flags |= NET_PRINT_TS; - break; - case 'a': - NET_print_flags |= NET_PRINT_ACKS; - break; - case 'A': - SSL_print_flags |= SSL_PRINT_ALL_FIELDS; - break; - case 'T': - NET_print_flags |= NET_PRINT_TCP_HDR; - break; - case 'i': - interface_name=strdup(optarg); - break; - case 'k': - SSL_keyfile=strdup(optarg); - break; - case 'l': - SSL_keylogfile=strdup(optarg); - break; - case 'w': - logger=&pcap_mod; - if(logger->vtbl->init(optarg)!=0){ - fprintf(stderr,"Can not open/create out pcap %s\n", - optarg); - exit(1); - } - break; - case 'p': - SSL_password=strdup(optarg); - break; - case 'P': - ++no_promiscuous; - break; - case 'n': - NET_print_flags |= NET_PRINT_NO_RESOLVE; - break; - case 't': - conn_ttl=atoi(optarg); - break; - case 'F': - conn_freq=atoi(optarg); - break; - case 'm': - for(m=modules;m->name!=0;m++){ - if(!strcmp(m->name,optarg)){ - mod=m->mod; - break; - } - } - if(!m->name){ - fprintf(stderr,"Request analysis module %s not found\n", - optarg); - exit(1); - } - break; - case 'h': - usage(); - printf("Do 'man ssldump' for documentation\n"); + char errbuf[PCAP_ERRBUF_SIZE]; + + signal(SIGINT, sig_handler); + + while((c = getopt(argc, argv, "vr:F:f:S:jyTt:ai:k:l:w:p:znsAxXhHVNdqem:P")) != + EOF) { + switch(c) { + case 'v': + print_version(); + break; + case 'f': + fprintf(stderr, "-f option replaced by -r. Use that in the future\n"); + case 'r': + file = strdup(optarg); + break; + case 'S': + ssl_mod.vtbl->parse_flags(optarg); + break; + case 'y': + NET_print_flags |= NET_PRINT_TYPESET; + /*Kludge*/ + SSL_print_flags |= SSL_PRINT_NROFF; + break; + case 'j': + NET_print_flags |= NET_PRINT_JSON; + SSL_print_flags |= SSL_PRINT_JSON; + break; + case 'z': + NET_print_flags |= NET_PRINT_TS; + break; + case 'a': + NET_print_flags |= NET_PRINT_ACKS; + break; + case 'A': + SSL_print_flags |= SSL_PRINT_ALL_FIELDS; + break; + case 'T': + NET_print_flags |= NET_PRINT_TCP_HDR; + break; + case 'i': + interface_name = strdup(optarg); + break; + case 'k': + SSL_keyfile = strdup(optarg); + break; + case 'l': + SSL_keylogfile = strdup(optarg); + break; + case 'w': + logger = &pcap_mod; + if(logger->vtbl->init(optarg) != 0) { + fprintf(stderr, "Can not open/create out pcap %s\n", optarg); exit(1); - - case '?': - usage(); - exit(1); - - /* must be an SSL flag. This is kind of a gross - special case */ - default: - parse_ssl_flag(c); - break; - } - } - - argv+=optind; - argc-=optind; - - if(!file){ - if(!interface_name){ - if(pcap_findalldevs(&interfaces,errbuf)==-1) { - fprintf(stderr,"PCAP: %s\n",errbuf); - err_exit("Aborting",-1); } - interface_name=interfaces->name; - if(!interface_name){ - fprintf(stderr,"PCAP: %s\n",errbuf); - err_exit("Aborting",-1); - } - } - if(!(p=pcap_open_live(interface_name,65535,!no_promiscuous,1000,errbuf))){ - fprintf(stderr,"PCAP: %s\n",errbuf); - err_exit("Aborting",-1); - } - - if (pcap_lookupnet(interface_name, &localnet, &netmask, errbuf) < 0) - fprintf(stderr,"PCAP: %s\n", errbuf); - } - else{ - if(!(p=pcap_open_offline(file,errbuf))){ - fprintf(stderr,"PCAP: %s\n",errbuf); - err_exit("Aborting",-1); - } - - netmask=0; - localnet=0; - } - - if(argc!=0) - filter=collapse_args(argc,argv); - - if(filter){ - struct bpf_program fp; - - /* (F5 patch) - * reformat filter to include traffic with or without the 802.1q - * vlan header. for example, "port 80" becomes: - * "( port 80 ) or ( vlan and port 80 )". - * note that if the filter includes the literals vlan, tagged, or - * untagged, then it is assumed that the user knows what she is - * doing, and the filter is not reformatted. - */ - if ((pcap_datalink(p) == DLT_EN10MB) && - (filter != NULL) && - (strstr(filter,"vlan") == NULL)) { - char *tmp_filter; - char *fmt = "( (not ether proto 0x8100) and (%s) ) or ( vlan and (%s) )"; - - tmp_filter = (char *)malloc((strlen(filter) * 2) + strlen(fmt) + 1); - if (tmp_filter == NULL) { - fprintf(stderr,"PCAP: malloc failed\n"); - err_exit("Aborting",-1); + break; + case 'p': + SSL_password = strdup(optarg); + break; + case 'P': + ++no_promiscuous; + break; + case 'n': + NET_print_flags |= NET_PRINT_NO_RESOLVE; + break; + case 't': + conn_ttl = atoi(optarg); + break; + case 'F': + conn_freq = atoi(optarg); + break; + case 'm': + for(m = modules; m->name != 0; m++) { + if(!strcmp(m->name, optarg)) { + mod = m->mod; + break; } - - sprintf(tmp_filter,fmt,filter,filter); - free(filter); - filter = tmp_filter; + } + if(!m->name) { + fprintf(stderr, "Request analysis module %s not found\n", optarg); + exit(1); + } + break; + case 'h': + usage(); + printf("Do 'man ssldump' for documentation\n"); + exit(1); + + case '?': + usage(); + exit(1); + + /* must be an SSL flag. This is kind of a gross + special case */ + default: + parse_ssl_flag(c); + break; + } + } + + argv += optind; + argc -= optind; + + if(!file) { + if(!interface_name) { + if(pcap_findalldevs(&interfaces, errbuf) == -1) { + fprintf(stderr, "PCAP: %s\n", errbuf); + err_exit("Aborting", -1); + } + interface_name = interfaces->name; + if(!interface_name) { + fprintf(stderr, "PCAP: %s\n", errbuf); + err_exit("Aborting", -1); + } + } + if(!(p = pcap_open_live(interface_name, 65535, !no_promiscuous, 1000, + errbuf))) { + fprintf(stderr, "PCAP: %s\n", errbuf); + err_exit("Aborting", -1); + } + + if(pcap_lookupnet(interface_name, &localnet, &netmask, errbuf) < 0) + fprintf(stderr, "PCAP: %s\n", errbuf); + } else { + if(!(p = pcap_open_offline(file, errbuf))) { + fprintf(stderr, "PCAP: %s\n", errbuf); + err_exit("Aborting", -1); + } + + netmask = 0; + localnet = 0; + } + + if(argc != 0) + filter = collapse_args(argc, argv); + + if(filter) { + struct bpf_program fp; + + /* (F5 patch) + * reformat filter to include traffic with or without the 802.1q + * vlan header. for example, "port 80" becomes: + * "( port 80 ) or ( vlan and port 80 )". + * note that if the filter includes the literals vlan, tagged, or + * untagged, then it is assumed that the user knows what she is + * doing, and the filter is not reformatted. + */ + if((pcap_datalink(p) == DLT_EN10MB) && (filter != NULL) && + (strstr(filter, "vlan") == NULL)) { + char *tmp_filter; + char *fmt = "( (not ether proto 0x8100) and (%s) ) or ( vlan and (%s) )"; + + tmp_filter = (char *)malloc((strlen(filter) * 2) + strlen(fmt) + 1); + if(tmp_filter == NULL) { + fprintf(stderr, "PCAP: malloc failed\n"); + err_exit("Aborting", -1); } - if(pcap_compile(p,&fp,filter,0,netmask)<0) - verr_exit("PCAP: %s\n",pcap_geterr(p)); - - if(pcap_setfilter(p,&fp)<0) - verr_exit("PCAP: %s\n",pcap_geterr(p)); + sprintf(tmp_filter, fmt, filter, filter); + free(filter); + filter = tmp_filter; } - pcap_if_type=pcap_datalink(p); + if(pcap_compile(p, &fp, filter, 0, netmask) < 0) + verr_exit("PCAP: %s\n", pcap_geterr(p)); - if(!(NET_print_flags & NET_PRINT_JSON)) - if(NET_print_flags & NET_PRINT_TYPESET) - printf("\n.nf\n.ps -2\n"); - - if((r=network_handler_create(mod,&n))) - err_exit("Couldn't create network handler",r); - - pcap_loop(p,-1,pcap_cb,(u_char *)n); - - if(!(NET_print_flags & NET_PRINT_JSON)) - if(NET_print_flags & NET_PRINT_TYPESET) - printf("\n.ps\n.fi\n"); - - freed_conn = destroy_all_conn(); - 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); - - if(filter) - free(filter); - if(file) - free(file); - if(interface_name) - free(interface_name); - if(SSL_keyfile) - free(SSL_keyfile); - if(SSL_keylogfile) - free(SSL_keylogfile); - if(SSL_password) - free(SSL_password); - if (logger) - { - logger->vtbl->deinit(); - } - - exit(0); + if(pcap_setfilter(p, &fp) < 0) + verr_exit("PCAP: %s\n", pcap_geterr(p)); } - -char * -collapse_args (int argc, char **argv) - { - int i,len=0; - char *ret; - - if(!argc) - return(0); + pcap_if_type = pcap_datalink(p); - for(i=0;ivtbl->deinit(); } + + exit(0); +} + +char *collapse_args(int argc, char **argv) { + int i, len = 0; + char *ret; + + if(!argc) + return (0); + + for(i = 0; i < argc; i++) { + len += strlen(argv[i]) + 1; + } + + if(!(ret = (char *)malloc(len))) + err_exit("Out of memory", 1); + + len = 0; + for(i = 0; i < argc; i++) { + strcpy(ret + len, argv[i]); + len += strlen(argv[i]); + + if(i != (argc - 1)) + ret[len++] = ' '; + } + + return (ret); +} diff --git a/base/print_utils.c b/base/print_utils.c index 08739b7..c597942 100644 --- a/base/print_utils.c +++ b/base/print_utils.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: print_utils.c,v 1.2 2000/10/17 16:09:58 ekr Exp $ @@ -43,45 +44,43 @@ ekr@rtfm.com Mon Feb 15 17:23:36 1999 */ +int explain(char *format, ...) { + va_list ap; -int explain(char *format,...) - { - va_list ap; + va_start(ap, format); - va_start(ap,format); + INDENT; - INDENT; + vprintf(format, ap); + va_end(ap); + return (0); +} - vprintf(format,ap); - va_end(ap); - return(0); +int exdump(name, data) char *name; +Data *data; +{ + int i, j; + char prefix[100]; + + INDENT; + + if(name) { + sprintf(prefix, "%s[%d]=\n", name, data->len); + printf("%s", prefix); + INDENT_INCR; } - -int exdump(name,data) - char *name; - Data *data; - { - int i,j; - char prefix[100]; - - INDENT; - - if(name){ - sprintf(prefix,"%s[%d]=\n",name,data->len); - printf("%s",prefix); - INDENT_INCR; - } - for(i=0;ilen;i++){ - if(!i && (data->len>8)) INDENT; - if((data->len>8) && i && !(i%12)){ - LF;INDENT; - } - printf("%.2x ",data->data[i]&255); - } - if(name) INDENT_POP; - if(data->len>8 && i%12) + for(i = 0; i < data->len; i++) { + if(!i && (data->len > 8)) + INDENT; + if((data->len > 8) && i && !(i % 12)) { LF; - return(0); + INDENT; + } + printf("%.2x ", data->data[i] & 255); } - - + if(name) + INDENT_POP; + if(data->len > 8 && i % 12) + LF; + return (0); +} diff --git a/base/print_utils.h b/base/print_utils.h index 4f7d14d..1dc57b3 100644 --- a/base/print_utils.h +++ b/base/print_utils.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: print_utils.h,v 1.2 2000/10/17 16:09:58 ekr Exp $ @@ -43,14 +44,10 @@ ekr@rtfm.com Mon Feb 15 17:23:56 1999 */ - #ifndef _print_utils_h #define _print_utils_h -int explain PROTO_LIST((char *format,...)); -int exdump PROTO_LIST((char *name, - Data *data)); - +int explain PROTO_LIST((char *format, ...)); +int exdump PROTO_LIST((char *name, Data *data)); #endif - diff --git a/base/proto_mod.c b/base/proto_mod.c index 80cebd2..aadf775 100644 --- a/base/proto_mod.c +++ b/base/proto_mod.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: proto_mod.c,v 1.3 2001/07/20 23:33:14 ekr Exp $ @@ -43,41 +44,40 @@ ekr@rtfm.com Thu Jan 7 22:35:23 1999 */ - - #include "network.h" -int -create_proto_handler (proto_mod *mod, proto_ctx *ctx, proto_handler **handlerp, tcp_conn *conn, struct timeval *first_packet) - { - int r,_status; - proto_handler *handler=0; +int create_proto_handler(proto_mod *mod, + proto_ctx *ctx, + proto_handler **handlerp, + tcp_conn *conn, + struct timeval *first_packet) { + int r, _status; + proto_handler *handler = 0; - if(!(handler=(proto_handler *)calloc(1,sizeof(proto_handler)))) - ABORT(R_NO_MEMORY); - handler->vtbl=mod->vtbl; - if((r=mod->vtbl->create(mod->handle,ctx,conn,&handler->obj, - &conn->i_addr,conn->i_port,&conn->r_addr,conn->r_port,first_packet))) - ABORT(r); + if(!(handler = (proto_handler *)calloc(1, sizeof(proto_handler)))) + ABORT(R_NO_MEMORY); + handler->vtbl = mod->vtbl; + if((r = mod->vtbl->create(mod->handle, ctx, conn, &handler->obj, + &conn->i_addr, conn->i_port, &conn->r_addr, + conn->r_port, first_packet))) + ABORT(r); - *handlerp=handler; + *handlerp = handler; - _status=0; - abort: - if(_status){ - destroy_proto_handler(&handler); - } - return(_status); + _status = 0; +abort: + if(_status) { + destroy_proto_handler(&handler); } + return (_status); +} -int -destroy_proto_handler (proto_handler **handlerp) - { - if(!handlerp || !*handlerp) - return(0); +int destroy_proto_handler(proto_handler **handlerp) { + if(!handlerp || !*handlerp) + return (0); - (*handlerp)->vtbl->destroy(&(*handlerp)->obj); - free(*handlerp); - *handlerp=0; - return(0); - } + (*handlerp)->vtbl->destroy(&(*handlerp)->obj); + free(*handlerp); + *handlerp = 0; + return (0); +} diff --git a/base/proto_mod.h b/base/proto_mod.h index 5e96c54..9e01f28 100644 --- a/base/proto_mod.h +++ b/base/proto_mod.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: proto_mod.h,v 1.4 2001/11/26 22:28:16 ekr Exp $ @@ -43,67 +44,76 @@ ekr@rtfm.com Thu Dec 24 21:10:05 1998 */ - #ifndef _proto_mod_h #define _proto_mod_h typedef struct proto_obj_ proto_obj; typedef struct proto_ctx_ proto_ctx; -#define DIR_I2R 1 -#define DIR_R2I 2 +#define DIR_I2R 1 +#define DIR_R2I 2 struct proto_mod_vtbl_ { - int (*parse_flags) PROTO_LIST((char *str)); - int (*parse_flag) PROTO_LIST((int flag)); - int (*create_ctx) PROTO_LIST((void *handle,proto_ctx **ctxp)); - int (*create) PROTO_LIST((void *handle,proto_ctx *ctx, - tcp_conn *conn, - proto_obj **objp, - struct sockaddr_storage *i_addr,u_short i_port, - struct sockaddr_storage *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)); + int(*parse_flags) PROTO_LIST((char *str)); + int(*parse_flag) PROTO_LIST((int flag)); + int(*create_ctx) PROTO_LIST((void *handle, proto_ctx **ctxp)); + int(*create) PROTO_LIST((void *handle, + proto_ctx *ctx, + tcp_conn *conn, + proto_obj **objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *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)); }; struct proto_mod_ { - void *handle; - struct proto_mod_vtbl_ *vtbl; + void *handle; + struct proto_mod_vtbl_ *vtbl; }; struct proto_handler_ { - proto_obj *obj; - struct proto_mod_vtbl_ *vtbl; + proto_obj *obj; + struct proto_mod_vtbl_ *vtbl; }; -int create_proto_handler PROTO_LIST((proto_mod *mod,proto_ctx *ctx, - proto_handler **handlerp, - tcp_conn *conn,struct timeval *first_packet)); -int destroy_proto_handler PROTO_LIST((proto_handler **handlerp)); +int create_proto_handler PROTO_LIST((proto_mod * mod, + proto_ctx *ctx, + proto_handler **handlerp, + tcp_conn *conn, + struct timeval *first_packet)); +int destroy_proto_handler PROTO_LIST((proto_handler * *handlerp)); - -//add logger +// add logger struct logger_mod_vtbl_ { - int (*init) PROTO_LIST((void *data)); - //deinit must be async signal safe(!!!) - int (*deinit) PROTO_LIST(()); - int (*create) PROTO_LIST((proto_obj **objp, struct sockaddr_storage *i_addr,u_short i_port, - struct sockaddr_storage *r_addr,u_short r_port,struct timeval *time_base)); - int (*destroy) PROTO_LIST((proto_obj **objp)); - int (*data) PROTO_LIST((proto_obj *obj,unsigned char *data,unsigned int len,int direction)); - int (*close) PROTO_LIST((proto_obj *obj,unsigned char *data,unsigned int len,int direction)); + int(*init) PROTO_LIST((void *data)); + // deinit must be async signal safe(!!!) + int(*deinit) PROTO_LIST(()); + int(*create) PROTO_LIST((proto_obj * *objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *time_base)); + int(*destroy) PROTO_LIST((proto_obj * *objp)); + int(*data) PROTO_LIST( + (proto_obj * obj, unsigned char *data, unsigned int len, int direction)); + int(*close) PROTO_LIST( + (proto_obj * obj, unsigned char *data, unsigned int len, int direction)); }; struct logger_mod_ { - char *name; - struct logger_mod_vtbl_ *vtbl; + char *name; + struct logger_mod_vtbl_ *vtbl; }; typedef struct logger_mod_ logger_mod; -extern logger_mod *logger; +extern logger_mod *logger; #endif - diff --git a/base/tcpconn.c b/base/tcpconn.c index f9bcb5f..f980593 100644 --- a/base/tcpconn.c +++ b/base/tcpconn.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: tcpconn.c,v 1.7 2002/08/17 01:33:16 ekr Exp $ @@ -43,193 +44,182 @@ ekr@rtfm.com Tue Dec 29 15:13:03 1998 */ - #include "network.h" #include "tcpconn.h" - typedef struct conn_struct_ { - tcp_conn conn; - struct conn_struct_ *next; - struct conn_struct_ *prev; + tcp_conn conn; + struct conn_struct_ *next; + struct conn_struct_ *prev; } conn_struct; -int conn_number=1; +int conn_number = 1; -static conn_struct *first_conn=0; +static conn_struct *first_conn = 0; extern struct timeval last_packet_seen_time; extern int conn_ttl; -static int zero_conn PROTO_LIST((tcp_conn *conn)); +static int zero_conn PROTO_LIST((tcp_conn * conn)); -static int -zero_conn (tcp_conn *conn) - { - memset(conn,0,sizeof(tcp_conn)); - return(0); - } +static int zero_conn(tcp_conn *conn) { + memset(conn, 0, sizeof(tcp_conn)); + return (0); +} -int tcp_find_conn(tcp_conn **connp, int *directionp,struct sockaddr_storage *saddr, - u_short sport, struct sockaddr_storage *daddr, u_short dport) - { - conn_struct *conn; +int tcp_find_conn(tcp_conn **connp, + int *directionp, + struct sockaddr_storage *saddr, + u_short sport, + struct sockaddr_storage *daddr, + u_short dport) { + conn_struct *conn; - for(conn=first_conn;conn;conn=conn->next){ - - if(sport == conn->conn.i_port && dport==conn->conn.r_port){ - if(!memcmp(saddr,&conn->conn.i_addr,sizeof(struct sockaddr_storage)) - && !memcmp(daddr,&conn->conn.r_addr,sizeof(struct sockaddr_storage))) - { - *directionp=DIR_I2R; - *connp=&(conn->conn); - return(0); - } - } - - if(dport == conn->conn.i_port && sport==conn->conn.r_port){ - if(!memcmp(saddr,&conn->conn.r_addr,sizeof(struct sockaddr_storage)) - && !memcmp(daddr,&conn->conn.i_addr,sizeof(struct sockaddr_storage))) - { - *directionp=DIR_R2I; - *connp=&(conn->conn); - return(0); - } + for(conn = first_conn; conn; conn = conn->next) { + if(sport == conn->conn.i_port && dport == conn->conn.r_port) { + if(!memcmp(saddr, &conn->conn.i_addr, sizeof(struct sockaddr_storage)) && + !memcmp(daddr, &conn->conn.r_addr, sizeof(struct sockaddr_storage))) { + *directionp = DIR_I2R; + *connp = &(conn->conn); + return (0); } } - return(R_NOT_FOUND); + if(dport == conn->conn.i_port && sport == conn->conn.r_port) { + if(!memcmp(saddr, &conn->conn.r_addr, sizeof(struct sockaddr_storage)) && + !memcmp(daddr, &conn->conn.i_addr, sizeof(struct sockaddr_storage))) { + *directionp = DIR_R2I; + *connp = &(conn->conn); + return (0); + } + } } -int tcp_create_conn(tcp_conn **connp,struct sockaddr_storage *i_addr, - u_short i_port, struct sockaddr_storage *r_addr, u_short r_port) - { - conn_struct *conn=0; - - if(!(conn=(conn_struct *)malloc(sizeof(conn_struct)))) - return(R_NO_MEMORY); - - conn->prev=0; - - zero_conn(&conn->conn); - conn->conn.backptr=conn; - conn->conn.conn_number=conn_number++; - - memcpy(&conn->conn.i_addr,i_addr,sizeof(struct sockaddr_storage)); - conn->conn.i_port=i_port; - memcpy(&conn->conn.r_addr,r_addr,sizeof(struct sockaddr_storage)); - conn->conn.r_port=r_port; - *connp=&(conn->conn); - - /* Insert at the head of the list */ - conn->next=first_conn; - if(first_conn) - first_conn->prev=conn; - first_conn=conn; - - - return(0); - } - -int -tcp_destroy_conn (tcp_conn *conn) - { - conn_struct *c=conn->backptr; - - /* Detach from the list */ - if(c->next){ - c->next->prev=c->prev; - } - if(c->prev){ - c->prev->next=c->next; - } - else { - first_conn=c->next; - } - - destroy_proto_handler(&conn->analyzer); - free_tcp_segment_queue(conn->i2r.oo_queue); - free_tcp_segment_queue(conn->r2i.oo_queue); - free(conn->i_name); - free(conn->r_name); - free(conn->i_num); - free(conn->r_num); - zero_conn(conn); - free(conn->backptr); - free(conn); - - return(0); - } - -int -clean_old_conn (void) { - conn_struct *conn; - tcp_conn *tcpconn; - struct timeval dt; - int i = 0; - - if(!last_packet_seen_time.tv_sec) - return 0; // Still processing first block of packets - - conn = first_conn; - while(conn) { - tcpconn = &conn->conn; - conn=conn->next; - if(timestamp_diff(&last_packet_seen_time, &tcpconn->last_seen_time, &dt)) - continue; - if(dt.tv_sec > conn_ttl) { - i++; - tcp_destroy_conn(tcpconn); - } - } - return i; + return (R_NOT_FOUND); } -int -destroy_all_conn (void) { - int i = 0; - while(first_conn) { - i++; - tcp_destroy_conn(&first_conn->conn); - } - return i; +int tcp_create_conn(tcp_conn **connp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port) { + conn_struct *conn = 0; + + if(!(conn = (conn_struct *)malloc(sizeof(conn_struct)))) + return (R_NO_MEMORY); + + conn->prev = 0; + + zero_conn(&conn->conn); + conn->conn.backptr = conn; + conn->conn.conn_number = conn_number++; + + memcpy(&conn->conn.i_addr, i_addr, sizeof(struct sockaddr_storage)); + conn->conn.i_port = i_port; + memcpy(&conn->conn.r_addr, r_addr, sizeof(struct sockaddr_storage)); + conn->conn.r_port = r_port; + *connp = &(conn->conn); + + /* Insert at the head of the list */ + conn->next = first_conn; + if(first_conn) + first_conn->prev = conn; + first_conn = conn; + + return (0); } -int -free_tcp_segment_queue (segment *seg) - { - segment *tmp; +int tcp_destroy_conn(tcp_conn *conn) { + conn_struct *c = conn->backptr; - while(seg){ - tmp=seg->next; - packet_destroy(seg->p); - free(seg); - seg=tmp; - } - - return(0); + /* Detach from the list */ + if(c->next) { + c->next->prev = c->prev; + } + if(c->prev) { + c->prev->next = c->next; + } else { + first_conn = c->next; } -int -copy_tcp_segment_queue (segment **out, segment *in) - { - int r,_status; - segment *base=0; - - for(;in;in=in->next){ - if(!(*out=(segment *)calloc(1,sizeof(segment)))) - ABORT(R_NO_MEMORY); - if(!base) base=*out; + destroy_proto_handler(&conn->analyzer); + free_tcp_segment_queue(conn->i2r.oo_queue); + free_tcp_segment_queue(conn->r2i.oo_queue); + free(conn->i_name); + free(conn->r_name); + free(conn->i_num); + free(conn->r_num); + zero_conn(conn); + free(conn->backptr); + free(conn); - if((r=packet_copy(in->p,&(*out)->p))) - ABORT(r); - out=&(*out)->next; /* Move the pointer we're assigning to */ - } + return (0); +} - _status=0; - abort: - if(_status){ - free_tcp_segment_queue(base); +int clean_old_conn(void) { + conn_struct *conn; + tcp_conn *tcpconn; + struct timeval dt; + int i = 0; + + if(!last_packet_seen_time.tv_sec) + return 0; // Still processing first block of packets + + conn = first_conn; + while(conn) { + tcpconn = &conn->conn; + conn = conn->next; + if(timestamp_diff(&last_packet_seen_time, &tcpconn->last_seen_time, &dt)) + continue; + if(dt.tv_sec > conn_ttl) { + i++; + tcp_destroy_conn(tcpconn); } - return(_status); } + return i; +} + +int destroy_all_conn(void) { + int i = 0; + while(first_conn) { + i++; + tcp_destroy_conn(&first_conn->conn); + } + return i; +} + +int free_tcp_segment_queue(segment *seg) { + segment *tmp; + + while(seg) { + tmp = seg->next; + packet_destroy(seg->p); + free(seg); + seg = tmp; + } + + return (0); +} + +int copy_tcp_segment_queue(segment **out, segment *in) { + int r, _status; + segment *base = 0; + + for(; in; in = in->next) { + if(!(*out = (segment *)calloc(1, sizeof(segment)))) + ABORT(R_NO_MEMORY); + if(!base) + base = *out; + + if((r = packet_copy(in->p, &(*out)->p))) + ABORT(r); + out = &(*out)->next; /* Move the pointer we're assigning to */ + } + + _status = 0; +abort: + if(_status) { + free_tcp_segment_queue(base); + } + return (_status); +} diff --git a/base/tcpconn.h b/base/tcpconn.h index 6748d6c..fc5ae22 100644 --- a/base/tcpconn.h +++ b/base/tcpconn.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: tcpconn.h,v 1.4 2001/07/20 23:33:15 ekr Exp $ @@ -43,70 +44,72 @@ ekr@rtfm.com Tue Dec 29 13:00:52 1998 */ - #ifndef _tcpconn_h #define _tcpconn_h typedef struct segment_ { - u_char *data; - u_int len; - tcp_seq s_seq; - packet *p; - struct segment_ *next; + u_char *data; + u_int len; + tcp_seq s_seq; + packet *p; + struct segment_ *next; } segment; typedef struct stream_data_ { - tcp_seq seq; - tcp_seq ack; - short close; - segment *oo_queue; + tcp_seq seq; + tcp_seq ack; + short close; + segment *oo_queue; } stream_data; typedef struct tcp_conn_ { - int conn_number; - int state; -#define TCP_STATE_SYN1 1 -#define TCP_STATE_SYN2 2 -#define TCP_STATE_ACK 3 -#define TCP_STATE_ESTABLISHED 4 -#define TCP_STATE_FIN1 5 + int conn_number; + int state; +#define TCP_STATE_SYN1 1 +#define TCP_STATE_SYN2 2 +#define TCP_STATE_ACK 3 +#define TCP_STATE_ESTABLISHED 4 +#define TCP_STATE_FIN1 5 #define TCP_STATE_CLOSED 6 - /*The address which sent the first SYN*/ - struct sockaddr_storage i_addr; - u_short i_port; - char *i_name; - char *i_num; + /*The address which sent the first SYN*/ + struct sockaddr_storage i_addr; + u_short i_port; + char *i_name; + char *i_num; - /*The address which sent the second SYN*/ - struct sockaddr_storage r_addr; - u_short r_port; - char *r_name; - char *r_num; + /*The address which sent the second SYN*/ + struct sockaddr_storage r_addr; + u_short r_port; + char *r_name; + char *r_num; - stream_data i2r; /*The stream from initiator to responder*/ - stream_data r2i; /*The stream from responder to initiator*/ - - struct timeval start_time; - struct timeval last_seen_time; - proto_handler *analyzer; /*The analyzer to call with new data*/ - struct conn_struct_ *backptr; + stream_data i2r; /*The stream from initiator to responder*/ + stream_data r2i; /*The stream from responder to initiator*/ + + struct timeval start_time; + struct timeval last_seen_time; + proto_handler *analyzer; /*The analyzer to call with new data*/ + struct conn_struct_ *backptr; } tcp_conn; -int tcp_find_conn PROTO_LIST((tcp_conn **connp, - int *directionp, - struct sockaddr_storage *src_addr, u_short src_port, - struct sockaddr_storage *dst_addr, u_short dst_port)); +int tcp_find_conn PROTO_LIST((tcp_conn * *connp, + int *directionp, + struct sockaddr_storage *src_addr, + u_short src_port, + struct sockaddr_storage *dst_addr, + u_short dst_port)); -int tcp_create_conn PROTO_LIST((tcp_conn **connp, - struct sockaddr_storage *initiator_addr, u_short initiator_port, - struct sockaddr_storage *responder_addr, u_short responder_port)); +int tcp_create_conn PROTO_LIST((tcp_conn * *connp, + struct sockaddr_storage *initiator_addr, + u_short initiator_port, + struct sockaddr_storage *responder_addr, + u_short responder_port)); -int tcp_destroy_conn PROTO_LIST((tcp_conn *conn)); -int free_tcp_segment_queue PROTO_LIST((segment *seg)); -int copy_tcp_segment_queue PROTO_LIST((segment **out,segment *in)); +int tcp_destroy_conn PROTO_LIST((tcp_conn * conn)); +int free_tcp_segment_queue PROTO_LIST((segment * seg)); +int copy_tcp_segment_queue PROTO_LIST((segment * *out, segment *in)); int clean_old_conn(void); int destroy_all_conn(void); #endif - diff --git a/base/tcppack.c b/base/tcppack.c index 04fceed..3421a7c 100644 --- a/base/tcppack.c +++ b/base/tcppack.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: tcppack.c,v 1.11 2002/09/09 21:02:58 ekr Exp $ @@ -43,164 +44,159 @@ ekr@rtfm.com Tue Dec 29 12:43:39 1998 */ - - #include "network.h" #ifndef _WIN32 -# include -# include -# ifndef LINUX -# include -# else -# define SEQ_LT(x,y) ((int)((x)-(y))<0) -# endif +#include +#include +#ifndef LINUX +#include #else -# include -# define SEQ_LT(x,y) ((int)((x)-(y))<0) +#define SEQ_LT(x, y) ((int)((x) - (y)) < 0) +#endif +#else +#include +#define SEQ_LT(x, y) ((int)((x) - (y)) < 0) #endif #include #include "debug.h" #include "tcpconn.h" #include "tcppack.h" +static int process_data_segment PROTO_LIST((tcp_conn * conn, + proto_mod *handler, + packet *p, + stream_data *stream, + int direction)); +static int new_connection PROTO_LIST( + (proto_mod * handler, proto_ctx *ctx, packet *p, tcp_conn **connp)); +static int print_tcp_packet PROTO_LIST((packet * p)); +int STRIM PROTO_LIST((UINT4 _seq, segment *s)); -static int process_data_segment PROTO_LIST((tcp_conn *conn, - proto_mod *handler,packet *p,stream_data *stream,int direction)); -static int new_connection PROTO_LIST((proto_mod *handler,proto_ctx *ctx, - packet *p,tcp_conn **connp)); -static int print_tcp_packet PROTO_LIST((packet *p)); -int STRIM PROTO_LIST((UINT4 _seq,segment *s)); +int process_tcp_packet(proto_mod *handler, proto_ctx *ctx, packet *p) { + int r, _status; + int direction; + stream_data *stream; + tcp_conn *conn; -int -process_tcp_packet (proto_mod *handler, proto_ctx *ctx, packet *p) - { - int r,_status; - int direction; - stream_data *stream; - tcp_conn *conn; + if(p->len < 20) + ABORT(1); - if(p->len < 20) - ABORT(1); + p->tcp = (struct tcphdr *)p->data; - p->tcp=(struct tcphdr *)p->data; + print_tcp_packet(p); - print_tcp_packet(p); - - if((r=tcp_find_conn(&conn,&direction,&p->i_addr.so_st, - ntohs(p->tcp->th_sport),&p->r_addr.so_st,ntohs(p->tcp->th_dport)))){ - if(r!=R_NOT_FOUND) - ABORT(r); - - if((p->tcp->th_flags & TH_SYN)!=TH_SYN){ - DBG((0,"TCP: rejecting packet from unknown connection, seq: %u\n",ntohl(p->tcp->th_seq))); - return(0); - } - - if((r=new_connection(handler,ctx,p,&conn))) - ABORT(r); - return(0); - } - - stream=direction==DIR_R2I?&conn->r2i:&conn->i2r; - - memcpy(&conn->last_seen_time,&p->ts,sizeof(struct timeval)); - - switch(conn->state){ - case TCP_STATE_SYN1: - if(direction == DIR_R2I && (p->tcp->th_flags & TH_SYN)) { - DBG((0,"SYN2 seq: %u",ntohl(p->tcp->th_seq))); - conn->r2i.seq=ntohl(p->tcp->th_seq)+1; - conn->r2i.ack=ntohl(p->tcp->th_ack)+1; - conn->state=TCP_STATE_ACK; - } - break; - case TCP_STATE_SYN2: - if(direction == DIR_I2R && (p->tcp->th_flags & TH_SYN)) { - DBG((0,"SYN1 seq: %u",ntohl(p->tcp->th_seq))); - conn->i2r.seq=ntohl(p->tcp->th_seq)+1; - conn->i2r.ack=ntohl(p->tcp->th_ack)+1; - conn->state=TCP_STATE_ACK; - } - break; - case TCP_STATE_ACK: - { - if(direction != DIR_I2R) - break; - DBG((0,"ACK seq: %u",ntohl(p->tcp->th_seq))); - conn->i2r.ack=ntohl(p->tcp->th_ack)+1; - if(!(NET_print_flags & NET_PRINT_JSON)) { - if(NET_print_flags & NET_PRINT_TYPESET) - printf("\\fC"); - printf("New TCP connection #%d: %s(%d) <-> %s(%d)\n", - conn->conn_number, - conn->i_name,conn->i_port, - conn->r_name,conn->r_port); - if(NET_print_flags & NET_PRINT_TYPESET) - printf("\\fR"); - } - conn->state=TCP_STATE_ESTABLISHED; - } - case TCP_STATE_ESTABLISHED: - case TCP_STATE_FIN1: - { - if(p->tcp->th_flags & TH_SYN) - break; - if((r=process_data_segment(conn,handler,p,stream,direction))) - ABORT(r); - } - break; - default: - break; - } - - if(conn->state==TCP_STATE_CLOSED) - tcp_destroy_conn(conn); - - - _status=0; - abort: - - return(_status); - } - -static int -new_connection (proto_mod *handler, proto_ctx *ctx, packet *p, tcp_conn **connp) - { - int r,_status; - tcp_conn *conn=0; - - if ((p->tcp->th_flags & (TH_SYN|TH_ACK))==TH_SYN) { - if((r=tcp_create_conn(&conn,&p->i_addr.so_st,ntohs(p->tcp->th_sport), - &p->r_addr.so_st,ntohs(p->tcp->th_dport)))) - ABORT(r); - DBG((0,"SYN1 seq: %u",ntohl(p->tcp->th_seq))); - conn->i2r.seq=ntohl(p->tcp->th_seq)+1; - conn->i2r.ack=ntohl(p->tcp->th_ack)+1; - conn->state=TCP_STATE_SYN1; - } else { // SYN&ACK comes first somehow - if((r=tcp_create_conn(&conn,&p->r_addr.so_st,ntohs(p->tcp->th_dport), - &p->i_addr.so_st,ntohs(p->tcp->th_sport)))) - ABORT(r); - DBG((0,"SYN2 seq: %u",ntohl(p->tcp->th_seq))); - conn->r2i.seq=ntohl(p->tcp->th_seq)+1; - conn->r2i.ack=ntohl(p->tcp->th_ack)+1; - conn->state=TCP_STATE_SYN2; - } - memcpy(&conn->start_time,&p->ts,sizeof(struct timeval)); - memcpy(&conn->last_seen_time,&p->ts,sizeof(struct timeval)); - lookuphostname(&conn->i_addr,&conn->i_name); - lookuphostname(&conn->r_addr,&conn->r_name); - addrtotext(&conn->i_addr,&conn->i_num); - addrtotext(&conn->r_addr,&conn->r_num); - if((r=create_proto_handler(handler,ctx,&conn->analyzer,conn,&p->ts))) + if((r = tcp_find_conn(&conn, &direction, &p->i_addr.so_st, + ntohs(p->tcp->th_sport), &p->r_addr.so_st, + ntohs(p->tcp->th_dport)))) { + if(r != R_NOT_FOUND) ABORT(r); - - *connp=conn; - _status=0; - abort: - return(_status); + + if((p->tcp->th_flags & TH_SYN) != TH_SYN) { + DBG((0, "TCP: rejecting packet from unknown connection, seq: %u\n", + ntohl(p->tcp->th_seq))); + return (0); + } + + if((r = new_connection(handler, ctx, p, &conn))) + ABORT(r); + return (0); } + stream = direction == DIR_R2I ? &conn->r2i : &conn->i2r; + + memcpy(&conn->last_seen_time, &p->ts, sizeof(struct timeval)); + + switch(conn->state) { + case TCP_STATE_SYN1: + if(direction == DIR_R2I && (p->tcp->th_flags & TH_SYN)) { + DBG((0, "SYN2 seq: %u", ntohl(p->tcp->th_seq))); + conn->r2i.seq = ntohl(p->tcp->th_seq) + 1; + conn->r2i.ack = ntohl(p->tcp->th_ack) + 1; + conn->state = TCP_STATE_ACK; + } + break; + case TCP_STATE_SYN2: + if(direction == DIR_I2R && (p->tcp->th_flags & TH_SYN)) { + DBG((0, "SYN1 seq: %u", ntohl(p->tcp->th_seq))); + conn->i2r.seq = ntohl(p->tcp->th_seq) + 1; + conn->i2r.ack = ntohl(p->tcp->th_ack) + 1; + conn->state = TCP_STATE_ACK; + } + break; + case TCP_STATE_ACK: { + if(direction != DIR_I2R) + break; + DBG((0, "ACK seq: %u", ntohl(p->tcp->th_seq))); + conn->i2r.ack = ntohl(p->tcp->th_ack) + 1; + if(!(NET_print_flags & NET_PRINT_JSON)) { + if(NET_print_flags & NET_PRINT_TYPESET) + printf("\\fC"); + printf("New TCP connection #%d: %s(%d) <-> %s(%d)\n", conn->conn_number, + conn->i_name, conn->i_port, conn->r_name, conn->r_port); + if(NET_print_flags & NET_PRINT_TYPESET) + printf("\\fR"); + } + conn->state = TCP_STATE_ESTABLISHED; + } + case TCP_STATE_ESTABLISHED: + case TCP_STATE_FIN1: { + if(p->tcp->th_flags & TH_SYN) + break; + if((r = process_data_segment(conn, handler, p, stream, direction))) + ABORT(r); + } break; + default: + break; + } + + if(conn->state == TCP_STATE_CLOSED) + tcp_destroy_conn(conn); + + _status = 0; +abort: + + return (_status); +} + +static int new_connection(proto_mod *handler, + proto_ctx *ctx, + packet *p, + tcp_conn **connp) { + int r, _status; + tcp_conn *conn = 0; + + if((p->tcp->th_flags & (TH_SYN | TH_ACK)) == TH_SYN) { + if((r = tcp_create_conn(&conn, &p->i_addr.so_st, ntohs(p->tcp->th_sport), + &p->r_addr.so_st, ntohs(p->tcp->th_dport)))) + ABORT(r); + DBG((0, "SYN1 seq: %u", ntohl(p->tcp->th_seq))); + conn->i2r.seq = ntohl(p->tcp->th_seq) + 1; + conn->i2r.ack = ntohl(p->tcp->th_ack) + 1; + conn->state = TCP_STATE_SYN1; + } else { // SYN&ACK comes first somehow + if((r = tcp_create_conn(&conn, &p->r_addr.so_st, ntohs(p->tcp->th_dport), + &p->i_addr.so_st, ntohs(p->tcp->th_sport)))) + ABORT(r); + DBG((0, "SYN2 seq: %u", ntohl(p->tcp->th_seq))); + conn->r2i.seq = ntohl(p->tcp->th_seq) + 1; + conn->r2i.ack = ntohl(p->tcp->th_ack) + 1; + conn->state = TCP_STATE_SYN2; + } + memcpy(&conn->start_time, &p->ts, sizeof(struct timeval)); + memcpy(&conn->last_seen_time, &p->ts, sizeof(struct timeval)); + lookuphostname(&conn->i_addr, &conn->i_name); + lookuphostname(&conn->r_addr, &conn->r_name); + addrtotext(&conn->i_addr, &conn->i_num); + addrtotext(&conn->r_addr, &conn->r_num); + if((r = create_proto_handler(handler, ctx, &conn->analyzer, conn, &p->ts))) + ABORT(r); + + *connp = conn; + _status = 0; +abort: + return (_status); +} + /*#define STRIM(_seq,s) { \ int l;\ int off;\ @@ -213,258 +209,253 @@ new_connection (proto_mod *handler, proto_ctx *ctx, packet *p, tcp_conn **connp) if((s)->next) { \ if((s)->s_seq >= (s)->next->s_seq) {\ l=(s)->next->s_seq - (s)->s_seq; \ - if((s)->len){\ - (s)->len-=(l+1); \ - (s)->s_seq-=(l+1);\ - }\ + if((s)->len){\ + (s)->len-=(l+1); \ + (s)->s_seq-=(l+1);\ + }\ }\ }\ } */ -static int -process_data_segment (tcp_conn *conn, proto_mod *handler, packet *p, stream_data *stream, int direction) - { - int r,_status; - tcp_seq seq,right_edge; - segment _seg; - segment *seg,*nseg=0; - long l; +static int process_data_segment(tcp_conn *conn, + proto_mod *handler, + packet *p, + stream_data *stream, + int direction) { + int r, _status; + tcp_seq seq, right_edge; + segment _seg; + segment *seg, *nseg = 0; + long l; - l=p->len - p->tcp->th_off * 4; + l = p->len - p->tcp->th_off * 4; - if(l < 0) { - fprintf(stderr,"Malformed packet, computed TCP segment size is negative, skipping ...\n"); - return(0); - } - - if(stream->close){ - DBG((0,"Rejecting packet received after FIN: %u:%u(%u)", - ntohl(p->tcp->th_seq),ntohl(p->tcp->th_seq+l),l)); - return(0); - } - - /*The idea here is to pass all available segments - to the analyzer at once. Since we want to preserve - the segment packet data, we pass the data as a linked list of - segments*/ - seq=ntohl(p->tcp->th_seq); - - /*Add ACK processing logic here */ - if(p->tcp->th_flags & TH_ACK){ - long acknum,acked; - - - acknum=ntohl(p->tcp->th_ack); - acked=acknum-stream->ack; - - if(acked && !l){ - /* - if((r=timestamp_diff(&p->ts,&conn->start_time,&dt))) - ERETURN(r); - printf("%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100); - if(direction == DIR_R2I) - printf("S>C "); - else - printf("C>S "); - - printf("ACK (%d)\n",acked); */ - } - - stream->ack=acknum; - } - - - DBG((0,"Stream Seq %u ",stream->seq)); - - /* Check to see if this packet has been processed already */ - right_edge=seq + (p->len - (p->tcp->th_off)*4); - if(!(p->tcp->th_flags & (TH_RST)) && SEQ_LT(right_edge,stream->seq)) - return(0); - - if(SEQ_LT(stream->seq,seq)){ - /* Out of order segment */ - tcp_seq left_edge; - - for(seg=0;seg;seg=seg?seg->next:stream->oo_queue){ - if(seg->next->s_seq > seq) - break; - } - - if(!(nseg=(segment *)calloc(1,sizeof(segment)))) - ABORT(R_NO_MEMORY); - if((r=packet_copy(p,&nseg->p))) - ABORT(r); - nseg->s_seq=seq; - - /*Insert this segment into the reassembly queue*/ - if(seg){ - nseg->next=seg->next; - seg->next=nseg; - } - else{ - nseg->next=stream->oo_queue; - stream->oo_queue=nseg; - } - - left_edge=seg?seg->s_seq:stream->seq; - STRIM(left_edge,nseg); - } - else{ - /*First segment -- just thread the unallocated data on the - list so we can pass to the analyzer*/ - _seg.next=0; - _seg.p=p; - _seg.s_seq=seq; - - /*Now split the queue. Assemble as many packets as possible - and pass them to the analyzer. But process anything with a - RST in it immediately and ignore any data that might be in it - */ - if(_seg.p->tcp->th_flags & (TH_RST)){ - stream->close=_seg.p->tcp->th_flags & (TH_RST); - seg=&_seg; - - conn->state=TCP_STATE_CLOSED; - } - else{ - STRIM(stream->seq,&_seg); - - if(_seg.p->tcp->th_flags & (TH_FIN)){ - stream->close=_seg.p->tcp->th_flags & (TH_FIN); - seg=&_seg; - } - else { - for(seg=&_seg;seg->next;seg=seg->next){ - if(seg->p->tcp->th_flags & (TH_FIN)){ - stream->close=_seg.p->tcp->th_flags & (TH_FIN); - break; - } - if(seg->len + seg->s_seq != seg->next->s_seq) - break; - } - } - - /*Note that this logic is broken because it doesn't - do the CLOSE_WAIT/FIN_WAIT stuff, but it's probably - close enough, since this is a higher level protocol analyzer, - not a TCP analyzer*/ - if(seg->p->tcp->th_flags & (TH_FIN) ){ - if(conn->state == TCP_STATE_ESTABLISHED) - conn->state=TCP_STATE_FIN1; - else - conn->state=TCP_STATE_CLOSED; - } - - free_tcp_segment_queue(stream->oo_queue); - stream->oo_queue=seg->next; - seg->next=0; - stream->seq=seg->s_seq + seg->len; - - DBG((0,"Analyzing segment: %u:%u(%u)", seg->s_seq, seg->s_seq+seg->len, seg->len)); - if((r=conn->analyzer->vtbl->data(conn->analyzer->obj,&_seg,direction))) { - DBG((0,"ABORT due to segment: %u:%u(%u)", seg->s_seq, seg->s_seq+seg->len, seg->len)); - ABORT(r); - } - } - - if(stream->close){ - DBG((0,"Closing with segment: %u:%u(%u)", seg->s_seq, stream->seq, seg->len)); - if((r=conn->analyzer->vtbl->close(conn->analyzer->obj,p,direction))) { - DBG((0,"ABORT due to segment: %u:%u(%u)", seg->s_seq, stream->seq, seg->len)); - ABORT(r); - } - } - - free_tcp_segment_queue(_seg.next); - } - - _status=0; - abort: - return(_status); + if(l < 0) { + fprintf(stderr, + "Malformed packet, computed TCP segment size is negative, skipping " + "...\n"); + return (0); } -static int -print_tcp_packet (packet *p) - { - char *src=0,*dst=0; - - struct timeval *ts = &p->ts; - - if(!(NET_print_flags & NET_PRINT_TCP_HDR)) - return(0); - - lookuphostname(&p->i_addr.so_st,&src); - lookuphostname(&p->r_addr.so_st,&dst); - - if(!(NET_print_flags & NET_PRINT_JSON)) { - if(NET_print_flags & NET_PRINT_TS) { - printf("%lld%c%4.4lld ", (long long)ts->tv_sec,'.',(long long)ts->tv_usec/100); - } - printf("TCP: %s(%d) -> %s(%d) ", - src, - ntohs(p->tcp->th_sport), - dst, - ntohs(p->tcp->th_dport)); - - printf("Seq %u.(%d) ", - ntohl(p->tcp->th_seq), - p->len - p->tcp->th_off *4); - - if(p->tcp->th_flags & TH_ACK) - printf("ACK %u ",ntohl(p->tcp->th_ack)); - - if(p->tcp->th_flags & TH_FIN) - printf("FIN "); - if(p->tcp->th_flags & TH_SYN) - printf("SYN "); - if(p->tcp->th_flags & TH_RST) - printf("RST "); - if(p->tcp->th_flags & TH_PUSH) - printf("PUSH "); - if(p->tcp->th_flags & TH_URG) - printf("URG "); - - printf("\n"); - } - free(src); - free(dst); - return(0); + if(stream->close) { + DBG((0, "Rejecting packet received after FIN: %u:%u(%u)", + ntohl(p->tcp->th_seq), ntohl(p->tcp->th_seq + l), l)); + return (0); } -int -STRIM (UINT4 _seq, segment *s) - { - int l; - int off; + /*The idea here is to pass all available segments + to the analyzer at once. Since we want to preserve + the segment packet data, we pass the data as a linked list of + segments*/ + seq = ntohl(p->tcp->th_seq); - /* Test: this shouldn't damage things at all - s->p->data-=4; - s->p->len+=4; - s->s_seq-=4; + /*Add ACK processing logic here */ + if(p->tcp->th_flags & TH_ACK) { + long acknum, acked; + + acknum = ntohl(p->tcp->th_ack); + acked = acknum - stream->ack; + + if(acked && !l) { + /* + if((r=timestamp_diff(&p->ts,&conn->start_time,&dt))) + ERETURN(r); + printf("%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100); + if(direction == DIR_R2I) + printf("S>C "); + else + printf("C>S "); + + printf("ACK (%d)\n",acked); */ + } + + stream->ack = acknum; + } + + DBG((0, "Stream Seq %u ", stream->seq)); + + /* Check to see if this packet has been processed already */ + right_edge = seq + (p->len - (p->tcp->th_off) * 4); + if(!(p->tcp->th_flags & (TH_RST)) && SEQ_LT(right_edge, stream->seq)) + return (0); + + if(SEQ_LT(stream->seq, seq)) { + /* Out of order segment */ + tcp_seq left_edge; + + for(seg = 0; seg; seg = seg ? seg->next : stream->oo_queue) { + if(seg->next->s_seq > seq) + break; + } + + if(!(nseg = (segment *)calloc(1, sizeof(segment)))) + ABORT(R_NO_MEMORY); + if((r = packet_copy(p, &nseg->p))) + ABORT(r); + nseg->s_seq = seq; + + /*Insert this segment into the reassembly queue*/ + if(seg) { + nseg->next = seg->next; + seg->next = nseg; + } else { + nseg->next = stream->oo_queue; + stream->oo_queue = nseg; + } + + left_edge = seg ? seg->s_seq : stream->seq; + STRIM(left_edge, nseg); + } else { + /*First segment -- just thread the unallocated data on the + list so we can pass to the analyzer*/ + _seg.next = 0; + _seg.p = p; + _seg.s_seq = seq; + + /*Now split the queue. Assemble as many packets as possible + and pass them to the analyzer. But process anything with a + RST in it immediately and ignore any data that might be in it */ - - l=_seq - (s)->s_seq; /* number of bytes to trim - from the left of s */ - off=(s)->p->tcp->th_off*4; - if(l>((s)->p->len-off)) ERETURN(R_BAD_DATA); + if(_seg.p->tcp->th_flags & (TH_RST)) { + stream->close = _seg.p->tcp->th_flags & (TH_RST); + seg = &_seg; - /* Now remove the leading l bytes */ - (s)->data=(s)->p->data + off + (l) ; - (s)->len=(s)->p->len - (off + l); - (s)->s_seq += (l); + conn->state = TCP_STATE_CLOSED; + } else { + STRIM(stream->seq, &_seg); - /* Now trim to the right if necessary */ - if((s)->next) { - if((s)->s_seq >= (s)->next->s_seq) { - l=(s)->s_seq - (s)->next->s_seq; - - if((s)->len){ - (s)->len-=(l+1); - } + if(_seg.p->tcp->th_flags & (TH_FIN)) { + stream->close = _seg.p->tcp->th_flags & (TH_FIN); + seg = &_seg; + } else { + for(seg = &_seg; seg->next; seg = seg->next) { + if(seg->p->tcp->th_flags & (TH_FIN)) { + stream->close = _seg.p->tcp->th_flags & (TH_FIN); + break; + } + if(seg->len + seg->s_seq != seg->next->s_seq) + break; + } + } + + /*Note that this logic is broken because it doesn't + do the CLOSE_WAIT/FIN_WAIT stuff, but it's probably + close enough, since this is a higher level protocol analyzer, + not a TCP analyzer*/ + if(seg->p->tcp->th_flags & (TH_FIN)) { + if(conn->state == TCP_STATE_ESTABLISHED) + conn->state = TCP_STATE_FIN1; + else + conn->state = TCP_STATE_CLOSED; + } + + free_tcp_segment_queue(stream->oo_queue); + stream->oo_queue = seg->next; + seg->next = 0; + stream->seq = seg->s_seq + seg->len; + + DBG((0, "Analyzing segment: %u:%u(%u)", seg->s_seq, seg->s_seq + seg->len, + seg->len)); + if((r = conn->analyzer->vtbl->data(conn->analyzer->obj, &_seg, + direction))) { + DBG((0, "ABORT due to segment: %u:%u(%u)", seg->s_seq, + seg->s_seq + seg->len, seg->len)); + ABORT(r); } } - - return(0); + + if(stream->close) { + DBG((0, "Closing with segment: %u:%u(%u)", seg->s_seq, stream->seq, + seg->len)); + if((r = conn->analyzer->vtbl->close(conn->analyzer->obj, p, direction))) { + DBG((0, "ABORT due to segment: %u:%u(%u)", seg->s_seq, stream->seq, + seg->len)); + ABORT(r); + } + } + + free_tcp_segment_queue(_seg.next); } + _status = 0; +abort: + return (_status); +} + +static int print_tcp_packet(packet *p) { + char *src = 0, *dst = 0; + + struct timeval *ts = &p->ts; + + if(!(NET_print_flags & NET_PRINT_TCP_HDR)) + return (0); + + lookuphostname(&p->i_addr.so_st, &src); + lookuphostname(&p->r_addr.so_st, &dst); + + if(!(NET_print_flags & NET_PRINT_JSON)) { + if(NET_print_flags & NET_PRINT_TS) { + printf("%lld%c%4.4lld ", (long long)ts->tv_sec, '.', + (long long)ts->tv_usec / 100); + } + printf("TCP: %s(%d) -> %s(%d) ", src, ntohs(p->tcp->th_sport), dst, + ntohs(p->tcp->th_dport)); + + printf("Seq %u.(%d) ", ntohl(p->tcp->th_seq), p->len - p->tcp->th_off * 4); + + if(p->tcp->th_flags & TH_ACK) + printf("ACK %u ", ntohl(p->tcp->th_ack)); + + if(p->tcp->th_flags & TH_FIN) + printf("FIN "); + if(p->tcp->th_flags & TH_SYN) + printf("SYN "); + if(p->tcp->th_flags & TH_RST) + printf("RST "); + if(p->tcp->th_flags & TH_PUSH) + printf("PUSH "); + if(p->tcp->th_flags & TH_URG) + printf("URG "); + + printf("\n"); + } + free(src); + free(dst); + return (0); +} + +int STRIM(UINT4 _seq, segment *s) { + int l; + int off; + + /* Test: this shouldn't damage things at all + s->p->data-=4; + s->p->len+=4; + s->s_seq-=4; + */ + + l = _seq - (s)->s_seq; /* number of bytes to trim + from the left of s */ + off = (s)->p->tcp->th_off * 4; + if(l > ((s)->p->len - off)) + ERETURN(R_BAD_DATA); + + /* Now remove the leading l bytes */ + (s)->data = (s)->p->data + off + (l); + (s)->len = (s)->p->len - (off + l); + (s)->s_seq += (l); + + /* Now trim to the right if necessary */ + if((s)->next) { + if((s)->s_seq >= (s)->next->s_seq) { + l = (s)->s_seq - (s)->next->s_seq; + + if((s)->len) { + (s)->len -= (l + 1); + } + } + } + + return (0); +} diff --git a/base/tcppack.h b/base/tcppack.h index b9ed111..fb51618 100644 --- a/base/tcppack.h +++ b/base/tcppack.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: tcppack.h,v 1.3 2001/07/20 23:33:15 ekr Exp $ @@ -43,12 +44,9 @@ ekr@rtfm.com Wed Jan 6 15:08:30 1999 */ - #ifndef _tcppack_h #define _tcppack_h -int process_tcp_packet PROTO_LIST((proto_mod *mod,proto_ctx *ctx, - packet *p)); +int process_tcp_packet PROTO_LIST((proto_mod * mod, proto_ctx *ctx, packet *p)); #endif - diff --git a/common/include/r_assoc.h b/common/include/r_assoc.h index 699f287..e2ee3cc 100644 --- a/common/include/r_assoc.h +++ b/common/include/r_assoc.h @@ -4,7 +4,7 @@ Associative array code. This code has the advantage that different elements can have different create and destroy operators. Unfortunately, this can waste space. - + Copyright (C) 1999-2000 RTFM, Inc. All Rights Reserved @@ -22,7 +22,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -39,7 +39,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_assoc.h,v 1.3 2001/12/24 06:06:26 ekr Exp $ @@ -47,37 +48,39 @@ ekr@rtfm.com Sun Jan 17 17:57:18 1999 */ - #ifndef _r_assoc_h #define _r_assoc_h typedef struct r_assoc_ r_assoc; -int r_assoc_create PROTO_LIST((r_assoc **assocp)); -int r_assoc_insert PROTO_LIST((r_assoc *assoc,char *key,int len, - void *value,int (*copy)(void **new,void *old), - int (*destroy)(void *ptr),int how)); -#define R_ASSOC_REPLACE 0x1 -#define R_ASSOC_NEW 0x2 +int r_assoc_create PROTO_LIST((r_assoc * *assocp)); +int r_assoc_insert PROTO_LIST((r_assoc * assoc, + char *key, + int len, + void *value, + int (*copy)(void **new, void *old), + int (*destroy)(void *ptr), + int how)); +#define R_ASSOC_REPLACE 0x1 +#define R_ASSOC_NEW 0x2 -int r_assoc_fetch PROTO_LIST((r_assoc *assoc,char *key, int len, - void **value)); -int r_assoc_copy PROTO_LIST((r_assoc **new,r_assoc *old)); -int r_assoc_destroy PROTO_LIST((r_assoc **assocp)); +int r_assoc_fetch + PROTO_LIST((r_assoc * assoc, char *key, int len, void **value)); +int r_assoc_copy PROTO_LIST((r_assoc * *new, r_assoc *old)); +int r_assoc_destroy PROTO_LIST((r_assoc * *assocp)); /*We need iterators, but I haven't written them yet*/ typedef struct r_assoc_iterator_ { - r_assoc *assoc; - int prev_chain; - struct r_assoc_el_ *prev; - int next_chain; - struct r_assoc_el_ *next; + r_assoc *assoc; + int prev_chain; + struct r_assoc_el_ *prev; + int next_chain; + struct r_assoc_el_ *next; } r_assoc_iterator; -int r_assoc_init_iter PROTO_LIST((r_assoc *assoc,r_assoc_iterator *)); -int r_assoc_iter PROTO_LIST((r_assoc_iterator *iter,void **key,int *keyl, - void **val)); +int r_assoc_init_iter PROTO_LIST((r_assoc * assoc, r_assoc_iterator *)); +int r_assoc_iter + PROTO_LIST((r_assoc_iterator * iter, void **key, int *keyl, void **val)); int r_assoc_iter_delete PROTO_LIST((r_assoc_iterator *)); #endif - diff --git a/common/include/r_bitfield.h b/common/include/r_bitfield.h index a5b89b0..fbcd1f3 100644 --- a/common/include/r_bitfield.h +++ b/common/include/r_bitfield.h @@ -7,20 +7,18 @@ ekr@rtfm.com Wed Oct 3 10:43:50 2001 */ - #ifndef _r_bitfield_h #define _r_bitfield_h typedef struct r_bitfield_ { - UINT4 *data; - UINT4 len; - UINT4 base; + UINT4 *data; + UINT4 len; + UINT4 base; } r_bitfield; -int r_bitfield_set PROTO_LIST((r_bitfield *,int bit)); -int r_bitfield_isset PROTO_LIST((r_bitfield *,int bit)); -int r_bitfield_create PROTO_LIST((r_bitfield **setp,UINT4 size)); -int r_bitfield_destroy PROTO_LIST((r_bitfield **setp)); +int r_bitfield_set PROTO_LIST((r_bitfield *, int bit)); +int r_bitfield_isset PROTO_LIST((r_bitfield *, int bit)); +int r_bitfield_create PROTO_LIST((r_bitfield * *setp, UINT4 size)); +int r_bitfield_destroy PROTO_LIST((r_bitfield * *setp)); #endif - diff --git a/common/include/r_common.h b/common/include/r_common.h index 834db34..a0aa8b6 100644 --- a/common/include/r_common.h +++ b/common/include/r_common.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_common.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Dec 22 10:40:07 1998 */ - #ifndef _r_common_h #define _r_common_h @@ -59,7 +59,7 @@ #include "r_data.h" /*AAH*/ -int xdump PROTO_LIST((char *label,UCHAR *data,int len)); +int xdump PROTO_LIST((char *label, UCHAR *data, int len)); /* defines for possibly replaced functions */ #ifndef HAVE_STRDUP @@ -67,4 +67,3 @@ char *strdup PROTO_LIST((char *in)); #endif #endif - diff --git a/common/include/r_data.h b/common/include/r_data.h index 8ec136a..179d822 100644 --- a/common/include/r_data.h +++ b/common/include/r_data.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_data.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,26 +44,30 @@ ekr@rtfm.com Wed Feb 10 14:18:19 1999 */ - #ifndef _r_data_h #define _r_data_h typedef struct Data_ { - UCHAR *data; - int len; + UCHAR *data; + int len; } Data; -int r_data_create PROTO_LIST((Data **dp,UCHAR *d,int l)); -int r_data_alloc PROTO_LIST((Data **dp, int l)); -int r_data_make PROTO_LIST((Data *dp, UCHAR *d,int l)); -int r_data_destroy PROTO_LIST((Data **dp)); -int r_data_copy PROTO_LIST((Data *dst,Data *src)); -int r_data_zfree PROTO_LIST((Data *d)); -int r_data_compare PROTO_LIST((Data *d1,Data *d2)); +int r_data_create PROTO_LIST((Data * *dp, UCHAR *d, int l)); +int r_data_alloc PROTO_LIST((Data * *dp, int l)); +int r_data_make PROTO_LIST((Data * dp, UCHAR *d, int l)); +int r_data_destroy PROTO_LIST((Data * *dp)); +int r_data_copy PROTO_LIST((Data * dst, Data *src)); +int r_data_zfree PROTO_LIST((Data * d)); +int r_data_compare PROTO_LIST((Data * d1, Data *d2)); -#define INIT_DATA(a,b,c) (a).data=b; (a).len=c -#define ATTACH_DATA(a,b) (a).data=b; (a).len=sizeof(b) -#define ZERO_DATA(a) (a).data=0; (a).len=0 +#define INIT_DATA(a, b, c) \ + (a).data = b; \ + (a).len = c +#define ATTACH_DATA(a, b) \ + (a).data = b; \ + (a).len = sizeof(b) +#define ZERO_DATA(a) \ + (a).data = 0; \ + (a).len = 0 #endif - diff --git a/common/include/r_defaults.h b/common/include/r_defaults.h index 180ab0d..e8188a5 100644 --- a/common/include/r_defaults.h +++ b/common/include/r_defaults.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_defaults.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Dec 22 10:39:14 1998 */ - #ifndef _r_defaults_h #define _r_defaults_h @@ -51,9 +51,7 @@ #define R_USE_PROTOTYPES 1 #endif - /*The needs defines don't belong here*/ #define R_NEEDS_STDLIB_H #endif - diff --git a/common/include/r_errors.h b/common/include/r_errors.h index d3d93c0..741c78f 100644 --- a/common/include/r_errors.h +++ b/common/include/r_errors.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_errors.h,v 1.3 2002/01/21 17:36:51 ekr Exp $ @@ -43,20 +44,18 @@ ekr@rtfm.com Tue Dec 22 10:59:49 1998 */ - #ifndef _r_errors_h #define _r_errors_h -#define R_NO_MEMORY 1 /*out of memory*/ -#define R_NOT_FOUND 2 /*Item not found*/ -#define R_INTERNAL 3 /*Unspecified internal error*/ -#define R_ALREADY 4 /*Action already done*/ -#define R_EOD 5 /*end of data*/ -#define R_BAD_ARGS 6 /*Bad arguments*/ -#define R_BAD_DATA 7 /*Bad data*/ -#define R_WOULDBLOCK 8 /*Operation would block */ +#define R_NO_MEMORY 1 /*out of memory*/ +#define R_NOT_FOUND 2 /*Item not found*/ +#define R_INTERNAL 3 /*Unspecified internal error*/ +#define R_ALREADY 4 /*Action already done*/ +#define R_EOD 5 /*end of data*/ +#define R_BAD_ARGS 6 /*Bad arguments*/ +#define R_BAD_DATA 7 /*Bad data*/ +#define R_WOULDBLOCK 8 /*Operation would block */ -int verr_exit PROTO_LIST((char *fmt,...)); +int verr_exit PROTO_LIST((char *fmt, ...)); #endif - diff --git a/common/include/r_includes.h b/common/include/r_includes.h index de9b76c..943a294 100644 --- a/common/include/r_includes.h +++ b/common/include/r_includes.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_includes.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Dec 22 11:38:50 1998 */ - #ifndef _r_includes_h #define _r_includes_h @@ -59,4 +59,3 @@ #include #endif - diff --git a/common/include/r_list.h b/common/include/r_list.h index 6addb7c..3a88fcd 100644 --- a/common/include/r_list.h +++ b/common/include/r_list.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_list.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,27 +44,28 @@ ekr@rtfm.com Tue Jan 19 08:36:48 1999 */ - #ifndef _r_list_h #define _r_list_h typedef struct r_list_ r_list; typedef struct r_list_iterator_ { - r_list *list; - struct r_list_el_ *ptr; + r_list *list; + struct r_list_el_ *ptr; } r_list_iterator; -int r_list_create PROTO_LIST((r_list **listp)); -int r_list_destroy PROTO_LIST((r_list **listp)); -int r_list_copy PROTO_LIST((r_list **out,r_list *in)); -int r_list_insert PROTO_LIST((r_list *list,void *value, - int (*copy)(void **new,void *old), - int (*destroy)(void **ptr))); -int r_list_append PROTO_LIST((r_list *list,void *value, - int (*copy)(void **new,void *old), - int (*destroy)(void **ptr))); -int r_list_init_iter PROTO_LIST((r_list *list,r_list_iterator *iter)); -int r_list_iter PROTO_LIST((r_list_iterator *iter,void **val)); +int r_list_create PROTO_LIST((r_list * *listp)); +int r_list_destroy PROTO_LIST((r_list * *listp)); +int r_list_copy PROTO_LIST((r_list * *out, r_list *in)); +int r_list_insert PROTO_LIST((r_list * list, + void *value, + int (*copy)(void **new, void *old), + int (*destroy)(void **ptr))); +int r_list_append PROTO_LIST((r_list * list, + void *value, + int (*copy)(void **new, void *old), + int (*destroy)(void **ptr))); +int r_list_init_iter PROTO_LIST((r_list * list, r_list_iterator *iter)); +int r_list_iter PROTO_LIST((r_list_iterator * iter, void **val)); #endif diff --git a/common/include/r_macros.h b/common/include/r_macros.h index 46f940f..46d4954 100644 --- a/common/include/r_macros.h +++ b/common/include/r_macros.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_macros.h,v 1.4 2001/11/20 17:45:18 ekr Exp $ @@ -43,11 +44,10 @@ ekr@rtfm.com Tue Dec 22 10:37:32 1998 */ - #ifndef _r_macros_h #define _r_macros_h -#if (R_USE_PROTOTYPES==1) +#if(R_USE_PROTOTYPES == 1) #define PROTO_LIST(a) a #else #define PROTO_LIST(a) () @@ -58,34 +58,52 @@ #endif #ifdef R_TRACE_ERRORS -#define REPORT_ERROR_(caller,a) fprintf(stderr,"%s: error %d at %s:%d (function %s)\n", \ - caller,a,__FILE__,__LINE__,__FUNCTION__) +#define REPORT_ERROR_(caller, a) \ + fprintf(stderr, "%s: error %d at %s:%d (function %s)\n", caller, a, \ + __FILE__, __LINE__, __FUNCTION__) #else -#define REPORT_ERROR_(caller,a) -#endif +#define REPORT_ERROR_(caller, a) +#endif #ifndef ERETURN -#define ERETURN(a) do {int _r=a; if(!_r) _r=-1; REPORT_ERROR_("ERETURN",_r); return(_r);} while(0) +#define ERETURN(a) \ + do { \ + int _r = a; \ + if(!_r) \ + _r = -1; \ + REPORT_ERROR_("ERETURN", _r); \ + return (_r); \ + } while(0) #endif #ifndef ABORT -#define ABORT(a) do { int _r=a; if(!_r) _r=-1; REPORT_ERROR_("ABORT",_r); _status=_r; goto abort;} while(0) +#define ABORT(a) \ + do { \ + int _r = a; \ + if(!_r) \ + _r = -1; \ + REPORT_ERROR_("ABORT", _r); \ + _status = _r; \ + goto abort; \ + } while(0) #endif #ifndef FREE -#define FREE(a) if(a) free(a) +#define FREE(a) \ + if(a) \ + free(a) #endif #ifndef MIN -#define MIN(a,b) (((a)>(b))?(b):(a)) +#define MIN(a, b) (((a) > (b)) ? (b) : (a)) #endif #ifndef MAX -#define MAX(a,b) (((b)>(a))?(b):(a)) +#define MAX(a, b) (((b) > (a)) ? (b) : (a)) #endif #ifdef DEBUG #define DBG(a) debug a -int debug(int class,char *format,...); +int debug(int class, char *format, ...); #else #define DBG(a) #endif @@ -95,18 +113,24 @@ int debug(int class,char *format,...); #endif #ifndef RCALLOC -#define RCALLOC(a) calloc(1,a) +#define RCALLOC(a) calloc(1, a) #endif #ifndef RFREE -#define RFREE(a) if(a) free(a) +#define RFREE(a) \ + if(a) \ + free(a) #endif #ifndef RREALLOC -#define RREALLOC(a,b) realloc(a,b) +#define RREALLOC(a, b) realloc(a, b) #endif -#define UNIMPLEMENTED do { fprintf(stderr,"Function %s unimplemented\n",__FUNCTION__); abort(); } while(0) +#define UNIMPLEMENTED \ + do { \ + fprintf(stderr, "Function %s unimplemented\n", __FUNCTION__); \ + abort(); \ + } while(0) #ifdef STDC_HEADERS #include @@ -115,11 +139,11 @@ int debug(int class,char *format,...); #ifndef STRNICMP #ifdef _WIN32 -#define STRNICMP(a,b,n) strnicmp(a,b,n) +#define STRNICMP(a, b, n) strnicmp(a, b, n) #else -#define STRNICMP(a,b,n) strncasecmp(a,b,n) +#define STRNICMP(a, b, n) strncasecmp(a, b, n) #endif #endif -#endif +#endif diff --git a/common/include/r_thread.h b/common/include/r_thread.h index 9c72825..f36b8b8 100644 --- a/common/include/r_thread.h +++ b/common/include/r_thread.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_thread.h,v 1.2 2000/10/17 16:09:59 ekr Exp $ @@ -43,27 +44,24 @@ ekr@rtfm.com Tue Feb 23 14:58:36 1999 */ - #ifndef _r_thread_h #define _r_thread_h typedef void *r_thread; typedef void *r_rwlock; -int r_thread_fork PROTO_LIST((void (*func)(void *),void *arg, - r_thread *tid)); +int r_thread_fork PROTO_LIST((void (*func)(void *), void *arg, r_thread *tid)); int r_thread_destroy PROTO_LIST((r_thread tid)); int r_thread_yield PROTO_LIST((void)); int r_thread_exit PROTO_LIST((void)); int r_thread_wait_last PROTO_LIST((void)); -int r_rwlock_create PROTO_LIST((r_rwlock **lockp)); -int r_rwlock_destroy PROTO_LIST((r_rwlock **lock)); -int r_rwlock_lock PROTO_LIST((r_rwlock *lock,int action)); +int r_rwlock_create PROTO_LIST((r_rwlock * *lockp)); +int r_rwlock_destroy PROTO_LIST((r_rwlock * *lock)); +int r_rwlock_lock PROTO_LIST((r_rwlock * lock, int action)); #define R_RWLOCK_UNLOCK 0 #define R_RWLOCK_RLOCK 1 #define R_RWLOCK_WLOCK 2 #endif - diff --git a/common/include/r_time.h b/common/include/r_time.h index 01db707..27f2ca0 100644 --- a/common/include/r_time.h +++ b/common/include/r_time.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_time.h,v 1.4 2001/12/24 06:06:26 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Thu Mar 4 08:45:41 1999 */ - #ifndef _r_time_h #define _r_time_h @@ -52,28 +52,29 @@ #endif #ifdef _WIN32 -# include +#include #else /* Cribbed from the autoconf doc */ -# if TIME_WITH_SYS_TIME -# include -# include -# else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -# endif +#if TIME_WITH_SYS_TIME +#include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif #endif -int r_timeval_diff PROTO_LIST((struct timeval *t1,struct timeval *t0, - struct timeval *diff)); -int r_timeval_add PROTO_LIST((struct timeval *t1,struct timeval *t2, - struct timeval *sum)); +int r_timeval_diff PROTO_LIST((struct timeval * t1, + struct timeval *t0, + struct timeval *diff)); +int r_timeval_add PROTO_LIST((struct timeval * t1, + struct timeval *t2, + struct timeval *sum)); -UINT8 r_timeval2int PROTO_LIST((struct timeval *tv)); +UINT8 r_timeval2int PROTO_LIST((struct timeval * tv)); UINT8 r_gettimeint PROTO_LIST((void)); #endif - diff --git a/common/include/r_types.h b/common/include/r_types.h index df5243e..676a20e 100644 --- a/common/include/r_types.h +++ b/common/include/r_types.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_types.h,v 1.3 2002/09/09 21:02:58 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Dec 22 10:36:02 1998 */ - #ifndef _r_types_h #define _r_types_h @@ -55,15 +55,15 @@ #ifndef SIZEOF_UNSIGNED_INT typedef unsigned int UINT4; #else -# if (SIZEOF_UNSIGNED_INT==4) +#if(SIZEOF_UNSIGNED_INT == 4) typedef unsigned int UINT4; -# elif (SIZEOF_UNSIGNED_SHORT==4) +#elif(SIZEOF_UNSIGNED_SHORT == 4) typedef unsigned short UINT4; -# elif (SIZEOF_UNSIGNED_LONG==4) +#elif(SIZEOF_UNSIGNED_LONG == 4) typedef unsigned long UINT4; -# else -# error no type for UINT4 -# endif +#else +#error no type for UINT4 +#endif #endif #endif @@ -71,19 +71,19 @@ typedef unsigned long UINT4; #ifndef SIZEOF_UNSIGNED_LONG typedef unsigned long UINT8; #else -# if (SIZEOF_UNSIGNED_INT==8) +#if(SIZEOF_UNSIGNED_INT == 8) typedef unsigned int UINT8; -# elif (SIZEOF_UNSIGNED_SHORT==8) +#elif(SIZEOF_UNSIGNED_SHORT == 8) typedef unsigned short UINT8; -# elif (SIZEOF_UNSIGNED_LONG==8) +#elif(SIZEOF_UNSIGNED_LONG == 8) typedef unsigned long UINT8; -# elif (SIZEOF_UNSIGNED_LONG_LONG==8) +#elif(SIZEOF_UNSIGNED_LONG_LONG == 8) typedef unsigned long long UINT8; -# elif defined (_WIN32) && defined (_MSC_VER) +#elif defined(_WIN32) && defined(_MSC_VER) typedef unsigned __int64 UINT8; -# else -# error no type for UINT8 -# endif +#else +#error no type for UINT8 +#endif #endif #endif @@ -92,4 +92,3 @@ typedef unsigned char UCHAR; #endif #endif - diff --git a/common/lib/assoc.h b/common/lib/assoc.h index 5fbd0d5..bf77394 100644 --- a/common/lib/assoc.h +++ b/common/lib/assoc.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: assoc.h,v 1.2 2000/10/17 16:10:00 ekr Exp $ @@ -43,11 +44,9 @@ ekr@rtfm.com Sun Jan 17 17:56:35 1999 */ - #ifndef _assoc_h #define _assoc_h typedef struct assoc_ assoc; #endif - diff --git a/common/lib/debug.c b/common/lib/debug.c index ff3d17b..662a883 100644 --- a/common/lib/debug.c +++ b/common/lib/debug.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: debug.c,v 1.3 2001/12/24 06:06:26 ekr Exp $ @@ -43,47 +44,34 @@ ekr@rtfm.com Wed Jan 6 17:08:58 1999 */ - - - #include #include #include "r_common.h" #include "debug.h" -int debug(int class,char *format,...) - { - va_list ap; +int debug(int class, char *format, ...) { + va_list ap; - va_start(ap,format); - vfprintf(stderr,format,ap); - fprintf(stderr,"\n"); - va_end(ap); - return(0); + va_start(ap, format); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); + return (0); +} + +int xdump(char *name, UCHAR *data, int len) { + int i; + + if(name) { + printf("%s[%d]=\n", name, len); } - -int -xdump (char *name, UCHAR *data, int len) - { - int i; - - if(name){ - printf("%s[%d]=\n",name,len); - } - for(i=0;i8) && i && !(i%12)){ - printf("\n"); - } - printf("%.2x ",data[i]&255); - } - if(i%12) + for(i = 0; i < len; i++) { + if((len > 8) && i && !(i % 12)) { printf("\n"); - return(0); + } + printf("%.2x ", data[i] & 255); } - - - - - - + if(i % 12) + printf("\n"); + return (0); +} diff --git a/common/lib/debug.h b/common/lib/debug.h index 9fb10f4..7773702 100644 --- a/common/lib/debug.h +++ b/common/lib/debug.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: debug.h,v 1.3 2001/12/24 06:06:26 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Wed Jan 6 17:13:00 1999 */ - #ifndef _debug_h #define _debug_h @@ -53,9 +53,7 @@ #define DBG(a) #endif -int debug(int class,char *format,...); -int xdump PROTO_LIST((char *name,UCHAR *data, - int len)); +int debug(int class, char *format, ...); +int xdump PROTO_LIST((char *name, UCHAR *data, int len)); #endif - diff --git a/common/lib/r_assoc.c b/common/lib/r_assoc.c index edce3a7..037987f 100644 --- a/common/lib/r_assoc.c +++ b/common/lib/r_assoc.c @@ -11,7 +11,7 @@ The major problem with this code is it's not resizable, though it could be made so. - + Copyright (C) 1999-2000 RTFM, Inc. All Rights Reserved @@ -29,7 +29,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -46,7 +46,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_assoc.c,v 1.4 2001/12/24 06:06:26 ekr Exp $ @@ -54,360 +55,331 @@ ekr@rtfm.com Sun Jan 17 17:57:15 1999 */ - #include #include "r_assoc.h" typedef struct r_assoc_el_ { - char *key; - int key_len; - void *data; - struct r_assoc_el_ *prev; - struct r_assoc_el_ *next; - int (*copy) PROTO_LIST((void **new,void *old)); - int (*destroy) PROTO_LIST((void *ptr)); + char *key; + int key_len; + void *data; + struct r_assoc_el_ *prev; + struct r_assoc_el_ *next; + int(*copy) PROTO_LIST((void **new, void *old)); + int(*destroy) PROTO_LIST((void *ptr)); } r_assoc_el; - + struct r_assoc_ { - int size; - int bits; - r_assoc_el **chains; + int size; + int bits; + r_assoc_el **chains; }; #define DEFAULT_TABLE_BITS 5 -static int destroy_assoc_chain PROTO_LIST((r_assoc_el *chain)); -static int r_assoc_fetch_bucket PROTO_LIST((r_assoc *assoc, - char *key,int len,r_assoc_el **bucketp)); -UINT4 hash_compute PROTO_LIST((char *key,int len,int size)); -static int copy_assoc_chain PROTO_LIST((r_assoc_el **newp, - r_assoc_el *old)); +static int destroy_assoc_chain PROTO_LIST((r_assoc_el * chain)); +static int r_assoc_fetch_bucket + PROTO_LIST((r_assoc * assoc, char *key, int len, r_assoc_el **bucketp)); +UINT4 hash_compute PROTO_LIST((char *key, int len, int size)); +static int copy_assoc_chain PROTO_LIST((r_assoc_el * *newp, r_assoc_el *old)); -int -r_assoc_create (r_assoc **assocp) - { - r_assoc *assoc=0; - int _status; - - if(!(assoc=(r_assoc *)calloc(sizeof(r_assoc),1))) - ABORT(R_NO_MEMORY); - assoc->size=(1<bits=DEFAULT_TABLE_BITS; - - if(!(assoc->chains=(r_assoc_el **)calloc(sizeof(r_assoc_el *), - assoc->size))) +int r_assoc_create(r_assoc **assocp) { + r_assoc *assoc = 0; + int _status; + + if(!(assoc = (r_assoc *)calloc(sizeof(r_assoc), 1))) + ABORT(R_NO_MEMORY); + assoc->size = (1 << DEFAULT_TABLE_BITS); + assoc->bits = DEFAULT_TABLE_BITS; + + if(!(assoc->chains = + (r_assoc_el **)calloc(sizeof(r_assoc_el *), assoc->size))) + ABORT(R_NO_MEMORY); + + *assocp = assoc; + + _status = 0; +abort: + if(_status) { + r_assoc_destroy(&assoc); + } + return (_status); +} + +int r_assoc_destroy(r_assoc **assocp) { + r_assoc *assoc; + int i; + + if(!assocp || !*assocp) + return (0); + + assoc = *assocp; + for(i = 0; i < assoc->size; i++) + destroy_assoc_chain(assoc->chains[i]); + + free(assoc->chains); + free(assoc); + + return (0); +} + +static int destroy_assoc_chain(r_assoc_el *chain) { + r_assoc_el *nxt; + + while(chain) { + nxt = chain->next; + + if(chain->destroy) + chain->destroy(chain->data); + + free(chain->key); + + free(chain); + chain = nxt; + } + + return (0); +} + +static int copy_assoc_chain(r_assoc_el **newp, r_assoc_el *old) { + r_assoc_el *new = 0, *ptr, *tmp; + int r, _status; + + if(!old) { + *newp = 0; + return (0); + } + for(; old; old = old->next) { + if(!(tmp = (r_assoc_el *)calloc(sizeof(r_assoc_el), 1))) ABORT(R_NO_MEMORY); - *assocp=assoc; - - _status=0; - abort: - if(_status){ - r_assoc_destroy(&assoc); + if(!new) { + new = tmp; + ptr = new; + } else { + ptr->next = tmp; + tmp->prev = ptr; + ptr = tmp; } - return(_status); + + ptr->destroy = old->destroy; + ptr->copy = old->copy; + + if(old->copy) { + if((r = old->copy(&ptr->data, old->data))) + ABORT(r); + } else + ptr->data = old->data; + + if(!(ptr->key = (char *)malloc(old->key_len))) + ABORT(R_NO_MEMORY); + memcpy(ptr->key, old->key, ptr->key_len = old->key_len); } -int -r_assoc_destroy (r_assoc **assocp) - { - r_assoc *assoc; - int i; - - if(!assocp || !*assocp) - return(0); + *newp = new; - assoc=*assocp; - for(i=0;isize;i++) - destroy_assoc_chain(assoc->chains[i]); + _status = 0; +abort: + if(_status) { + destroy_assoc_chain(new); + } + return (_status); +} - free(assoc->chains); - free(assoc); +static int r_assoc_fetch_bucket(r_assoc *assoc, + char *key, + int len, + r_assoc_el **bucketp) { + UINT4 hash_value; + r_assoc_el *bucket; - return(0); + hash_value = hash_compute(key, len, assoc->bits); + + for(bucket = assoc->chains[hash_value]; bucket; bucket = bucket->next) { + if(bucket->key_len == len && !memcmp(bucket->key, key, len)) { + *bucketp = bucket; + return (0); + } } -static int -destroy_assoc_chain (r_assoc_el *chain) - { - r_assoc_el *nxt; - - while(chain){ - nxt=chain->next; + return (R_NOT_FOUND); +} - if(chain->destroy) - chain->destroy(chain->data); +int r_assoc_fetch(r_assoc *assoc, char *key, int len, void **datap) { + r_assoc_el *bucket; + int r; - free(chain->key); - - free(chain); - chain=nxt; - } - - return(0); + if((r = r_assoc_fetch_bucket(assoc, key, len, &bucket))) { + if(r != R_NOT_FOUND) + ERETURN(r); + return (r); } -static int -copy_assoc_chain (r_assoc_el **newp, r_assoc_el *old) - { - r_assoc_el *new=0,*ptr,*tmp; - int r,_status; + *datap = bucket->data; + return (0); +} - if(!old) { - *newp=0; - return(0); - } - for(;old;old=old->next){ - if(!(tmp=(r_assoc_el *)calloc(sizeof(r_assoc_el),1))) - ABORT(R_NO_MEMORY); - - if(!new){ - new=tmp; - ptr=new; - } - else{ - ptr->next=tmp; - tmp->prev=ptr; - ptr=tmp; - } +int r_assoc_insert(r_assoc *assoc, + char *key, + int len, + void *data, + int(*copy) PROTO_LIST((void **new, void *old)), + int(*destroy) PROTO_LIST((void *ptr)), + int how) { + r_assoc_el *bucket, *new_bucket = 0; + int r, _status; - ptr->destroy=old->destroy; - ptr->copy=old->copy; - - if(old->copy){ - if((r=old->copy(&ptr->data,old->data))) - ABORT(r); - } - else - ptr->data=old->data; - - if(!(ptr->key=(char *)malloc(old->key_len))) - ABORT(R_NO_MEMORY); - memcpy(ptr->key,old->key,ptr->key_len=old->key_len); - } - - *newp=new; - - _status=0; - abort: - if(_status){ - destroy_assoc_chain(new); - } - return(_status); - } - -static int -r_assoc_fetch_bucket (r_assoc *assoc, char *key, int len, r_assoc_el **bucketp) - { + if((r = r_assoc_fetch_bucket(assoc, key, len, &bucket))) { + /*Note that we compute the hash value twice*/ UINT4 hash_value; - r_assoc_el *bucket; - - hash_value=hash_compute(key,len,assoc->bits); - for(bucket=assoc->chains[hash_value];bucket;bucket=bucket->next){ - if(bucket->key_len == len && !memcmp(bucket->key,key,len)){ - *bucketp=bucket; - return(0); - } - } + if(r != R_NOT_FOUND) + ABORT(r); + hash_value = hash_compute(key, len, assoc->bits); - return(R_NOT_FOUND); - } - -int -r_assoc_fetch (r_assoc *assoc, char *key, int len, void **datap) - { - r_assoc_el *bucket; - int r; - - if((r=r_assoc_fetch_bucket(assoc,key,len,&bucket))){ - if(r!=R_NOT_FOUND) - ERETURN(r); - return(r); - } - - *datap=bucket->data; - return(0); - } - -int r_assoc_insert( - r_assoc *assoc, - char *key, - int len, - void *data, - int (*copy) PROTO_LIST((void **new,void *old)), - int (*destroy) PROTO_LIST((void *ptr)), - int how) - { - r_assoc_el *bucket,*new_bucket=0; - int r,_status; - - if((r=r_assoc_fetch_bucket(assoc,key,len,&bucket))){ - /*Note that we compute the hash value twice*/ - UINT4 hash_value; - - if(r!=R_NOT_FOUND) - ABORT(r); - hash_value=hash_compute(key,len,assoc->bits); - - if(!(new_bucket=(r_assoc_el *)calloc(sizeof(r_assoc_el),1))) - ABORT(R_NO_MEMORY); - if(!(new_bucket->key=(char *)malloc(len))) - ABORT(R_NO_MEMORY); - memcpy(new_bucket->key,key,len); - new_bucket->key_len=len; - - /*Insert at the list head. Is FIFO a good algorithm?*/ - if(assoc->chains[hash_value]) - assoc->chains[hash_value]->prev=new_bucket; - new_bucket->next=assoc->chains[hash_value]; - assoc->chains[hash_value]=new_bucket; - bucket=new_bucket; - } - else{ - if(!(how&R_ASSOC_REPLACE)) - ABORT(R_ALREADY); - - if(bucket->destroy) - bucket->destroy(bucket->data); - } - - bucket->data=data; - bucket->copy=copy; - bucket->destroy=destroy; - - _status=0; - abort: - if(_status && new_bucket){ - free(new_bucket->key); - free(new_bucket); - } - return(_status); - } - -int -r_assoc_copy (r_assoc **newp, r_assoc *old) - { - int r,_status,i; - r_assoc *new; - - if(!(new=(r_assoc *)calloc(sizeof(r_assoc),1))) + if(!(new_bucket = (r_assoc_el *)calloc(sizeof(r_assoc_el), 1))) ABORT(R_NO_MEMORY); - new->size=old->size; - new->bits=old->bits; - - if(!(new->chains=(r_assoc_el **)calloc(sizeof(r_assoc_el),old->size))) + if(!(new_bucket->key = (char *)malloc(len))) ABORT(R_NO_MEMORY); - for(i=0;isize;i++){ - if((r=copy_assoc_chain(new->chains+i,old->chains[i]))) - ABORT(R_NO_MEMORY); - } - *newp=new; - - _status=0; - abort: - if(_status){ - r_assoc_destroy(&new); - } - return(_status); + memcpy(new_bucket->key, key, len); + new_bucket->key_len = len; + + /*Insert at the list head. Is FIFO a good algorithm?*/ + if(assoc->chains[hash_value]) + assoc->chains[hash_value]->prev = new_bucket; + new_bucket->next = assoc->chains[hash_value]; + assoc->chains[hash_value] = new_bucket; + bucket = new_bucket; + } else { + if(!(how & R_ASSOC_REPLACE)) + ABORT(R_ALREADY); + + if(bucket->destroy) + bucket->destroy(bucket->data); } -int -r_assoc_init_iter (r_assoc *assoc, r_assoc_iterator *iter) - { - int i; - - iter->assoc=assoc; - iter->prev_chain=-1; - iter->prev=0; + bucket->data = data; + bucket->copy = copy; + bucket->destroy = destroy; - iter->next_chain=assoc->size; - iter->next=0; - - for(i=0;isize;i++){ - if(assoc->chains[i]!=0){ - iter->next_chain=i; - iter->next=assoc->chains[i]; - break; + _status = 0; +abort: + if(_status && new_bucket) { + free(new_bucket->key); + free(new_bucket); + } + return (_status); +} + +int r_assoc_copy(r_assoc **newp, r_assoc *old) { + int r, _status, i; + r_assoc *new; + + if(!(new = (r_assoc *)calloc(sizeof(r_assoc), 1))) + ABORT(R_NO_MEMORY); + new->size = old->size; + new->bits = old->bits; + + if(!(new->chains = (r_assoc_el **)calloc(sizeof(r_assoc_el), old->size))) + ABORT(R_NO_MEMORY); + for(i = 0; i < new->size; i++) { + if((r = copy_assoc_chain(new->chains + i, old->chains[i]))) + ABORT(R_NO_MEMORY); + } + *newp = new; + + _status = 0; +abort: + if(_status) { + r_assoc_destroy(&new); + } + return (_status); +} + +int r_assoc_init_iter(r_assoc *assoc, r_assoc_iterator *iter) { + int i; + + iter->assoc = assoc; + iter->prev_chain = -1; + iter->prev = 0; + + iter->next_chain = assoc->size; + iter->next = 0; + + for(i = 0; i < assoc->size; i++) { + if(assoc->chains[i] != 0) { + iter->next_chain = i; + iter->next = assoc->chains[i]; + break; + } + } + + return (0); +} + +int r_assoc_iter(r_assoc_iterator *iter, void **key, int *keyl, void **val) { + int i; + r_assoc_el *ret; + + if(!iter->next) + return (R_EOD); + ret = iter->next; + + *key = ret->key; + *keyl = ret->key_len; + *val = ret->data; + + /* Now increment */ + iter->prev_chain = iter->next_chain; + iter->prev = iter->next; + + /* More on this chain */ + if(iter->next->next) { + iter->next = iter->next->next; + } else { + iter->next = 0; + + /* FInd the next occupied chain*/ + for(i = iter->next_chain; i < iter->assoc->size; i++) { + if(iter->assoc->chains[i]) { + iter->next_chain = i; + iter->next = iter->assoc->chains[i]; + break; } } - - return(0); } -int -r_assoc_iter (r_assoc_iterator *iter, void **key, int *keyl, void **val) - { - int i; - r_assoc_el *ret; - - if(!iter->next) - return(R_EOD); - ret=iter->next; - - *key=ret->key; - *keyl=ret->key_len; - *val=ret->data; - - /* Now increment */ - iter->prev_chain=iter->next_chain; - iter->prev=iter->next; - - /* More on this chain */ - if(iter->next->next){ - iter->next=iter->next->next; - } - else{ - iter->next=0; - - /* FInd the next occupied chain*/ - for(i=iter->next_chain;iassoc->size;i++){ - if(iter->assoc->chains[i]){ - iter->next_chain=i; - iter->next=iter->assoc->chains[i]; - break; - } - } - } - - return(0); - } + return (0); +} /* Delete the last returned value*/ -int -r_assoc_iter_delete (r_assoc_iterator *iter) - { - /* First unhook it from the list*/ - if(!iter->prev->prev){ - /* First element*/ - iter->assoc->chains[iter->prev_chain]=iter->prev->next; - } - else{ - iter->prev->prev->next=iter->prev->next; - } - - if(iter->prev->next){ - iter->prev->next->prev=iter->prev->prev; - } - - iter->prev->destroy(iter->prev->data); - free(iter->prev->data); - free(iter->prev); - return(0); +int r_assoc_iter_delete(r_assoc_iterator *iter) { + /* First unhook it from the list*/ + if(!iter->prev->prev) { + /* First element*/ + iter->assoc->chains[iter->prev_chain] = iter->prev->next; + } else { + iter->prev->prev->next = iter->prev->next; } - - + + if(iter->prev->next) { + iter->prev->next->prev = iter->prev->prev; + } + + iter->prev->destroy(iter->prev->data); + free(iter->prev->data); + free(iter->prev); + return (0); +} + /*This is a hack from AMS. Supposedly, it's pretty good for strings, even though it doesn't take into account all the data*/ -UINT4 -hash_compute (char *key, int len, int bits) - { - UINT4 h=0; +UINT4 +hash_compute(char *key, int len, int bits) { + UINT4 h = 0; - h=key[0] +(key[len-1] * len); + h = key[0] + (key[len - 1] * len); - h &= (1< #include -int -main (void) - { - char test_vector[1024],*v; - int rnd,ct,r; - r_assoc *assoc,*new_assoc; +int main(void) { + char test_vector[1024], *v; + int rnd, ct, r; + r_assoc *assoc, *new_assoc; - if(r=r_assoc_create(&assoc)){ - fprintf(stderr,"Couldn't create\n"); + if(r = r_assoc_create(&assoc)) { + fprintf(stderr, "Couldn't create\n"); + exit(1); + } + + srand(getpid()); + + v = test_vector; + for(ct = 0; ct < 256; ct++) { + v[0] = ct & 255; + v[1] = (ct >> 8) & 255; + v[2] = (ct >> 16) & 255; + v[3] = (ct >> 24) & 255; + + if(r = r_assoc_insert(assoc, v, 4, v, 0, 0, R_ASSOC_REPLACE)) { + fprintf(stderr, "Couldn't insert %d\n", ct); exit(1); } - srand(getpid()); + v += 4; + } - v=test_vector; - for(ct=0;ct<256;ct++){ - v[0]=ct & 255; - v[1]=(ct>>8) & 255; - v[2]=(ct>>16) & 255; - v[3]=(ct>>24) & 255; + fetch_test(assoc); - - if(r=r_assoc_insert(assoc,v,4,v,0,0,R_ASSOC_REPLACE)){ - fprintf(stderr,"Couldn't insert %d\n",ct); - exit(1); + if(r = r_assoc_copy(&new_assoc, assoc)) { + fprintf(stderr, "Couldn't copy\n"); + exit(1); + } + + r_assoc_destroy(&assoc); + + fetch_test(new_assoc); + + r_assoc_destroy(&new_assoc); + + printf("Tests pass\n"); + exit(0); +} + +int fetch_test(r_assoc *assoc) { + int ct; + char vec[4], *v; + int r, _status, rnd; + + for(ct = 0; ct < 65537; ct++) { + rnd = rand(); + + rnd &= 0x3ff; + + vec[0] = rnd & 255; + vec[1] = (rnd >> 8) & 255; + vec[2] = (rnd >> 16) & 255; + vec[3] = (rnd >> 24) & 255; + + if(r = r_assoc_fetch(assoc, vec, 4, (void **)&v)) { + if(rnd < 256) { + fprintf(stderr, "Couldn't fetch\n"); + exit(1); + } else + continue; + } else { + if(rnd > 255) { + fprintf(stderr, "Spurious fetch\n"); + exit(1); } - - v+=4; } - fetch_test(assoc); - - if(r=r_assoc_copy(&new_assoc,assoc)){ - fprintf(stderr,"Couldn't copy\n"); + if(memcmp(vec, v, 4)) { + fprintf(stderr, "Fetch error\n"); exit(1); } - - r_assoc_destroy(&assoc); - - fetch_test(new_assoc); - - r_assoc_destroy(&new_assoc); - - printf("Tests pass\n"); - exit(0); - } - -int -fetch_test (r_assoc *assoc) - { - int ct; - char vec[4],*v; - int r,_status,rnd; - - for(ct=0;ct<65537;ct++){ - rnd=rand(); - - rnd &= 0x3ff; - - vec[0]=rnd & 255; - vec[1]=(rnd>>8) & 255; - vec[2]=(rnd>>16) & 255; - vec[3]=(rnd>>24) & 255; - - if(r=r_assoc_fetch(assoc,vec,4,(void **)&v)){ - - if(rnd<256){ - fprintf(stderr,"Couldn't fetch\n"); - exit(1); - } - else - continue; - } - else{ - if(rnd>255){ - fprintf(stderr,"Spurious fetch\n"); - exit(1); - } - } - - if(memcmp(vec,v,4)){ - fprintf(stderr,"Fetch error\n"); - exit(1); - } - } - return(0); } + return (0); +} diff --git a/common/lib/r_bitfield.c b/common/lib/r_bitfield.c index 4b91880..74e63ea 100644 --- a/common/lib/r_bitfield.c +++ b/common/lib/r_bitfield.c @@ -7,100 +7,90 @@ ekr@rtfm.com Wed Oct 3 11:15:23 2001 */ - - #include #include "r_bitfield.h" -int -r_bitfield_create (r_bitfield **setp, UINT4 size) - { - r_bitfield *set=0; - int _status; - int num_words=size/32+!!(size%32); - - if(!(set=(r_bitfield *)RMALLOC(sizeof(r_bitfield)))) - ABORT(R_NO_MEMORY); +int r_bitfield_create(r_bitfield **setp, UINT4 size) { + r_bitfield *set = 0; + int _status; + int num_words = size / 32 + !!(size % 32); - if(!(set->data=(UINT4 *)RMALLOC(num_words*4))) - ABORT(R_NO_MEMORY); - memset(set->data,0,4*num_words); - - set->base=0; - set->len=num_words; + if(!(set = (r_bitfield *)RMALLOC(sizeof(r_bitfield)))) + ABORT(R_NO_MEMORY); - *setp=set; - - _status=0; - abort: - if(_status){ - r_bitfield_destroy(&set); - } - return(_status); + if(!(set->data = (UINT4 *)RMALLOC(num_words * 4))) + ABORT(R_NO_MEMORY); + memset(set->data, 0, 4 * num_words); + + set->base = 0; + set->len = num_words; + + *setp = set; + + _status = 0; +abort: + if(_status) { + r_bitfield_destroy(&set); } + return (_status); +} -int -r_bitfield_destroy (r_bitfield **setp) - { - r_bitfield *set; - - if(!setp || !*setp) - return(0); +int r_bitfield_destroy(r_bitfield **setp) { + r_bitfield *set; - set=*setp; + if(!setp || !*setp) + return (0); + + set = *setp; + + RFREE(set->data); + RFREE(set); + + *setp = 0; + return (0); +} + +int r_bitfield_set(r_bitfield *set, int bit) { + int word = (bit - set->base) / 32; + int bbit = (bit - set->base) % 32; + int _status; + + /* Resize? */ + if(word > set->len) { + UINT4 newlen = set->len; + UINT4 *tmp; + + while(newlen < word) + newlen *= 2; + + if(!(tmp = (UINT4 *)RMALLOC(newlen))) + ABORT(R_NO_MEMORY); + + memcpy(tmp, set->data, set->len * 4); + memset(tmp + set->len * 4, 0, (newlen - set->len) * 4); RFREE(set->data); - RFREE(set); - - *setp=0; - return(0); + set->data = tmp; } -int -r_bitfield_set (r_bitfield *set, int bit) - { - int word=(bit-set->base)/32; - int bbit=(bit-set->base)%32; - int _status; + set->data[word] |= 1 << bbit; - /* Resize? */ - if(word>set->len){ - UINT4 newlen=set->len; - UINT4 *tmp; - - while(newlendata,set->len*4); - memset(tmp+set->len*4,0,(newlen-set->len)*4); + _status = 0; +abort: + return (_status); +} - RFREE(set->data); - set->data=tmp; - } +int r_bitfield_isset(r_bitfield *set, int bit) { + int word = (bit - set->base) / 32; + int bbit = (bit - set->base) % 32; + int _status; - set->data[word]|=1<base) + return (0); - _status=0; - abort: - return(_status); - } + /* Resize? */ + if(word > set->len) + return (0); -int -r_bitfield_isset (r_bitfield *set, int bit) - { - int word=(bit-set->base)/32; - int bbit=(bit-set->base)%32; - int _status; - - if(bitbase) - return(0); - - /* Resize? */ - if(word>set->len) - return(0); - - return(set->data[word]&(1<data[word] & (1 << bbit)); +} diff --git a/common/lib/r_data.c b/common/lib/r_data.c index 9b4606c..4eb9e31 100644 --- a/common/lib/r_data.c +++ b/common/lib/r_data.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_data.c,v 1.3 2001/07/20 23:33:15 ekr Exp $ @@ -43,112 +44,95 @@ ekr@rtfm.com Tue Aug 17 15:39:50 1999 */ - - #include #include -int -r_data_create (Data **dp, UCHAR *d, int l) - { - Data *d_=0; - int _status; - - if(!(d_=(Data *)calloc(sizeof(Data),1))) - ABORT(R_NO_MEMORY); - if(!(d_->data=(UCHAR *)malloc(l))) - ABORT(R_NO_MEMORY); +int r_data_create(Data **dp, UCHAR *d, int l) { + Data *d_ = 0; + int _status; - memcpy(d_->data,d,l); - d_->len=l; + if(!(d_ = (Data *)calloc(sizeof(Data), 1))) + ABORT(R_NO_MEMORY); + if(!(d_->data = (UCHAR *)malloc(l))) + ABORT(R_NO_MEMORY); - *dp=d_; + memcpy(d_->data, d, l); + d_->len = l; - _status=0; - abort: - if(_status) - r_data_destroy(&d_); + *dp = d_; - return(_status); - } + _status = 0; +abort: + if(_status) + r_data_destroy(&d_); -int -r_data_alloc (Data **dp, int l) - { - Data *d_=0; - int _status; - - if(!(d_=(Data *)calloc(sizeof(Data),1))) - ABORT(R_NO_MEMORY); - if(!(d_->data=(UCHAR *)calloc(l,1))) - ABORT(R_NO_MEMORY); + return (_status); +} - d_->len=l; - - *dp=d_; - _status=0; - abort: - if(_status) - r_data_destroy(&d_); +int r_data_alloc(Data **dp, int l) { + Data *d_ = 0; + int _status; - return(_status); - } + if(!(d_ = (Data *)calloc(sizeof(Data), 1))) + ABORT(R_NO_MEMORY); + if(!(d_->data = (UCHAR *)calloc(l, 1))) + ABORT(R_NO_MEMORY); -int -r_data_make (Data *dp, UCHAR *d, int l) - { - if(!(dp->data=(UCHAR *)malloc(l))) - ERETURN(R_NO_MEMORY); + d_->len = l; - memcpy(dp->data,d,l); - dp->len=l; + *dp = d_; + _status = 0; +abort: + if(_status) + r_data_destroy(&d_); - return(0); - } - -int -r_data_destroy (Data **dp) - { - if(!dp || !*dp) - return(0); + return (_status); +} - if((*dp)->data) - free((*dp)->data); +int r_data_make(Data *dp, UCHAR *d, int l) { + if(!(dp->data = (UCHAR *)malloc(l))) + ERETURN(R_NO_MEMORY); - free(*dp); - *dp=0; + memcpy(dp->data, d, l); + dp->len = l; - return(0); - } - -int -r_data_copy (Data *dst, Data *src) - { - if(!(dst->data=(UCHAR *)malloc(src->len))) - ERETURN(R_NO_MEMORY); - memcpy(dst->data,src->data,dst->len=src->len); - return(0); - } + return (0); +} -int -r_data_zfree (Data *d) - { - if(!d) - return(0); - if(!d->data) - return(0); - memset(d->data,0,d->len); - free(d->data); - return(0); - } +int r_data_destroy(Data **dp) { + if(!dp || !*dp) + return (0); -int -r_data_compare (Data *d1, Data *d2) - { - if(d1->lenlen) - return(-1); - if(d2->lenlen) - return(-1); - return(memcmp(d1->data,d2->data,d1->len)); - } - + if((*dp)->data) + free((*dp)->data); + + free(*dp); + *dp = 0; + + return (0); +} + +int r_data_copy(Data *dst, Data *src) { + if(!(dst->data = (UCHAR *)malloc(src->len))) + ERETURN(R_NO_MEMORY); + memcpy(dst->data, src->data, dst->len = src->len); + return (0); +} + +int r_data_zfree(Data *d) { + if(!d) + return (0); + if(!d->data) + return (0); + memset(d->data, 0, d->len); + free(d->data); + return (0); +} + +int r_data_compare(Data *d1, Data *d2) { + if(d1->len < d2->len) + return (-1); + if(d2->len < d1->len) + return (-1); + return (memcmp(d1->data, d2->data, d1->len)); +} diff --git a/common/lib/r_data.h b/common/lib/r_data.h index bc3507b..0ab0d26 100644 --- a/common/lib/r_data.h +++ b/common/lib/r_data.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_data.h,v 1.2 2000/10/17 16:10:00 ekr Exp $ @@ -43,10 +44,7 @@ ekr@rtfm.com Fri Feb 4 08:58:48 2000 */ - #ifndef _r_data_h #define _r_data_h - #endif - diff --git a/common/lib/r_errors.c b/common/lib/r_errors.c index 8cb9d2f..54192f4 100644 --- a/common/lib/r_errors.c +++ b/common/lib/r_errors.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_errors.c,v 1.3 2001/12/24 06:06:27 ekr Exp $ @@ -43,18 +44,15 @@ ekr@rtfm.com Tue Feb 16 16:37:05 1999 */ - - #include #include #include "r_common.h" #include "r_errors.h" -int verr_exit(char *fmt,...) - { - va_list ap; +int verr_exit(char *fmt, ...) { + va_list ap; - va_start(ap,fmt); - vfprintf(stderr,fmt,ap); - exit(1); - } + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + exit(1); +} diff --git a/common/lib/r_list.c b/common/lib/r_list.c index 5fb9ae7..3b64bb7 100644 --- a/common/lib/r_list.c +++ b/common/lib/r_list.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_list.c,v 1.4 2001/12/24 06:06:27 ekr Exp $ @@ -43,188 +44,171 @@ ekr@rtfm.com Tue Jan 19 08:36:39 1999 */ - - #include #include "r_list.h" typedef struct r_list_el_ { - void *data; - struct r_list_el_ *next; - struct r_list_el_ *prev; - int (*copy) PROTO_LIST((void **new,void *old)); - int (*destroy) PROTO_LIST((void **ptr)); + void *data; + struct r_list_el_ *next; + struct r_list_el_ *prev; + int(*copy) PROTO_LIST((void **new, void *old)); + int(*destroy) PROTO_LIST((void **ptr)); } r_list_el; struct r_list_ { - struct r_list_el_ *first; - struct r_list_el_ *last; + struct r_list_el_ *first; + struct r_list_el_ *last; }; -int -r_list_create (r_list **listp) - { - r_list *list=0; - int _status; +int r_list_create(r_list **listp) { + r_list *list = 0; + int _status; - if(!(list=(r_list *)calloc(sizeof(r_list),1))) - ABORT(R_NO_MEMORY); + if(!(list = (r_list *)calloc(sizeof(r_list), 1))) + ABORT(R_NO_MEMORY); - list->first=0; - list->last=0; - *listp=list; - - _status=0; - abort: - return(_status); - } + list->first = 0; + list->last = 0; + *listp = list; -int -r_list_destroy (r_list **listp) - { - r_list *list; - r_list_el *el; - - if(!listp || !*listp) - return(0); - list=*listp; + _status = 0; +abort: + return (_status); +} - el=list->first; - - while(el){ - r_list_el *el_t; - - if(el->destroy && el->data) - el->destroy(&el->data); - el_t=el; - el=el->next; - free(el_t); - } - - free(list); - *listp=0; - - return(0); - } - -int -r_list_copy (r_list **outp, r_list *in) - { - r_list *out=0; - r_list_el *el,*el2,*last=0; - int r, _status; - - if(r=r_list_create(&out)) - ABORT(r); - - for(el=in->first;in;el=el->next){ - if(!(el2=(r_list_el *)calloc(sizeof(r_list_el),1))) - ABORT(R_NO_MEMORY); - - if(el->copy && el->data){ - if(r=el->copy(&el2->data,el->data)) - ABORT(r); - } - - el2->copy=el->copy; - el2->destroy=el->destroy; - - if(!(out->first)) - out->first=el2; - - el2->prev=last; - last->next=el2; - last=el2; - } - - out->last=last; - - *outp=out; - - _status=0; - abort: - if(_status) - r_list_destroy(&out); - return(_status); - } - -int r_list_insert(list,value,copy,destroy) +int r_list_destroy(r_list **listp) { r_list *list; - void *value; - int (*copy) PROTO_LIST((void **out, void *in)); - int (*destroy) PROTO_LIST((void **val)); - { - r_list_el *el=0; - int _status; - - if(!(el=(r_list_el *)calloc(sizeof(r_list_el),1))) - ABORT(R_NO_MEMORY); - el->data=value; - el->copy=copy; - el->destroy=destroy; + r_list_el *el; - el->prev=0; - el->next=list->first; - if(list->first){ - list->first->prev=el; + if(!listp || !*listp) + return (0); + list = *listp; + + el = list->first; + + while(el) { + r_list_el *el_t; + + if(el->destroy && el->data) + el->destroy(&el->data); + el_t = el; + el = el->next; + free(el_t); + } + + free(list); + *listp = 0; + + return (0); +} + +int r_list_copy(r_list **outp, r_list *in) { + r_list *out = 0; + r_list_el *el, *el2, *last = 0; + int r, _status; + + if(r = r_list_create(&out)) + ABORT(r); + + for(el = in->first; in; el = el->next) { + if(!(el2 = (r_list_el *)calloc(sizeof(r_list_el), 1))) + ABORT(R_NO_MEMORY); + + if(el->copy && el->data) { + if(r = el->copy(&el2->data, el->data)) + ABORT(r); } - list->first=el; - _status=0; - abort: - return(_status); + el2->copy = el->copy; + el2->destroy = el->destroy; + + if(!(out->first)) + out->first = el2; + + el2->prev = last; + last->next = el2; + last = el2; } -int r_list_append(list,value,copy,destroy) - r_list *list; - void *value; - int (*copy) PROTO_LIST((void **out, void *in)); - int (*destroy) PROTO_LIST((void **val)); - { - r_list_el *el=0; - int _status; - - if(!(el=(r_list_el *)calloc(sizeof(r_list_el),1))) - ABORT(R_NO_MEMORY); - el->data=value; - el->copy=copy; - el->destroy=destroy; + out->last = last; - el->prev=list->last; - el->next=0; - - if(list->last) list->last->next=el; - else list->first=el; - - list->last=el; + *outp = out; - _status=0; - abort: - return(_status); + _status = 0; +abort: + if(_status) + r_list_destroy(&out); + return (_status); +} + +int r_list_insert(list, value, copy, destroy) r_list *list; +void *value; +int(*copy) PROTO_LIST((void **out, void *in)); +int(*destroy) PROTO_LIST((void **val)); +{ + r_list_el *el = 0; + int _status; + + if(!(el = (r_list_el *)calloc(sizeof(r_list_el), 1))) + ABORT(R_NO_MEMORY); + el->data = value; + el->copy = copy; + el->destroy = destroy; + + el->prev = 0; + el->next = list->first; + if(list->first) { + list->first->prev = el; } + list->first = el; -int -r_list_init_iter (r_list *list, r_list_iterator *iter) - { - iter->list=list; - iter->ptr=list->first; + _status = 0; +abort: + return (_status); +} - return(0); - } +int r_list_append(list, value, copy, destroy) r_list *list; +void *value; +int(*copy) PROTO_LIST((void **out, void *in)); +int(*destroy) PROTO_LIST((void **val)); +{ + r_list_el *el = 0; + int _status; -int -r_list_iter (r_list_iterator *iter, void **val) - { - if(!iter->ptr) - return(R_EOD); + if(!(el = (r_list_el *)calloc(sizeof(r_list_el), 1))) + ABORT(R_NO_MEMORY); + el->data = value; + el->copy = copy; + el->destroy = destroy; - *val=iter->ptr->data; - iter->ptr=iter->ptr->next; - - return(0); - } + el->prev = list->last; + el->next = 0; - - - - + if(list->last) + list->last->next = el; + else + list->first = el; + + list->last = el; + + _status = 0; +abort: + return (_status); +} + +int r_list_init_iter(r_list *list, r_list_iterator *iter) { + iter->list = list; + iter->ptr = list->first; + + return (0); +} + +int r_list_iter(r_list_iterator *iter, void **val) { + if(!iter->ptr) + return (R_EOD); + + *val = iter->ptr->data; + iter->ptr = iter->ptr->next; + + return (0); +} diff --git a/common/lib/r_replace.c b/common/lib/r_replace.c index 39571e6..baece4a 100644 --- a/common/lib/r_replace.c +++ b/common/lib/r_replace.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_replace.c,v 1.2 2000/10/17 16:10:00 ekr Exp $ @@ -43,24 +44,19 @@ ekr@rtfm.com Sun Oct 1 11:18:49 2000 */ - - -#include "r_common.h" +#include "r_common.h" #ifndef HAVE_STRDUP -char * -strdup (char *str) - { - int len=strlen(str); - char *n; - - if(!(n=(char *)malloc(len+1))) - return(0); +char *strdup(char *str) { + int len = strlen(str); + char *n; - memcpy(n,str,len+1); + if(!(n = (char *)malloc(len + 1))) + return (0); - return(n); - } -#endif - + memcpy(n, str, len + 1); + + return (n); +} +#endif diff --git a/common/lib/r_time.c b/common/lib/r_time.c index e0a0b98..4d61224 100644 --- a/common/lib/r_time.c +++ b/common/lib/r_time.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: r_time.c,v 1.6 2002/09/09 21:02:58 ekr Exp $ @@ -43,8 +44,6 @@ ekr@rtfm.com Thu Mar 4 08:43:46 1999 */ - - #include #include @@ -52,103 +51,97 @@ #include -int gettimeofday(struct timeval *tv, struct timezone *tzp) -{ - /* JAN1_1970_OFFSET is the number of 100-nanoseconds ticks - between midnight jan 1, 1970 and jan 1, 1601. - */ +int gettimeofday(struct timeval *tv, struct timezone *tzp) { + /* JAN1_1970_OFFSET is the number of 100-nanoseconds ticks + between midnight jan 1, 1970 and jan 1, 1601. + */ - const ULARGE_INTEGER JAN1_1970_OFFSET = {0xd53e8000, 0x019db1de}; - ULARGE_INTEGER currentTimeSinceJan_1_1970; - FILETIME currentTime; + const ULARGE_INTEGER JAN1_1970_OFFSET = {0xd53e8000, 0x019db1de}; + ULARGE_INTEGER currentTimeSinceJan_1_1970; + FILETIME currentTime; - GetSystemTimeAsFileTime( ¤tTime ); - currentTimeSinceJan_1_1970.LowPart = currentTime.dwLowDateTime; - currentTimeSinceJan_1_1970.HighPart = currentTime.dwHighDateTime; - currentTimeSinceJan_1_1970.QuadPart -= JAN1_1970_OFFSET.QuadPart; + GetSystemTimeAsFileTime(¤tTime); + currentTimeSinceJan_1_1970.LowPart = currentTime.dwLowDateTime; + currentTimeSinceJan_1_1970.HighPart = currentTime.dwHighDateTime; + currentTimeSinceJan_1_1970.QuadPart -= JAN1_1970_OFFSET.QuadPart; - /* At this point, currentTimeSinceJan_1_1970 contains the - number of 100-nanosecond 'ticks' since midnight, Jan. 1, - 1970. This is equivalent to 10 * the number of microseconds - elapsed since this time. The BSD man pages for gettimeofday() - suggest that we should return the whole number of seconds in - the tv_sec field, and the fractional number of seconds in units - of microseconds in the tv_usec field. + /* At this point, currentTimeSinceJan_1_1970 contains the + number of 100-nanosecond 'ticks' since midnight, Jan. 1, + 1970. This is equivalent to 10 * the number of microseconds + elapsed since this time. The BSD man pages for gettimeofday() + suggest that we should return the whole number of seconds in + the tv_sec field, and the fractional number of seconds in units + of microseconds in the tv_usec field. - sec = time / 10000000, usec = (time % 10000000) / 10; - */ + sec = time / 10000000, usec = (time % 10000000) / 10; + */ - tv->tv_sec = currentTimeSinceJan_1_1970.QuadPart / 10000000; - tv->tv_usec = (currentTimeSinceJan_1_1970.QuadPart % 10000000) / 10; - return 0; + tv->tv_sec = currentTimeSinceJan_1_1970.QuadPart / 10000000; + tv->tv_usec = (currentTimeSinceJan_1_1970.QuadPart % 10000000) / 10; + return 0; } #endif /*Note that t1 must be > t0 */ -int -r_timeval_diff (struct timeval *t1, struct timeval *t0, struct timeval *diff) - { - long d; +int r_timeval_diff(struct timeval *t1, + struct timeval *t0, + struct timeval *diff) { + long d; - if(t0->tv_sec > t1->tv_sec) - ERETURN(R_BAD_ARGS); + if(t0->tv_sec > t1->tv_sec) + ERETURN(R_BAD_ARGS); - /*Easy case*/ - if(t0->tv_usec <= t1->tv_usec){ - diff->tv_sec=t1->tv_sec - t0->tv_sec; - diff->tv_usec=t1->tv_usec - t0->tv_usec; - return(0); - } - - /*Hard case*/ - d=t0->tv_usec - t1->tv_usec; - if(t1->tv_sec < (t0->tv_sec + 1)) - ERETURN(R_BAD_ARGS); - diff->tv_sec=t1->tv_sec - (t0->tv_sec + 1); - diff->tv_usec=1000000 - d; - - return(0); + /*Easy case*/ + if(t0->tv_usec <= t1->tv_usec) { + diff->tv_sec = t1->tv_sec - t0->tv_sec; + diff->tv_usec = t1->tv_usec - t0->tv_usec; + return (0); } -int -r_timeval_add (struct timeval *t1, struct timeval *t2, struct timeval *sum) - { - long tv_sec,tv_usec,d; + /*Hard case*/ + d = t0->tv_usec - t1->tv_usec; + if(t1->tv_sec < (t0->tv_sec + 1)) + ERETURN(R_BAD_ARGS); + diff->tv_sec = t1->tv_sec - (t0->tv_sec + 1); + diff->tv_usec = 1000000 - d; - tv_sec=t1->tv_sec + t2->tv_sec; + return (0); +} - d=t1->tv_usec + t2->tv_usec; - if(d>1000000){ - tv_sec++; - tv_usec=d-1000000; - } - else{ - tv_usec=d; - } +int r_timeval_add(struct timeval *t1, struct timeval *t2, struct timeval *sum) { + long tv_sec, tv_usec, d; - sum->tv_sec=tv_sec; - sum->tv_usec=tv_usec; - - return(0); + tv_sec = t1->tv_sec + t2->tv_sec; + + d = t1->tv_usec + t2->tv_usec; + if(d > 1000000) { + tv_sec++; + tv_usec = d - 1000000; + } else { + tv_usec = d; } -UINT8 -r_timeval2int (struct timeval *tv) - { - UINT8 r=0; - - r=(tv->tv_sec); - r*=1000000; - r+=tv->tv_usec; - - return r; - } + sum->tv_sec = tv_sec; + sum->tv_usec = tv_usec; -UINT8 -r_gettimeint (void) - { - struct timeval tv; + return (0); +} - gettimeofday(&tv,0); +UINT8 +r_timeval2int(struct timeval *tv) { + UINT8 r = 0; - return r_timeval2int(&tv); - } + r = (tv->tv_sec); + r *= 1000000; + r += tv->tv_usec; + + return r; +} + +UINT8 +r_gettimeint(void) { + struct timeval tv; + + gettimeofday(&tv, 0); + + return r_timeval2int(&tv); +} diff --git a/common/lib/threads/pthreads/pthread.c b/common/lib/threads/pthreads/pthread.c index cffd97f..75e0622 100644 --- a/common/lib/threads/pthreads/pthread.c +++ b/common/lib/threads/pthreads/pthread.c @@ -7,146 +7,125 @@ ekr@rtfm.com Tue Feb 23 15:08:03 1999 */ - - #include #include #include -static int thread_count=0; +static int thread_count = 0; typedef struct { - void (*func) PROTO_LIST((void *)); - void *arg; + void(*func) PROTO_LIST((void *)); + void *arg; } helper; - static void *r_thread_real_create PROTO_LIST((void *arg)); -static void * -r_thread_real_create (void *arg) - { - helper *h; +static void *r_thread_real_create(void *arg) { + helper *h; - h=(helper *)arg; + h = (helper *)arg; - thread_count++; + thread_count++; - h->func(h->arg); + h->func(h->arg); - thread_count--; - free(h); - return(0); - } - -int r_thread_fork(func,arg,id) - void (*func) PROTO_LIST((void *)); - void *arg; - r_thread *id; - { - pthread_t thread; - helper *h; - int r,_status; + thread_count--; + free(h); + return (0); +} - h=(helper *)malloc(sizeof(helper)); - - h->func=func; - h->arg=arg; - - if(r=pthread_create(&thread,0,r_thread_real_create,(void *)h)) - ABORT(R_INTERNAL); +int r_thread_fork(func, arg, id) void(*func) PROTO_LIST((void *)); +void *arg; +r_thread *id; +{ + pthread_t thread; + helper *h; + int r, _status; - _status=0; - abort: - return(_status); - } + h = (helper *)malloc(sizeof(helper)); -int -r_thread_yield (void) - { + h->func = func; + h->arg = arg; + + if(r = pthread_create(&thread, 0, r_thread_real_create, (void *)h)) + ABORT(R_INTERNAL); + + _status = 0; +abort: + return (_status); +} + +int r_thread_yield(void) { + pthread_yield(); +} + +int r_thread_exit(void) { + thread_count--; + pthread_exit(0); + return (0); +} + +int r_thread_wait_last(void) { + do { pthread_yield(); + usleep(10000); + DBG((0, "%d threads left", thread_count)); + } while(thread_count); + + return (0); +} + +int r_rwlock_create(r_rwlock **lockp) { + pthread_rwlock_t *lock; + int r; + + if(!(lock = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)))) + ERETURN(R_NO_MEMORY); + + if(r = pthread_rwlock_init(lock, 0)) + ERETURN(R_INTERNAL); + + *lockp = (void *)lock; + return (0); +} + +int r_rwlock_destroy(r_rwlock **lock) { + pthread_rwlock_t *plock; + + if(!lock || !*lock) + return (0); + + plock = (pthread_rwlock_t *)(*lock); + + pthread_rwlock_destroy(plock); + + return (0); +} + +int r_rwlock_lock(r_rwlock *lock, int action) { + pthread_rwlock_t *plock; + int r, _status; + + plock = (pthread_rwlock_t *)lock; + + switch(action) { + case R_RWLOCK_UNLOCK: + if(r = pthread_rwlock_unlock(plock)) + ABORT(R_INTERNAL); + break; + case R_RWLOCK_RLOCK: + if(r = pthread_rwlock_rdlock(plock)) + ABORT(R_INTERNAL); + break; + case R_RWLOCK_WLOCK: + if(r = pthread_rwlock_wrlock(plock)) + ABORT(R_INTERNAL); + break; + default: + ABORT(R_BAD_ARGS); } -int -r_thread_exit (void) - { - thread_count--; - pthread_exit(0); - return(0); - } - -int -r_thread_wait_last (void) - { - do { - pthread_yield(); - usleep(10000); - DBG((0,"%d threads left",thread_count)); - } while (thread_count); - - return(0); - } - -int -r_rwlock_create (r_rwlock **lockp) - { - pthread_rwlock_t *lock; - int r; - - if(!(lock=(pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t)))) - ERETURN(R_NO_MEMORY); - - if(r=pthread_rwlock_init(lock,0)) - ERETURN(R_INTERNAL); - - *lockp=(void *)lock; - return(0); - } - -int -r_rwlock_destroy (r_rwlock **lock) - { - pthread_rwlock_t *plock; - - if(!lock || !*lock) - return(0); - - plock=(pthread_rwlock_t *)(*lock); - - pthread_rwlock_destroy(plock); - - return(0); - } - -int -r_rwlock_lock (r_rwlock *lock, int action) - { - pthread_rwlock_t *plock; - int r,_status; - - plock=(pthread_rwlock_t *)lock; - - switch(action){ - case R_RWLOCK_UNLOCK: - if(r=pthread_rwlock_unlock(plock)) - ABORT(R_INTERNAL); - break; - case R_RWLOCK_RLOCK: - if(r=pthread_rwlock_rdlock(plock)) - ABORT(R_INTERNAL); - break; - case R_RWLOCK_WLOCK: - if(r=pthread_rwlock_wrlock(plock)) - ABORT(R_INTERNAL); - break; - default: - ABORT(R_BAD_ARGS); - } - - _status=0; - abort: - return(_status); - } - - - + _status = 0; +abort: + return (_status); +} diff --git a/null/null_analyze.c b/null/null_analyze.c index cb98eef..d16b06f 100644 --- a/null/null_analyze.c +++ b/null/null_analyze.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: null_analyze.c,v 1.6 2001/11/26 22:28:16 ekr Exp $ @@ -43,110 +44,105 @@ ekr@rtfm.com Thu Jan 7 22:58:27 1999 */ - - #include #include "network.h" #include "proto_mod.h" #include "debug.h" typedef struct null_analyzer_ { - int num; + int num; } null_analyzer; static int create_null_analyzer PROTO_LIST((void *handle, - proto_ctx *ctx,tcp_conn *conn,proto_obj **objp, - struct sockaddr_storage *i_addr,u_short i_port, - struct sockaddr_storage *r_addr,u_short r_port, struct timeval *base_time)); + proto_ctx *ctx, + tcp_conn *conn, + proto_obj **objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *base_time)); -static int create_null_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn, - proto_obj **objp, struct sockaddr_storage *i_addr, u_short i_port, struct sockaddr_storage *r_addr, - u_short r_port, struct timeval *base_time) - { - null_analyzer *obj=0; - static int ctr; - - if(!(obj=(null_analyzer *)calloc(1,sizeof(null_analyzer)))) - ERETURN(R_NO_MEMORY); +static int create_null_analyzer(void *handle, + proto_ctx *ctx, + tcp_conn *conn, + proto_obj **objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *base_time) { + null_analyzer *obj = 0; + static int ctr; - obj->num=ctr++; - - DBG((0,"Creating analyzer for connection %d\n",obj->num)); - - *objp=(proto_obj *)obj; - return(0); - } + if(!(obj = (null_analyzer *)calloc(1, sizeof(null_analyzer)))) + ERETURN(R_NO_MEMORY); -int -destroy_null_analyzer (proto_obj **objp) - { - null_analyzer *obj; - - if(!objp || !*objp) - return(0); + obj->num = ctr++; - obj=(null_analyzer *)*objp; - DBG((0,"Destroying analyzer for connection %d\n",obj->num)); - - free(*objp); - *objp=0; + DBG((0, "Creating analyzer for connection %d\n", obj->num)); - return(0); - } + *objp = (proto_obj *)obj; + return (0); +} -int -data_null_analyzer (proto_obj *_obj, segment *seg, int direction) - { -#ifdef DEBUG - null_analyzer *obj=(null_analyzer *)_obj; -#endif - DBG((0,"Processing data for connection %d dir %d\n",obj->num, - direction)); +int destroy_null_analyzer(proto_obj **objp) { + null_analyzer *obj; - for(;seg;seg=seg->next){ - int i; - - for(i=0;ilen,20);i++){ - if(!isascii(seg->data[i])) - break; - } - if(i<20) - xdump("NSEGMENT",seg->data,seg->len); - else{ - printf("NSEGMENT: "); - fwrite(seg->data,1,seg->len,stdout); - } - printf("====\n"); + if(!objp || !*objp) + return (0); + + obj = (null_analyzer *)*objp; + DBG((0, "Destroying analyzer for connection %d\n", obj->num)); + + free(*objp); + *objp = 0; + + return (0); +} + +int data_null_analyzer(proto_obj *_obj, segment *seg, int direction) { +#ifdef DEBUG + null_analyzer *obj = (null_analyzer *)_obj; +#endif + DBG((0, "Processing data for connection %d dir %d\n", obj->num, direction)); + + for(; seg; seg = seg->next) { + int i; + + for(i = 0; i < MIN(seg->len, 20); i++) { + if(!isascii(seg->data[i])) + break; } - - return(0); + if(i < 20) + xdump("NSEGMENT", seg->data, seg->len); + else { + printf("NSEGMENT: "); + fwrite(seg->data, 1, seg->len, stdout); + } + printf("====\n"); } -int -fin_null_analyzer (proto_obj *_obj, packet *p, int direction) - { -#ifdef DEBUG - null_analyzer *obj=(null_analyzer *)_obj; -#endif - DBG((0,"Received FIN on connection %d\n",obj->num)); - return(0); - } + return (0); +} +int fin_null_analyzer(proto_obj *_obj, packet *p, int direction) { +#ifdef DEBUG + null_analyzer *obj = (null_analyzer *)_obj; +#endif + DBG((0, "Received FIN on connection %d\n", obj->num)); + return (0); +} - - -static struct proto_mod_vtbl_ null_vtbl ={ - 0, - 0, - 0, - create_null_analyzer, - 0, - destroy_null_analyzer, - data_null_analyzer, - fin_null_analyzer, +static struct proto_mod_vtbl_ null_vtbl = { + 0, + 0, + 0, + create_null_analyzer, + 0, + destroy_null_analyzer, + data_null_analyzer, + fin_null_analyzer, }; -struct proto_mod_ null_mod = { - 0, - &null_vtbl -}; +struct proto_mod_ null_mod = {0, &null_vtbl}; diff --git a/null/null_analyze.h b/null/null_analyze.h index 3902c2a..e96afe0 100644 --- a/null/null_analyze.h +++ b/null/null_analyze.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: null_analyze.h,v 1.2 2000/10/17 16:10:01 ekr Exp $ @@ -43,11 +44,9 @@ ekr@rtfm.com Fri Jan 8 11:23:10 1999 */ - #ifndef _null_analyze_h #define _null_analyze_h extern proto_mod null_mod; #endif - diff --git a/pcap/attrib.h b/pcap/attrib.h index d2e8081..397e6db 100644 --- a/pcap/attrib.h +++ b/pcap/attrib.h @@ -43,17 +43,17 @@ */ #if !defined(__GNUC__) && !defined(__clang__) -#define __attribute__(x) +#define __attribute__(x) #endif -#define UNUSED __attribute__((unused)) -#define NORET __attribute__((noreturn)) -#define PRINTF(f,a) __attribute__((format(printf,(f),(a)))) -#define SCANF(f,a) __attribute__((format(scanf,(f),(a)))) -#define WUNRES __attribute__((warn_unused_result)) -#define MALLOC __attribute__((malloc)) WUNRES -#define NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) -#define PURE __attribute__((pure)) +#define UNUSED __attribute__((unused)) +#define NORET __attribute__((noreturn)) +#define PRINTF(f, a) __attribute__((format(printf, (f), (a)))) +#define SCANF(f, a) __attribute__((format(scanf, (f), (a)))) +#define WUNRES __attribute__((warn_unused_result)) +#define MALLOC __attribute__((malloc)) WUNRES +#define NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#define PURE __attribute__((pure)) /* * Branch prediction macros. @@ -61,11 +61,11 @@ */ #if !defined(__GNUC__) && !defined(__clang__) -#define likely(expr) (expr) -#define unlikely(expr) (expr) +#define likely(expr) (expr) +#define unlikely(expr) (expr) #else -#define likely(expr) __builtin_expect((expr), 1) -#define unlikely(expr) __builtin_expect((expr), 0) +#define likely(expr) __builtin_expect((expr), 1) +#define unlikely(expr) __builtin_expect((expr), 0) #endif #endif /* !ATTRIB_H */ diff --git a/pcap/logpkt.c b/pcap/logpkt.c index 6320a16..f134b8f 100644 --- a/pcap/logpkt.c +++ b/pcap/logpkt.c @@ -46,84 +46,84 @@ #endif /* !WITHOUT_MIRROR */ typedef struct __attribute__((packed)) { - uint32_t magic_number; /* magic number */ - uint16_t version_major; /* major version number */ - uint16_t version_minor; /* minor version number */ - uint32_t thiszone; /* GMT to local correction */ - uint32_t sigfigs; /* accuracy of timestamps */ - uint32_t snaplen; /* max length of captured packets, in octets */ - uint32_t network; /* data link type */ + uint32_t magic_number; /* magic number */ + uint16_t version_major; /* major version number */ + uint16_t version_minor; /* minor version number */ + uint32_t thiszone; /* GMT to local correction */ + uint32_t sigfigs; /* accuracy of timestamps */ + uint32_t snaplen; /* max length of captured packets, in octets */ + uint32_t network; /* data link type */ } pcap_file_hdr_t; typedef struct __attribute__((packed)) { - uint32_t ts_sec; /* timestamp seconds */ - uint32_t ts_usec; /* timestamp microseconds */ - uint32_t incl_len; /* number of octets of packet saved in file */ - uint32_t orig_len; /* actual length of packet */ + uint32_t ts_sec; /* timestamp seconds */ + uint32_t ts_usec; /* timestamp microseconds */ + uint32_t incl_len; /* number of octets of packet saved in file */ + uint32_t orig_len; /* actual length of packet */ } pcap_rec_hdr_t; -#define PCAP_MAGIC 0xa1b2c3d4 +#define PCAP_MAGIC 0xa1b2c3d4 typedef struct __attribute__((packed)) { - uint8_t dst_mac[ETHER_ADDR_LEN]; - uint8_t src_mac[ETHER_ADDR_LEN]; - uint16_t ethertype; + uint8_t dst_mac[ETHER_ADDR_LEN]; + uint8_t src_mac[ETHER_ADDR_LEN]; + uint16_t ethertype; } ether_hdr_t; #ifndef ETHERTYPE_IP -#define ETHERTYPE_IP 0x0800 +#define ETHERTYPE_IP 0x0800 #endif #ifndef ETHERTYPE_IPV6 -#define ETHERTYPE_IPV6 0x86dd +#define ETHERTYPE_IPV6 0x86dd #endif typedef struct __attribute__((packed)) { - uint8_t version_ihl; - uint8_t dscp_ecn; - uint16_t len; - uint16_t id; - uint16_t frag; - uint8_t ttl; - uint8_t proto; - uint16_t chksum; - uint32_t src_addr; - uint32_t dst_addr; + uint8_t version_ihl; + uint8_t dscp_ecn; + uint16_t len; + uint16_t id; + uint16_t frag; + uint8_t ttl; + uint8_t proto; + uint16_t chksum; + uint32_t src_addr; + uint32_t dst_addr; } ip4_hdr_t; typedef struct __attribute__((packed)) { - uint32_t flags; - uint16_t len; - uint8_t next_hdr; - uint8_t hop_limit; - uint8_t src_addr[16]; - uint8_t dst_addr[16]; + uint32_t flags; + uint16_t len; + uint8_t next_hdr; + uint8_t hop_limit; + uint8_t src_addr[16]; + uint8_t dst_addr[16]; } ip6_hdr_t; typedef struct __attribute__((packed)) { - uint16_t src_port; - uint16_t dst_port; - uint32_t seq; - uint32_t ack; - uint16_t flags; - uint16_t win; - uint16_t chksum; - uint16_t urgp; + uint16_t src_port; + uint16_t dst_port; + uint32_t seq; + uint32_t ack; + uint16_t flags; + uint16_t win; + uint16_t chksum; + uint16_t urgp; } tcp_hdr_t; #ifndef TH_FIN -#define TH_FIN 0x01 +#define TH_FIN 0x01 #endif #ifndef TH_SYN -#define TH_SYN 0x02 +#define TH_SYN 0x02 #endif #ifndef TH_RST -#define TH_RST 0x04 +#define TH_RST 0x04 #endif #ifndef TH_PUSH -#define TH_PUSH 0x08 +#define TH_PUSH 0x08 #endif #ifndef TH_ACK -#define TH_ACK 0x10 +#define TH_ACK 0x10 #endif /* @@ -140,48 +140,42 @@ typedef struct __attribute__((packed)) { * These constants are only used for PCAP writing, not for mirroring. */ //#define MTU 1500 -#define MTU 65535//we add support for jumboframes and offload -#define MAX_PKTSZ (MTU + sizeof(ether_hdr_t)) -#define MSS_IP4 (MTU - sizeof(ip4_hdr_t) - sizeof(tcp_hdr_t)) -#define MSS_IP6 (MTU - sizeof(ip6_hdr_t) - sizeof(tcp_hdr_t)) +#define MTU 65535 // we add support for jumboframes and offload +#define MAX_PKTSZ (MTU + sizeof(ether_hdr_t)) +#define MSS_IP4 (MTU - sizeof(ip4_hdr_t) - sizeof(tcp_hdr_t)) +#define MSS_IP6 (MTU - sizeof(ip6_hdr_t) - sizeof(tcp_hdr_t)) /* * IP/TCP checksumming operating on uint32_t intermediate state variable C. */ #define CHKSUM_INIT(C) \ - { \ - (C) = 0; \ - } -#define CHKSUM_ADD_RANGE(C,B,S) \ - { \ - uint16_t *p = (uint16_t *)(B); \ - size_t words = (S) >> 1; \ - while (words--) { \ - (C) += *p++; \ - } \ - if ((S) & 1) { \ - (C) += htons(*((char *)p) << 8); \ - } \ - } -#define CHKSUM_ADD_UINT32(C,U) \ - { \ - (C) += ((U) >> 16) + ((U) & 0xFFFF); \ - } -#define CHKSUM_ADD_UINT16(C,U) \ - { \ - (C) += (U); \ - } -#define CHKSUM_FINALIZE(C) \ - { \ - (C) = ((C) >> 16) + ((C) & 0xffff); \ - (C) += ((C) >> 16); \ - (C) = ~(C); \ - } + { (C) = 0; } +#define CHKSUM_ADD_RANGE(C, B, S) \ + { \ + uint16_t *p = (uint16_t *)(B); \ + size_t words = (S) >> 1; \ + while(words--) { \ + (C) += *p++; \ + } \ + if((S)&1) { \ + (C) += htons(*((char *)p) << 8); \ + } \ + } +#define CHKSUM_ADD_UINT32(C, U) \ + { (C) += ((U) >> 16) + ((U)&0xFFFF); } +#define CHKSUM_ADD_UINT16(C, U) \ + { (C) += (U); } +#define CHKSUM_FINALIZE(C) \ + { \ + (C) = ((C) >> 16) + ((C)&0xffff); \ + (C) += ((C) >> 16); \ + (C) = ~(C); \ + } /* Socket address typecasting shorthand notations. */ -#define CSA(X) ((const struct sockaddr *)(X)) -#define CSIN(X) ((const struct sockaddr_in *)(X)) -#define CSIN6(X) ((const struct sockaddr_in6 *)(X)) +#define CSA(X) ((const struct sockaddr *)(X)) +#define CSIN(X) ((const struct sockaddr_in *)(X)) +#define CSIN6(X) ((const struct sockaddr_in6 *)(X)) /* * Write the PCAP file-level header to file descriptor *fd* open for writing, @@ -189,18 +183,16 @@ typedef struct __attribute__((packed)) { * * Returns 0 on success and -1 on failure. */ -static int -logpkt_write_global_pcap_hdr(int fd) -{ - pcap_file_hdr_t hdr; +static int logpkt_write_global_pcap_hdr(int fd) { + pcap_file_hdr_t hdr; - memset(&hdr, 0x0, sizeof(hdr)); - hdr.magic_number = PCAP_MAGIC; - hdr.version_major = 2; - hdr.version_minor = 4; - hdr.snaplen = MAX_PKTSZ; - hdr.network = 1; - return write(fd, &hdr, sizeof(hdr)) != sizeof(hdr) ? -1 : 0; + memset(&hdr, 0x0, sizeof(hdr)); + hdr.magic_number = PCAP_MAGIC; + hdr.version_major = 2; + hdr.version_minor = 4; + hdr.snaplen = MAX_PKTSZ; + hdr.network = 1; + return write(fd, &hdr, sizeof(hdr)) != sizeof(hdr) ? -1 : 0; } /* @@ -214,36 +206,35 @@ logpkt_write_global_pcap_hdr(int fd) * file descriptor. On error, -1 is returned and the file descriptor is in an * undefined but still open state. */ -int -logpkt_pcap_open_fd(int fd) { - pcap_file_hdr_t hdr; - off_t sz; - ssize_t n; - struct stat st; +int logpkt_pcap_open_fd(int fd) { + pcap_file_hdr_t hdr; + off_t sz; + ssize_t n; + struct stat st; - if(fstat(fd, &st)) - return -1; + if(fstat(fd, &st)) + return -1; - if(!S_ISFIFO(st.st_mode)) { - sz = lseek(fd, 0, SEEK_END); - if (sz == -1) - return -1; + if(!S_ISFIFO(st.st_mode)) { + sz = lseek(fd, 0, SEEK_END); + if(sz == -1) + return -1; - if (sz > 0) { - if (lseek(fd, 0, SEEK_SET) == -1) - return -1; - n = read(fd, &hdr, sizeof(pcap_file_hdr_t)); - if (n != sizeof(pcap_file_hdr_t)) - return -1; - if (hdr.magic_number == PCAP_MAGIC) - return lseek(fd, 0, SEEK_END) == -1 ? -1 : 0; - if (lseek(fd, 0, SEEK_SET) == -1) - return -1; - if (ftruncate(fd, 0) == -1) - return -1; - } - } - return logpkt_write_global_pcap_hdr(fd); + if(sz > 0) { + if(lseek(fd, 0, SEEK_SET) == -1) + return -1; + n = read(fd, &hdr, sizeof(pcap_file_hdr_t)); + if(n != sizeof(pcap_file_hdr_t)) + return -1; + if(hdr.magic_number == PCAP_MAGIC) + return lseek(fd, 0, SEEK_END) == -1 ? -1 : 0; + if(lseek(fd, 0, SEEK_SET) == -1) + return -1; + if(ftruncate(fd, 0) == -1) + return -1; + } + } + return logpkt_write_global_pcap_hdr(fd); } /* @@ -255,55 +246,53 @@ logpkt_pcap_open_fd(int fd) { * match the actual link layer addresses to be used when sending traffic, not * some emulated addresses. */ -void -logpkt_ctx_init(logpkt_ctx_t *ctx, libnet_t *libnet, size_t mtu, - const uint8_t *src_ether, const uint8_t *dst_ether, - const struct sockaddr *src_addr, socklen_t src_addr_len, - const struct sockaddr *dst_addr, socklen_t dst_addr_len) -{ - ctx->libnet = libnet; - memcpy(ctx->src_ether, src_ether, ETHER_ADDR_LEN); - memcpy(ctx->dst_ether, dst_ether, ETHER_ADDR_LEN); - memcpy(&ctx->src_addr, src_addr, src_addr_len); - memcpy(&ctx->dst_addr, dst_addr, dst_addr_len); - ctx->src_seq = 0; - ctx->dst_seq = 0; - if (mtu) { - ctx->mss = mtu - sizeof(tcp_hdr_t) - - (dst_addr->sa_family == AF_INET - ? sizeof(ip4_hdr_t) - : sizeof(ip6_hdr_t)); - } else { - ctx->mss = dst_addr->sa_family == AF_INET ? MSS_IP4 : MSS_IP6; - } +void logpkt_ctx_init(logpkt_ctx_t *ctx, + libnet_t *libnet, + size_t mtu, + const uint8_t *src_ether, + const uint8_t *dst_ether, + const struct sockaddr *src_addr, + socklen_t src_addr_len, + const struct sockaddr *dst_addr, + socklen_t dst_addr_len) { + ctx->libnet = libnet; + memcpy(ctx->src_ether, src_ether, ETHER_ADDR_LEN); + memcpy(ctx->dst_ether, dst_ether, ETHER_ADDR_LEN); + memcpy(&ctx->src_addr, src_addr, src_addr_len); + memcpy(&ctx->dst_addr, dst_addr, dst_addr_len); + ctx->src_seq = 0; + ctx->dst_seq = 0; + if(mtu) { + ctx->mss = mtu - sizeof(tcp_hdr_t) - + (dst_addr->sa_family == AF_INET ? sizeof(ip4_hdr_t) + : sizeof(ip6_hdr_t)); + } else { + ctx->mss = dst_addr->sa_family == AF_INET ? MSS_IP4 : MSS_IP6; + } } /* * Write the layer 2 frame contained in *pkt* to file descriptor *fd* already * open for writing. First writes a PCAP record header, then the actual frame. */ -static int -logpkt_pcap_write(const uint8_t *pkt, size_t pktsz, int fd) -{ - pcap_rec_hdr_t rec_hdr; - struct timeval tv; +static int logpkt_pcap_write(const uint8_t *pkt, size_t pktsz, int fd) { + pcap_rec_hdr_t rec_hdr; + struct timeval tv; - gettimeofday(&tv, NULL); - rec_hdr.ts_sec = tv.tv_sec; - rec_hdr.ts_usec = tv.tv_usec; - rec_hdr.orig_len = rec_hdr.incl_len = pktsz; + gettimeofday(&tv, NULL); + rec_hdr.ts_sec = tv.tv_sec; + rec_hdr.ts_usec = tv.tv_usec; + rec_hdr.orig_len = rec_hdr.incl_len = pktsz; - if (write(fd, &rec_hdr, sizeof(rec_hdr)) != sizeof(rec_hdr)) { - printf("Error writing pcap record hdr: %s\n", - strerror(errno)); - return -1; - } - if (write(fd, pkt, pktsz) != (ssize_t)pktsz) { - printf("Error writing pcap record: %s\n", - strerror(errno)); - return -1; - } - return 0; + if(write(fd, &rec_hdr, sizeof(rec_hdr)) != sizeof(rec_hdr)) { + printf("Error writing pcap record hdr: %s\n", strerror(errno)); + return -1; + } + if(write(fd, pkt, pktsz) != (ssize_t)pktsz) { + printf("Error writing pcap record: %s\n", strerror(errno)); + return -1; + } + return 0; } /* @@ -317,94 +306,88 @@ logpkt_pcap_write(const uint8_t *pkt, size_t pktsz, int fd) * This function is stateless. For header fields that cannot be directly * derived from the arguments, default values will be used. */ -static size_t -logpkt_pcap_build(uint8_t *pkt, - uint8_t *src_ether, uint8_t *dst_ether, - const struct sockaddr *src_addr, - const struct sockaddr *dst_addr, - char flags, uint32_t seq, uint32_t ack, - const uint8_t *payload, size_t payloadlen) -{ - ether_hdr_t *ether_hdr; - ip4_hdr_t *ip4_hdr; - ip6_hdr_t *ip6_hdr; - tcp_hdr_t *tcp_hdr; - size_t sz; - uint32_t sum; +static size_t logpkt_pcap_build(uint8_t *pkt, + uint8_t *src_ether, + uint8_t *dst_ether, + const struct sockaddr *src_addr, + const struct sockaddr *dst_addr, + char flags, + uint32_t seq, + uint32_t ack, + const uint8_t *payload, + size_t payloadlen) { + ether_hdr_t *ether_hdr; + ip4_hdr_t *ip4_hdr; + ip6_hdr_t *ip6_hdr; + tcp_hdr_t *tcp_hdr; + size_t sz; + uint32_t sum; - ether_hdr = (ether_hdr_t *)pkt; - memcpy(ether_hdr->src_mac, src_ether, sizeof(ether_hdr->src_mac)); - memcpy(ether_hdr->dst_mac, dst_ether, sizeof(ether_hdr->dst_mac)); - sz = sizeof(ether_hdr_t); + ether_hdr = (ether_hdr_t *)pkt; + memcpy(ether_hdr->src_mac, src_ether, sizeof(ether_hdr->src_mac)); + memcpy(ether_hdr->dst_mac, dst_ether, sizeof(ether_hdr->dst_mac)); + sz = sizeof(ether_hdr_t); - if (dst_addr->sa_family == AF_INET) { - ether_hdr->ethertype = htons(ETHERTYPE_IP); - ip4_hdr = (ip4_hdr_t *)(((uint8_t *)ether_hdr) + - sizeof(ether_hdr_t)); - ip4_hdr->version_ihl = 0x45; /* version 4, ihl 5 words */ - ip4_hdr->dscp_ecn = 0; - ip4_hdr->len = htons(sizeof(ip4_hdr_t) + - sizeof(tcp_hdr_t) + payloadlen); - ip4_hdr->id = sys_rand16(), - ip4_hdr->frag = 0; - ip4_hdr->ttl = 64; - ip4_hdr->proto = IPPROTO_TCP; - ip4_hdr->src_addr = CSIN(src_addr)->sin_addr.s_addr; - ip4_hdr->dst_addr = CSIN(dst_addr)->sin_addr.s_addr; - ip4_hdr->chksum = 0; - CHKSUM_INIT(sum); - CHKSUM_ADD_RANGE(sum, ip4_hdr, sizeof(ip4_hdr_t)); - CHKSUM_FINALIZE(sum); - ip4_hdr->chksum = sum; - sz += sizeof(ip4_hdr_t); - tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip4_hdr) + - sizeof(ip4_hdr_t)); - tcp_hdr->src_port = CSIN(src_addr)->sin_port; - tcp_hdr->dst_port = CSIN(dst_addr)->sin_port; - /* pseudo header */ - CHKSUM_INIT(sum); - CHKSUM_ADD_UINT32(sum, ip4_hdr->src_addr); - CHKSUM_ADD_UINT32(sum, ip4_hdr->dst_addr); - CHKSUM_ADD_UINT16(sum, htons(ip4_hdr->proto)); - CHKSUM_ADD_UINT16(sum, htons(sizeof(tcp_hdr_t) + payloadlen)); - } else { - ether_hdr->ethertype = htons(ETHERTYPE_IPV6); - ip6_hdr = (ip6_hdr_t *)(((uint8_t *)ether_hdr) + - sizeof(ether_hdr_t)); - ip6_hdr->flags = htonl(0x60000000UL); /* version 6 */ - ip6_hdr->len = htons(sizeof(tcp_hdr_t) + payloadlen); - ip6_hdr->next_hdr = IPPROTO_TCP; - ip6_hdr->hop_limit = 255; - memcpy(ip6_hdr->src_addr, CSIN6(src_addr)->sin6_addr.s6_addr, - sizeof(ip6_hdr->src_addr)); - memcpy(ip6_hdr->dst_addr, CSIN6(dst_addr)->sin6_addr.s6_addr, - sizeof(ip6_hdr->dst_addr)); - sz += sizeof(ip6_hdr_t); - tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip6_hdr) + - sizeof(ip6_hdr_t)); - tcp_hdr->src_port = CSIN6(src_addr)->sin6_port; - tcp_hdr->dst_port = CSIN6(dst_addr)->sin6_port; - /* pseudo header */ - CHKSUM_INIT(sum); - CHKSUM_ADD_RANGE(sum, ip6_hdr->src_addr, - sizeof(ip6_hdr->src_addr)); - CHKSUM_ADD_RANGE(sum, ip6_hdr->dst_addr, - sizeof(ip6_hdr->dst_addr)); - CHKSUM_ADD_UINT32(sum, ip6_hdr->len); - CHKSUM_ADD_UINT16(sum, htons(IPPROTO_TCP)); - } - tcp_hdr->seq = htonl(seq); - tcp_hdr->ack = htonl(ack); - tcp_hdr->flags = htons(0x5000|flags); /* data offset 5 words */ - tcp_hdr->win = htons(32767); - tcp_hdr->urgp = 0; - tcp_hdr->chksum = 0; - sz += sizeof(tcp_hdr_t); - memcpy(((uint8_t *)tcp_hdr) + sizeof(tcp_hdr_t), payload, payloadlen); - CHKSUM_ADD_RANGE(sum, tcp_hdr, sizeof(tcp_hdr_t) + payloadlen); - CHKSUM_FINALIZE(sum); - tcp_hdr->chksum = sum; - return sz + payloadlen; + if(dst_addr->sa_family == AF_INET) { + ether_hdr->ethertype = htons(ETHERTYPE_IP); + ip4_hdr = (ip4_hdr_t *)(((uint8_t *)ether_hdr) + sizeof(ether_hdr_t)); + ip4_hdr->version_ihl = 0x45; /* version 4, ihl 5 words */ + ip4_hdr->dscp_ecn = 0; + ip4_hdr->len = htons(sizeof(ip4_hdr_t) + sizeof(tcp_hdr_t) + payloadlen); + ip4_hdr->id = sys_rand16(), ip4_hdr->frag = 0; + ip4_hdr->ttl = 64; + ip4_hdr->proto = IPPROTO_TCP; + ip4_hdr->src_addr = CSIN(src_addr)->sin_addr.s_addr; + ip4_hdr->dst_addr = CSIN(dst_addr)->sin_addr.s_addr; + ip4_hdr->chksum = 0; + CHKSUM_INIT(sum); + CHKSUM_ADD_RANGE(sum, ip4_hdr, sizeof(ip4_hdr_t)); + CHKSUM_FINALIZE(sum); + ip4_hdr->chksum = sum; + sz += sizeof(ip4_hdr_t); + tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip4_hdr) + sizeof(ip4_hdr_t)); + tcp_hdr->src_port = CSIN(src_addr)->sin_port; + tcp_hdr->dst_port = CSIN(dst_addr)->sin_port; + /* pseudo header */ + CHKSUM_INIT(sum); + CHKSUM_ADD_UINT32(sum, ip4_hdr->src_addr); + CHKSUM_ADD_UINT32(sum, ip4_hdr->dst_addr); + CHKSUM_ADD_UINT16(sum, htons(ip4_hdr->proto)); + CHKSUM_ADD_UINT16(sum, htons(sizeof(tcp_hdr_t) + payloadlen)); + } else { + ether_hdr->ethertype = htons(ETHERTYPE_IPV6); + ip6_hdr = (ip6_hdr_t *)(((uint8_t *)ether_hdr) + sizeof(ether_hdr_t)); + ip6_hdr->flags = htonl(0x60000000UL); /* version 6 */ + ip6_hdr->len = htons(sizeof(tcp_hdr_t) + payloadlen); + ip6_hdr->next_hdr = IPPROTO_TCP; + ip6_hdr->hop_limit = 255; + memcpy(ip6_hdr->src_addr, CSIN6(src_addr)->sin6_addr.s6_addr, + sizeof(ip6_hdr->src_addr)); + memcpy(ip6_hdr->dst_addr, CSIN6(dst_addr)->sin6_addr.s6_addr, + sizeof(ip6_hdr->dst_addr)); + sz += sizeof(ip6_hdr_t); + tcp_hdr = (tcp_hdr_t *)(((uint8_t *)ip6_hdr) + sizeof(ip6_hdr_t)); + tcp_hdr->src_port = CSIN6(src_addr)->sin6_port; + tcp_hdr->dst_port = CSIN6(dst_addr)->sin6_port; + /* pseudo header */ + CHKSUM_INIT(sum); + CHKSUM_ADD_RANGE(sum, ip6_hdr->src_addr, sizeof(ip6_hdr->src_addr)); + CHKSUM_ADD_RANGE(sum, ip6_hdr->dst_addr, sizeof(ip6_hdr->dst_addr)); + CHKSUM_ADD_UINT32(sum, ip6_hdr->len); + CHKSUM_ADD_UINT16(sum, htons(IPPROTO_TCP)); + } + tcp_hdr->seq = htonl(seq); + tcp_hdr->ack = htonl(ack); + tcp_hdr->flags = htons(0x5000 | flags); /* data offset 5 words */ + tcp_hdr->win = htons(32767); + tcp_hdr->urgp = 0; + tcp_hdr->chksum = 0; + sz += sizeof(tcp_hdr_t); + memcpy(((uint8_t *)tcp_hdr) + sizeof(tcp_hdr_t), payload, payloadlen); + CHKSUM_ADD_RANGE(sum, tcp_hdr, sizeof(tcp_hdr_t) + payloadlen); + CHKSUM_FINALIZE(sum); + tcp_hdr->chksum = sum; + return sz + payloadlen; } #ifndef WITHOUT_MIRROR @@ -412,83 +395,66 @@ logpkt_pcap_build(uint8_t *pkt, * Build a packet using libnet intended for mirroring mode. The packet will * be dynamically allocated on the heap by the libnet instance *libnet*. */ -static int -logpkt_mirror_build(libnet_t *libnet, - uint8_t *src_ether, uint8_t *dst_ether, - const struct sockaddr *src_addr, - const struct sockaddr *dst_addr, - char flags, uint32_t seq, uint32_t ack, - const uint8_t *payload, size_t payloadlen) -{ - libnet_ptag_t ptag; +static int logpkt_mirror_build(libnet_t *libnet, + uint8_t *src_ether, + uint8_t *dst_ether, + const struct sockaddr *src_addr, + const struct sockaddr *dst_addr, + char flags, + uint32_t seq, + uint32_t ack, + const uint8_t *payload, + size_t payloadlen) { + libnet_ptag_t ptag; - ptag = libnet_build_tcp(htons(src_addr->sa_family == AF_INET - ? CSIN(src_addr)->sin_port - : CSIN6(src_addr)->sin6_port), - htons(dst_addr->sa_family == AF_INET - ? CSIN(dst_addr)->sin_port - : CSIN6(dst_addr)->sin6_port), - seq, - ack, - flags, - 32767, /* window size */ - 0, /* checksum */ - 0, /* urgent pointer */ - LIBNET_TCP_H + payloadlen, - (uint8_t *)payload, payloadlen, - libnet, 0); - if (ptag == -1) { - printf("Error building tcp header: %s", - libnet_geterror(libnet)); - return -1; - } + ptag = libnet_build_tcp( + htons(src_addr->sa_family == AF_INET ? CSIN(src_addr)->sin_port + : CSIN6(src_addr)->sin6_port), + htons(dst_addr->sa_family == AF_INET ? CSIN(dst_addr)->sin_port + : CSIN6(dst_addr)->sin6_port), + seq, ack, flags, 32767, /* window size */ + 0, /* checksum */ + 0, /* urgent pointer */ + LIBNET_TCP_H + payloadlen, (uint8_t *)payload, payloadlen, libnet, 0); + if(ptag == -1) { + printf("Error building tcp header: %s", libnet_geterror(libnet)); + return -1; + } - if (dst_addr->sa_family == AF_INET) { - ptag = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_TCP_H + - payloadlen, - 0, /* TOS */ - (uint16_t) - sys_rand16(), /* id */ - 0x4000, /* frag */ - 64, /* TTL */ - IPPROTO_TCP, /* protocol */ - 0, /* checksum */ - CSIN(src_addr)->sin_addr.s_addr, - CSIN(dst_addr)->sin_addr.s_addr, - NULL, 0, - libnet, 0); - } else { - ptag = libnet_build_ipv6(0, /* traffic class */ - 0, /* flow label */ - LIBNET_IPV6_H + LIBNET_TCP_H + - payloadlen, - IPPROTO_TCP, - 255, /* hop limit */ - *(struct libnet_in6_addr *) - &CSIN6(src_addr)->sin6_addr, - *(struct libnet_in6_addr *) - &CSIN6(dst_addr)->sin6_addr, - NULL, 0, - libnet, 0); - } - if (ptag == -1) { - printf("Error building ip header: %s", - libnet_geterror(libnet)); - return -1; - } + if(dst_addr->sa_family == AF_INET) { + ptag = libnet_build_ipv4( + LIBNET_IPV4_H + LIBNET_TCP_H + payloadlen, 0, /* TOS */ + (uint16_t)sys_rand16(), /* id */ + 0x4000, /* frag */ + 64, /* TTL */ + IPPROTO_TCP, /* protocol */ + 0, /* checksum */ + CSIN(src_addr)->sin_addr.s_addr, CSIN(dst_addr)->sin_addr.s_addr, NULL, + 0, libnet, 0); + } else { + ptag = libnet_build_ipv6( + 0, /* traffic class */ + 0, /* flow label */ + LIBNET_IPV6_H + LIBNET_TCP_H + payloadlen, IPPROTO_TCP, + 255, /* hop limit */ + *(struct libnet_in6_addr *)&CSIN6(src_addr)->sin6_addr, + *(struct libnet_in6_addr *)&CSIN6(dst_addr)->sin6_addr, NULL, 0, libnet, + 0); + } + if(ptag == -1) { + printf("Error building ip header: %s", libnet_geterror(libnet)); + return -1; + } - ptag = libnet_build_ethernet(dst_ether, - src_ether, - dst_addr->sa_family == AF_INET - ? ETHERTYPE_IP : ETHERTYPE_IPV6, - NULL, 0, - libnet, 0); - if (ptag == -1) { - printf("Error building ethernet header: %s", - libnet_geterror(libnet)); - return -1; - } - return 0; + ptag = libnet_build_ethernet( + dst_ether, src_ether, + dst_addr->sa_family == AF_INET ? ETHERTYPE_IP : ETHERTYPE_IPV6, NULL, 0, + libnet, 0); + if(ptag == -1) { + printf("Error building ethernet header: %s", libnet_geterror(libnet)); + return -1; + } + return 0; } #endif /* !WITHOUT_MIRROR */ @@ -502,96 +468,77 @@ logpkt_mirror_build(libnet_t *libnet, * Caller must ensure that *payload* fits into a frame depending on the MTU * selected (interface in mirroring mode, MTU value in PCAP writing mode). */ -static int -logpkt_write_packet(logpkt_ctx_t *ctx, int fd, int direction, char flags, - const uint8_t *payload, size_t payloadlen) -{ - int rv; +static int logpkt_write_packet(logpkt_ctx_t *ctx, + int fd, + int direction, + char flags, + const uint8_t *payload, + size_t payloadlen) { + int rv; - if (fd != -1) { - uint8_t buf[MAX_PKTSZ]; - size_t sz; - if (direction == LOGPKT_REQUEST) { - sz = logpkt_pcap_build(buf, - ctx->src_ether, ctx->dst_ether, - CSA(&ctx->src_addr), - CSA(&ctx->dst_addr), - flags, - ctx->src_seq, ctx->dst_seq, - payload, payloadlen); - } else { - sz = logpkt_pcap_build(buf, - ctx->dst_ether, ctx->src_ether, - CSA(&ctx->dst_addr), - CSA(&ctx->src_addr), - flags, - ctx->dst_seq, ctx->src_seq, - payload, payloadlen); - } - rv = logpkt_pcap_write(buf, sz, fd); - if (rv == -1) { - printf("Error writing packet to PCAP file\n"); - return -1; - } - } else { + if(fd != -1) { + uint8_t buf[MAX_PKTSZ]; + size_t sz; + if(direction == LOGPKT_REQUEST) { + sz = logpkt_pcap_build(buf, ctx->src_ether, ctx->dst_ether, + CSA(&ctx->src_addr), CSA(&ctx->dst_addr), flags, + ctx->src_seq, ctx->dst_seq, payload, payloadlen); + } else { + sz = logpkt_pcap_build(buf, ctx->dst_ether, ctx->src_ether, + CSA(&ctx->dst_addr), CSA(&ctx->src_addr), flags, + ctx->dst_seq, ctx->src_seq, payload, payloadlen); + } + rv = logpkt_pcap_write(buf, sz, fd); + if(rv == -1) { + printf("Error writing packet to PCAP file\n"); + return -1; + } + } else { #ifndef WITHOUT_MIRROR - /* Source and destination ether are determined by the actual - * local MAC address and target MAC address for mirroring the - * packets to; use them as-is for both directions. */ - if (direction == LOGPKT_REQUEST) { - rv = logpkt_mirror_build(ctx->libnet, - ctx->src_ether, ctx->dst_ether, - CSA(&ctx->src_addr), - CSA(&ctx->dst_addr), - flags, - ctx->src_seq, ctx->dst_seq, - payload, payloadlen); - } else { - rv = logpkt_mirror_build(ctx->libnet, - ctx->src_ether, ctx->dst_ether, - CSA(&ctx->dst_addr), - CSA(&ctx->src_addr), - flags, - ctx->dst_seq, ctx->src_seq, - payload, payloadlen); - } - if (rv == -1) { - printf("Error building packet\n"); - return -1; - } - rv = libnet_write(ctx->libnet); - if (rv == -1) { - printf("Error writing packet: %s\n", - libnet_geterror(ctx->libnet)); - } - libnet_clear_packet(ctx->libnet); -#else /* WITHOUT_MIRROR */ - rv = -1; + /* Source and destination ether are determined by the actual + * local MAC address and target MAC address for mirroring the + * packets to; use them as-is for both directions. */ + if(direction == LOGPKT_REQUEST) { + rv = logpkt_mirror_build(ctx->libnet, ctx->src_ether, ctx->dst_ether, + CSA(&ctx->src_addr), CSA(&ctx->dst_addr), flags, + ctx->src_seq, ctx->dst_seq, payload, payloadlen); + } else { + rv = logpkt_mirror_build(ctx->libnet, ctx->src_ether, ctx->dst_ether, + CSA(&ctx->dst_addr), CSA(&ctx->src_addr), flags, + ctx->dst_seq, ctx->src_seq, payload, payloadlen); + } + if(rv == -1) { + printf("Error building packet\n"); + return -1; + } + rv = libnet_write(ctx->libnet); + if(rv == -1) { + printf("Error writing packet: %s\n", libnet_geterror(ctx->libnet)); + } + libnet_clear_packet(ctx->libnet); +#else /* WITHOUT_MIRROR */ + rv = -1; #endif /* WITHOUT_MIRROR */ - } - return rv; + } + return rv; } /* * Emulate the initial SYN handshake. */ -static int -logpkt_write_syn_handshake(logpkt_ctx_t *ctx, int fd) -{ - ctx->src_seq = sys_rand32(); - if (logpkt_write_packet(ctx, fd, LOGPKT_REQUEST, - TH_SYN, NULL, 0) == -1) - return -1; - ctx->src_seq += 1; - ctx->dst_seq = sys_rand32(); - if (logpkt_write_packet(ctx, fd, LOGPKT_RESPONSE, - TH_SYN|TH_ACK, NULL, 0) == -1) - return -1; - ctx->dst_seq += 1; - if (logpkt_write_packet(ctx, fd, LOGPKT_REQUEST, - TH_ACK, NULL, 0) == -1) - return -1; - return 0; +static int logpkt_write_syn_handshake(logpkt_ctx_t *ctx, int fd) { + ctx->src_seq = sys_rand32(); + if(logpkt_write_packet(ctx, fd, LOGPKT_REQUEST, TH_SYN, NULL, 0) == -1) + return -1; + ctx->src_seq += 1; + ctx->dst_seq = sys_rand32(); + if(logpkt_write_packet(ctx, fd, LOGPKT_RESPONSE, TH_SYN | TH_ACK, NULL, 0) == + -1) + return -1; + ctx->dst_seq += 1; + if(logpkt_write_packet(ctx, fd, LOGPKT_REQUEST, TH_ACK, NULL, 0) == -1) + return -1; + return 0; } /* @@ -599,129 +546,124 @@ logpkt_write_syn_handshake(logpkt_ctx_t *ctx, int fd) * necessary, a SYN handshake will automatically be generated before emitting * the packet carrying the payload plus a matching ACK. */ -int -logpkt_write_payload(logpkt_ctx_t *ctx, int fd, int direction, - const uint8_t *payload, size_t payloadlen) -{ - int other_direction = (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE - : LOGPKT_REQUEST; +int logpkt_write_payload(logpkt_ctx_t *ctx, + int fd, + int direction, + const uint8_t *payload, + size_t payloadlen) { + int other_direction = + (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE : LOGPKT_REQUEST; - if (ctx->src_seq == 0) { - if (logpkt_write_syn_handshake(ctx, fd) == -1) - return -1; - } + if(ctx->src_seq == 0) { + if(logpkt_write_syn_handshake(ctx, fd) == -1) + return -1; + } - while (payloadlen > 0) { - size_t n = payloadlen > ctx->mss ? ctx->mss : payloadlen; - if (logpkt_write_packet(ctx, fd, direction, - TH_PUSH|TH_ACK, payload, n) == -1) { - printf("Warning: Failed to write to pcap log" - ": %s\n", strerror(errno)); - return -1; - } - if (direction == LOGPKT_REQUEST) { - ctx->src_seq += n; - } else { - ctx->dst_seq += n; - } - payload += n; - payloadlen -= n; - } + while(payloadlen > 0) { + size_t n = payloadlen > ctx->mss ? ctx->mss : payloadlen; + if(logpkt_write_packet(ctx, fd, direction, TH_PUSH | TH_ACK, payload, n) == + -1) { + printf( + "Warning: Failed to write to pcap log" + ": %s\n", + strerror(errno)); + return -1; + } + if(direction == LOGPKT_REQUEST) { + ctx->src_seq += n; + } else { + ctx->dst_seq += n; + } + payload += n; + payloadlen -= n; + } - if (logpkt_write_packet(ctx, fd, other_direction, - TH_ACK, NULL, 0) == -1) { - printf("Warning: Failed to write to pcap log: %s\n", - strerror(errno)); - return -1; - } - return 0; + if(logpkt_write_packet(ctx, fd, other_direction, TH_ACK, NULL, 0) == -1) { + printf("Warning: Failed to write to pcap log: %s\n", strerror(errno)); + return -1; + } + return 0; } /* * Emulate a connection close, emitting a FIN handshake in the correct * direction. Does not close the file descriptor. */ -int -logpkt_write_close(logpkt_ctx_t *ctx, int fd, int direction) { - int other_direction = (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE - : LOGPKT_REQUEST; +int logpkt_write_close(logpkt_ctx_t *ctx, int fd, int direction) { + int other_direction = + (direction == LOGPKT_REQUEST) ? LOGPKT_RESPONSE : LOGPKT_REQUEST; - if (ctx->src_seq == 0) { - if (logpkt_write_syn_handshake(ctx, fd) == -1) - return -1; - } + if(ctx->src_seq == 0) { + if(logpkt_write_syn_handshake(ctx, fd) == -1) + return -1; + } - if (logpkt_write_packet(ctx, fd, direction, - TH_FIN|TH_ACK, NULL, 0) == -1) { - printf("Warning: Failed to write packet\n"); - return -1; - } - if (direction == LOGPKT_REQUEST) { - ctx->src_seq += 1; - } else { - ctx->dst_seq += 1; - } + if(logpkt_write_packet(ctx, fd, direction, TH_FIN | TH_ACK, NULL, 0) == -1) { + printf("Warning: Failed to write packet\n"); + return -1; + } + if(direction == LOGPKT_REQUEST) { + ctx->src_seq += 1; + } else { + ctx->dst_seq += 1; + } - if (logpkt_write_packet(ctx, fd, other_direction, - TH_FIN|TH_ACK, NULL, 0) == -1) { - printf("Warning: Failed to write packet\n"); - return -1; - } - if (other_direction == LOGPKT_REQUEST) { - ctx->src_seq += 1; - } else { - ctx->dst_seq += 1; - } + if(logpkt_write_packet(ctx, fd, other_direction, TH_FIN | TH_ACK, NULL, 0) == + -1) { + printf("Warning: Failed to write packet\n"); + return -1; + } + if(other_direction == LOGPKT_REQUEST) { + ctx->src_seq += 1; + } else { + ctx->dst_seq += 1; + } - if (logpkt_write_packet(ctx, fd, direction, - TH_ACK, NULL, 0) == -1) { - printf("Warning: Failed to write packet\n"); - return -1; - } + if(logpkt_write_packet(ctx, fd, direction, TH_ACK, NULL, 0) == -1) { + printf("Warning: Failed to write packet\n"); + return -1; + } - return 0; + return 0; } #ifndef WITHOUT_MIRROR typedef struct { - uint32_t ip; - int result; - uint8_t ether[ETHER_ADDR_LEN]; + uint32_t ip; + int result; + uint8_t ether[ETHER_ADDR_LEN]; } logpkt_recv_arp_reply_ctx_t; /* * Receive a single ARP reply and copy the resulting ether to ctx->ether. */ -static void -logpkt_recv_arp_reply(uint8_t *user, - UNUSED const struct pcap_pkthdr *h, - const uint8_t *packet) -{ - logpkt_recv_arp_reply_ctx_t *ctx = (logpkt_recv_arp_reply_ctx_t*)user; - struct libnet_802_3_hdr *heth = (void*)packet; - struct libnet_arp_hdr *harp = (void*)((char*)heth + LIBNET_ETH_H); +static void logpkt_recv_arp_reply(uint8_t *user, + UNUSED const struct pcap_pkthdr *h, + const uint8_t *packet) { + logpkt_recv_arp_reply_ctx_t *ctx = (logpkt_recv_arp_reply_ctx_t *)user; + struct libnet_802_3_hdr *heth = (void *)packet; + struct libnet_arp_hdr *harp = (void *)((char *)heth + LIBNET_ETH_H); - /* skip if wrong protocol */ - if (htons(harp->ar_op) != ARPOP_REPLY) - return; - if (htons(harp->ar_pro) != ETHERTYPE_IP) - return; - if (htons(harp->ar_hrd) != ARPHRD_ETHER) - return; + /* skip if wrong protocol */ + if(htons(harp->ar_op) != ARPOP_REPLY) + return; + if(htons(harp->ar_pro) != ETHERTYPE_IP) + return; + if(htons(harp->ar_hrd) != ARPHRD_ETHER) + return; - /* skip if wrong target IP address */ - if (!!memcmp(&ctx->ip, (char*)harp + harp->ar_hln + LIBNET_ARP_H, 4)) - return; + /* skip if wrong target IP address */ + if(!!memcmp(&ctx->ip, (char *)harp + harp->ar_hln + LIBNET_ARP_H, 4)) + return; - /* skip if source ether mismatch */ - if (!!memcmp((u_char*)harp + sizeof(struct libnet_arp_hdr), - heth->_802_3_shost, ETHER_ADDR_LEN)) - return; + /* skip if source ether mismatch */ + if(!!memcmp((u_char *)harp + sizeof(struct libnet_arp_hdr), + heth->_802_3_shost, ETHER_ADDR_LEN)) + return; - memcpy(ctx->ether, - (u_char*)harp + sizeof(struct libnet_arp_hdr), - ETHER_ADDR_LEN); - ctx->result = 0; + memcpy(ctx->ether, (u_char *)harp + sizeof(struct libnet_arp_hdr), + ETHER_ADDR_LEN); + ctx->result = 0; } /* @@ -729,119 +671,101 @@ logpkt_recv_arp_reply(uint8_t *user, * mirroring packets to dst_ip_s on interface dst_if_s. * Only IPv4 mirror targets are supported. */ -int -logpkt_ether_lookup(libnet_t *libnet, - uint8_t *src_ether, uint8_t *dst_ether, - const char *dst_ip_s, const char *dst_if_s) -{ - char errbuf[PCAP_ERRBUF_SIZE]; - uint8_t broadcast_ether[ETHER_ADDR_LEN] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - uint8_t zero_ether[ETHER_ADDR_LEN] = { - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - struct libnet_ether_addr *src_ether_addr; - uint32_t src_ip; - struct bpf_program bp; - int count = 50; - logpkt_recv_arp_reply_ctx_t ctx; +int logpkt_ether_lookup(libnet_t *libnet, + uint8_t *src_ether, + uint8_t *dst_ether, + const char *dst_ip_s, + const char *dst_if_s) { + char errbuf[PCAP_ERRBUF_SIZE]; + uint8_t broadcast_ether[ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, + 0xff, 0xff, 0xff}; + uint8_t zero_ether[ETHER_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + struct libnet_ether_addr *src_ether_addr; + uint32_t src_ip; + struct bpf_program bp; + int count = 50; + logpkt_recv_arp_reply_ctx_t ctx; - if (sys_get_af(dst_ip_s) != AF_INET) { - printf("Mirroring target must be an IPv4 address.\n"); - return -1; - } + if(sys_get_af(dst_ip_s) != AF_INET) { + printf("Mirroring target must be an IPv4 address.\n"); + return -1; + } - ctx.result = -1; - ctx.ip = libnet_name2addr4(libnet, (char *)dst_ip_s, - LIBNET_DONT_RESOLVE); - if (ctx.ip == (uint32_t)-1) { - printf("Error converting dst IP address: %s\n", - libnet_geterror(libnet)); - goto out; - } - src_ip = libnet_get_ipaddr4(libnet); - if (src_ip == (uint32_t)-1) { - printf("Error getting src IP address: %s\n", - libnet_geterror(libnet)); - goto out; - } - src_ether_addr = libnet_get_hwaddr(libnet); - if (src_ether_addr == NULL) { - printf("Error getting src ethernet address: %s\n", - libnet_geterror(libnet)); - goto out; - } - memcpy(src_ether, src_ether_addr->ether_addr_octet, ETHER_ADDR_LEN); + ctx.result = -1; + ctx.ip = libnet_name2addr4(libnet, (char *)dst_ip_s, LIBNET_DONT_RESOLVE); + if(ctx.ip == (uint32_t)-1) { + printf("Error converting dst IP address: %s\n", libnet_geterror(libnet)); + goto out; + } + src_ip = libnet_get_ipaddr4(libnet); + if(src_ip == (uint32_t)-1) { + printf("Error getting src IP address: %s\n", libnet_geterror(libnet)); + goto out; + } + src_ether_addr = libnet_get_hwaddr(libnet); + if(src_ether_addr == NULL) { + printf("Error getting src ethernet address: %s\n", libnet_geterror(libnet)); + goto out; + } + memcpy(src_ether, src_ether_addr->ether_addr_octet, ETHER_ADDR_LEN); - if (libnet_autobuild_arp(ARPOP_REQUEST, - src_ether, - (uint8_t*)&src_ip, - zero_ether, - (uint8_t*)&ctx.ip, - libnet) == -1) { - printf("Error building arp header: %s\n", - libnet_geterror(libnet)); - goto out; - } + if(libnet_autobuild_arp(ARPOP_REQUEST, src_ether, (uint8_t *)&src_ip, + zero_ether, (uint8_t *)&ctx.ip, libnet) == -1) { + printf("Error building arp header: %s\n", libnet_geterror(libnet)); + goto out; + } - if (libnet_autobuild_ethernet(broadcast_ether, - ETHERTYPE_ARP, - libnet) == -1) { - printf("Error building ethernet header: %s", - libnet_geterror(libnet)); - goto out; - } + if(libnet_autobuild_ethernet(broadcast_ether, ETHERTYPE_ARP, libnet) == -1) { + printf("Error building ethernet header: %s", libnet_geterror(libnet)); + goto out; + } - pcap_t *pcap = pcap_open_live(dst_if_s, 100, 0, 10, errbuf); - if (pcap == NULL) { - printf("Error in pcap_open_live(): %s\n", errbuf); - goto out; - } + pcap_t *pcap = pcap_open_live(dst_if_s, 100, 0, 10, errbuf); + if(pcap == NULL) { + printf("Error in pcap_open_live(): %s\n", errbuf); + goto out; + } - if (pcap_compile(pcap, &bp, "arp", 0, -1) == -1) { - printf("Error in pcap_compile(): %s\n", - pcap_geterr(pcap)); - goto out2; - } - if (pcap_setfilter(pcap, &bp) == -1) { - printf("Error in pcap_setfilter(): %s\n", - pcap_geterr(pcap)); - goto out3; - } + if(pcap_compile(pcap, &bp, "arp", 0, -1) == -1) { + printf("Error in pcap_compile(): %s\n", pcap_geterr(pcap)); + goto out2; + } + if(pcap_setfilter(pcap, &bp) == -1) { + printf("Error in pcap_setfilter(): %s\n", pcap_geterr(pcap)); + goto out3; + } - do { - if (libnet_write(libnet) != -1) { - /* Limit # of packets to process, so we can loop to - * send arp requests on busy networks. */ - if (pcap_dispatch(pcap, 1000, - (pcap_handler)logpkt_recv_arp_reply, - (u_char*)&ctx) < 0) { - printf("Error in pcap_dispatch(): %s\n", - pcap_geterr(pcap)); - break; - } - } else { - printf("Error writing arp packet: %s", - libnet_geterror(libnet)); - break; - } - sleep(1); - } while (ctx.result == -1 && --count > 0); + do { + if(libnet_write(libnet) != -1) { + /* Limit # of packets to process, so we can loop to + * send arp requests on busy networks. */ + if(pcap_dispatch(pcap, 1000, (pcap_handler)logpkt_recv_arp_reply, + (u_char *)&ctx) < 0) { + printf("Error in pcap_dispatch(): %s\n", pcap_geterr(pcap)); + break; + } + } else { + printf("Error writing arp packet: %s", libnet_geterror(libnet)); + break; + } + sleep(1); + } while(ctx.result == -1 && --count > 0); - if (ctx.result == 0) { - memcpy(dst_ether, &ctx.ether, ETHER_ADDR_LEN); - //log_dbg_printf("Mirror target is up: " - // "%02x:%02x:%02x:%02x:%02x:%02x\n", - // dst_ether[0], dst_ether[1], dst_ether[2], - // dst_ether[3], dst_ether[4], dst_ether[5]); - } + if(ctx.result == 0) { + memcpy(dst_ether, &ctx.ether, ETHER_ADDR_LEN); + // log_dbg_printf("Mirror target is up: " + // "%02x:%02x:%02x:%02x:%02x:%02x\n", + // dst_ether[0], dst_ether[1], dst_ether[2], + // dst_ether[3], dst_ether[4], dst_ether[5]); + } out3: - pcap_freecode(&bp); + pcap_freecode(&bp); out2: - pcap_close(pcap); + pcap_close(pcap); out: - libnet_clear_packet(libnet); - return ctx.result; + libnet_clear_packet(libnet); + return ctx.result; } #endif /* !WITHOUT_MIRROR */ diff --git a/pcap/logpkt.h b/pcap/logpkt.h index 7545c2b..a6ee283 100644 --- a/pcap/logpkt.h +++ b/pcap/logpkt.h @@ -35,7 +35,6 @@ #include #include - #ifndef WITHOUT_MIRROR #include #else /* WITHOUT_MIRROR */ @@ -44,28 +43,39 @@ #endif /* WITHOUT_MIRROR */ typedef struct { - libnet_t *libnet; - uint8_t src_ether[ETHER_ADDR_LEN]; - uint8_t dst_ether[ETHER_ADDR_LEN]; - struct sockaddr_storage src_addr; - struct sockaddr_storage dst_addr; - uint32_t src_seq; - uint32_t dst_seq; - size_t mss; + libnet_t *libnet; + uint8_t src_ether[ETHER_ADDR_LEN]; + uint8_t dst_ether[ETHER_ADDR_LEN]; + struct sockaddr_storage src_addr; + struct sockaddr_storage dst_addr; + uint32_t src_seq; + uint32_t dst_seq; + size_t mss; } logpkt_ctx_t; -#define LOGPKT_REQUEST 0 +#define LOGPKT_REQUEST 0 #define LOGPKT_RESPONSE 1 int logpkt_pcap_open_fd(int fd) WUNRES; -void logpkt_ctx_init(logpkt_ctx_t *, libnet_t *, size_t, - const uint8_t *, const uint8_t *, - const struct sockaddr *, socklen_t, - const struct sockaddr *, socklen_t); -int logpkt_write_payload(logpkt_ctx_t *, int, int, - const unsigned char *, size_t) WUNRES; +void logpkt_ctx_init(logpkt_ctx_t *, + libnet_t *, + size_t, + const uint8_t *, + const uint8_t *, + const struct sockaddr *, + socklen_t, + const struct sockaddr *, + socklen_t); +int logpkt_write_payload(logpkt_ctx_t *, + int, + int, + const unsigned char *, + size_t) WUNRES; int logpkt_write_close(logpkt_ctx_t *, int, int); -int logpkt_ether_lookup(libnet_t *, uint8_t *, uint8_t *, - const char *, const char *) WUNRES; +int logpkt_ether_lookup(libnet_t *, + uint8_t *, + uint8_t *, + const char *, + const char *) WUNRES; #endif /* !LOGPKT_H */ diff --git a/pcap/pcap_logger.c b/pcap/pcap_logger.c index b9db7bb..fdbe634 100644 --- a/pcap/pcap_logger.c +++ b/pcap/pcap_logger.c @@ -17,132 +17,137 @@ #define DFLT_FILEMODE 0666 -static int init_pcap_logger PROTO_LIST((void * data)); +static int init_pcap_logger PROTO_LIST((void *data)); static int deinit_pcap_logger PROTO_LIST(()); -static int create_pcap_logger PROTO_LIST((proto_obj **objp, struct sockaddr_storage *i_addr, - u_short i_port,struct sockaddr_storage *r_addr, u_short r_port, struct timeval *base_time)); -static int destroy_pcap_logger PROTO_LIST((proto_obj **objp)); -static int data_pcap_logger PROTO_LIST((proto_obj *_obj, unsigned char *data,unsigned int len, int dir)); -static int close_pcap_logger PROTO_LIST((proto_obj *_obj, unsigned char *data,unsigned int len, int dir)); +static int create_pcap_logger PROTO_LIST((proto_obj * *objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *base_time)); +static int destroy_pcap_logger PROTO_LIST((proto_obj * *objp)); +static int data_pcap_logger PROTO_LIST( + (proto_obj * _obj, unsigned char *data, unsigned int len, int dir)); +static int close_pcap_logger PROTO_LIST( + (proto_obj * _obj, unsigned char *data, unsigned int len, int dir)); int pcap_fd = -1; -static uint8_t content_pcap_src_ether[ETHER_ADDR_LEN] = {0x02, 0x00, 0x00, 0x11, 0x11, 0x11}; -static uint8_t content_pcap_dst_ether[ETHER_ADDR_LEN] = {0x02, 0x00, 0x00, 0x22, 0x22, 0x22}; - -static int -init_pcap_logger (void *data) - { - char *pcap_outfile = (char *) data; - pcap_fd = open(pcap_outfile, O_RDWR|O_CREAT, DFLT_FILEMODE); - if (pcap_fd == -1) { - //printf("Failed to open pcap '%s' for writing\n", pcap_outfile); - return -1; - } - if (logpkt_pcap_open_fd(pcap_fd) == -1) { - //printf("Failed to prepare '%s' for PCAP writing\n", pcap_outfile); - close(pcap_fd); - pcap_fd = -1; - return -1; - } - return 0; - } +static uint8_t content_pcap_src_ether[ETHER_ADDR_LEN] = {0x02, 0x00, 0x00, + 0x11, 0x11, 0x11}; +static uint8_t content_pcap_dst_ether[ETHER_ADDR_LEN] = {0x02, 0x00, 0x00, + 0x22, 0x22, 0x22}; -static int -deinit_pcap_logger (void) - { - fdatasync(pcap_fd); +static int init_pcap_logger(void *data) { + char *pcap_outfile = (char *)data; + pcap_fd = open(pcap_outfile, O_RDWR | O_CREAT, DFLT_FILEMODE); + if(pcap_fd == -1) { + // printf("Failed to open pcap '%s' for writing\n", pcap_outfile); + return -1; + } + if(logpkt_pcap_open_fd(pcap_fd) == -1) { + // printf("Failed to prepare '%s' for PCAP writing\n", pcap_outfile); close(pcap_fd); - return 0; + pcap_fd = -1; + return -1; } + return 0; +} -static int create_pcap_logger(proto_obj **objp, struct sockaddr_storage *i_addr, u_short i_port, struct sockaddr_storage *r_addr, u_short r_port, struct timeval *base_time) - { - int r,_status; - logpkt_ctx_t *pcap_obj=0; - struct sockaddr_in src_addr, dst_addr; +static int deinit_pcap_logger(void) { + fdatasync(pcap_fd); + close(pcap_fd); + return 0; +} - if(!(pcap_obj=(logpkt_ctx_t *)calloc(1,sizeof(logpkt_ctx_t)))) - ABORT(R_NO_MEMORY); +static int create_pcap_logger(proto_obj **objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *base_time) { + int r, _status; + logpkt_ctx_t *pcap_obj = 0; + struct sockaddr_in src_addr, dst_addr; - //src_addr.sin_family = AF_INET; - //src_addr.sin_addr = *i_addr; - memcpy(&src_addr, i_addr, sizeof(struct sockaddr_in)); - src_addr.sin_port = htons(i_port); + if(!(pcap_obj = (logpkt_ctx_t *)calloc(1, sizeof(logpkt_ctx_t)))) + ABORT(R_NO_MEMORY); - //dst_addr.sin_family = AF_INET; - //dst_addr.sin_addr = *r_addr; - memcpy(&dst_addr, r_addr, sizeof(struct sockaddr_in)); - dst_addr.sin_port = htons(r_port); + // src_addr.sin_family = AF_INET; + // src_addr.sin_addr = *i_addr; + memcpy(&src_addr, i_addr, sizeof(struct sockaddr_in)); + src_addr.sin_port = htons(i_port); - logpkt_ctx_init(pcap_obj,NULL,0,content_pcap_src_ether, content_pcap_dst_ether, - (const struct sockaddr*)&src_addr, sizeof(src_addr), - (const struct sockaddr*)&dst_addr, sizeof(dst_addr)); - *objp=(proto_obj *)pcap_obj; - _status=0; - abort: - if(_status){ - destroy_pcap_logger((proto_obj **)&pcap_obj); - } - return(_status); + // dst_addr.sin_family = AF_INET; + // dst_addr.sin_addr = *r_addr; + memcpy(&dst_addr, r_addr, sizeof(struct sockaddr_in)); + dst_addr.sin_port = htons(r_port); + + logpkt_ctx_init(pcap_obj, NULL, 0, content_pcap_src_ether, + content_pcap_dst_ether, (const struct sockaddr *)&src_addr, + sizeof(src_addr), (const struct sockaddr *)&dst_addr, + sizeof(dst_addr)); + *objp = (proto_obj *)pcap_obj; + _status = 0; +abort: + if(_status) { + destroy_pcap_logger((proto_obj **)&pcap_obj); } + return (_status); +} -static int -destroy_pcap_logger (proto_obj **objp) - { - logpkt_ctx_t *pcap_obj; +static int destroy_pcap_logger(proto_obj **objp) { + logpkt_ctx_t *pcap_obj; - if(!objp || !*objp) - return(0); + if(!objp || !*objp) + return (0); - pcap_obj=(logpkt_ctx_t *)*objp; + pcap_obj = (logpkt_ctx_t *)*objp; - free(pcap_obj); - *objp=0; + free(pcap_obj); + *objp = 0; - return(0); - } + return (0); +} -static int -data_pcap_logger (proto_obj *_obj, unsigned char *data, unsigned int len, int dir) - { - logpkt_ctx_t *pcap_obj = (logpkt_ctx_t *)_obj; - int direction; - int status; - - if (dir == DIR_I2R ) direction = LOGPKT_REQUEST; - else direction = LOGPKT_RESPONSE; +static int data_pcap_logger(proto_obj *_obj, + unsigned char *data, + unsigned int len, + int dir) { + logpkt_ctx_t *pcap_obj = (logpkt_ctx_t *)_obj; + int direction; + int status; - status = logpkt_write_payload(pcap_obj,pcap_fd,direction,data,len); + if(dir == DIR_I2R) + direction = LOGPKT_REQUEST; + else + direction = LOGPKT_RESPONSE; - return status; - } + status = logpkt_write_payload(pcap_obj, pcap_fd, direction, data, len); -int -close_pcap_logger (proto_obj *_obj, unsigned char *data, unsigned int len, int dir) - { - logpkt_ctx_t *pcap_obj = (logpkt_ctx_t *)_obj; - int direction; - int status; - - if (dir == DIR_I2R ) direction = LOGPKT_REQUEST; - else direction = LOGPKT_RESPONSE; + return status; +} - status = logpkt_write_close(pcap_obj, pcap_fd, direction); - - return status; - } +int close_pcap_logger(proto_obj *_obj, + unsigned char *data, + unsigned int len, + int dir) { + logpkt_ctx_t *pcap_obj = (logpkt_ctx_t *)_obj; + int direction; + int status; -static struct logger_mod_vtbl_ pcap_vtbl ={ - init_pcap_logger, - deinit_pcap_logger, - create_pcap_logger, - destroy_pcap_logger, - data_pcap_logger, - close_pcap_logger, + if(dir == DIR_I2R) + direction = LOGPKT_REQUEST; + else + direction = LOGPKT_RESPONSE; + + status = logpkt_write_close(pcap_obj, pcap_fd, direction); + + return status; +} + +static struct logger_mod_vtbl_ pcap_vtbl = { + init_pcap_logger, deinit_pcap_logger, create_pcap_logger, + destroy_pcap_logger, data_pcap_logger, close_pcap_logger, }; -struct logger_mod_ pcap_mod = { - "PCAP", - &pcap_vtbl -}; - +struct logger_mod_ pcap_mod = {"PCAP", &pcap_vtbl}; diff --git a/pcap/pcap_logger.h b/pcap/pcap_logger.h index 8490ea3..b7ab7b5 100644 --- a/pcap/pcap_logger.h +++ b/pcap/pcap_logger.h @@ -4,4 +4,3 @@ extern logger_mod pcap_mod; #endif - diff --git a/pcap/sys.c b/pcap/sys.c index 3d8c33d..11d4c3b 100644 --- a/pcap/sys.c +++ b/pcap/sys.c @@ -53,47 +53,41 @@ /* * Determine address family of addr */ -int -sys_get_af(const char *addr) -{ - if (strstr(addr, ":")) - return AF_INET6; - else if (!strpbrk(addr, "abcdefghijklmnopqrstu" - "vwxyzABCDEFGHIJKLMNOP" - "QRSTUVWXYZ-")) - return AF_INET; - else - return AF_UNSPEC; +int sys_get_af(const char *addr) { + if(strstr(addr, ":")) + return AF_INET6; + else if(!strpbrk(addr, + "abcdefghijklmnopqrstu" + "vwxyzABCDEFGHIJKLMNOP" + "QRSTUVWXYZ-")) + return AF_INET; + else + return AF_UNSPEC; } - static int sys_rand_seeded = 0; -static void -sys_rand_seed(void) { - struct timeval seed; +static void sys_rand_seed(void) { + struct timeval seed; - if (gettimeofday(&seed, NULL) == -1) { - srandom((unsigned)time(NULL)); - } else { - srandom((unsigned)(seed.tv_sec ^ seed.tv_usec)); - } - sys_rand_seeded = 1; + if(gettimeofday(&seed, NULL) == -1) { + srandom((unsigned)time(NULL)); + } else { + srandom((unsigned)(seed.tv_sec ^ seed.tv_usec)); + } + sys_rand_seeded = 1; } -uint16_t -sys_rand16(void) { - if (unlikely(!sys_rand_seeded)) - sys_rand_seed(); - return random(); +uint16_t sys_rand16(void) { + if(unlikely(!sys_rand_seeded)) + sys_rand_seed(); + return random(); } -uint32_t -sys_rand32(void) { - if (unlikely(!sys_rand_seeded)) - sys_rand_seed(); - return random(); +uint32_t sys_rand32(void) { + if(unlikely(!sys_rand_seeded)) + sys_rand_seed(); + return random(); } /* vim: set noet ft=c: */ - diff --git a/ssl/ciphersuites.c b/ssl/ciphersuites.c index faab334..7ea0e08 100644 --- a/ssl/ciphersuites.c +++ b/ssl/ciphersuites.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ciphersuites.c,v 1.3 2002/08/17 01:33:17 ekr Exp $ @@ -43,209 +44,203 @@ ekr@rtfm.com Tue Mar 30 17:19:56 1999 */ - - #include #include "sslciphers.h" -static SSL_CipherSuite CipherSuites[]={ - {1,KEX_RSA,SIG_RSA,ENC_NULL,0,0,0,DIG_MD5,16,0}, - {2,KEX_RSA,SIG_RSA,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {3,KEX_RSA,SIG_RSA,ENC_RC4,1,128,40,DIG_MD5,16,1}, - {4,KEX_RSA,SIG_RSA,ENC_RC4,1,128,128,DIG_MD5,16,0}, - {5,KEX_RSA,SIG_RSA,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {6,KEX_RSA,SIG_RSA,ENC_RC2,8,128,40,DIG_SHA,20,1}, - {7,KEX_RSA,SIG_RSA,ENC_IDEA,8,128,128,DIG_SHA,20,0}, - {8,KEX_RSA,SIG_RSA,ENC_DES,8,64,40,DIG_SHA,20,1}, - {9,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,0}, - {10,KEX_RSA,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {11,KEX_DH,SIG_DSS,ENC_DES,8,64,40,DIG_SHA,20,1}, - {12,KEX_DH,SIG_DSS,ENC_DES,8,64,64,DIG_SHA,20,0}, - {13,KEX_DH,SIG_DSS,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {14,KEX_DH,SIG_RSA,ENC_DES,8,64,40,DIG_SHA,20,1}, - {15,KEX_DH,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,0}, - {16,KEX_DH,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {17,KEX_DH,SIG_DSS,ENC_DES,8,64,40,DIG_SHA,20,1}, - {18,KEX_DH,SIG_DSS,ENC_DES,8,64,64,DIG_SHA,20,0}, - {19,KEX_DH,SIG_DSS,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {20,KEX_DH,SIG_RSA,ENC_DES,8,64,40,DIG_SHA,20,1}, - {21,KEX_DH,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,0}, - {22,KEX_DH,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {23,KEX_DH,SIG_NONE,ENC_RC4,1,128,40,DIG_MD5,16,1}, - {24,KEX_DH,SIG_NONE,ENC_RC4,1,128,128,DIG_MD5,16,0}, - {25,KEX_DH,SIG_NONE,ENC_DES,8,64,40,DIG_MD5,16,1}, - {26,KEX_DH,SIG_NONE,ENC_DES,8,64,64,DIG_MD5,16,0}, - {27,KEX_DH,SIG_NONE,ENC_3DES,8,192,192,DIG_MD5,16,0}, - // Missing: 44-46 - {47,KEX_RSA,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {48,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {50,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {51,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {52,KEX_DH,SIG_NONE,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {53,KEX_RSA,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {54,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {55,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {56,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {57,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {58,KEX_DH,SIG_NONE,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {59,KEX_RSA,SIG_RSA,ENC_NULL,0,0,0,DIG_SHA256,32,0}, - {60,KEX_RSA,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {61,KEX_RSA,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {62,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {63,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {64,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {65,KEX_RSA,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {66,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {67,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {68,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {69,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {70,KEX_DH,SIG_NONE,ENC_CAMELLIA128,16,128,128,DIG_SHA,20,0}, - {96,KEX_RSA,SIG_RSA,ENC_RC4,1,128,56,DIG_MD5,16,1}, - {97,KEX_RSA,SIG_RSA,ENC_RC2,1,128,56,DIG_MD5,16,1}, - {98,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,1}, - {99,KEX_DH,SIG_DSS,ENC_DES,8,64,64,DIG_SHA,20,1}, - {100,KEX_RSA,SIG_RSA,ENC_RC4,1,128,56,DIG_SHA,20,1}, - {101,KEX_DH,SIG_DSS,ENC_RC4,1,128,56,DIG_SHA,20,1}, - {102,KEX_DH,SIG_DSS,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {103,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {104,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {105,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {106,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {107,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {108,KEX_DH,SIG_NONE,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {109,KEX_DH,SIG_NONE,ENC_AES256,16,256,256,DIG_SHA256,32,0}, - {132,KEX_RSA,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - {133,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - {134,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - {135,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - {136,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - {137,KEX_DH,SIG_NONE,ENC_CAMELLIA256,16,256,256,DIG_SHA,20,0}, - // Missing: 138-149 - {150,KEX_RSA,SIG_RSA,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {151,KEX_DH,SIG_DSS,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {152,KEX_DH,SIG_RSA,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {153,KEX_DH,SIG_DSS,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {154,KEX_DH,SIG_RSA,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {155,KEX_DH,SIG_NONE,ENC_SEED,16,128,128,DIG_SHA,20,0}, - {156,KEX_RSA,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {157,KEX_RSA,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {158,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {159,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {160,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {161,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {162,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {163,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {164,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {165,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {166,KEX_DH,SIG_NONE,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {167,KEX_DH,SIG_NONE,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - // Missing: 168-185 - {186,KEX_RSA,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {187,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {188,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {189,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {190,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {191,KEX_DH,SIG_NONE,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {192,KEX_RSA,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {193,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {194,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {195,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {196,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {197,KEX_DH,SIG_NONE,ENC_CAMELLIA256,16,256,256,DIG_SHA256,32,0}, - {4865,KEX_DH,SIG_NONE,ENC_AES128_GCM,16,128,128,DIG_SHA256,32,0}, - {4866,KEX_DH,SIG_NONE,ENC_AES256_GCM,16,256,256,DIG_SHA384,48,0}, - {4867,KEX_DH,SIG_NONE,ENC_CHACHA20_POLY1305,64,256,256,DIG_SHA256,32,0}, - {4868,KEX_DH,SIG_NONE,ENC_AES128_CCM,16,128,128,DIG_SHA256,32,0}, - {4869,KEX_DH,SIG_NONE,ENC_AES128_CCM_8,16,128,128,DIG_SHA256,32,0}, - {49153,KEX_DH,SIG_DSS,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {49154,KEX_DH,SIG_DSS,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {49155,KEX_DH,SIG_DSS,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {49156,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49157,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {49158,KEX_DH,SIG_DSS,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {49159,KEX_DH,SIG_DSS,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {49160,KEX_DH,SIG_DSS,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {49161,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49162,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {49163,KEX_DH,SIG_RSA,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {49164,KEX_DH,SIG_RSA,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {49165,KEX_DH,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {49166,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49167,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {49168,KEX_DH,SIG_RSA,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {49169,KEX_DH,SIG_RSA,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {49170,KEX_DH,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {49171,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49172,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {49173,KEX_DH,SIG_NONE,ENC_NULL,0,0,0,DIG_SHA,20,0}, - {49174,KEX_DH,SIG_NONE,ENC_RC4,1,128,128,DIG_SHA,20,0}, - {49175,KEX_DH,SIG_NONE,ENC_3DES,8,192,192,DIG_SHA,20,0}, - {49176,KEX_DH,SIG_NONE,ENC_AES128,16,128,128,DIG_SHA,20,0}, - {49177,KEX_DH,SIG_NONE,ENC_AES256,16,256,256,DIG_SHA,20,0}, - {49187,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {49188,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA384,48,0}, - {49189,KEX_DH,SIG_DSS,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {49190,KEX_DH,SIG_DSS,ENC_AES256,16,256,256,DIG_SHA384,48,0}, - {49191,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {49192,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA384,48,0}, - {49193,KEX_DH,SIG_RSA,ENC_AES128,16,128,128,DIG_SHA256,32,0}, - {49194,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA384,48,0}, - {49195,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {49196,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {49197,KEX_DH,SIG_DSS,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {49198,KEX_DH,SIG_DSS,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {49199,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {49200,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - {49201,KEX_DH,SIG_RSA,ENC_AES128_GCM,4,128,128,DIG_SHA256,32,0}, - {49202,KEX_DH,SIG_RSA,ENC_AES256_GCM,4,256,256,DIG_SHA384,48,0}, - // Missing: 49203-49211 - {49266,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {49267,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,48,0}, - {49268,KEX_DH,SIG_DSS,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {49269,KEX_DH,SIG_DSS,ENC_CAMELLIA256,16,256,256,DIG_SHA256,48,0}, - {49270,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {49271,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,48,0}, - {49272,KEX_DH,SIG_RSA,ENC_CAMELLIA128,16,128,128,DIG_SHA256,32,0}, - {49273,KEX_DH,SIG_RSA,ENC_CAMELLIA256,16,256,256,DIG_SHA256,48,0}, - {49274,KEX_RSA,SIG_RSA,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49275,KEX_RSA,SIG_RSA,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49276,KEX_DH,SIG_RSA,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49277,KEX_DH,SIG_RSA,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49278,KEX_DH,SIG_RSA,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49279,KEX_DH,SIG_RSA,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49280,KEX_DH,SIG_DSS,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49281,KEX_DH,SIG_DSS,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49282,KEX_DH,SIG_DSS,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49283,KEX_DH,SIG_DSS,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49284,KEX_DH,SIG_NONE,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49285,KEX_DH,SIG_NONE,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49286,KEX_DH,SIG_DSS,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49287,KEX_DH,SIG_DSS,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49288,KEX_DH,SIG_DSS,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49289,KEX_DH,SIG_DSS,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49290,KEX_DH,SIG_RSA,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49291,KEX_DH,SIG_RSA,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - {49292,KEX_DH,SIG_RSA,ENC_CAMELLIA128,4,128,128,DIG_SHA256,32,0}, - {49293,KEX_DH,SIG_RSA,ENC_CAMELLIA256,4,256,256,DIG_SHA384,48,0}, - // Missing: 49294-49307 - {-1} -}; +static SSL_CipherSuite CipherSuites[] = { + {1, KEX_RSA, SIG_RSA, ENC_NULL, 0, 0, 0, DIG_MD5, 16, 0}, + {2, KEX_RSA, SIG_RSA, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {3, KEX_RSA, SIG_RSA, ENC_RC4, 1, 128, 40, DIG_MD5, 16, 1}, + {4, KEX_RSA, SIG_RSA, ENC_RC4, 1, 128, 128, DIG_MD5, 16, 0}, + {5, KEX_RSA, SIG_RSA, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {6, KEX_RSA, SIG_RSA, ENC_RC2, 8, 128, 40, DIG_SHA, 20, 1}, + {7, KEX_RSA, SIG_RSA, ENC_IDEA, 8, 128, 128, DIG_SHA, 20, 0}, + {8, KEX_RSA, SIG_RSA, ENC_DES, 8, 64, 40, DIG_SHA, 20, 1}, + {9, KEX_RSA, SIG_RSA, ENC_DES, 8, 64, 64, DIG_SHA, 20, 0}, + {10, KEX_RSA, SIG_RSA, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {11, KEX_DH, SIG_DSS, ENC_DES, 8, 64, 40, DIG_SHA, 20, 1}, + {12, KEX_DH, SIG_DSS, ENC_DES, 8, 64, 64, DIG_SHA, 20, 0}, + {13, KEX_DH, SIG_DSS, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {14, KEX_DH, SIG_RSA, ENC_DES, 8, 64, 40, DIG_SHA, 20, 1}, + {15, KEX_DH, SIG_RSA, ENC_DES, 8, 64, 64, DIG_SHA, 20, 0}, + {16, KEX_DH, SIG_RSA, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {17, KEX_DH, SIG_DSS, ENC_DES, 8, 64, 40, DIG_SHA, 20, 1}, + {18, KEX_DH, SIG_DSS, ENC_DES, 8, 64, 64, DIG_SHA, 20, 0}, + {19, KEX_DH, SIG_DSS, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {20, KEX_DH, SIG_RSA, ENC_DES, 8, 64, 40, DIG_SHA, 20, 1}, + {21, KEX_DH, SIG_RSA, ENC_DES, 8, 64, 64, DIG_SHA, 20, 0}, + {22, KEX_DH, SIG_RSA, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {23, KEX_DH, SIG_NONE, ENC_RC4, 1, 128, 40, DIG_MD5, 16, 1}, + {24, KEX_DH, SIG_NONE, ENC_RC4, 1, 128, 128, DIG_MD5, 16, 0}, + {25, KEX_DH, SIG_NONE, ENC_DES, 8, 64, 40, DIG_MD5, 16, 1}, + {26, KEX_DH, SIG_NONE, ENC_DES, 8, 64, 64, DIG_MD5, 16, 0}, + {27, KEX_DH, SIG_NONE, ENC_3DES, 8, 192, 192, DIG_MD5, 16, 0}, + // Missing: 44-46 + {47, KEX_RSA, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {48, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {50, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {51, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {52, KEX_DH, SIG_NONE, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {53, KEX_RSA, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {54, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {55, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {56, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {57, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {58, KEX_DH, SIG_NONE, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {59, KEX_RSA, SIG_RSA, ENC_NULL, 0, 0, 0, DIG_SHA256, 32, 0}, + {60, KEX_RSA, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {61, KEX_RSA, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {62, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {63, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {64, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {65, KEX_RSA, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {66, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {67, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {68, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {69, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {70, KEX_DH, SIG_NONE, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA, 20, 0}, + {96, KEX_RSA, SIG_RSA, ENC_RC4, 1, 128, 56, DIG_MD5, 16, 1}, + {97, KEX_RSA, SIG_RSA, ENC_RC2, 1, 128, 56, DIG_MD5, 16, 1}, + {98, KEX_RSA, SIG_RSA, ENC_DES, 8, 64, 64, DIG_SHA, 20, 1}, + {99, KEX_DH, SIG_DSS, ENC_DES, 8, 64, 64, DIG_SHA, 20, 1}, + {100, KEX_RSA, SIG_RSA, ENC_RC4, 1, 128, 56, DIG_SHA, 20, 1}, + {101, KEX_DH, SIG_DSS, ENC_RC4, 1, 128, 56, DIG_SHA, 20, 1}, + {102, KEX_DH, SIG_DSS, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {103, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {104, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {105, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {106, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {107, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {108, KEX_DH, SIG_NONE, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {109, KEX_DH, SIG_NONE, ENC_AES256, 16, 256, 256, DIG_SHA256, 32, 0}, + {132, KEX_RSA, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + {133, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + {134, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + {135, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + {136, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + {137, KEX_DH, SIG_NONE, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA, 20, 0}, + // Missing: 138-149 + {150, KEX_RSA, SIG_RSA, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {151, KEX_DH, SIG_DSS, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {152, KEX_DH, SIG_RSA, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {153, KEX_DH, SIG_DSS, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {154, KEX_DH, SIG_RSA, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {155, KEX_DH, SIG_NONE, ENC_SEED, 16, 128, 128, DIG_SHA, 20, 0}, + {156, KEX_RSA, SIG_RSA, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {157, KEX_RSA, SIG_RSA, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {158, KEX_DH, SIG_RSA, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {159, KEX_DH, SIG_RSA, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {160, KEX_DH, SIG_RSA, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {161, KEX_DH, SIG_RSA, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {162, KEX_DH, SIG_DSS, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {163, KEX_DH, SIG_DSS, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {164, KEX_DH, SIG_DSS, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {165, KEX_DH, SIG_DSS, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {166, KEX_DH, SIG_NONE, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {167, KEX_DH, SIG_NONE, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + // Missing: 168-185 + {186, KEX_RSA, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {187, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {188, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {189, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {190, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {191, KEX_DH, SIG_NONE, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {192, KEX_RSA, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {193, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {194, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {195, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {196, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {197, KEX_DH, SIG_NONE, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 32, 0}, + {4865, KEX_DH, SIG_NONE, ENC_AES128_GCM, 16, 128, 128, DIG_SHA256, 32, 0}, + {4866, KEX_DH, SIG_NONE, ENC_AES256_GCM, 16, 256, 256, DIG_SHA384, 48, 0}, + {4867, KEX_DH, SIG_NONE, ENC_CHACHA20_POLY1305, 64, 256, 256, DIG_SHA256, + 32, 0}, + {4868, KEX_DH, SIG_NONE, ENC_AES128_CCM, 16, 128, 128, DIG_SHA256, 32, 0}, + {4869, KEX_DH, SIG_NONE, ENC_AES128_CCM_8, 16, 128, 128, DIG_SHA256, 32, 0}, + {49153, KEX_DH, SIG_DSS, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {49154, KEX_DH, SIG_DSS, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {49155, KEX_DH, SIG_DSS, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {49156, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49157, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {49158, KEX_DH, SIG_DSS, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {49159, KEX_DH, SIG_DSS, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {49160, KEX_DH, SIG_DSS, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {49161, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49162, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {49163, KEX_DH, SIG_RSA, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {49164, KEX_DH, SIG_RSA, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {49165, KEX_DH, SIG_RSA, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {49166, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49167, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {49168, KEX_DH, SIG_RSA, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {49169, KEX_DH, SIG_RSA, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {49170, KEX_DH, SIG_RSA, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {49171, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49172, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {49173, KEX_DH, SIG_NONE, ENC_NULL, 0, 0, 0, DIG_SHA, 20, 0}, + {49174, KEX_DH, SIG_NONE, ENC_RC4, 1, 128, 128, DIG_SHA, 20, 0}, + {49175, KEX_DH, SIG_NONE, ENC_3DES, 8, 192, 192, DIG_SHA, 20, 0}, + {49176, KEX_DH, SIG_NONE, ENC_AES128, 16, 128, 128, DIG_SHA, 20, 0}, + {49177, KEX_DH, SIG_NONE, ENC_AES256, 16, 256, 256, DIG_SHA, 20, 0}, + {49187, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49188, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA384, 48, 0}, + {49189, KEX_DH, SIG_DSS, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49190, KEX_DH, SIG_DSS, ENC_AES256, 16, 256, 256, DIG_SHA384, 48, 0}, + {49191, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49192, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA384, 48, 0}, + {49193, KEX_DH, SIG_RSA, ENC_AES128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49194, KEX_DH, SIG_RSA, ENC_AES256, 16, 256, 256, DIG_SHA384, 48, 0}, + {49195, KEX_DH, SIG_DSS, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {49196, KEX_DH, SIG_DSS, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {49197, KEX_DH, SIG_DSS, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {49198, KEX_DH, SIG_DSS, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {49199, KEX_DH, SIG_RSA, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {49200, KEX_DH, SIG_RSA, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + {49201, KEX_DH, SIG_RSA, ENC_AES128_GCM, 4, 128, 128, DIG_SHA256, 32, 0}, + {49202, KEX_DH, SIG_RSA, ENC_AES256_GCM, 4, 256, 256, DIG_SHA384, 48, 0}, + // Missing: 49203-49211 + {49266, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49267, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 48, 0}, + {49268, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49269, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 48, 0}, + {49270, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49271, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 48, 0}, + {49272, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 16, 128, 128, DIG_SHA256, 32, 0}, + {49273, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 16, 256, 256, DIG_SHA256, 48, 0}, + {49274, KEX_RSA, SIG_RSA, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49275, KEX_RSA, SIG_RSA, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49276, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49277, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49278, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49279, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49280, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49281, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49282, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49283, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49284, KEX_DH, SIG_NONE, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49285, KEX_DH, SIG_NONE, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49286, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49287, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49288, KEX_DH, SIG_DSS, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49289, KEX_DH, SIG_DSS, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49290, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49291, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + {49292, KEX_DH, SIG_RSA, ENC_CAMELLIA128, 4, 128, 128, DIG_SHA256, 32, 0}, + {49293, KEX_DH, SIG_RSA, ENC_CAMELLIA256, 4, 256, 256, DIG_SHA384, 48, 0}, + // Missing: 49294-49307 + {-1}}; -int -ssl_find_cipher (int num, SSL_CipherSuite **cs) - { - SSL_CipherSuite *c; +int ssl_find_cipher(int num, SSL_CipherSuite **cs) { + SSL_CipherSuite *c; - for(c=CipherSuites;c->number!=-1;c++){ - if(c->number==num){ - *cs=c; - return(0); - } + for(c = CipherSuites; c->number != -1; c++) { + if(c->number == num) { + *cs = c; + return (0); } - - ERETURN(R_NOT_FOUND); } - - + + ERETURN(R_NOT_FOUND); +} diff --git a/ssl/ssl.enums.c b/ssl/ssl.enums.c index 8c8ab6a..86b994f 100644 --- a/ssl/ssl.enums.c +++ b/ssl/ssl.enums.c @@ -10,585 +10,517 @@ #include "ssl.enums.h" static int decode_extension(ssl_obj *ssl, int dir, segment *seg, Data *data); static int decode_server_name(ssl_obj *ssl, int dir, segment *seg, Data *data); -static int -decode_ContentType_ChangeCipherSpec (ssl_obj *ssl, int dir, segment *seg, Data *data) - { +static int decode_ContentType_ChangeCipherSpec(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; - struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "msg_type", + json_object_new_string("ChangeCipherSpec")); - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "msg_type", json_object_new_string("ChangeCipherSpec")); - - ssl_process_change_cipher_spec(ssl,ssl->decoder,dir); - - if(dir==DIR_I2R){ - ssl->i_state=SSL_ST_SENT_CHANGE_CIPHER_SPEC; - } - else{ - ssl->r_state=SSL_ST_SENT_CHANGE_CIPHER_SPEC; - } - - LF; - return(0); + ssl_process_change_cipher_spec(ssl, ssl->decoder, dir); + if(dir == DIR_I2R) { + ssl->i_state = SSL_ST_SENT_CHANGE_CIPHER_SPEC; + } else { + ssl->r_state = SSL_ST_SENT_CHANGE_CIPHER_SPEC; } -static int -decode_ContentType_Alert (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - int r; - struct json_object *jobj; - - if(ssl->record_encryption==REC_CIPHERTEXT){ - LF; - return(0); - } - - if(data->len!=2){ - fprintf(stderr,"Wrong length for alert message: %d\n", - data->len); - ERETURN(R_EOD); - } - - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "msg_type", json_object_new_string("Alert")); - - P_(P_HL){ - LF; - SSL_DECODE_ENUM(ssl,"level",1,AlertLevel_decoder,P_HL,data,0); - LF; - SSL_DECODE_ENUM(ssl,"value",1,AlertDescription_decoder,P_HL,data,0); - LF; - } - else { - SSL_DECODE_ENUM(ssl,0,1,AlertLevel_decoder,SSL_PRINT_ALL,data,0); - SSL_DECODE_ENUM(ssl,0,1,AlertDescription_decoder,SSL_PRINT_ALL,data,0); - LF; - } - return(0); - - } -static int -decode_ContentType_Handshake (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - - extern decoder HandshakeType_decoder[]; - int r; - UINT4 t,l; - int rs=0; - Data d; - struct json_object *jobj; - - if(ssl->record_encryption==REC_CIPHERTEXT){ - LF; - return(0); - } - - while(data->len>0){ - SSL_DECODE_UINT8(ssl,0,0,data,&t); - SSL_DECODE_UINT24(ssl,0,0,data,&l); - - if(data->lenlen); - ERETURN(R_EOD); - } - - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "msg_type", json_object_new_string("Handshake")); - - d.data=data->data; - d.len=l; - data->len-=l; - data->data+=l; - P_(P_HL){ - if(!rs){ - LF; - rs=1; - } - } - ssl_decode_switch(ssl,HandshakeType_decoder,t,dir,seg,&d); - } - return(0); - - } -static int -decode_ContentType_application_data (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - - int r; - Data d; - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "msg_type", json_object_new_string("application data")); - - SSL_DECODE_OPAQUE_ARRAY(ssl,"data",data->len,0,data,&d); - - if(NET_print_flags & NET_PRINT_JSON) { - json_object_object_add(jobj, "msg_data", json_object_new_string_len(d.data, d.len)); - } else P_(P_AD) { - print_data(ssl,&d); - } else { - LF; - } - return(0); - - } -decoder ContentType_decoder[]={ - { - 20, - "ChangeCipherSpec", - decode_ContentType_ChangeCipherSpec - }, - { - 21, - "Alert", - decode_ContentType_Alert - }, - { - 22, - "Handshake", - decode_ContentType_Handshake - }, - { - 23, - "application_data", - decode_ContentType_application_data - }, -{-1} -}; - -static int -decode_HandshakeType_HelloRequest (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("HelloRequest")); - LF; - return(0); - - } -static int -decode_HandshakeType_ClientHello (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("ClientHello")); - - UINT4 vj,vn,cs,cslen,complen,comp,odd,exlen,ex; - Data session_id,random; - int r; - char *ja3_fp = NULL; - char *ja3_str = NULL; - char *ja3_ver_str = NULL; - char *ja3_cs_str = NULL; - char *ja3_ex_str = NULL; - char *ja3_ec_str = NULL; - char *ja3_ecp_str = NULL; - - ssl->cur_ja3_ec_str = NULL; - ssl->cur_ja3_ecp_str = NULL; - - extern decoder cipher_suite_decoder[]; - extern decoder compression_method_decoder[]; - extern decoder extension_decoder[]; - - LF; - ssl_update_handshake_messages(ssl,data); - SSL_DECODE_UINT8(ssl,0,0,data,&vj); - SSL_DECODE_UINT8(ssl,0,0,data,&vn); - - ja3_ver_str = calloc(7,sizeof(char)); - snprintf(ja3_ver_str, 7, "%u", ((vj & 0xff) << 8) | (vn & 0xff)); - - P_(P_HL) {explain(ssl,"Version %d.%d ",vj,vn); - LF; - } - - SSL_DECODE_OPAQUE_ARRAY(ssl,"random",32,P_ND,data,&random); - ssl_set_client_random(ssl->decoder,random.data,random.len); - - SSL_DECODE_OPAQUE_ARRAY(ssl,"session_id",-32,0,data,&session_id); - ssl_set_client_session_id(ssl->decoder,session_id.data,session_id.len); - - P_(P_HL){ - if(session_id.len) - exdump(ssl,"resume ",&session_id); - } - - ssl_process_client_session_id(ssl,ssl->decoder,session_id.data, - session_id.len); - - P_(P_HL){ - SSL_DECODE_UINT16(ssl,"cipher Suites len",0,data,&cslen); - explain(ssl,"cipher suites\n"); - - odd = cslen % 2; - if(odd) { - printf("Wrong cipher suites length, fixing ...\n"); - cslen -= odd; - } - - for(;cslen;cslen-=2){ - if(ssl_decode_enum(ssl,0,2,cipher_suite_decoder, - 0,data,&cs)) - return(1); - ssl_print_cipher_suite(ssl,(vj<<8)|vn,P_HL,cs); - if(!ja3_cs_str) - ja3_cs_str = calloc(7, 1); - else - ja3_cs_str = realloc(ja3_cs_str, strlen(ja3_cs_str) + 7); - - snprintf(ja3_cs_str + strlen(ja3_cs_str), 7, "%u-", cs); - LF; - } - if(ja3_cs_str && ja3_cs_str[strlen(ja3_cs_str) - 1] == '-') - ja3_cs_str[strlen(ja3_cs_str) - 1] = '\0'; - } - - SSL_DECODE_UINT8(ssl,"compressionMethod len",0,data,&complen); - if(complen){ - explain(ssl,"compression methods\n"); - for(;complen;complen--){ - SSL_DECODE_ENUM(ssl,0,1,compression_method_decoder,P_HL,data,&comp); - LF; - } - } - - SSL_DECODE_UINT16(ssl,"extensions len",0,data,&exlen); - if (exlen) { - explain(ssl , "extensions\n"); - while(data->len) { - SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); - if(!ja3_ex_str) - ja3_ex_str = calloc(7, 1); - else - ja3_ex_str = realloc(ja3_ex_str, strlen(ja3_ex_str) + 7); - - snprintf(ja3_ex_str + strlen(ja3_ex_str), 7, "%u-", ex); - - if (ssl_decode_switch(ssl,extension_decoder,ex,dir,seg,data) == R_NOT_FOUND) { - decode_extension(ssl,dir,seg,data); - P_(P_RH){ - explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); - } - continue; - } - LF; - } - if(ja3_ex_str && ja3_ex_str[strlen(ja3_ex_str) - 1] == '-') - ja3_ex_str[strlen(ja3_ex_str) - 1] = '\0'; - } - - ja3_ec_str = ssl->cur_ja3_ec_str; - ja3_ecp_str = ssl->cur_ja3_ecp_str; - - if(!ja3_ver_str) { - ja3_ver_str = calloc(1, 1); - *ja3_ver_str = '\0'; - } - - if(!ja3_cs_str) { - ja3_cs_str = calloc(1, 1); - *ja3_cs_str = '\0'; - } - - if(!ja3_ex_str) { - ja3_ex_str = calloc(1, 1); - *ja3_ex_str = '\0'; - } - - if(!ja3_ec_str) { - ja3_ec_str = calloc(1, 1); - *ja3_ec_str = '\0'; - } - - if(!ja3_ecp_str) { - ja3_ecp_str = calloc(1, 1); - *ja3_ecp_str = '\0'; - } - - int ja3_str_len = - strlen(ja3_ver_str) + 1 - + strlen(ja3_cs_str) + 1 - + strlen(ja3_ex_str) + 1 - + strlen(ja3_ec_str) + 1 - + strlen(ja3_ecp_str) + 1; - ja3_str = calloc(ja3_str_len, 1); - snprintf(ja3_str, ja3_str_len, "%s,%s,%s,%s,%s", - ja3_ver_str, ja3_cs_str, ja3_ex_str, ja3_ec_str, ja3_ecp_str); - - EVP_MD_CTX *mdctx; - const EVP_MD *md; - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len, i; - - md = EVP_get_digestbyname("MD5"); - mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, md, NULL); - EVP_DigestUpdate(mdctx, ja3_str, strlen(ja3_str)); - EVP_DigestFinal_ex(mdctx, md_value, &md_len); - EVP_MD_CTX_free(mdctx); - - ja3_fp = calloc(33,1); - *ja3_fp = '\0'; - for(i=0; i<16; i++) { - snprintf(ja3_fp + strlen(ja3_fp), 3, "%02x", md_value[i]); - } - - json_object_object_add(jobj, "ja3_str", json_object_new_string(ja3_str)); - json_object_object_add(jobj, "ja3_fp", json_object_new_string(ja3_fp)); - - explain(ssl, "ja3 string: %s\n", ja3_str); - explain(ssl, "ja3 fingerprint: %s\n", ja3_fp); - - free(ja3_fp); - free(ja3_str); - free(ja3_ver_str); - free(ja3_cs_str); - free(ja3_ex_str); - free(ja3_ec_str); - free(ja3_ecp_str); - - return(0); - - } -static int -decode_HandshakeType_ServerHello (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - int r; - Data rnd,session_id; - UINT4 vj,vn,exlen,ex; - char *ja3s_fp = NULL; - char *ja3s_str = NULL; - char *ja3s_ver_str = NULL; - char *ja3s_c_str = NULL; - char *ja3s_ex_str = NULL; - - - extern decoder extension_decoder[]; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("ServerHello")); - - LF; - ssl_update_handshake_messages(ssl,data); - SSL_DECODE_UINT8(ssl,0,0,data,&vj); - SSL_DECODE_UINT8(ssl,0,0,data,&vn); - - ja3s_ver_str = calloc(7,sizeof(char)); - snprintf(ja3s_ver_str, 7, "%u", ((vj & 0xff) << 8) | (vn & 0xff)); - - ssl->version=vj*256+vn; - P_(P_HL) {explain(ssl,"Version %d.%d ",vj,vn); - LF; - } - - - SSL_DECODE_OPAQUE_ARRAY(ssl,"random",32,P_ND,data,&rnd); - ssl_set_server_random(ssl->decoder,rnd.data,rnd.len); - SSL_DECODE_OPAQUE_ARRAY(ssl,"session_id",-32,P_HL,data,&session_id); - SSL_DECODE_ENUM(ssl,"cipherSuite",2,cipher_suite_decoder, - 0,data,&ssl->cipher_suite); - P_(P_HL){ - explain(ssl,"cipherSuite "); - ssl_print_cipher_suite(ssl,ssl->version,P_HL,ssl->cipher_suite); - } - ssl_find_cipher(ssl->cipher_suite,&ssl->cs); - - ja3s_c_str = calloc(6, 1); - snprintf(ja3s_c_str, 6, "%u", ssl->cipher_suite); - - - P_(P_HL) LF; - SSL_DECODE_ENUM(ssl,"compressionMethod",1,compression_method_decoder,P_HL,data,0); - P_(P_HL) LF; - - SSL_DECODE_UINT16(ssl,"extensions len",0,data,&exlen); - if (exlen) { - explain(ssl , "extensions\n"); - while(data->len) { - SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); - if(!ja3s_ex_str) - ja3s_ex_str = calloc(7, 1); - else - ja3s_ex_str = realloc(ja3s_ex_str, strlen(ja3s_ex_str) + 7); - - snprintf(ja3s_ex_str + strlen(ja3s_ex_str), 7, "%u-", ex); - - if (ssl_decode_switch(ssl,extension_decoder,ex,dir,seg,data) == R_NOT_FOUND) { - decode_extension(ssl,dir,seg,data); - P_(P_RH){ - explain(ssl, "Extension type: %u not yet implemented in ssldump,\n", ex); - } - continue; - } - LF; - } - if(ja3s_ex_str && ja3s_ex_str[strlen(ja3s_ex_str) - 1] == '-') - ja3s_ex_str[strlen(ja3s_ex_str) - 1] = '\0'; - } - - if (ssl->version==TLSV13_VERSION){ - // tls version is known in server hello for tls1.3 hence generate keying material here - ssl_tls13_generate_keying_material(ssl,ssl->decoder); - } - - ssl_process_server_session_id(ssl,ssl->decoder,session_id.data, - session_id.len); - - if(!ja3s_ver_str) { - ja3s_ver_str = calloc(1, 1); - *ja3s_ver_str = '\0'; - } - - if(!ja3s_c_str) { - ja3s_c_str = calloc(1, 1); - *ja3s_c_str = '\0'; - } - - if(!ja3s_ex_str) { - ja3s_ex_str = calloc(1, 1); - *ja3s_ex_str = '\0'; - } - - int ja3s_str_len = - strlen(ja3s_ver_str) + 1 - + strlen(ja3s_c_str) + 1 - + strlen(ja3s_ex_str) + 1; - ja3s_str = calloc(ja3s_str_len, 1); - snprintf(ja3s_str, ja3s_str_len, "%s,%s,%s", - ja3s_ver_str, ja3s_c_str, ja3s_ex_str); - - EVP_MD_CTX *mdctx; - const EVP_MD *md; - unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len, i; - - md = EVP_get_digestbyname("MD5"); - mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, md, NULL); - EVP_DigestUpdate(mdctx, ja3s_str, strlen(ja3s_str)); - EVP_DigestFinal_ex(mdctx, md_value, &md_len); - EVP_MD_CTX_free(mdctx); - - ja3s_fp = calloc(33,1); - *ja3s_fp = '\0'; - for(i=0; i<16; i++) { - snprintf(ja3s_fp + strlen(ja3s_fp), 3, "%02x", md_value[i]); - } - - json_object_object_add(jobj, "ja3s_str", json_object_new_string(ja3s_str)); - json_object_object_add(jobj, "ja3s_fp", json_object_new_string(ja3s_fp)); - - explain(ssl, "ja3s string: %s\n", ja3s_str); - explain(ssl, "ja3s fingerprint: %s\n", ja3s_fp); - - free(ja3s_fp); - free(ja3s_str); - free(ja3s_ver_str); - free(ja3s_c_str); - free(ja3s_ex_str); - - return(0); - - } -static int -decode_HandshakeType_Certificate (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - UINT4 len,exlen,ex; - Data cert; - int r; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("Certificate")); - extern decoder extension_decoder[]; - - LF; - ssl_update_handshake_messages(ssl,data); - if (ssl->version==TLSV13_VERSION){ - SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate request context",-((1<<7)-1),0, data, NULL); - } - SSL_DECODE_UINT24(ssl,"certificates len",0,data,&len); - - json_object_object_add(jobj, "cert_chain", json_object_new_array()); - - while(len){ - SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate",-((1<<23)-1), - 0,data,&cert); - sslx_print_certificate(ssl,&cert,P_ND); - len-=(cert.len + 3); - if (ssl->version==TLSV13_VERSION) { // TLS 1.3 has certificate extensions - SSL_DECODE_UINT16(ssl,"certificate extensions len",0,data,&exlen); - len-=2; - while (exlen) { - SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); - len -= (2+ex); - if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { - decode_extension(ssl, dir, seg, data); - P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } - continue; - } - LF; - } - } - } - - return(0); - - } - -static int -decode_HandshakeType_SessionTicket (ssl_obj *ssl, int dir, segment *seg, Data *data) -{ - int r; - UINT4 exlen, ex, val; - extern decoder extension_decoder[]; - - SSL_DECODE_UINT32(ssl, "ticket_lifetime",P_HL, data, &val); - if (ssl->version == TLSV13_VERSION) { - SSL_DECODE_UINT32(ssl, "ticket_age_add", P_HL, data, &val); - SSL_DECODE_OPAQUE_ARRAY(ssl,"ticket_nonce",-((1<<7)-1), P_ND, data, NULL); - } - SSL_DECODE_OPAQUE_ARRAY(ssl,"ticket",-((1<<15)-1), P_ND, data, NULL); - if (ssl->version == TLSV13_VERSION) { - SSL_DECODE_UINT16(ssl, "exlen", 0, data, &exlen); - if (exlen) { - while (data->len) { - SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); - if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { - if ((r=decode_extension(ssl, dir, seg, data))) ERETURN(r); - P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } - continue; - } - LF; - } - } - } + return (0); } +static int decode_ContentType_Alert(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + struct json_object *jobj; -static int -decode_HandshakeType_EncryptedExtensions (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r; - UINT4 exlen, ex; - extern decoder extension_decoder[]; - - SSL_DECODE_UINT16(ssl, 0, 0, data, &exlen); + if(ssl->record_encryption == REC_CIPHERTEXT) { LF; - if (exlen) { - while (data->len) { + return (0); + } + + if(data->len != 2) { + fprintf(stderr, "Wrong length for alert message: %d\n", data->len); + ERETURN(R_EOD); + } + + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "msg_type", json_object_new_string("Alert")); + + P_(P_HL) { + LF; + SSL_DECODE_ENUM(ssl, "level", 1, AlertLevel_decoder, P_HL, data, 0); + LF; + SSL_DECODE_ENUM(ssl, "value", 1, AlertDescription_decoder, P_HL, data, 0); + LF; + } + else { + SSL_DECODE_ENUM(ssl, 0, 1, AlertLevel_decoder, SSL_PRINT_ALL, data, 0); + SSL_DECODE_ENUM(ssl, 0, 1, AlertDescription_decoder, SSL_PRINT_ALL, data, + 0); + LF; + } + return (0); +} +static int decode_ContentType_Handshake(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + extern decoder HandshakeType_decoder[]; + int r; + UINT4 t, l; + int rs = 0; + Data d; + struct json_object *jobj; + + if(ssl->record_encryption == REC_CIPHERTEXT) { + LF; + return (0); + } + + while(data->len > 0) { + SSL_DECODE_UINT8(ssl, 0, 0, data, &t); + SSL_DECODE_UINT24(ssl, 0, 0, data, &l); + + if(data->len < l) { + fprintf(stderr, "Error: short handshake length: expected %d got %d\n", l, + data->len); + ERETURN(R_EOD); + } + + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "msg_type", + json_object_new_string("Handshake")); + + d.data = data->data; + d.len = l; + data->len -= l; + data->data += l; + P_(P_HL) { + if(!rs) { + LF; + rs = 1; + } + } + ssl_decode_switch(ssl, HandshakeType_decoder, t, dir, seg, &d); + } + return (0); +} +static int decode_ContentType_application_data(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + Data d; + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "msg_type", + json_object_new_string("application data")); + + SSL_DECODE_OPAQUE_ARRAY(ssl, "data", data->len, 0, data, &d); + + if(NET_print_flags & NET_PRINT_JSON) { + json_object_object_add(jobj, "msg_data", + json_object_new_string_len(d.data, d.len)); + } else + P_(P_AD) { print_data(ssl, &d); } + else { + LF; + } + return (0); +} +decoder ContentType_decoder[] = { + {20, "ChangeCipherSpec", decode_ContentType_ChangeCipherSpec}, + {21, "Alert", decode_ContentType_Alert}, + {22, "Handshake", decode_ContentType_Handshake}, + {23, "application_data", decode_ContentType_application_data}, + {-1}}; + +static int decode_HandshakeType_HelloRequest(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("HelloRequest")); + + LF; + return (0); +} +static int decode_HandshakeType_ClientHello(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("ClientHello")); + + UINT4 vj, vn, cs, cslen, complen, comp, odd, exlen, ex; + Data session_id, random; + int r; + char *ja3_fp = NULL; + char *ja3_str = NULL; + char *ja3_ver_str = NULL; + char *ja3_cs_str = NULL; + char *ja3_ex_str = NULL; + char *ja3_ec_str = NULL; + char *ja3_ecp_str = NULL; + + ssl->cur_ja3_ec_str = NULL; + ssl->cur_ja3_ecp_str = NULL; + + extern decoder cipher_suite_decoder[]; + extern decoder compression_method_decoder[]; + extern decoder extension_decoder[]; + + LF; + ssl_update_handshake_messages(ssl, data); + SSL_DECODE_UINT8(ssl, 0, 0, data, &vj); + SSL_DECODE_UINT8(ssl, 0, 0, data, &vn); + + ja3_ver_str = calloc(7, sizeof(char)); + snprintf(ja3_ver_str, 7, "%u", ((vj & 0xff) << 8) | (vn & 0xff)); + + P_(P_HL) { + explain(ssl, "Version %d.%d ", vj, vn); + LF; + } + + SSL_DECODE_OPAQUE_ARRAY(ssl, "random", 32, P_ND, data, &random); + ssl_set_client_random(ssl->decoder, random.data, random.len); + + SSL_DECODE_OPAQUE_ARRAY(ssl, "session_id", -32, 0, data, &session_id); + ssl_set_client_session_id(ssl->decoder, session_id.data, session_id.len); + + P_(P_HL) { + if(session_id.len) + exdump(ssl, "resume ", &session_id); + } + + ssl_process_client_session_id(ssl, ssl->decoder, session_id.data, + session_id.len); + + P_(P_HL) { + SSL_DECODE_UINT16(ssl, "cipher Suites len", 0, data, &cslen); + explain(ssl, "cipher suites\n"); + + odd = cslen % 2; + if(odd) { + printf("Wrong cipher suites length, fixing ...\n"); + cslen -= odd; + } + + for(; cslen; cslen -= 2) { + if(ssl_decode_enum(ssl, 0, 2, cipher_suite_decoder, 0, data, &cs)) + return (1); + ssl_print_cipher_suite(ssl, (vj << 8) | vn, P_HL, cs); + if(!ja3_cs_str) + ja3_cs_str = calloc(7, 1); + else + ja3_cs_str = realloc(ja3_cs_str, strlen(ja3_cs_str) + 7); + + snprintf(ja3_cs_str + strlen(ja3_cs_str), 7, "%u-", cs); + LF; + } + if(ja3_cs_str && ja3_cs_str[strlen(ja3_cs_str) - 1] == '-') + ja3_cs_str[strlen(ja3_cs_str) - 1] = '\0'; + } + + SSL_DECODE_UINT8(ssl, "compressionMethod len", 0, data, &complen); + if(complen) { + explain(ssl, "compression methods\n"); + for(; complen; complen--) { + SSL_DECODE_ENUM(ssl, 0, 1, compression_method_decoder, P_HL, data, &comp); + LF; + } + } + + SSL_DECODE_UINT16(ssl, "extensions len", 0, data, &exlen); + if(exlen) { + explain(ssl, "extensions\n"); + while(data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if(!ja3_ex_str) + ja3_ex_str = calloc(7, 1); + else + ja3_ex_str = realloc(ja3_ex_str, strlen(ja3_ex_str) + 7); + + snprintf(ja3_ex_str + strlen(ja3_ex_str), 7, "%u-", ex); + + if(ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == + R_NOT_FOUND) { + decode_extension(ssl, dir, seg, data); + P_(P_RH) { + explain(ssl, "Extension type: %u not yet implemented in ssldump\n", + ex); + } + continue; + } + LF; + } + if(ja3_ex_str && ja3_ex_str[strlen(ja3_ex_str) - 1] == '-') + ja3_ex_str[strlen(ja3_ex_str) - 1] = '\0'; + } + + ja3_ec_str = ssl->cur_ja3_ec_str; + ja3_ecp_str = ssl->cur_ja3_ecp_str; + + if(!ja3_ver_str) { + ja3_ver_str = calloc(1, 1); + *ja3_ver_str = '\0'; + } + + if(!ja3_cs_str) { + ja3_cs_str = calloc(1, 1); + *ja3_cs_str = '\0'; + } + + if(!ja3_ex_str) { + ja3_ex_str = calloc(1, 1); + *ja3_ex_str = '\0'; + } + + if(!ja3_ec_str) { + ja3_ec_str = calloc(1, 1); + *ja3_ec_str = '\0'; + } + + if(!ja3_ecp_str) { + ja3_ecp_str = calloc(1, 1); + *ja3_ecp_str = '\0'; + } + + int ja3_str_len = strlen(ja3_ver_str) + 1 + strlen(ja3_cs_str) + 1 + + strlen(ja3_ex_str) + 1 + strlen(ja3_ec_str) + 1 + + strlen(ja3_ecp_str) + 1; + ja3_str = calloc(ja3_str_len, 1); + snprintf(ja3_str, ja3_str_len, "%s,%s,%s,%s,%s", ja3_ver_str, ja3_cs_str, + ja3_ex_str, ja3_ec_str, ja3_ecp_str); + + EVP_MD_CTX *mdctx; + const EVP_MD *md; + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len, i; + + md = EVP_get_digestbyname("MD5"); + mdctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(mdctx, md, NULL); + EVP_DigestUpdate(mdctx, ja3_str, strlen(ja3_str)); + EVP_DigestFinal_ex(mdctx, md_value, &md_len); + EVP_MD_CTX_free(mdctx); + + ja3_fp = calloc(33, 1); + *ja3_fp = '\0'; + for(i = 0; i < 16; i++) { + snprintf(ja3_fp + strlen(ja3_fp), 3, "%02x", md_value[i]); + } + + json_object_object_add(jobj, "ja3_str", json_object_new_string(ja3_str)); + json_object_object_add(jobj, "ja3_fp", json_object_new_string(ja3_fp)); + + explain(ssl, "ja3 string: %s\n", ja3_str); + explain(ssl, "ja3 fingerprint: %s\n", ja3_fp); + + free(ja3_fp); + free(ja3_str); + free(ja3_ver_str); + free(ja3_cs_str); + free(ja3_ex_str); + free(ja3_ec_str); + free(ja3_ecp_str); + + return (0); +} +static int decode_HandshakeType_ServerHello(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + Data rnd, session_id; + UINT4 vj, vn, exlen, ex; + char *ja3s_fp = NULL; + char *ja3s_str = NULL; + char *ja3s_ver_str = NULL; + char *ja3s_c_str = NULL; + char *ja3s_ex_str = NULL; + + extern decoder extension_decoder[]; + + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("ServerHello")); + + LF; + ssl_update_handshake_messages(ssl, data); + SSL_DECODE_UINT8(ssl, 0, 0, data, &vj); + SSL_DECODE_UINT8(ssl, 0, 0, data, &vn); + + ja3s_ver_str = calloc(7, sizeof(char)); + snprintf(ja3s_ver_str, 7, "%u", ((vj & 0xff) << 8) | (vn & 0xff)); + + ssl->version = vj * 256 + vn; + P_(P_HL) { + explain(ssl, "Version %d.%d ", vj, vn); + LF; + } + + SSL_DECODE_OPAQUE_ARRAY(ssl, "random", 32, P_ND, data, &rnd); + ssl_set_server_random(ssl->decoder, rnd.data, rnd.len); + SSL_DECODE_OPAQUE_ARRAY(ssl, "session_id", -32, P_HL, data, &session_id); + SSL_DECODE_ENUM(ssl, "cipherSuite", 2, cipher_suite_decoder, 0, data, + &ssl->cipher_suite); + P_(P_HL) { + explain(ssl, "cipherSuite "); + ssl_print_cipher_suite(ssl, ssl->version, P_HL, ssl->cipher_suite); + } + ssl_find_cipher(ssl->cipher_suite, &ssl->cs); + + ja3s_c_str = calloc(6, 1); + snprintf(ja3s_c_str, 6, "%u", ssl->cipher_suite); + + P_(P_HL) LF; + SSL_DECODE_ENUM(ssl, "compressionMethod", 1, compression_method_decoder, P_HL, + data, 0); + P_(P_HL) LF; + + SSL_DECODE_UINT16(ssl, "extensions len", 0, data, &exlen); + if(exlen) { + explain(ssl, "extensions\n"); + while(data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if(!ja3s_ex_str) + ja3s_ex_str = calloc(7, 1); + else + ja3s_ex_str = realloc(ja3s_ex_str, strlen(ja3s_ex_str) + 7); + + snprintf(ja3s_ex_str + strlen(ja3s_ex_str), 7, "%u-", ex); + + if(ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == + R_NOT_FOUND) { + decode_extension(ssl, dir, seg, data); + P_(P_RH) { + explain(ssl, "Extension type: %u not yet implemented in ssldump,\n", + ex); + } + continue; + } + LF; + } + if(ja3s_ex_str && ja3s_ex_str[strlen(ja3s_ex_str) - 1] == '-') + ja3s_ex_str[strlen(ja3s_ex_str) - 1] = '\0'; + } + + if(ssl->version == TLSV13_VERSION) { + // tls version is known in server hello for tls1.3 hence generate keying + // material here + ssl_tls13_generate_keying_material(ssl, ssl->decoder); + } + + ssl_process_server_session_id(ssl, ssl->decoder, session_id.data, + session_id.len); + + if(!ja3s_ver_str) { + ja3s_ver_str = calloc(1, 1); + *ja3s_ver_str = '\0'; + } + + if(!ja3s_c_str) { + ja3s_c_str = calloc(1, 1); + *ja3s_c_str = '\0'; + } + + if(!ja3s_ex_str) { + ja3s_ex_str = calloc(1, 1); + *ja3s_ex_str = '\0'; + } + + int ja3s_str_len = strlen(ja3s_ver_str) + 1 + strlen(ja3s_c_str) + 1 + + strlen(ja3s_ex_str) + 1; + ja3s_str = calloc(ja3s_str_len, 1); + snprintf(ja3s_str, ja3s_str_len, "%s,%s,%s", ja3s_ver_str, ja3s_c_str, + ja3s_ex_str); + + EVP_MD_CTX *mdctx; + const EVP_MD *md; + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len, i; + + md = EVP_get_digestbyname("MD5"); + mdctx = EVP_MD_CTX_new(); + EVP_DigestInit_ex(mdctx, md, NULL); + EVP_DigestUpdate(mdctx, ja3s_str, strlen(ja3s_str)); + EVP_DigestFinal_ex(mdctx, md_value, &md_len); + EVP_MD_CTX_free(mdctx); + + ja3s_fp = calloc(33, 1); + *ja3s_fp = '\0'; + for(i = 0; i < 16; i++) { + snprintf(ja3s_fp + strlen(ja3s_fp), 3, "%02x", md_value[i]); + } + + json_object_object_add(jobj, "ja3s_str", json_object_new_string(ja3s_str)); + json_object_object_add(jobj, "ja3s_fp", json_object_new_string(ja3s_fp)); + + explain(ssl, "ja3s string: %s\n", ja3s_str); + explain(ssl, "ja3s fingerprint: %s\n", ja3s_fp); + + free(ja3s_fp); + free(ja3s_str); + free(ja3s_ver_str); + free(ja3s_c_str); + free(ja3s_ex_str); + + return (0); +} +static int decode_HandshakeType_Certificate(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + UINT4 len, exlen, ex; + Data cert; + int r; + + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("Certificate")); + extern decoder extension_decoder[]; + + LF; + ssl_update_handshake_messages(ssl, data); + if(ssl->version == TLSV13_VERSION) { + SSL_DECODE_OPAQUE_ARRAY(ssl, "certificate request context", -((1 << 7) - 1), + 0, data, NULL); + } + SSL_DECODE_UINT24(ssl, "certificates len", 0, data, &len); + + json_object_object_add(jobj, "cert_chain", json_object_new_array()); + + while(len) { + SSL_DECODE_OPAQUE_ARRAY(ssl, "certificate", -((1 << 23) - 1), 0, data, + &cert); + sslx_print_certificate(ssl, &cert, P_ND); + len -= (cert.len + 3); + if(ssl->version == TLSV13_VERSION) { // TLS 1.3 has certificate extensions + SSL_DECODE_UINT16(ssl, "certificate extensions len", 0, data, &exlen); + len -= 2; + while(exlen) { SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); - if (ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == R_NOT_FOUND) { + len -= (2 + ex); + if(ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == + R_NOT_FOUND) { decode_extension(ssl, dir, seg, data); - P_(P_RH) { explain(ssl, "Extension type: %u not yet implemented in ssldump\n", ex); } + P_(P_RH) { + explain(ssl, "Extension type: %u not yet implemented in ssldump\n", + ex); + } continue; } LF; @@ -596,2682 +528,1227 @@ decode_HandshakeType_EncryptedExtensions (ssl_obj *ssl, int dir, segment *seg, D } } -static int -decode_HandshakeType_ServerKeyExchange (ssl_obj *ssl, int dir, segment *seg, Data *data) - { + return (0); +} +static int decode_HandshakeType_SessionTicket(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 exlen, ex, val; + extern decoder extension_decoder[]; - int r; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("ServerKeyExchange")); - - LF; - ssl_update_handshake_messages(ssl,data); - if(ssl->cs){ - P_(P_ND){ - explain(ssl,"params\n"); - } - INDENT_INCR; - - switch(ssl->cs->kex){ - case KEX_DH: - SSL_DECODE_OPAQUE_ARRAY(ssl,"DH_p",-((1<<15)-1),P_ND,data,0); - SSL_DECODE_OPAQUE_ARRAY(ssl,"DH_g",-((1<<15)-1),P_ND,data,0); - SSL_DECODE_OPAQUE_ARRAY(ssl,"DH_Ys",-((1<<15)-1),P_ND,data,0); - break; - case KEX_RSA: - SSL_DECODE_OPAQUE_ARRAY(ssl,"RSA_modulus",-((1<<15)-1),P_ND,data,0); - SSL_DECODE_OPAQUE_ARRAY(ssl,"RSA_exponent",-((1<<15)-1),P_ND,data,0); - break; - } - INDENT_POP; - SSL_DECODE_OPAQUE_ARRAY(ssl,"signature",-((1<<15)-1),P_ND,data,0); - } - - return(0); - + SSL_DECODE_UINT32(ssl, "ticket_lifetime", P_HL, data, &val); + if(ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT32(ssl, "ticket_age_add", P_HL, data, &val); + SSL_DECODE_OPAQUE_ARRAY(ssl, "ticket_nonce", -((1 << 7) - 1), P_ND, data, + NULL); } -static int -decode_HandshakeType_CertificateRequest (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - - UINT4 len; - Data ca; - int r; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("CertificateRequest")); - - LF; - ssl_update_handshake_messages(ssl,data); - SSL_DECODE_UINT8(ssl,"certificate_types len",0,data,&len); - for(;len;len--){ - SSL_DECODE_ENUM(ssl,"certificate_types",1, - client_certificate_type_decoder, P_HL,data,0); - P_(P_HL){ - LF; + SSL_DECODE_OPAQUE_ARRAY(ssl, "ticket", -((1 << 15) - 1), P_ND, data, NULL); + if(ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT16(ssl, "exlen", 0, data, &exlen); + if(exlen) { + while(data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if(ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == + R_NOT_FOUND) { + if((r = decode_extension(ssl, dir, seg, data))) + ERETURN(r); + P_(P_RH) { + explain(ssl, "Extension type: %u not yet implemented in ssldump\n", + ex); + } + continue; + } + LF; } - }; - - SSL_DECODE_UINT16(ssl,"certificate_authorities len",0,data,&len); - while(len){ - SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate_authorities", - -((1<<15)-1),0,data,&ca); - explain(ssl,"certificate_authority\n"); - INDENT_INCR; - sslx_print_dn(ssl,&ca,P_HL); - INDENT_POP; - len-=(ca.len + 2); } - return(0); - } -static int -decode_HandshakeType_ServerHelloDone (ssl_obj *ssl, int dir, segment *seg, Data *data) - { +} - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("ServerHelloDone")); +static int decode_HandshakeType_EncryptedExtensions(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 exlen, ex; + extern decoder extension_decoder[]; + + SSL_DECODE_UINT16(ssl, 0, 0, data, &exlen); + LF; + if(exlen) { + while(data->len) { + SSL_DECODE_UINT16(ssl, "extension type", 0, data, &ex); + if(ssl_decode_switch(ssl, extension_decoder, ex, dir, seg, data) == + R_NOT_FOUND) { + decode_extension(ssl, dir, seg, data); + P_(P_RH) { + explain(ssl, "Extension type: %u not yet implemented in ssldump\n", + ex); + } + continue; + } + LF; + } + } +} + +static int decode_HandshakeType_ServerKeyExchange(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("ServerKeyExchange")); LF; - ssl_update_handshake_messages(ssl,data); - return(0); + ssl_update_handshake_messages(ssl, data); + if(ssl->cs) { + P_(P_ND) { explain(ssl, "params\n"); } + INDENT_INCR; + switch(ssl->cs->kex) { + case KEX_DH: + SSL_DECODE_OPAQUE_ARRAY(ssl, "DH_p", -((1 << 15) - 1), P_ND, data, 0); + SSL_DECODE_OPAQUE_ARRAY(ssl, "DH_g", -((1 << 15) - 1), P_ND, data, 0); + SSL_DECODE_OPAQUE_ARRAY(ssl, "DH_Ys", -((1 << 15) - 1), P_ND, data, 0); + break; + case KEX_RSA: + SSL_DECODE_OPAQUE_ARRAY(ssl, "RSA_modulus", -((1 << 15) - 1), P_ND, + data, 0); + SSL_DECODE_OPAQUE_ARRAY(ssl, "RSA_exponent", -((1 << 15) - 1), P_ND, + data, 0); + break; + } + INDENT_POP; + SSL_DECODE_OPAQUE_ARRAY(ssl, "signature", -((1 << 15) - 1), P_ND, data, 0); } -static int -decode_HandshakeType_CertificateVerify (ssl_obj *ssl, int dir, segment *seg, Data *data) - { + return (0); +} +static int decode_HandshakeType_CertificateRequest(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + UINT4 len; + Data ca; + int r; + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("CertificateRequest")); + + LF; + ssl_update_handshake_messages(ssl, data); + SSL_DECODE_UINT8(ssl, "certificate_types len", 0, data, &len); + for(; len; len--) { + SSL_DECODE_ENUM(ssl, "certificate_types", 1, + client_certificate_type_decoder, P_HL, data, 0); + P_(P_HL) { LF; } + }; + + SSL_DECODE_UINT16(ssl, "certificate_authorities len", 0, data, &len); + while(len) { + SSL_DECODE_OPAQUE_ARRAY(ssl, "certificate_authorities", -((1 << 15) - 1), 0, + data, &ca); + explain(ssl, "certificate_authority\n"); + INDENT_INCR; + sslx_print_dn(ssl, &ca, P_HL); + INDENT_POP; + len -= (ca.len + 2); + } + return (0); +} +static int decode_HandshakeType_ServerHelloDone(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("ServerHelloDone")); + + LF; + ssl_update_handshake_messages(ssl, data); + return (0); +} +static int decode_HandshakeType_CertificateVerify(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { int r; UINT4 signature_type; - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("CertificateVerify")); + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("CertificateVerify")); LF; - ssl_update_handshake_messages(ssl,data); - if (ssl->version == TLSV13_VERSION) { - SSL_DECODE_UINT16(ssl,"signature_type",P_HL,data,&signature_type); + ssl_update_handshake_messages(ssl, data); + if(ssl->version == TLSV13_VERSION) { + SSL_DECODE_UINT16(ssl, "signature_type", P_HL, data, &signature_type); } - SSL_DECODE_OPAQUE_ARRAY(ssl,"Signature",-((1<<15)-1),P_HL,data,0); - return(0); + SSL_DECODE_OPAQUE_ARRAY(ssl, "Signature", -((1 << 15) - 1), P_HL, data, 0); + return (0); +} +static int decode_HandshakeType_ClientKeyExchange(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + Data pms; + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("ClientKeyExchange")); + + LF; + ssl_update_handshake_messages(ssl, data); + if(ssl->cs) { + switch(ssl->cs->kex) { + case KEX_RSA: + if(ssl->version > 768) { + SSL_DECODE_OPAQUE_ARRAY(ssl, "EncryptedPreMasterSecret", + -((1 << 15) - 1), P_ND, data, &pms); + + } else { + SSL_DECODE_OPAQUE_ARRAY(ssl, "EncryptedPreMasterSecret", data->len, + P_ND, data, &pms); + } + ssl_process_client_key_exchange(ssl, ssl->decoder, pms.data, pms.len); + + break; + case KEX_DH: + SSL_DECODE_OPAQUE_ARRAY(ssl, "DiffieHellmanClientPublicValue", + -((1 << 7) - 1), P_HL, data, 0); + ssl_process_client_key_exchange(ssl, ssl->decoder, NULL, 0); + } } -static int -decode_HandshakeType_ClientKeyExchange (ssl_obj *ssl, int dir, segment *seg, Data *data) - { + return (0); +} +static int decode_HandshakeType_Finished(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "handshake_type", + json_object_new_string("Finished")); - int r; - Data pms; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("ClientKeyExchange")); - - LF; - ssl_update_handshake_messages(ssl,data); - if(ssl->cs){ - switch(ssl->cs->kex){ - - case KEX_RSA: - if(ssl->version > 768) { - SSL_DECODE_OPAQUE_ARRAY(ssl,"EncryptedPreMasterSecret",-((1<<15)-1), - P_ND,data,&pms); - - } - else { - SSL_DECODE_OPAQUE_ARRAY(ssl,"EncryptedPreMasterSecret",data->len,P_ND,data,&pms); - } - ssl_process_client_key_exchange(ssl, - ssl->decoder,pms.data,pms.len); - - break; - case KEX_DH: - SSL_DECODE_OPAQUE_ARRAY(ssl,"DiffieHellmanClientPublicValue", - -((1<<7)-1),P_HL,data,0); - ssl_process_client_key_exchange(ssl, - ssl->decoder,NULL,0); - } - } - return(0); - - } -static int -decode_HandshakeType_Finished (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - - - int r; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "handshake_type", json_object_new_string("Finished")); - - LF; - switch(ssl->version){ - case 0x300: - SSL_DECODE_OPAQUE_ARRAY(ssl,"md5_hash",16,P_ND,data,0); - - SSL_DECODE_OPAQUE_ARRAY(ssl,"sha_hash",20,P_ND,data,0); - break; - case 0x301: - SSL_DECODE_OPAQUE_ARRAY(ssl,"verify_data",12,P_ND,data,0); - P_(P_ND) - LF; - break; - } - - ssl_process_handshake_finished(ssl,ssl->decoder,data); - return (0); + LF; + switch(ssl->version) { + case 0x300: + SSL_DECODE_OPAQUE_ARRAY(ssl, "md5_hash", 16, P_ND, data, 0); + SSL_DECODE_OPAQUE_ARRAY(ssl, "sha_hash", 20, P_ND, data, 0); + break; + case 0x301: + SSL_DECODE_OPAQUE_ARRAY(ssl, "verify_data", 12, P_ND, data, 0); + P_(P_ND) + LF; + break; } -static int -decode_HandshakeType_KeyUpdate (ssl_obj *ssl, int dir, segment *seg, Data *data) -{ - LF; - ssl_tls13_update_keying_material(ssl, ssl->decoder, dir); - return 0; + ssl_process_handshake_finished(ssl, ssl->decoder, data); + return (0); } -decoder HandshakeType_decoder[]={ - { - 0, - "HelloRequest", - decode_HandshakeType_HelloRequest - }, - { - 1, - "ClientHello", - decode_HandshakeType_ClientHello - }, - { - 2, - "ServerHello", - decode_HandshakeType_ServerHello - }, - { - 4, - "SessionTicket", - decode_HandshakeType_SessionTicket - }, - { - 8, - "EncryptedExtensions", - decode_HandshakeType_EncryptedExtensions - }, - { - 11, - "Certificate", - decode_HandshakeType_Certificate - }, - { - 12, - "ServerKeyExchange", - decode_HandshakeType_ServerKeyExchange - }, - { - 13, - "CertificateRequest", - decode_HandshakeType_CertificateRequest - }, - { - 14, - "ServerHelloDone", - decode_HandshakeType_ServerHelloDone - }, - { - 15, - "CertificateVerify", - decode_HandshakeType_CertificateVerify - }, - { - 16, - "ClientKeyExchange", - decode_HandshakeType_ClientKeyExchange - }, - { - 20, - "Finished", - decode_HandshakeType_Finished - }, - { - 24, - "KeyUpdate", - decode_HandshakeType_KeyUpdate - }, -{-1} -}; +static int decode_HandshakeType_KeyUpdate(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + LF; + ssl_tls13_update_keying_material(ssl, ssl->decoder, dir); + return 0; +} -decoder cipher_suite_decoder[]={ - // https://www.iana.org/assignments/tls-parameters/tls-parameters.txt - { - 0, - "TLS_NULL_WITH_NULL_NULL", - 0 }, - { - 1, - "TLS_RSA_WITH_NULL_MD5", - 0 }, - { - 2, - "TLS_RSA_WITH_NULL_SHA", - 0 }, - { - 3, - "TLS_RSA_EXPORT_WITH_RC4_40_MD5", - 0 }, - { - 4, - "TLS_RSA_WITH_RC4_128_MD5", - 0 }, - { - 5, - "TLS_RSA_WITH_RC4_128_SHA", - 0 }, - { - 6, - "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", - 0 }, - { - 7, - "TLS_RSA_WITH_IDEA_CBC_SHA", - 0 }, - { - 8, - "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 9, - "TLS_RSA_WITH_DES_CBC_SHA", - 0 }, - { - 10, - "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 11, - "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 12, - "TLS_DH_DSS_WITH_DES_CBC_SHA", - 0 }, - { - 13, - "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 14, - "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 15, - "TLS_DH_RSA_WITH_DES_CBC_SHA", - 0 }, - { - 16, - "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 17, - "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 18, - "TLS_DHE_DSS_WITH_DES_CBC_SHA", - 0 }, - { - 19, - "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 20, - "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 21, - "TLS_DHE_RSA_WITH_DES_CBC_SHA", - 0 }, - { - 22, - "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 23, - "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", - 0 }, - { - 24, - "TLS_DH_anon_WITH_RC4_128_MD5", - 0 }, - { - 25, - "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 26, - "TLS_DH_anon_WITH_DES_CBC_SHA", - 0 }, - { - 27, - "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 30, - "TLS_KRB5_WITH_DES_CBC_SHA", - 0 }, - { - 31, - "TLS_KRB5_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 32, - "TLS_KRB5_WITH_RC4_128_SHA", - 0 }, - { - 33, - "TLS_KRB5_WITH_IDEA_CBC_SHA", - 0 }, - { - 34, - "TLS_KRB5_WITH_DES_CBC_MD5", - 0 }, - { - 35, - "TLS_KRB5_WITH_3DES_EDE_CBC_MD5", - 0 }, - { - 36, - "TLS_KRB5_WITH_RC4_128_MD5", - 0 }, - { - 37, - "TLS_KRB5_WITH_IDEA_CBC_MD5", - 0 }, - { - 38, - "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", - 0 }, - { - 39, - "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", - 0 }, - { - 40, - "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", - 0 }, - { - 41, - "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", - 0 }, - { - 42, - "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", - 0 }, - { - 43, - "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", - 0 }, - { - 44, - "TLS_PSK_WITH_NULL_SHA", - 0 }, - { - 45, - "TLS_DHE_PSK_WITH_NULL_SHA", - 0 }, - { - 46, - "TLS_RSA_PSK_WITH_NULL_SHA", - 0 }, - { - 47, - "TLS_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 48, - "TLS_DH_DSS_WITH_AES_128_CBC_SHA", - 0 }, - { - 49, - "TLS_DH_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 50, - "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - 0 }, - { - 51, - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 52, - "TLS_DH_anon_WITH_AES_128_CBC_SHA", - 0 }, - { - 53, - "TLS_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 54, - "TLS_DH_DSS_WITH_AES_256_CBC_SHA", - 0 }, - { - 55, - "TLS_DH_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 56, - "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", - 0 }, - { - 57, - "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 58, - "TLS_DH_anon_WITH_AES_256_CBC_SHA", - 0 }, - { - 59, - "TLS_RSA_WITH_NULL_SHA256", - 0 }, - { - 60, - "TLS_RSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 61, - "TLS_RSA_WITH_AES_256_CBC_SHA256", - 0 }, - { - 62, - "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", - 0 }, - { - 63, - "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 64, - "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", - 0 }, - { - 65, - "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 66, - "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 67, - "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 68, - "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 69, - "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 70, - "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", - 0 }, - { - 103, - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 104, - "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", - 0 }, - { - 105, - "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", - 0 }, - { - 106, - "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", - 0 }, - { - 107, - "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", - 0 }, - { - 108, - "TLS_DH_anon_WITH_AES_128_CBC_SHA256", - 0 }, - { - 109, - "TLS_DH_anon_WITH_AES_256_CBC_SHA256", - 0 }, - { - 132, - "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 133, - "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 134, - "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 135, - "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 136, - "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 137, - "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", - 0 }, - { - 138, - "TLS_PSK_WITH_RC4_128_SHA", - 0 }, - { - 139, - "TLS_PSK_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 140, - "TLS_PSK_WITH_AES_128_CBC_SHA", - 0 }, - { - 141, - "TLS_PSK_WITH_AES_256_CBC_SHA", - 0 }, - { - 142, - "TLS_DHE_PSK_WITH_RC4_128_SHA", - 0 }, - { - 143, - "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 144, - "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", - 0 }, - { - 145, - "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", - 0 }, - { - 146, - "TLS_RSA_PSK_WITH_RC4_128_SHA", - 0 }, - { - 147, - "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 148, - "TLS_RSA_PSK_WITH_AES_128_CBC_SHA", - 0 }, - { - 149, - "TLS_RSA_PSK_WITH_AES_256_CBC_SHA", - 0 }, - { - 150, - "TLS_RSA_WITH_SEED_CBC_SHA", - 0 }, - { - 151, - "TLS_DH_DSS_WITH_SEED_CBC_SHA", - 0 }, - { - 152, - "TLS_DH_RSA_WITH_SEED_CBC_SHA", - 0 }, - { - 153, - "TLS_DHE_DSS_WITH_SEED_CBC_SHA", - 0 }, - { - 154, - "TLS_DHE_RSA_WITH_SEED_CBC_SHA", - 0 }, - { - 155, - "TLS_DH_anon_WITH_SEED_CBC_SHA", - 0 }, - { - 156, - "TLS_RSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 157, - "TLS_RSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 158, - "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 159, - "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 160, - "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 161, - "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 162, - "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", - 0 }, - { - 163, - "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", - 0 }, - { - 164, - "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", - 0 }, - { - 165, - "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", - 0 }, - { - 166, - "TLS_DH_anon_WITH_AES_128_GCM_SHA256", - 0 }, - { - 167, - "TLS_DH_anon_WITH_AES_256_GCM_SHA384", - 0 }, - { - 168, - "TLS_PSK_WITH_AES_128_GCM_SHA256", - 0 }, - { - 169, - "TLS_PSK_WITH_AES_256_GCM_SHA384", - 0 }, - { - 170, - "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", - 0 }, - { - 171, - "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", - 0 }, - { - 172, - "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", - 0 }, - { - 173, - "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", - 0 }, - { - 174, - "TLS_PSK_WITH_AES_128_CBC_SHA256", - 0 }, - { - 175, - "TLS_PSK_WITH_AES_256_CBC_SHA384", - 0 }, - { - 176, - "TLS_PSK_WITH_NULL_SHA256", - 0 }, - { - 177, - "TLS_PSK_WITH_NULL_SHA384", - 0 }, - { - 178, - "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", - 0 }, - { - 179, - "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", - 0 }, - { - 180, - "TLS_DHE_PSK_WITH_NULL_SHA256", - 0 }, - { - 181, - "TLS_DHE_PSK_WITH_NULL_SHA384", - 0 }, - { - 182, - "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", - 0 }, - { - 183, - "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", - 0 }, - { - 184, - "TLS_RSA_PSK_WITH_NULL_SHA256", - 0 }, - { - 185, - "TLS_RSA_PSK_WITH_NULL_SHA384", - 0 }, - { - 186, - "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 187, - "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 188, - "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 189, - "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 190, - "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 191, - "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 192, - "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 193, - "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 194, - "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 195, - "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 196, - "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 197, - "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", - 0 }, - { - 255, - "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", - 0 }, - { - 4865, - "TLS_AES_128_GCM_SHA256", - 0 }, - { - 4866, - "TLS_AES_256_GCM_SHA384", - 0 }, - { - 4867, - "TLS_CHACHA20_POLY1305_SHA256", - 0 }, - { - 4868, - "TLS_AES_128_CCM_SHA256", - 0 }, - { - 4869, - "TLS_AES_128_CCM_8_SHA256", - 0 }, - { - 22016, - "TLS_FALLBACK_SCSV", - 0 }, - { - 49153, - "TLS_ECDH_ECDSA_WITH_NULL_SHA", - 0 }, - { - 49154, - "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", - 0 }, - { - 49155, - "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49156, - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49157, - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49158, - "TLS_ECDHE_ECDSA_WITH_NULL_SHA", - 0 }, - { - 49159, - "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", - 0 }, - { - 49160, - "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49161, - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49162, - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49163, - "TLS_ECDH_RSA_WITH_NULL_SHA", - 0 }, - { - 49164, - "TLS_ECDH_RSA_WITH_RC4_128_SHA", - 0 }, - { - 49165, - "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49166, - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49167, - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49168, - "TLS_ECDHE_RSA_WITH_NULL_SHA", - 0 }, - { - 49169, - "TLS_ECDHE_RSA_WITH_RC4_128_SHA", - 0 }, - { - 49170, - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49171, - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49172, - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49173, - "TLS_ECDH_anon_WITH_NULL_SHA", - 0 }, - { - 49174, - "TLS_ECDH_anon_WITH_RC4_128_SHA", - 0 }, - { - 49175, - "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49176, - "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", - 0 }, - { - 49177, - "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", - 0 }, - { - 49178, - "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49179, - "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49180, - "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49181, - "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49182, - "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 49183, - "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", - 0 }, - { - 49184, - "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49185, - "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 49186, - "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", - 0 }, - { - 49187, - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 49188, - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", - 0 }, - { - 49189, - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 49190, - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", - 0 }, - { - 49191, - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 49192, - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - 0 }, - { - 49193, - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", - 0 }, - { - 49194, - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", - 0 }, - { - 49195, - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 49196, - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 49197, - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 49198, - "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 49199, - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 49200, - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 49201, - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - 0 }, - { - 49202, - "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", - 0 }, - { - 49203, - "TLS_ECDHE_PSK_WITH_RC4_128_SHA", - 0 }, - { - 49204, - "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 49205, - "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", - 0 }, - { - 49206, - "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", - 0 }, - { - 49207, - "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", - 0 }, - { - 49208, - "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", - 0 }, - { - 49209, - "TLS_ECDHE_PSK_WITH_NULL_SHA", - 0 }, - { - 49210, - "TLS_ECDHE_PSK_WITH_NULL_SHA256", - 0 }, - { - 49211, - "TLS_ECDHE_PSK_WITH_NULL_SHA384", - 0 }, - { - 49212, - "TLS_RSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49213, - "TLS_RSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49214, - "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49215, - "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49216, - "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49217, - "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49218, - "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49219, - "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49220, - "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49221, - "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49222, - "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49223, - "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49224, - "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49225, - "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49226, - "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49227, - "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49228, - "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49229, - "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49230, - "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49231, - "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49232, - "TLS_RSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49233, - "TLS_RSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49234, - "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49235, - "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49236, - "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49237, - "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49238, - "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49239, - "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49240, - "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49241, - "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49242, - "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49243, - "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49244, - "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49245, - "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49246, - "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49247, - "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49248, - "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49249, - "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49250, - "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49251, - "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49252, - "TLS_PSK_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49253, - "TLS_PSK_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49254, - "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49255, - "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49256, - "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49257, - "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49258, - "TLS_PSK_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49259, - "TLS_PSK_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49260, - "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49261, - "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49262, - "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", - 0 }, - { - 49263, - "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", - 0 }, - { - 49264, - "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", - 0 }, - { - 49265, - "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", - 0 }, - { - 49266, - "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49267, - "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49268, - "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49269, - "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49270, - "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49271, - "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49272, - "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49273, - "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49274, - "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49275, - "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49276, - "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49277, - "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49278, - "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49279, - "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49280, - "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49281, - "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49282, - "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49283, - "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49284, - "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49285, - "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49286, - "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49287, - "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49288, - "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49289, - "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49290, - "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49291, - "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49292, - "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49293, - "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49294, - "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49295, - "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49296, - "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49297, - "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49298, - "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", - 0 }, - { - 49299, - "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", - 0 }, - { - 49300, - "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49301, - "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49302, - "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49303, - "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49304, - "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49305, - "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49306, - "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", - 0 }, - { - 49307, - "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", - 0 }, - { - 49308, - "TLS_RSA_WITH_AES_128_CCM", - 0 }, - { - 49309, - "TLS_RSA_WITH_AES_256_CCM", - 0 }, - { - 49310, - "TLS_DHE_RSA_WITH_AES_128_CCM", - 0 }, - { - 49311, - "TLS_DHE_RSA_WITH_AES_256_CCM", - 0 }, - { - 49312, - "TLS_RSA_WITH_AES_128_CCM_8", - 0 }, - { - 49313, - "TLS_RSA_WITH_AES_256_CCM_8", - 0 }, - { - 49314, - "TLS_DHE_RSA_WITH_AES_128_CCM_8", - 0 }, - { - 49315, - "TLS_DHE_RSA_WITH_AES_256_CCM_8", - 0 }, - { - 49316, - "TLS_PSK_WITH_AES_128_CCM", - 0 }, - { - 49317, - "TLS_PSK_WITH_AES_256_CCM", - 0 }, - { - 49318, - "TLS_DHE_PSK_WITH_AES_128_CCM", - 0 }, - { - 49319, - "TLS_DHE_PSK_WITH_AES_256_CCM", - 0 }, - { - 49320, - "TLS_PSK_WITH_AES_128_CCM_8", - 0 }, - { - 49321, - "TLS_PSK_WITH_AES_256_CCM_8", - 0 }, - { - 49322, - "TLS_PSK_DHE_WITH_AES_128_CCM_8", - 0 }, - { - 49323, - "TLS_PSK_DHE_WITH_AES_256_CCM_8", - 0 }, - { - 49324, - "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", - 0 }, - { - 49325, - "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", - 0 }, - { - 49326, - "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", - 0 }, - { - 49327, - "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", - 0 }, - { - 52392, - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52393, - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52394, - "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52395, - "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52396, - "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52397, - "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - { - 52398, - "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256", - 0 }, - // DRAFT-IETF-TLS-ECC - { - 71, - "TLS_ECDH_ECDSA_WITH_NULL_SHA", - 0 }, - { - 72, - "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", - 0 }, - { - 73, - "TLS_ECDH_ECDSA_WITH_DES_CBC_SHA", - 0 }, - { - 74, - "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 75, - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 76, - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 75, - "TLS_ECDH_ECDSA_EXPORT_WITH_RC4_40_SHA", - 0 }, - { - 76, - "TLS_ECDH_ECDSA_EXPORT_WITH_RC4_56_SHA", - 0 }, - { - 77, - "TLS_ECDH_RSA_WITH_NULL_SHA", - 0 }, - { - 78, - "TLS_ECDH_RSA_WITH_RC4_128_SHA", - 0 }, - { - 79, - "TLS_ECDH_RSA_WITH_DES_CBC_SHA", - 0 }, - { - 80, - "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 81, - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", - 0 }, - { - 82, - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", - 0 }, - { - 83, - "TLS_ECDH_RSA_EXPORT_WITH_RC4_40_SHA", - 0 }, - { - 84, - "TLS_ECDH_RSA_EXPORT_WITH_RC4_56_SHA", - 0 }, - { - 85, - "TLS_ECDH_anon_NULL_WITH_SHA", - 0 }, - { - 86, - "TLS_ECDH_anon_WITH_RC4_128_SHA", - 0 }, - { - 87, - "TLS_ECDH_anon_WITH_DES_CBC_SHA", - 0 }, - { - 88, - "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", - 0 }, - { - 89, - "TLS_ECDH_anon_EXPORT_WITH_DES40_CBC_SHA", - 0 }, - { - 90, - "TLS_ECDH_anon_EXPORT_WITH_RC4_40_SHA", - 0 }, - // DRAFT-IETF-TLS-56-BIT-CIPHERSUITES - { - 96, - "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5", - 0 }, - { - 97, - "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5", - 0 }, - { - 98, - "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA", - 0 }, - { - 99, - "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", - 0 }, - { - 100, - "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA", - 0 }, - { - 101, - "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", - 0 }, - { - 102, - "TLS_DHE_DSS_WITH_RC4_128_SHA", - 0 }, - // FIPS SSL (Netscape) - { - 65278, - "SSL_RSA_FIPS_WITH_DES_CBC_SHA", - 0 }, - { - 65279, - "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", - 0 }, - // SSL 2.0 - { - 65664, - "SSL2_RC4_128_WITH_MD5", - 0 }, - { - 131200, - "SSL2_RC4_128_EXPORT40_WITH_MD5", - 0 }, - { - 196736, - "SSL2_RC2_CBC_128_CBC_WITH_MD5", - 0 }, - { - 262272, - "SSL2_RC2_128_CBC_EXPORT40_WITH_MD5", - 0 }, - { - 327808, - "SSL2_IDEA_128_CBC_WITH_MD5", - 0 }, - { - 393280, - "SSL2_DES_64_CBC_WITH_MD5", - 0 }, - { - 393536, - "SSL2_DES_64_CBC_WITH_SHA", - 0 }, - { - 458944, - "SSL2_DES_192_EDE3_CBC_WITH_MD5", - 0 }, - { - 459200, - "SSL2_DES_192_EDE3_CBC_WITH_SHA", - 0 }, - { - 524416, - "SSL2_RC4_64_WITH_MD5", - 0 }, - { - 2570, - "GREASE 0x0A0A", - 0 }, - { - 6682, - "GREASE 0x1A1A", - 0 }, - { - 10794, - "GREASE 0x2A2A", - 0 }, - { - 14906, - "GREASE 0x3A3A", - 0 }, - { - 19018, - "GREASE 0x4A4A", - 0 }, - { - 23130, - "GREASE 0x5A5A", - 0 }, - { - 27242, - "GREASE 0x6A6A", - 0 }, - { - 31354, - "GREASE 0x7A7A", - 0 }, - { - 35466, - "GREASE 0x8A8A", - 0 }, - { - 39578, - "GREASE 0x9A9A", - 0 }, - { - 43690, - "GREASE 0xAAAA", - 0 }, - { - 47802, - "GREASE 0xBABA", - 0 }, - { - 51914, - "GREASE 0xCACA", - 0 }, - { - 56026, - "GREASE 0xDADA", - 0 }, - { - 60138, - "GREASE 0xEAEA", - 0 }, - { - 64250, - "GREASE 0xFAFA", - 0 }, -{-1} -}; +decoder HandshakeType_decoder[] = { + {0, "HelloRequest", decode_HandshakeType_HelloRequest}, + {1, "ClientHello", decode_HandshakeType_ClientHello}, + {2, "ServerHello", decode_HandshakeType_ServerHello}, + {4, "SessionTicket", decode_HandshakeType_SessionTicket}, + {8, "EncryptedExtensions", decode_HandshakeType_EncryptedExtensions}, + {11, "Certificate", decode_HandshakeType_Certificate}, + {12, "ServerKeyExchange", decode_HandshakeType_ServerKeyExchange}, + {13, "CertificateRequest", decode_HandshakeType_CertificateRequest}, + {14, "ServerHelloDone", decode_HandshakeType_ServerHelloDone}, + {15, "CertificateVerify", decode_HandshakeType_CertificateVerify}, + {16, "ClientKeyExchange", decode_HandshakeType_ClientKeyExchange}, + {20, "Finished", decode_HandshakeType_Finished}, + {24, "KeyUpdate", decode_HandshakeType_KeyUpdate}, + {-1}}; -static int -decode_AlertLevel_warning (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "alert_level", json_object_new_string("warning")); - return(0); - } -static int -decode_AlertLevel_fatal (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - struct json_object *jobj; - jobj = ssl->cur_json_st; - json_object_object_add(jobj, "alert_level", json_object_new_string("fatal")); - return(0); - } -decoder AlertLevel_decoder[]={ - { - 1, - "warning", - decode_AlertLevel_warning - }, - { - 2, - "fatal", - decode_AlertLevel_fatal - }, -{-1} -}; +decoder cipher_suite_decoder[] = { + // https://www.iana.org/assignments/tls-parameters/tls-parameters.txt + {0, "TLS_NULL_WITH_NULL_NULL", 0}, + {1, "TLS_RSA_WITH_NULL_MD5", 0}, + {2, "TLS_RSA_WITH_NULL_SHA", 0}, + {3, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", 0}, + {4, "TLS_RSA_WITH_RC4_128_MD5", 0}, + {5, "TLS_RSA_WITH_RC4_128_SHA", 0}, + {6, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0}, + {7, "TLS_RSA_WITH_IDEA_CBC_SHA", 0}, + {8, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", 0}, + {9, "TLS_RSA_WITH_DES_CBC_SHA", 0}, + {10, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {11, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0}, + {12, "TLS_DH_DSS_WITH_DES_CBC_SHA", 0}, + {13, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0}, + {14, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0}, + {15, "TLS_DH_RSA_WITH_DES_CBC_SHA", 0}, + {16, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {17, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0}, + {18, "TLS_DHE_DSS_WITH_DES_CBC_SHA", 0}, + {19, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", 0}, + {20, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0}, + {21, "TLS_DHE_RSA_WITH_DES_CBC_SHA", 0}, + {22, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {23, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", 0}, + {24, "TLS_DH_anon_WITH_RC4_128_MD5", 0}, + {25, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0}, + {26, "TLS_DH_anon_WITH_DES_CBC_SHA", 0}, + {27, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", 0}, + {30, "TLS_KRB5_WITH_DES_CBC_SHA", 0}, + {31, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA", 0}, + {32, "TLS_KRB5_WITH_RC4_128_SHA", 0}, + {33, "TLS_KRB5_WITH_IDEA_CBC_SHA", 0}, + {34, "TLS_KRB5_WITH_DES_CBC_MD5", 0}, + {35, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5", 0}, + {36, "TLS_KRB5_WITH_RC4_128_MD5", 0}, + {37, "TLS_KRB5_WITH_IDEA_CBC_MD5", 0}, + {38, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0}, + {39, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0}, + {40, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 0}, + {41, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0}, + {42, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0}, + {43, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0}, + {44, "TLS_PSK_WITH_NULL_SHA", 0}, + {45, "TLS_DHE_PSK_WITH_NULL_SHA", 0}, + {46, "TLS_RSA_PSK_WITH_NULL_SHA", 0}, + {47, "TLS_RSA_WITH_AES_128_CBC_SHA", 0}, + {48, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", 0}, + {49, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0}, + {50, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 0}, + {51, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 0}, + {52, "TLS_DH_anon_WITH_AES_128_CBC_SHA", 0}, + {53, "TLS_RSA_WITH_AES_256_CBC_SHA", 0}, + {54, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0}, + {55, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0}, + {56, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", 0}, + {57, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 0}, + {58, "TLS_DH_anon_WITH_AES_256_CBC_SHA", 0}, + {59, "TLS_RSA_WITH_NULL_SHA256", 0}, + {60, "TLS_RSA_WITH_AES_128_CBC_SHA256", 0}, + {61, "TLS_RSA_WITH_AES_256_CBC_SHA256", 0}, + {62, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0}, + {63, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0}, + {64, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0}, + {65, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 0}, + {66, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 0}, + {67, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 0}, + {68, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 0}, + {69, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 0}, + {70, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 0}, + {103, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0}, + {104, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0}, + {105, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0}, + {106, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0}, + {107, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0}, + {108, "TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0}, + {109, "TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0}, + {132, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 0}, + {133, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 0}, + {134, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 0}, + {135, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 0}, + {136, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 0}, + {137, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 0}, + {138, "TLS_PSK_WITH_RC4_128_SHA", 0}, + {139, "TLS_PSK_WITH_3DES_EDE_CBC_SHA", 0}, + {140, "TLS_PSK_WITH_AES_128_CBC_SHA", 0}, + {141, "TLS_PSK_WITH_AES_256_CBC_SHA", 0}, + {142, "TLS_DHE_PSK_WITH_RC4_128_SHA", 0}, + {143, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 0}, + {144, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 0}, + {145, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 0}, + {146, "TLS_RSA_PSK_WITH_RC4_128_SHA", 0}, + {147, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 0}, + {148, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 0}, + {149, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 0}, + {150, "TLS_RSA_WITH_SEED_CBC_SHA", 0}, + {151, "TLS_DH_DSS_WITH_SEED_CBC_SHA", 0}, + {152, "TLS_DH_RSA_WITH_SEED_CBC_SHA", 0}, + {153, "TLS_DHE_DSS_WITH_SEED_CBC_SHA", 0}, + {154, "TLS_DHE_RSA_WITH_SEED_CBC_SHA", 0}, + {155, "TLS_DH_anon_WITH_SEED_CBC_SHA", 0}, + {156, "TLS_RSA_WITH_AES_128_GCM_SHA256", 0}, + {157, "TLS_RSA_WITH_AES_256_GCM_SHA384", 0}, + {158, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0}, + {159, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0}, + {160, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0}, + {161, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0}, + {162, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0}, + {163, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0}, + {164, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0}, + {165, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0}, + {166, "TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0}, + {167, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0}, + {168, "TLS_PSK_WITH_AES_128_GCM_SHA256", 0}, + {169, "TLS_PSK_WITH_AES_256_GCM_SHA384", 0}, + {170, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 0}, + {171, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 0}, + {172, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 0}, + {173, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 0}, + {174, "TLS_PSK_WITH_AES_128_CBC_SHA256", 0}, + {175, "TLS_PSK_WITH_AES_256_CBC_SHA384", 0}, + {176, "TLS_PSK_WITH_NULL_SHA256", 0}, + {177, "TLS_PSK_WITH_NULL_SHA384", 0}, + {178, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 0}, + {179, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 0}, + {180, "TLS_DHE_PSK_WITH_NULL_SHA256", 0}, + {181, "TLS_DHE_PSK_WITH_NULL_SHA384", 0}, + {182, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 0}, + {183, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 0}, + {184, "TLS_RSA_PSK_WITH_NULL_SHA256", 0}, + {185, "TLS_RSA_PSK_WITH_NULL_SHA384", 0}, + {186, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {187, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {188, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {189, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {190, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {191, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {192, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {193, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {194, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {195, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {196, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {197, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 0}, + {255, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", 0}, + {4865, "TLS_AES_128_GCM_SHA256", 0}, + {4866, "TLS_AES_256_GCM_SHA384", 0}, + {4867, "TLS_CHACHA20_POLY1305_SHA256", 0}, + {4868, "TLS_AES_128_CCM_SHA256", 0}, + {4869, "TLS_AES_128_CCM_8_SHA256", 0}, + {22016, "TLS_FALLBACK_SCSV", 0}, + {49153, "TLS_ECDH_ECDSA_WITH_NULL_SHA", 0}, + {49154, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 0}, + {49155, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 0}, + {49156, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 0}, + {49157, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 0}, + {49158, "TLS_ECDHE_ECDSA_WITH_NULL_SHA", 0}, + {49159, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 0}, + {49160, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", 0}, + {49161, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 0}, + {49162, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 0}, + {49163, "TLS_ECDH_RSA_WITH_NULL_SHA", 0}, + {49164, "TLS_ECDH_RSA_WITH_RC4_128_SHA", 0}, + {49165, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {49166, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 0}, + {49167, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 0}, + {49168, "TLS_ECDHE_RSA_WITH_NULL_SHA", 0}, + {49169, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 0}, + {49170, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {49171, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 0}, + {49172, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 0}, + {49173, "TLS_ECDH_anon_WITH_NULL_SHA", 0}, + {49174, "TLS_ECDH_anon_WITH_RC4_128_SHA", 0}, + {49175, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 0}, + {49176, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", 0}, + {49177, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", 0}, + {49178, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 0}, + {49179, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {49180, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 0}, + {49181, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 0}, + {49182, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 0}, + {49183, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 0}, + {49184, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 0}, + {49185, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0}, + {49186, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0}, + {49187, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0}, + {49188, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0}, + {49189, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0}, + {49190, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0}, + {49191, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0}, + {49192, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0}, + {49193, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0}, + {49194, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0}, + {49195, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0}, + {49196, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0}, + {49197, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0}, + {49198, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0}, + {49199, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0}, + {49200, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0}, + {49201, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0}, + {49202, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0}, + {49203, "TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0}, + {49204, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0}, + {49205, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0}, + {49206, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 0}, + {49207, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 0}, + {49208, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 0}, + {49209, "TLS_ECDHE_PSK_WITH_NULL_SHA", 0}, + {49210, "TLS_ECDHE_PSK_WITH_NULL_SHA256", 0}, + {49211, "TLS_ECDHE_PSK_WITH_NULL_SHA384", 0}, + {49212, "TLS_RSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49213, "TLS_RSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49214, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256", 0}, + {49215, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384", 0}, + {49216, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49217, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49218, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256", 0}, + {49219, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384", 0}, + {49220, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49221, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49222, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256", 0}, + {49223, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384", 0}, + {49224, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49225, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49226, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49227, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49228, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49229, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49230, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256", 0}, + {49231, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384", 0}, + {49232, "TLS_RSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49233, "TLS_RSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49234, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49235, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49236, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49237, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49238, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256", 0}, + {49239, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384", 0}, + {49240, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256", 0}, + {49241, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384", 0}, + {49242, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256", 0}, + {49243, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384", 0}, + {49244, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49245, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49246, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49247, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49248, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49249, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49250, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256", 0}, + {49251, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384", 0}, + {49252, "TLS_PSK_WITH_ARIA_128_CBC_SHA256", 0}, + {49253, "TLS_PSK_WITH_ARIA_256_CBC_SHA384", 0}, + {49254, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256", 0}, + {49255, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384", 0}, + {49256, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256", 0}, + {49257, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384", 0}, + {49258, "TLS_PSK_WITH_ARIA_128_GCM_SHA256", 0}, + {49259, "TLS_PSK_WITH_ARIA_256_GCM_SHA384", 0}, + {49260, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256", 0}, + {49261, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384", 0}, + {49262, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256", 0}, + {49263, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384", 0}, + {49264, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256", 0}, + {49265, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384", 0}, + {49266, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49267, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49268, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49269, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49270, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49271, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49272, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49273, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49274, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49275, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49276, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49277, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49278, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49279, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49280, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49281, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49282, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49283, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49284, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49285, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49286, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49287, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49288, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49289, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49290, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49291, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49292, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49293, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49294, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49295, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49296, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49297, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49298, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256", 0}, + {49299, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384", 0}, + {49300, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49301, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49302, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49303, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49304, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49305, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49306, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256", 0}, + {49307, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384", 0}, + {49308, "TLS_RSA_WITH_AES_128_CCM", 0}, + {49309, "TLS_RSA_WITH_AES_256_CCM", 0}, + {49310, "TLS_DHE_RSA_WITH_AES_128_CCM", 0}, + {49311, "TLS_DHE_RSA_WITH_AES_256_CCM", 0}, + {49312, "TLS_RSA_WITH_AES_128_CCM_8", 0}, + {49313, "TLS_RSA_WITH_AES_256_CCM_8", 0}, + {49314, "TLS_DHE_RSA_WITH_AES_128_CCM_8", 0}, + {49315, "TLS_DHE_RSA_WITH_AES_256_CCM_8", 0}, + {49316, "TLS_PSK_WITH_AES_128_CCM", 0}, + {49317, "TLS_PSK_WITH_AES_256_CCM", 0}, + {49318, "TLS_DHE_PSK_WITH_AES_128_CCM", 0}, + {49319, "TLS_DHE_PSK_WITH_AES_256_CCM", 0}, + {49320, "TLS_PSK_WITH_AES_128_CCM_8", 0}, + {49321, "TLS_PSK_WITH_AES_256_CCM_8", 0}, + {49322, "TLS_PSK_DHE_WITH_AES_128_CCM_8", 0}, + {49323, "TLS_PSK_DHE_WITH_AES_256_CCM_8", 0}, + {49324, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM", 0}, + {49325, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM", 0}, + {49326, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", 0}, + {49327, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8", 0}, + {52392, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52393, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52394, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52395, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52396, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52397, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256", 0}, + {52398, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256", 0}, + // DRAFT-IETF-TLS-ECC + {71, "TLS_ECDH_ECDSA_WITH_NULL_SHA", 0}, + {72, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", 0}, + {73, "TLS_ECDH_ECDSA_WITH_DES_CBC_SHA", 0}, + {74, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", 0}, + {75, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", 0}, + {76, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", 0}, + {75, "TLS_ECDH_ECDSA_EXPORT_WITH_RC4_40_SHA", 0}, + {76, "TLS_ECDH_ECDSA_EXPORT_WITH_RC4_56_SHA", 0}, + {77, "TLS_ECDH_RSA_WITH_NULL_SHA", 0}, + {78, "TLS_ECDH_RSA_WITH_RC4_128_SHA", 0}, + {79, "TLS_ECDH_RSA_WITH_DES_CBC_SHA", 0}, + {80, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", 0}, + {81, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", 0}, + {82, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", 0}, + {83, "TLS_ECDH_RSA_EXPORT_WITH_RC4_40_SHA", 0}, + {84, "TLS_ECDH_RSA_EXPORT_WITH_RC4_56_SHA", 0}, + {85, "TLS_ECDH_anon_NULL_WITH_SHA", 0}, + {86, "TLS_ECDH_anon_WITH_RC4_128_SHA", 0}, + {87, "TLS_ECDH_anon_WITH_DES_CBC_SHA", 0}, + {88, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", 0}, + {89, "TLS_ECDH_anon_EXPORT_WITH_DES40_CBC_SHA", 0}, + {90, "TLS_ECDH_anon_EXPORT_WITH_RC4_40_SHA", 0}, + // DRAFT-IETF-TLS-56-BIT-CIPHERSUITES + {96, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5", 0}, + {97, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5", 0}, + {98, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0}, + {99, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0}, + {100, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA", 0}, + {101, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0}, + {102, "TLS_DHE_DSS_WITH_RC4_128_SHA", 0}, + // FIPS SSL (Netscape) + {65278, "SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0}, + {65279, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0}, + // SSL 2.0 + {65664, "SSL2_RC4_128_WITH_MD5", 0}, + {131200, "SSL2_RC4_128_EXPORT40_WITH_MD5", 0}, + {196736, "SSL2_RC2_CBC_128_CBC_WITH_MD5", 0}, + {262272, "SSL2_RC2_128_CBC_EXPORT40_WITH_MD5", 0}, + {327808, "SSL2_IDEA_128_CBC_WITH_MD5", 0}, + {393280, "SSL2_DES_64_CBC_WITH_MD5", 0}, + {393536, "SSL2_DES_64_CBC_WITH_SHA", 0}, + {458944, "SSL2_DES_192_EDE3_CBC_WITH_MD5", 0}, + {459200, "SSL2_DES_192_EDE3_CBC_WITH_SHA", 0}, + {524416, "SSL2_RC4_64_WITH_MD5", 0}, + {2570, "GREASE 0x0A0A", 0}, + {6682, "GREASE 0x1A1A", 0}, + {10794, "GREASE 0x2A2A", 0}, + {14906, "GREASE 0x3A3A", 0}, + {19018, "GREASE 0x4A4A", 0}, + {23130, "GREASE 0x5A5A", 0}, + {27242, "GREASE 0x6A6A", 0}, + {31354, "GREASE 0x7A7A", 0}, + {35466, "GREASE 0x8A8A", 0}, + {39578, "GREASE 0x9A9A", 0}, + {43690, "GREASE 0xAAAA", 0}, + {47802, "GREASE 0xBABA", 0}, + {51914, "GREASE 0xCACA", 0}, + {56026, "GREASE 0xDADA", 0}, + {60138, "GREASE 0xEAEA", 0}, + {64250, "GREASE 0xFAFA", 0}, + {-1}}; -static int -decode_AlertDescription_close_notify (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_unexpected_message (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_bad_record_mac (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_decryption_failed (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_record_overflow (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_decompression_failure (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_handshake_failure (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_bad_certificate (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_unsupported_certificate (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_certificate_revoked (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_certificate_expired (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_certificate_unknown (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_illegal_parameter (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_unknown_ca (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_access_denied (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_decode_error (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_decrypt_error (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_export_restriction (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_protocol_version (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_insufficient_security (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_internal_error (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_user_canceled (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_AlertDescription_no_renegotiation (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -decoder AlertDescription_decoder[]={ - { - 0, - "close_notify", - decode_AlertDescription_close_notify - }, - { - 10, - "unexpected_message", - decode_AlertDescription_unexpected_message - }, - { - 20, - "bad_record_mac", - decode_AlertDescription_bad_record_mac - }, - { - 21, - "decryption_failed", - decode_AlertDescription_decryption_failed - }, - { - 22, - "record_overflow", - decode_AlertDescription_record_overflow - }, - { - 30, - "decompression_failure", - decode_AlertDescription_decompression_failure - }, - { - 40, - "handshake_failure", - decode_AlertDescription_handshake_failure - }, - { - 42, - "bad_certificate", - decode_AlertDescription_bad_certificate - }, - { - 43, - "unsupported_certificate", - decode_AlertDescription_unsupported_certificate - }, - { - 44, - "certificate_revoked", - decode_AlertDescription_certificate_revoked - }, - { - 45, - "certificate_expired", - decode_AlertDescription_certificate_expired - }, - { - 46, - "certificate_unknown", - decode_AlertDescription_certificate_unknown - }, - { - 47, - "illegal_parameter", - decode_AlertDescription_illegal_parameter - }, - { - 48, - "unknown_ca", - decode_AlertDescription_unknown_ca - }, - { - 49, - "access_denied", - decode_AlertDescription_access_denied - }, - { - 50, - "decode_error", - decode_AlertDescription_decode_error - }, - { - 51, - "decrypt_error", - decode_AlertDescription_decrypt_error - }, - { - 60, - "export_restriction", - decode_AlertDescription_export_restriction - }, - { - 70, - "protocol_version", - decode_AlertDescription_protocol_version - }, - { - 71, - "insufficient_security", - decode_AlertDescription_insufficient_security - }, - { - 80, - "internal_error", - decode_AlertDescription_internal_error - }, - { - 90, - "user_canceled", - decode_AlertDescription_user_canceled - }, - { - 100, - "no_renegotiation", - decode_AlertDescription_no_renegotiation - }, -{-1} -}; +static int decode_AlertLevel_warning(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "alert_level", + json_object_new_string("warning")); + return (0); +} +static int decode_AlertLevel_fatal(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + json_object_object_add(jobj, "alert_level", json_object_new_string("fatal")); + return (0); +} +decoder AlertLevel_decoder[] = {{1, "warning", decode_AlertLevel_warning}, + {2, "fatal", decode_AlertLevel_fatal}, + {-1}}; -decoder compression_method_decoder[]={ - { - 0, - "NULL", - 0 }, -{-1} -}; +static int decode_AlertDescription_close_notify(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_unexpected_message(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_bad_record_mac(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_decryption_failed(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_record_overflow(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_decompression_failure(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_handshake_failure(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_bad_certificate(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_unsupported_certificate(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_certificate_revoked(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_certificate_expired(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_certificate_unknown(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_illegal_parameter(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_unknown_ca(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_access_denied(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_decode_error(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_decrypt_error(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_export_restriction(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_protocol_version(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_insufficient_security(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_internal_error(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_user_canceled(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_AlertDescription_no_renegotiation(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +decoder AlertDescription_decoder[] = { + {0, "close_notify", decode_AlertDescription_close_notify}, + {10, "unexpected_message", decode_AlertDescription_unexpected_message}, + {20, "bad_record_mac", decode_AlertDescription_bad_record_mac}, + {21, "decryption_failed", decode_AlertDescription_decryption_failed}, + {22, "record_overflow", decode_AlertDescription_record_overflow}, + {30, "decompression_failure", + decode_AlertDescription_decompression_failure}, + {40, "handshake_failure", decode_AlertDescription_handshake_failure}, + {42, "bad_certificate", decode_AlertDescription_bad_certificate}, + {43, "unsupported_certificate", + decode_AlertDescription_unsupported_certificate}, + {44, "certificate_revoked", decode_AlertDescription_certificate_revoked}, + {45, "certificate_expired", decode_AlertDescription_certificate_expired}, + {46, "certificate_unknown", decode_AlertDescription_certificate_unknown}, + {47, "illegal_parameter", decode_AlertDescription_illegal_parameter}, + {48, "unknown_ca", decode_AlertDescription_unknown_ca}, + {49, "access_denied", decode_AlertDescription_access_denied}, + {50, "decode_error", decode_AlertDescription_decode_error}, + {51, "decrypt_error", decode_AlertDescription_decrypt_error}, + {60, "export_restriction", decode_AlertDescription_export_restriction}, + {70, "protocol_version", decode_AlertDescription_protocol_version}, + {71, "insufficient_security", + decode_AlertDescription_insufficient_security}, + {80, "internal_error", decode_AlertDescription_internal_error}, + {90, "user_canceled", decode_AlertDescription_user_canceled}, + {100, "no_renegotiation", decode_AlertDescription_no_renegotiation}, + {-1}}; -static int -decode_client_certificate_type_rsa_sign (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_client_certificate_type_dss_sign (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_client_certificate_type_rsa_fixed_dh (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -static int -decode_client_certificate_type_dss_fixed_dh (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - return(0); - } -decoder client_certificate_type_decoder[]={ - { - 1, - "rsa_sign", - decode_client_certificate_type_rsa_sign - }, - { - 2, - "dss_sign", - decode_client_certificate_type_dss_sign - }, - { - 3, - "rsa_fixed_dh", - decode_client_certificate_type_rsa_fixed_dh - }, - { - 4, - "dss_fixed_dh", - decode_client_certificate_type_dss_fixed_dh - }, -{-1} -}; +decoder compression_method_decoder[] = {{0, "NULL", 0}, {-1}}; -static int -decode_extension_server_name (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - UINT4 t,l; - int r,p; +static int decode_client_certificate_type_rsa_sign(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_client_certificate_type_dss_sign(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_client_certificate_type_rsa_fixed_dh(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +static int decode_client_certificate_type_dss_fixed_dh(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + return (0); +} +decoder client_certificate_type_decoder[] = { + {1, "rsa_sign", decode_client_certificate_type_rsa_sign}, + {2, "dss_sign", decode_client_certificate_type_dss_sign}, + {3, "rsa_fixed_dh", decode_client_certificate_type_rsa_fixed_dh}, + {4, "dss_fixed_dh", decode_client_certificate_type_dss_fixed_dh}, + {-1}}; - extern decoder server_name_type_decoder[]; +static int decode_extension_server_name(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + UINT4 t, l; + int r, p; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); + extern decoder server_name_type_decoder[]; - if(dir==DIR_I2R){ - SSL_DECODE_UINT16(ssl,"server name list length",0,data,&l); - LF; - while(l) { - p=data->len; - SSL_DECODE_UINT8(ssl, "server name type", 0, data, &t); + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); - if (ssl_decode_switch(ssl,server_name_type_decoder,t,dir,seg,data) == R_NOT_FOUND) { - decode_server_name(ssl,dir,seg,data); - P_(P_RH){ - explain(ssl, "Server Name type: %u not yet implemented in ssldump\n", t); - } - continue; - } - l-=(p-data->len); + if(dir == DIR_I2R) { + SSL_DECODE_UINT16(ssl, "server name list length", 0, data, &l); + LF; + while(l) { + p = data->len; + SSL_DECODE_UINT8(ssl, "server name type", 0, data, &t); + + if(ssl_decode_switch(ssl, server_name_type_decoder, t, dir, seg, data) == + R_NOT_FOUND) { + decode_server_name(ssl, dir, seg, data); + P_(P_RH) { + explain(ssl, "Server Name type: %u not yet implemented in ssldump\n", + t); + } + continue; } + l -= (p - data->len); } - else{ - data->len-=l; - data->data+=l; - } - return(0); + } else { + data->len -= l; + data->data += l; } -static int -decode_extension_encrypt_then_mac (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r,*etm; - UINT4 l; + return (0); +} +static int decode_extension_encrypt_then_mac(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r, *etm; + UINT4 l; - etm=&ssl->extensions->encrypt_then_mac; + etm = &ssl->extensions->encrypt_then_mac; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); - data->len-=l; - data->data+=l; + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); + data->len -= l; + data->data += l; - dir==DIR_I2R?*etm=1:++*etm; - return(0); - } -static int -decode_extension_extended_master_secret (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r,*ems; - UINT4 l; + dir == DIR_I2R ? *etm = 1 : ++*etm; + return (0); +} +static int decode_extension_extended_master_secret(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r, *ems; + UINT4 l; - ems=&ssl->extensions->extended_master_secret; + ems = &ssl->extensions->extended_master_secret; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); - data->len-=l; - data->data+=l; + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); + data->len -= l; + data->data += l; - dir==DIR_I2R?*ems=1:++*ems; - return(0); - } -static int -decode_extension (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r; - UINT4 l; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); - data->len-=l; - data->data+=l; - return(0); - } + dir == DIR_I2R ? *ems = 1 : ++*ems; + return (0); +} +static int decode_extension(ssl_obj *ssl, int dir, segment *seg, Data *data) { + int r; + UINT4 l; + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); + data->len -= l; + data->data += l; + return (0); +} decoder supported_groups_decoder[] = { - {0x0017,"secp256r1",0}, - {0x0018,"secp384r1",0}, - {0x0019,"secp521r1",0}, - {0x001d,"x25519",0}, - {0x001e,"x448",0}, - {0x0100,"ffdhe2048",0}, - {0x0101,"ffdhe3072",0}, - {0x0102,"ffdhe4096",0}, - {0x0103,"ffdhe6144",0}, - {0x0104,"ffdhe8192",0}, + {0x0017, "secp256r1", 0}, {0x0018, "secp384r1", 0}, + {0x0019, "secp521r1", 0}, {0x001d, "x25519", 0}, + {0x001e, "x448", 0}, {0x0100, "ffdhe2048", 0}, + {0x0101, "ffdhe3072", 0}, {0x0102, "ffdhe4096", 0}, + {0x0103, "ffdhe6144", 0}, {0x0104, "ffdhe8192", 0}, }; // Extension #10 supported_groups (renamed from "elliptic_curves") -static int -decode_extension_supported_groups (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r,p; - UINT4 l,g; - char *ja3_ec_str = NULL; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); +static int decode_extension_supported_groups(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r, p; + UINT4 l, g; + char *ja3_ec_str = NULL; + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); - if(dir==DIR_I2R){ - SSL_DECODE_UINT16(ssl,"supported_groups list length",0,data,&l); + if(dir == DIR_I2R) { + SSL_DECODE_UINT16(ssl, "supported_groups list length", 0, data, &l); + LF; + while(l) { + p = data->len; + SSL_DECODE_ENUM(ssl, "supported group", 2, supported_groups_decoder, + SSL_PRINT_ALL, data, &g); LF; - while(l) { - p=data->len; - SSL_DECODE_ENUM(ssl,"supported group",2,supported_groups_decoder,SSL_PRINT_ALL,data,&g); - LF; - if(!ja3_ec_str) - ja3_ec_str = calloc(7, 1); - else - ja3_ec_str = realloc(ja3_ec_str, strlen(ja3_ec_str) + 7); - snprintf(ja3_ec_str + strlen(ja3_ec_str), 7, "%u-", g); - l-=(p-data->len); - } - if(ja3_ec_str && ja3_ec_str[strlen(ja3_ec_str) - 1] == '-') - ja3_ec_str[strlen(ja3_ec_str) - 1] = '\0'; + if(!ja3_ec_str) + ja3_ec_str = calloc(7, 1); + else + ja3_ec_str = realloc(ja3_ec_str, strlen(ja3_ec_str) + 7); + snprintf(ja3_ec_str + strlen(ja3_ec_str), 7, "%u-", g); + l -= (p - data->len); } - else{ - data->len-=l; - data->data+=l; - } - ssl->cur_ja3_ec_str = ja3_ec_str; - return(0); + if(ja3_ec_str && ja3_ec_str[strlen(ja3_ec_str) - 1] == '-') + ja3_ec_str[strlen(ja3_ec_str) - 1] = '\0'; + } else { + data->len -= l; + data->data += l; } + ssl->cur_ja3_ec_str = ja3_ec_str; + return (0); +} -decoder ec_point_formats_decoder[] = { - {0,"uncompressed",0,}, - {1,"ansiX962_compressed_prime",0,}, - {2,"ansiX962_compressed_char2",0,} -}; +decoder ec_point_formats_decoder[] = {{ + 0, + "uncompressed", + 0, + }, + { + 1, + "ansiX962_compressed_prime", + 0, + }, + { + 2, + "ansiX962_compressed_char2", + 0, + }}; // Extension #11 ec_point_formats -static int -decode_extension_ec_point_formats (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r,p; - UINT4 l,f; - char *ja3_ecp_str = NULL; - SSL_DECODE_UINT16(ssl,"extension length",0,data,&l); +static int decode_extension_ec_point_formats(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r, p; + UINT4 l, f; + char *ja3_ecp_str = NULL; + SSL_DECODE_UINT16(ssl, "extension length", 0, data, &l); - if(dir==DIR_I2R){ - SSL_DECODE_UINT8(ssl,"ec_point_formats list length",0,data,&l); + if(dir == DIR_I2R) { + SSL_DECODE_UINT8(ssl, "ec_point_formats list length", 0, data, &l); + LF; + while(l) { + p = data->len; + SSL_DECODE_ENUM(ssl, "ec point format", 1, ec_point_formats_decoder, + SSL_PRINT_ALL, data, &f); LF; - while(l) { - p=data->len; - SSL_DECODE_ENUM(ssl,"ec point format",1,ec_point_formats_decoder,SSL_PRINT_ALL,data, &f); - LF; - if(!ja3_ecp_str) - ja3_ecp_str = calloc(5, 1); - else - ja3_ecp_str = realloc(ja3_ecp_str, strlen(ja3_ecp_str) + 5); - snprintf(ja3_ecp_str + strlen(ja3_ecp_str), 5, "%u-", f); - l-=(p-data->len); - } - if(ja3_ecp_str && ja3_ecp_str[strlen(ja3_ecp_str) - 1] == '-') - ja3_ecp_str[strlen(ja3_ecp_str) - 1] = '\0'; + if(!ja3_ecp_str) + ja3_ecp_str = calloc(5, 1); + else + ja3_ecp_str = realloc(ja3_ecp_str, strlen(ja3_ecp_str) + 5); + snprintf(ja3_ecp_str + strlen(ja3_ecp_str), 5, "%u-", f); + l -= (p - data->len); } - else{ - data->len-=l; - data->data+=l; - } - - ssl->cur_ja3_ecp_str = ja3_ecp_str; - return(0); + if(ja3_ecp_str && ja3_ecp_str[strlen(ja3_ecp_str) - 1] == '-') + ja3_ecp_str[strlen(ja3_ecp_str) - 1] = '\0'; + } else { + data->len -= l; + data->data += l; } -static int -decode_extension_supported_versions (ssl_obj *ssl, int dir, segment *seg, Data *data) -{ - int r; - UINT4 len, version; - SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); - LF; - if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "supported versions length", 0, data, &len);//client sends extension<..> - while (len) { - SSL_DECODE_UINT16(ssl, "supported version", 0, data, &version); - explain(ssl, "version: %u.%u", (version>>8)&0xff, version&0xff); - len -= 2; - if (len) printf("\n"); - } - if (dir == DIR_R2I) ssl->version = version; // Server sets the tls version + ssl->cur_ja3_ecp_str = ja3_ecp_str; + return (0); } -decoder tls13_certificate_types[] = { - {0,"x509",0}, - {1,"openpgp",0}, - {2,"raw public key",0}, - {3,"1609 dot 2",0} -}; -static int -decode_extension_client_certificate_type (ssl_obj *ssl, int dir, segment *seg, Data *data) -{ - int r; - UINT4 len, certificate_type; - SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); - LF; - if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "client certificates length", 0, data, &len);//client sends certificates<..> - while (len) { - SSL_DECODE_ENUM(ssl,"certificate type",1,tls13_certificate_types,SSL_PRINT_ALL,data, &certificate_type); - len -= 1; - data += 1; - if (len) printf("\n"); - } - if (dir == DIR_R2I) ssl->extensions->client_certificate_type = certificate_type; // Server sets the client_certificate_type +static int decode_extension_supported_versions(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 len, version; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if(dir == DIR_I2R) + SSL_DECODE_UINT8(ssl, "supported versions length", 0, data, + &len); // client sends extension<..> + while(len) { + SSL_DECODE_UINT16(ssl, "supported version", 0, data, &version); + explain(ssl, "version: %u.%u", (version >> 8) & 0xff, version & 0xff); + len -= 2; + if(len) + printf("\n"); + } + if(dir == DIR_R2I) + ssl->version = version; // Server sets the tls version } -static int -decode_extension_server_certificate_type (ssl_obj *ssl, int dir, segment *seg, Data *data) -{ - int r; - UINT4 len, certificate_type; - SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); - LF; - if (dir == DIR_I2R) SSL_DECODE_UINT8(ssl, "server certificates length", 0, data, &len);//client sends certificates<..> - while (len) { - SSL_DECODE_ENUM(ssl,"certificate type",1,tls13_certificate_types,SSL_PRINT_ALL,data, &certificate_type); - len -= 1; - data += 1; - if (len) printf("\n"); - } - if (dir == DIR_R2I) ssl->extensions->server_certificate_type = certificate_type; // Server sets the server_certificate_type +decoder tls13_certificate_types[] = {{0, "x509", 0}, + {1, "openpgp", 0}, + {2, "raw public key", 0}, + {3, "1609 dot 2", 0}}; +static int decode_extension_client_certificate_type(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 len, certificate_type; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if(dir == DIR_I2R) + SSL_DECODE_UINT8(ssl, "client certificates length", 0, data, + &len); // client sends certificates<..> + while(len) { + SSL_DECODE_ENUM(ssl, "certificate type", 1, tls13_certificate_types, + SSL_PRINT_ALL, data, &certificate_type); + len -= 1; + data += 1; + if(len) + printf("\n"); + } + if(dir == DIR_R2I) + ssl->extensions->client_certificate_type = + certificate_type; // Server sets the client_certificate_type +} + +static int decode_extension_server_certificate_type(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 len, certificate_type; + SSL_DECODE_UINT16(ssl, "extensions length", 0, data, &len); + LF; + if(dir == DIR_I2R) + SSL_DECODE_UINT8(ssl, "server certificates length", 0, data, + &len); // client sends certificates<..> + while(len) { + SSL_DECODE_ENUM(ssl, "certificate type", 1, tls13_certificate_types, + SSL_PRINT_ALL, data, &certificate_type); + len -= 1; + data += 1; + if(len) + printf("\n"); + } + if(dir == DIR_R2I) + ssl->extensions->server_certificate_type = + certificate_type; // Server sets the server_certificate_type } decoder extension_decoder[] = { - { - 0, - "server_name", - decode_extension_server_name, - }, - { - 1, - "max_fragment_length", - decode_extension - }, - { - 2, - "client_certificate_url", - decode_extension - }, - { - 3, - "trusted_ca_keys", - decode_extension - }, - { - 4, - "truncated_hmac", - decode_extension - }, - { - 5, - "status_request", - decode_extension - }, - { - 6, - "user_mapping", - decode_extension - }, - { - 7, - "client_authz", - decode_extension - }, - { - 8, - "server_authz", - decode_extension - }, - { - 9, - "cert_type", - decode_extension - }, - { - 10, - "supported_groups", - decode_extension_supported_groups - }, - { - 11, - "ec_point_formats", - decode_extension_ec_point_formats - }, - { - 12, - "srp", - decode_extension - }, - { - 13, - "signature_algorithms", - decode_extension - }, - { - 14, - "use_srtp", - decode_extension - }, - { - 15, - "heartbeat", - decode_extension - }, - { - 16, - "application_layer_protocol_negotiation", - decode_extension - }, - { - 17, - "status_request_v2", - decode_extension - }, - { - 18, - "signed_certificate_timestamp", - decode_extension - }, - { - 19, - "client_certificate_type", - decode_extension_client_certificate_type - }, - { - 20, - "server_certificate_type", - decode_extension_server_certificate_type - }, - { - 21, - "padding", - decode_extension - }, - { - 22, - "encrypt_then_mac", - decode_extension_encrypt_then_mac - }, - { - 23, - "extended_master_secret", - decode_extension_extended_master_secret - }, - { - 24, - "token_binding", - decode_extension - }, - { - 25, - "cached_info", - decode_extension - }, - { - 26, - "tls_lts", - decode_extension - }, - { - 27, - "compress_certificate", - decode_extension - }, - { - 28, - "record_size_limit", - decode_extension - }, - { - 29, - "pwd_protect", - decode_extension - }, - { - 30, - "pwd_clear", - decode_extension - }, - { - 31, - "password_salt", - decode_extension - }, - { - 32, - "ticket_pinning", - decode_extension - }, - { - 33, - "tls_cert_with_extern_psk", - decode_extension - }, - { - 34, - "delegated_credentials", - decode_extension - }, - { - 35, - "session_ticket", - decode_extension - }, - { - 36, - "TLMSP", - decode_extension - }, - { - 37, - "TLMSP_proxying", - decode_extension - }, - { - 38, - "TLMSP_delegate", - decode_extension - }, - { - 39, - "supported_ekt_ciphers", - decode_extension - }, - { - 41, - "pre_shared_key", - decode_extension - }, - { - 42, - "early_data", - decode_extension - }, - { - 43, - "supported_versions", - decode_extension_supported_versions - }, - { - 44, - "cookie", - decode_extension - }, - { - 45, - "psk_key_exchange_modes", - decode_extension - }, - { - 47, - "certificate_authorities", - decode_extension - }, - { - 48, - "oid_filters", - decode_extension - }, - { - 49, - "post_handshake_auth", - decode_extension - }, - { - 50, - "signature_algorithms_cert", - decode_extension - }, - { - 51, - "key_share", - decode_extension - }, - { - 52, - "transparency_info", - decode_extension - }, - { - 53, - "connection_id", - decode_extension - }, - { - 55, - "external_id_hash", - decode_extension - }, - { - 56, - "external_session_id", - decode_extension - }, - { - 13172, - "next_protocol_negotiation", - decode_extension - }, - { - 0xff01, - "renegotiation_info", - decode_extension - }, -{-1} -}; + { + 0, + "server_name", + decode_extension_server_name, + }, + {1, "max_fragment_length", decode_extension}, + {2, "client_certificate_url", decode_extension}, + {3, "trusted_ca_keys", decode_extension}, + {4, "truncated_hmac", decode_extension}, + {5, "status_request", decode_extension}, + {6, "user_mapping", decode_extension}, + {7, "client_authz", decode_extension}, + {8, "server_authz", decode_extension}, + {9, "cert_type", decode_extension}, + {10, "supported_groups", decode_extension_supported_groups}, + {11, "ec_point_formats", decode_extension_ec_point_formats}, + {12, "srp", decode_extension}, + {13, "signature_algorithms", decode_extension}, + {14, "use_srtp", decode_extension}, + {15, "heartbeat", decode_extension}, + {16, "application_layer_protocol_negotiation", decode_extension}, + {17, "status_request_v2", decode_extension}, + {18, "signed_certificate_timestamp", decode_extension}, + {19, "client_certificate_type", decode_extension_client_certificate_type}, + {20, "server_certificate_type", decode_extension_server_certificate_type}, + {21, "padding", decode_extension}, + {22, "encrypt_then_mac", decode_extension_encrypt_then_mac}, + {23, "extended_master_secret", decode_extension_extended_master_secret}, + {24, "token_binding", decode_extension}, + {25, "cached_info", decode_extension}, + {26, "tls_lts", decode_extension}, + {27, "compress_certificate", decode_extension}, + {28, "record_size_limit", decode_extension}, + {29, "pwd_protect", decode_extension}, + {30, "pwd_clear", decode_extension}, + {31, "password_salt", decode_extension}, + {32, "ticket_pinning", decode_extension}, + {33, "tls_cert_with_extern_psk", decode_extension}, + {34, "delegated_credentials", decode_extension}, + {35, "session_ticket", decode_extension}, + {36, "TLMSP", decode_extension}, + {37, "TLMSP_proxying", decode_extension}, + {38, "TLMSP_delegate", decode_extension}, + {39, "supported_ekt_ciphers", decode_extension}, + {41, "pre_shared_key", decode_extension}, + {42, "early_data", decode_extension}, + {43, "supported_versions", decode_extension_supported_versions}, + {44, "cookie", decode_extension}, + {45, "psk_key_exchange_modes", decode_extension}, + {47, "certificate_authorities", decode_extension}, + {48, "oid_filters", decode_extension}, + {49, "post_handshake_auth", decode_extension}, + {50, "signature_algorithms_cert", decode_extension}, + {51, "key_share", decode_extension}, + {52, "transparency_info", decode_extension}, + {53, "connection_id", decode_extension}, + {55, "external_id_hash", decode_extension}, + {56, "external_session_id", decode_extension}, + {13172, "next_protocol_negotiation", decode_extension}, + {0xff01, "renegotiation_info", decode_extension}, + {-1}}; -static int -decode_server_name_type_host_name (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r; - UINT4 l; - SSL_DECODE_UINT16(ssl,"server name length",0,data,&l); - if(!(NET_print_flags & NET_PRINT_JSON)) - printf(": %.*s",l,data->data); +static int decode_server_name_type_host_name(ssl_obj *ssl, + int dir, + segment *seg, + Data *data) { + int r; + UINT4 l; + SSL_DECODE_UINT16(ssl, "server name length", 0, data, &l); + if(!(NET_print_flags & NET_PRINT_JSON)) + printf(": %.*s", l, data->data); - /* Possibly use data->data to set/modify ssl->server_name */ - if (l!=0) - { - char* server_name; - server_name = calloc(l+1,sizeof(char)); - 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; - } - } - - data->len-=l; - data->data+=l; - return(0); - } -static int -decode_server_name (ssl_obj *ssl, int dir, segment *seg, Data *data) - { - int r; - UINT4 l; - SSL_DECODE_UINT16(ssl,"server name length",0,data,&l); - data->len-=l; - data->data+=l; - return(0); + /* Possibly use data->data to set/modify ssl->server_name */ + if(l != 0) { + char *server_name; + server_name = calloc(l + 1, sizeof(char)); + 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; + } } -decoder server_name_type_decoder[]={ - { - 0, - "host_name", - decode_server_name_type_host_name - }, -{-1} -}; + data->len -= l; + data->data += l; + return (0); +} +static int decode_server_name(ssl_obj *ssl, int dir, segment *seg, Data *data) { + int r; + UINT4 l; + SSL_DECODE_UINT16(ssl, "server name length", 0, data, &l); + data->len -= l; + data->data += l; + return (0); +} + +decoder server_name_type_decoder[] = { + {0, "host_name", decode_server_name_type_host_name}, + {-1}}; diff --git a/ssl/ssl_analyze.c b/ssl/ssl_analyze.c index 3cf7131..459b87b 100644 --- a/ssl/ssl_analyze.c +++ b/ssl/ssl_analyze.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssl_analyze.c,v 1.8 2002/01/21 18:46:13 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Fri Jan 8 14:07:05 1999 */ - #include #include #include @@ -57,581 +57,533 @@ UINT4 SSL_print_flags = 1 | P_HT | P_HL; static int parse_ssl_flags PROTO_LIST((char *str)); -static int create_ssl_ctx PROTO_LIST((void *handle,proto_ctx **ctxp)); +static int create_ssl_ctx PROTO_LIST((void *handle, proto_ctx **ctxp)); static int create_ssl_analyzer PROTO_LIST((void *handle, - proto_ctx *ctx,tcp_conn *conn,proto_obj **objp, - struct sockaddr_storage *i_addr,u_short i_port, - struct sockaddr_storage *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)); -static int read_data PROTO_LIST((r_queue *q,segment *seg,int offset, - segment **lastp,int *offsetp)); -static int data_ssl_analyzer PROTO_LIST((proto_obj *_obj,segment *seg, - int direction)); -int close_ssl_analyzer PROTO_LIST((proto_obj *_obj,packet *p,int direction)); + proto_ctx *ctx, + tcp_conn *conn, + proto_obj **objp, + struct sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *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)); +static int read_data PROTO_LIST( + (r_queue * q, segment *seg, int offset, segment **lastp, int *offsetp)); +static int data_ssl_analyzer PROTO_LIST((proto_obj * _obj, + segment *seg, + int direction)); +int close_ssl_analyzer PROTO_LIST((proto_obj * _obj, packet *p, int direction)); -static int create_r_queue PROTO_LIST((r_queue **qp)); +static int create_r_queue PROTO_LIST((r_queue * *qp)); -static int free_r_queue PROTO_LIST((r_queue *q)); -static int print_ssl_record PROTO_LIST((ssl_obj *obj,int direction, - segment *q,UCHAR *data,int len)); -char *SSL_keyfile=0; -char *SSL_password=0; -char *SSL_keylogfile=0; +static int free_r_queue PROTO_LIST((r_queue * q)); +static int print_ssl_record PROTO_LIST( + (ssl_obj * obj, int direction, segment *q, UCHAR *data, int len)); +char *SSL_keyfile = 0; +char *SSL_password = 0; +char *SSL_keylogfile = 0; #define NEGATE 0x800000 typedef struct { - int ch; - char *name; - UINT4 flag; + int ch; + char *name; + UINT4 flag; } flag_struct; -flag_struct flags[]={ - { - 't', - "ts", - SSL_PRINT_TIMESTAMP, - }, - { - 'e', - "tsa", - SSL_PRINT_TIMESTAMP|SSL_PRINT_TIMESTAMP_ABSOLUTE - }, - { - 'x', - "x", - SSL_PRINT_HEXDUMP - }, - { - 'X', - "X", - SSL_PRINT_HEX_ONLY - }, - { - 'r', - "rh", - SSL_PRINT_RECORD_HEADER - }, - { - 0, - "ht", - SSL_PRINT_HANDSHAKE_TYPE - }, - { - 0, - "H", - SSL_PRINT_HIGHLIGHTS - }, - { - 'A', - "all", - SSL_PRINT_ALL_FIELDS - }, - { - 0, - "d", - SSL_PRINT_DECODE - }, - { - 'y', - "nroff", - SSL_PRINT_NROFF - }, - { - 'N', - "asn", - SSL_PRINT_DECODE_ASN1 - }, - { - 0, - "crypto", - SSL_PRINT_CRYPTO - }, - { - 'd', - "appdata", - SSL_PRINT_APP_DATA - }, - { 'q', - "quiet", - P_HL | NEGATE - }, - {0} -}; +flag_struct flags[] = { + { + 't', + "ts", + SSL_PRINT_TIMESTAMP, + }, + {'e', "tsa", SSL_PRINT_TIMESTAMP | SSL_PRINT_TIMESTAMP_ABSOLUTE}, + {'x', "x", SSL_PRINT_HEXDUMP}, + {'X', "X", SSL_PRINT_HEX_ONLY}, + {'r', "rh", SSL_PRINT_RECORD_HEADER}, + {0, "ht", SSL_PRINT_HANDSHAKE_TYPE}, + {0, "H", SSL_PRINT_HIGHLIGHTS}, + {'A', "all", SSL_PRINT_ALL_FIELDS}, + {0, "d", SSL_PRINT_DECODE}, + {'y', "nroff", SSL_PRINT_NROFF}, + {'N', "asn", SSL_PRINT_DECODE_ASN1}, + {0, "crypto", SSL_PRINT_CRYPTO}, + {'d', "appdata", SSL_PRINT_APP_DATA}, + {'q', "quiet", P_HL | NEGATE}, + {0}}; -int -parse_ssl_flag (int flag) - { - flag_struct *fl; - - for(fl=flags;fl->name;fl++){ - if(fl->ch==flag){ - if(fl->flag & NEGATE){ - SSL_print_flags &= ~(fl->flag); - } - else +int parse_ssl_flag(int flag) { + flag_struct *fl; + + for(fl = flags; fl->name; fl++) { + if(fl->ch == flag) { + if(fl->flag & NEGATE) { + SSL_print_flags &= ~(fl->flag); + } else + SSL_print_flags |= fl->flag; + break; + } + } + + return (0); +} + +static int parse_ssl_flags(char *str) { + char *x, *y; + flag_struct *fl; + int bang; + + y = str; + + while((x = strtok(y, ","))) { + y = 0; + + if(*x == '!') { + bang = 1; + x++; + } else + bang = 0; + for(fl = flags; fl->name; fl++) { + if(!strcmp(x, fl->name)) { + if(!bang) SSL_print_flags |= fl->flag; + else + SSL_print_flags &= ~fl->flag; break; } } - - return(0); + if(!fl->name) { + fprintf(stderr, "SSL: Bad flag %s\n", x); + } } - -static int -parse_ssl_flags (char *str) - { - char *x,*y; - flag_struct *fl; - int bang; - - y=str; - - while((x=strtok(y,","))){ - y=0; - - if(*x=='!'){ - bang=1; - x++; - } - else - bang=0; - for(fl=flags;fl->name;fl++){ - if(!strcmp(x,fl->name)){ - if(!bang) SSL_print_flags |= fl->flag; - else SSL_print_flags &= ~fl->flag; + + return (0); +} + +static int create_ssl_ctx(void *handle, proto_ctx **ctxp) { + ssl_decode_ctx *ctx = 0; + int r, _status; + + if((r = ssl_decode_ctx_create(&ctx, SSL_keyfile, SSL_password, + SSL_keylogfile))) + ABORT(r); + + *ctxp = (proto_ctx *)ctx; + _status = 0; +abort: + return (_status); +} + +static int destroy_ssl_ctx(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 sockaddr_storage *i_addr, + u_short i_port, + struct sockaddr_storage *r_addr, + u_short r_port, + struct timeval *base_time) { + int r, _status; + ssl_obj *obj = 0; + + if(!(obj = (ssl_obj *)calloc(1, sizeof(ssl_obj)))) + ABORT(R_NO_MEMORY); + + obj->ssl_ctx = (ssl_decode_ctx *)ctx; + obj->conn = conn; + + if((r = create_r_queue(&obj->r2i_queue))) + ABORT(r); + if((r = create_r_queue(&obj->i2r_queue))) + ABORT(r); + + obj->client_name = strndup(conn->i_name, NI_MAXHOST); + obj->client_ip = strndup(conn->i_num, INET6_ADDRSTRLEN); + obj->client_port = i_port; + + obj->server_name = strndup(conn->r_name, NI_MAXHOST); + obj->server_ip = strndup(conn->r_num, INET6_ADDRSTRLEN); + obj->server_port = r_port; + + obj->i_state = SSL_ST_SENT_NOTHING; + obj->r_state = SSL_ST_HANDSHAKE; + + memcpy(&obj->time_start, base_time, sizeof(struct timeval)); + memcpy(&obj->time_last, base_time, sizeof(struct timeval)); + + if((r = ssl_decoder_create(&obj->decoder, obj->ssl_ctx))) + ABORT(r); + + if(!(obj->extensions = malloc(sizeof(ssl_extensions)))) + ABORT(R_NO_MEMORY); + + *objp = (proto_obj *)obj; + + _status = 0; + + // check logger... + if(logger) + _status = logger->vtbl->create(&obj->logger_obj, i_addr, i_port, r_addr, + r_port, base_time); + +abort: + if(_status) { + destroy_ssl_analyzer((proto_obj **)&obj); + } + return (_status); +} + +static int destroy_ssl_analyzer(proto_obj **objp) { + ssl_obj *obj; + + if(!objp || !*objp) + return (0); + + obj = (ssl_obj *)*objp; + DBG((0, "Destroying SSL analyzer")); + + // check logger... + if(logger) + logger->vtbl->destroy(&obj->logger_obj); + + free_r_queue(obj->i2r_queue); + free_r_queue(obj->r2i_queue); + ssl_decoder_destroy(&obj->decoder); + free(obj->client_name); + free(obj->client_ip); + free(obj->server_name); + free(obj->server_ip); + free(obj->extensions); + free(*objp); + *objp = 0; + + return (0); +} + +static int free_r_queue(r_queue *q) { + FREE(q->data); + if(q->q) + free_tcp_segment_queue(q->q); + free(q); + return (0); +} + +static int create_r_queue(r_queue **qp) { + r_queue *q = 0; + int _status; + + if(!(q = (r_queue *)calloc(1, sizeof(r_queue)))) + ABORT(R_NO_MEMORY); + + if(!(q->data = (UCHAR *)malloc(SSL_HEADER_SIZE))) + ABORT(R_NO_MEMORY); + q->ptr = q->data; + q->_allocated = SSL_HEADER_SIZE; + q->len = 0; + + q->state = SSL_READ_NONE; + *qp = q; + _status = 0; +abort: + if(_status) { + free_r_queue(q); + } + return (_status); +} + +static int read_ssl_record(ssl_obj *obj, + r_queue *q, + segment *seg, + int offset, + segment **lastp, + int *offsetp) + +{ + segment *last = seg; + int rec_len, r, _status; + + switch(q->state) { + case SSL_READ_NONE: + if(SSL_HEADER_SIZE < q->len) + ABORT(-1); + q->read_left = SSL_HEADER_SIZE - q->len; + if((r = read_data(q, seg, offset, &last, &offset))) + ABORT(r); + + q->state = SSL_READ_HEADER; + switch(q->data[0]) { + case 20: + case 21: + case 22: + case 23: break; - } + default: + DBG((0, "Unknown SSL content type %d for segment %u:%u(%u)", + q->data[0] & 255, seg->s_seq, seg->s_seq + seg->len, seg->len)); } - if(!fl->name){ - fprintf(stderr,"SSL: Bad flag %s\n",x); - } - } - return(0); - } - -static int -create_ssl_ctx (void *handle, proto_ctx **ctxp) - { - ssl_decode_ctx *ctx=0; - int r,_status; - - if((r=ssl_decode_ctx_create(&ctx,SSL_keyfile,SSL_password,SSL_keylogfile))) - ABORT(r); + rec_len = COMBINE(q->data[3], q->data[4]); - *ctxp=(proto_ctx *)ctx; - _status=0; - abort: - return(_status); + /* SSL v3.0 spec says a record may not exceed 2**14 + 2048 == 18432 */ + if(rec_len > 18432) + ABORT(R_INTERNAL); + + /*Expand the buffer*/ + if(q->_allocated < (rec_len + SSL_HEADER_SIZE)) { + if(!(q->data = realloc(q->data, rec_len + 5))) + ABORT(R_NO_MEMORY); + q->_allocated = rec_len + SSL_HEADER_SIZE; + q->ptr = q->data + SSL_HEADER_SIZE; + }; + + q->read_left = rec_len; + + case SSL_READ_HEADER: + if((r = read_data(q, last, offset, &last, &offset))) + ABORT(r); + break; + default: + ABORT(R_INTERNAL); } -static int -destroy_ssl_ctx (void *handle, proto_ctx **ctxp) - { - ssl_decode_ctx *ctx=0; - ctx=(ssl_decode_ctx *) *ctxp; - ssl_decode_ctx_destroy(&ctx); - return 0; - } + q->state = SSL_READ_NONE; + /*Whew. If we get here, we've managed to read a whole record*/ + *lastp = last; + *offsetp = offset; -static int create_ssl_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn, - proto_obj **objp, struct sockaddr_storage *i_addr, u_short i_port, struct sockaddr_storage *r_addr, - u_short r_port, struct timeval *base_time) - { - int r,_status; - ssl_obj *obj=0; - - if(!(obj=(ssl_obj *)calloc(1,sizeof(ssl_obj)))) - ABORT(R_NO_MEMORY); - - obj->ssl_ctx=(ssl_decode_ctx *)ctx; - obj->conn=conn; - - if((r=create_r_queue(&obj->r2i_queue))) - ABORT(r); - if((r=create_r_queue(&obj->i2r_queue))) - ABORT(r); + _status = 0; +abort: + return (_status); +} - obj->client_name = strndup(conn->i_name, NI_MAXHOST); - obj->client_ip = strndup(conn->i_num, INET6_ADDRSTRLEN); - obj->client_port=i_port; - - obj->server_name = strndup(conn->r_name, NI_MAXHOST); - obj->server_ip = strndup(conn->r_num, INET6_ADDRSTRLEN); - obj->server_port=r_port; - - obj->i_state=SSL_ST_SENT_NOTHING; - obj->r_state=SSL_ST_HANDSHAKE; - - memcpy(&obj->time_start,base_time,sizeof(struct timeval)); - memcpy(&obj->time_last,base_time,sizeof(struct timeval)); - - if((r=ssl_decoder_create(&obj->decoder,obj->ssl_ctx))) - ABORT(r); - - if (!(obj->extensions=malloc(sizeof(ssl_extensions)))) - ABORT(R_NO_MEMORY); - - *objp=(proto_obj *)obj; - - _status=0; - - //check logger... - if (logger) _status=logger->vtbl->create(&obj->logger_obj,i_addr,i_port,r_addr,r_port,base_time); - - abort: - if(_status){ - destroy_ssl_analyzer((proto_obj **)&obj); - } - return(_status); - } - -static int -destroy_ssl_analyzer (proto_obj **objp) - { - ssl_obj *obj; - - if(!objp || !*objp) - return(0); - - obj=(ssl_obj *)*objp; - DBG((0,"Destroying SSL analyzer")); - - //check logger... - if (logger) logger->vtbl->destroy(&obj->logger_obj); - - free_r_queue(obj->i2r_queue); - free_r_queue(obj->r2i_queue); - ssl_decoder_destroy(&obj->decoder); - free(obj->client_name); - free(obj->client_ip); - free(obj->server_name); - free(obj->server_ip); - free(obj->extensions); - free(*objp); - *objp=0; - - return(0); - } - - -static int -free_r_queue (r_queue *q) - { - FREE(q->data); - if(q->q) free_tcp_segment_queue(q->q); - free(q); - return(0); - } - -static int -create_r_queue (r_queue **qp) - { - r_queue *q=0; - int _status; - - if(!(q=(r_queue *)calloc(1,sizeof(r_queue)))) - ABORT(R_NO_MEMORY); - - if(!(q->data=(UCHAR *)malloc(SSL_HEADER_SIZE))) - ABORT(R_NO_MEMORY); - q->ptr=q->data; - q->_allocated=SSL_HEADER_SIZE; - q->len=0; - - q->state=SSL_READ_NONE; - *qp=q; - _status=0; - abort: - if(_status){ - free_r_queue(q); - } - return(_status); - } - -static int -read_ssl_record (ssl_obj *obj, r_queue *q, segment *seg, int offset, segment **lastp, int *offsetp) - - { - segment *last=seg; - int rec_len,r,_status; - - switch(q->state){ - case SSL_READ_NONE: - if (SSL_HEADER_SIZElen) - ABORT(-1); - q->read_left=SSL_HEADER_SIZE-q->len; - if((r=read_data(q,seg,offset,&last,&offset))) - ABORT(r); - - q->state=SSL_READ_HEADER; - switch(q->data[0]){ - case 20: - case 21: - case 22: - case 23: - break; - default: - DBG((0,"Unknown SSL content type %d for segment %u:%u(%u)", - q->data[0] & 255,seg->s_seq,seg->s_seq+seg->len,seg->len)); - } - - rec_len=COMBINE(q->data[3],q->data[4]); - - /* SSL v3.0 spec says a record may not exceed 2**14 + 2048 == 18432 */ - if(rec_len > 18432) - ABORT(R_INTERNAL); - - /*Expand the buffer*/ - if(q->_allocated<(rec_len+SSL_HEADER_SIZE)){ - if(!(q->data=realloc(q->data,rec_len+5))) - ABORT(R_NO_MEMORY); - q->_allocated=rec_len+SSL_HEADER_SIZE; - q->ptr=q->data+SSL_HEADER_SIZE; - }; - - q->read_left=rec_len; - - case SSL_READ_HEADER: - if((r=read_data(q,last,offset,&last,&offset))) - ABORT(r); - break; - default: - ABORT(R_INTERNAL); - } - - q->state=SSL_READ_NONE; - /*Whew. If we get here, we've managed to read a whole record*/ - *lastp=last; - *offsetp=offset; - - _status=0; - abort: - return(_status); - } - - -static int -read_data (r_queue *q, segment *seg, int offset, segment **lastp, int *offsetp) - { - int tocpy=0,r,_status; +static int read_data(r_queue *q, + segment *seg, + int offset, + segment **lastp, + int *offsetp) { + int tocpy = 0, r, _status; #ifdef DEBUG - int bread=0; + int bread = 0; #endif - - DBG((0,"read_data %d bytes requested",q->read_left)); - - for(;seg;seg=seg->next,offset=0){ - int left; - left=seg->len-offset; + DBG((0, "read_data %d bytes requested", q->read_left)); - tocpy=MIN(q->read_left,left); - memcpy(q->ptr,seg->data+offset,tocpy); - q->read_left-=tocpy; - q->ptr+=tocpy; - q->len+=tocpy; + for(; seg; seg = seg->next, offset = 0) { + int left; + + left = seg->len - offset; + + tocpy = MIN(q->read_left, left); + memcpy(q->ptr, seg->data + offset, tocpy); + q->read_left -= tocpy; + q->ptr += tocpy; + q->len += tocpy; #ifdef DEBUG - bread+=tocpy; + bread += tocpy; #endif - if(!q->read_left) - break; - }; - - if(q->read_left){ - if((r=copy_tcp_segment_queue(&q->q,seg))) - ABORT(r); - return(SSL_NO_DATA); - } + if(!q->read_left) + break; + }; - if(seg && tocpy==(seg->len - offset)){ - *lastp=0; - *offsetp=0; - } - else{ - *lastp=seg; - if(seg) *offsetp=tocpy+offset; - } - - if(q->read_left<0) abort(); - - DBG((0,"read_data %d bytes read",bread)); - - _status=0; - abort: - return(_status); + if(q->read_left) { + if((r = copy_tcp_segment_queue(&q->q, seg))) + ABORT(r); + return (SSL_NO_DATA); } - -static int -data_ssl_analyzer (proto_obj *_obj, segment *seg, int direction) - { - int _status,r; - r_queue *q; - segment *last,*q_next=NULL,*assembled; - ssl_obj *ssl=(ssl_obj *)_obj; - int offset=0; - - q=direction==DIR_R2I?ssl->r2i_queue:ssl->i2r_queue; - /* Handle SSLv2 backwards compat client hello - This is sloppy because we'll assume that it's - all in one TCP segment -- an assumption we make - nowhere else in the code - */ - if(direction==DIR_I2R && ssl->i_state==SSL_ST_SENT_NOTHING){ - r=process_v2_hello(ssl,seg); + if(seg && tocpy == (seg->len - offset)) { + *lastp = 0; + *offsetp = 0; + } else { + *lastp = seg; + if(seg) + *offsetp = tocpy + offset; + } - if(r==SSL_NO_DATA) - return(0); - - if(r==0) - return(0); + if(q->read_left < 0) + abort(); + + DBG((0, "read_data %d bytes read", bread)); + + _status = 0; +abort: + return (_status); +} + +static int data_ssl_analyzer(proto_obj *_obj, segment *seg, int direction) { + int _status, r; + r_queue *q; + segment *last, *q_next = NULL, *assembled; + ssl_obj *ssl = (ssl_obj *)_obj; + int offset = 0; + + q = direction == DIR_R2I ? ssl->r2i_queue : ssl->i2r_queue; + + /* Handle SSLv2 backwards compat client hello + This is sloppy because we'll assume that it's + all in one TCP segment -- an assumption we make + nowhere else in the code + */ + if(direction == DIR_I2R && ssl->i_state == SSL_ST_SENT_NOTHING) { + r = process_v2_hello(ssl, seg); + + if(r == SSL_NO_DATA) + return (0); + + if(r == 0) + return (0); + } + + if(ssl->i_state == SSL_ST_SENT_NOTHING) { + r = process_beginning_plaintext(ssl, seg, direction); + if(r == SSL_NO_DATA) + return (0); + + if(r == 0) + return (0); + } + + while(!(r = read_ssl_record(ssl, q, seg, offset, &last, &offset))) { + if(ssl->i_state == SSL_ST_SENT_NOTHING) + ssl->i_state = SSL_ST_HANDSHAKE; + if(last) { + q_next = last->next; + last->next = 0; } + if(q->q_last) { + q->q_last->next = seg; + assembled = q->q; + } else + assembled = seg; - if(ssl->i_state==SSL_ST_SENT_NOTHING){ - - r=process_beginning_plaintext(ssl,seg,direction); - if(r==SSL_NO_DATA) - return(0); - - if(r==0) - return(0); - } - - while(!(r=read_ssl_record(ssl,q,seg,offset,&last,&offset))){ - if(ssl->i_state==SSL_ST_SENT_NOTHING) - ssl->i_state=SSL_ST_HANDSHAKE; - if(last){ - q_next=last->next; - last->next=0; - } - if(q->q_last){ - q->q_last->next=seg; - assembled=q->q; - } - else - assembled=seg; + ssl->direction = direction; - ssl->direction=direction; - - if((r=print_ssl_record(ssl,direction,assembled,q->data,q->len))) - ABORT(r); - - /*Now reset things, so we can read another record*/ - if(q){ - if(q->q_last) q->q_last->next=0; - if(last) - last->next=q_next; - free_tcp_segment_queue(q->q); - q->q=0;q->q_last=0;q->offset=0;q->len=0;q->ptr=q->data; - q->state=SSL_READ_NONE; - } - - seg=last; - } - - if(r!=SSL_NO_DATA) + if((r = print_ssl_record(ssl, direction, assembled, q->data, q->len))) ABORT(r); - _status=0; - abort: - return(_status); - } - -static int -print_ssl_header (ssl_obj *obj, int direction, segment *q, UCHAR *data, int len) - { - int ct=0; - segment *s; - - ssl_print_record_num(obj); - - if(SSL_print_flags & SSL_PRINT_TIMESTAMP){ - for(s=q;s;s=s->next) ct++; - - for(s=q;s;s=s->next){ - ssl_print_timestamp(obj,&s->p->ts); - - if(s->next) - printf(", "); - } + /*Now reset things, so we can read another record*/ + if(q) { + if(q->q_last) + q->q_last->next = 0; + if(last) + last->next = q_next; + free_tcp_segment_queue(q->q); + q->q = 0; + q->q_last = 0; + q->offset = 0; + q->len = 0; + q->ptr = q->data; + q->state = SSL_READ_NONE; } - ssl_print_direction_indicator(obj,direction); - - return(0); + seg = last; } -static int -print_ssl_record (ssl_obj *obj, int direction, segment *q, UCHAR *data, int len) - { - int r; + if(r != SSL_NO_DATA) + ABORT(r); - obj->cur_json_st = json_object_new_object(); + _status = 0; +abort: + return (_status); +} - if((r=print_ssl_header(obj,direction,q,data,len))) - ERETURN(r); - - ssl_expand_record(obj,q,direction,data,len); - if(SSL_print_flags & SSL_PRINT_HEXDUMP){ - Data d; +static int print_ssl_header(ssl_obj *obj, + int direction, + segment *q, + UCHAR *data, + int len) { + int ct = 0; + segment *s; - INIT_DATA(d,data,len); - exdump(obj,"Packet data",&d); - LF;LF; + ssl_print_record_num(obj); + + if(SSL_print_flags & SSL_PRINT_TIMESTAMP) { + for(s = q; s; s = s->next) + ct++; + + for(s = q; s; s = s->next) { + ssl_print_timestamp(obj, &s->p->ts); + + if(s->next) + printf(", "); } - - if(SSL_print_flags & SSL_PRINT_JSON) - printf("%s\n", json_object_to_json_string(obj->cur_json_st)); - json_object_put(obj->cur_json_st); - obj->cur_json_st = NULL; - - return(0); } -int -close_ssl_analyzer (proto_obj *_obj, packet *p, int dir) - { - ssl_obj *ssl=(ssl_obj *)_obj; - char *what; - - if(p->tcp->th_flags & TH_RST) - what="RST"; - else - what="FIN"; + ssl_print_direction_indicator(obj, direction); - //check logger... - if (logger) logger->vtbl->close(ssl->logger_obj,NULL,0,dir); + return (0); +} - explain(ssl,"%d ",ssl->conn->conn_number); - ssl_print_timestamp(ssl,&p->ts); - ssl_print_direction_indicator(ssl,dir); - explain(ssl," TCP %s",what); +static int print_ssl_record(ssl_obj *obj, + int direction, + segment *q, + UCHAR *data, + int len) { + int r; + + obj->cur_json_st = json_object_new_object(); + + if((r = print_ssl_header(obj, direction, q, data, len))) + ERETURN(r); + + ssl_expand_record(obj, q, direction, data, len); + if(SSL_print_flags & SSL_PRINT_HEXDUMP) { + Data d; + + INIT_DATA(d, data, len); + exdump(obj, "Packet data", &d); + LF; LF; - return(0); } + if(SSL_print_flags & SSL_PRINT_JSON) + printf("%s\n", json_object_to_json_string(obj->cur_json_st)); + json_object_put(obj->cur_json_st); + obj->cur_json_st = NULL; -static struct proto_mod_vtbl_ ssl_vtbl ={ - parse_ssl_flags, - parse_ssl_flag, - create_ssl_ctx, - create_ssl_analyzer, - destroy_ssl_ctx, - destroy_ssl_analyzer, - data_ssl_analyzer, - close_ssl_analyzer, + return (0); +} + +int close_ssl_analyzer(proto_obj *_obj, packet *p, int dir) { + ssl_obj *ssl = (ssl_obj *)_obj; + char *what; + + if(p->tcp->th_flags & TH_RST) + what = "RST"; + else + what = "FIN"; + + // check logger... + if(logger) + logger->vtbl->close(ssl->logger_obj, NULL, 0, dir); + + explain(ssl, "%d ", ssl->conn->conn_number); + ssl_print_timestamp(ssl, &p->ts); + ssl_print_direction_indicator(ssl, dir); + explain(ssl, " TCP %s", what); + LF; + return (0); +} + +static struct proto_mod_vtbl_ ssl_vtbl = { + parse_ssl_flags, parse_ssl_flag, create_ssl_ctx, + create_ssl_analyzer, destroy_ssl_ctx, destroy_ssl_analyzer, + data_ssl_analyzer, close_ssl_analyzer, }; -struct proto_mod_ ssl_mod = { - 0, - &ssl_vtbl -}; - - - - +struct proto_mod_ ssl_mod = {0, &ssl_vtbl}; diff --git a/ssl/ssl_analyze.h b/ssl/ssl_analyze.h index c12ecca..1d0789c 100644 --- a/ssl/ssl_analyze.h +++ b/ssl/ssl_analyze.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssl_analyze.h,v 1.3 2000/11/09 18:52:24 ekr Exp $ @@ -43,43 +44,42 @@ ekr@rtfm.com Tue Jan 12 08:45:44 1999 */ - #ifndef _ssl_analyze_h #define _ssl_analyze_h extern proto_mod ssl_mod; /*The type of data this is*/ -#define P_RH (1<<3) -#define P_HT (1<<4) -#define P_HL (1<<5) -#define P_ND (1<<6) -#define P_DC (1<<7) -#define P_NR (1<<8) -#define P_ASN (1<<9) -#define P_CR (1<<10) -#define P_AD (1<<11) -#define P_TSA (1<<12) -#define P_QT (1<<13) -#define P_HO (1<<14) -#define P_JS (1<<15) +#define P_RH (1 << 3) +#define P_HT (1 << 4) +#define P_HL (1 << 5) +#define P_ND (1 << 6) +#define P_DC (1 << 7) +#define P_NR (1 << 8) +#define P_ASN (1 << 9) +#define P_CR (1 << 10) +#define P_AD (1 << 11) +#define P_TSA (1 << 12) +#define P_QT (1 << 13) +#define P_HO (1 << 14) +#define P_JS (1 << 15) -#define SSL_PRINT_TIMESTAMP (1) /*Timestamp records*/ -#define SSL_PRINT_HEXDUMP (1<<2) /*Print the whole record in hex*/ -#define SSL_PRINT_RECORD_HEADER P_RH /*Print the record header*/ -#define SSL_PRINT_HANDSHAKE_TYPE P_HT /*Print the handshake type*/ -#define SSL_PRINT_HIGHLIGHTS (P_HT | P_HL) -#define SSL_PRINT_ALL_FIELDS (P_RH | P_HT | P_HL | P_ND) -#define SSL_PRINT_DECODE (P_DC) /*Print fields as decoded*/ -#define SSL_PRINT_NROFF (P_NR) -#define SSL_PRINT_DECODE_ASN1 (P_ASN) -#define SSL_PRINT_CRYPTO (P_CR) -#define SSL_PRINT_APP_DATA (P_AD) -#define SSL_PRINT_TIMESTAMP_ABSOLUTE (P_TSA) -#define SSL_PRINT_QUIET (P_QT) -#define SSL_PRINT_HEX_ONLY (P_HO) -#define SSL_PRINT_JSON (P_JS) -#define SSL_PRINT_ALL 0xfffffff +#define SSL_PRINT_TIMESTAMP (1) /*Timestamp records*/ +#define SSL_PRINT_HEXDUMP (1 << 2) /*Print the whole record in hex*/ +#define SSL_PRINT_RECORD_HEADER P_RH /*Print the record header*/ +#define SSL_PRINT_HANDSHAKE_TYPE P_HT /*Print the handshake type*/ +#define SSL_PRINT_HIGHLIGHTS (P_HT | P_HL) +#define SSL_PRINT_ALL_FIELDS (P_RH | P_HT | P_HL | P_ND) +#define SSL_PRINT_DECODE (P_DC) /*Print fields as decoded*/ +#define SSL_PRINT_NROFF (P_NR) +#define SSL_PRINT_DECODE_ASN1 (P_ASN) +#define SSL_PRINT_CRYPTO (P_CR) +#define SSL_PRINT_APP_DATA (P_AD) +#define SSL_PRINT_TIMESTAMP_ABSOLUTE (P_TSA) +#define SSL_PRINT_QUIET (P_QT) +#define SSL_PRINT_HEX_ONLY (P_HO) +#define SSL_PRINT_JSON (P_JS) +#define SSL_PRINT_ALL 0xfffffff extern UINT4 SSL_print_flags; extern char *SSL_keyfile; @@ -87,4 +87,3 @@ extern char *SSL_password; extern char *SSL_keylogfile; #endif - diff --git a/ssl/ssl_h.h b/ssl/ssl_h.h index c95025e..f4f39f8 100644 --- a/ssl/ssl_h.h +++ b/ssl/ssl_h.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssl_h.h,v 1.6 2002/08/17 01:33:17 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Fri Jan 8 14:09:37 1999 */ - #ifndef _ssl_h #define _ssl_h @@ -52,19 +52,18 @@ typedef struct ssl_decode_ctx_ ssl_decode_ctx; typedef struct ssl_decoder_ ssl_decoder; - typedef struct d_queue_ { - short state; /*What state we're in*/ -#define SSL_READ_NONE 1 -#define SSL_READ_HEADER 2 - int read_left; /*How many more bytes to read in this state*/ - int len; /*The length of the total record, including header*/ - UCHAR *data; /*The data for this record*/ - UCHAR *ptr; /*The data ptr*/ - int _allocated; /*The number of data bytes allocated for this record*/ - segment *q; /*The segments that match this record*/ - segment *q_last; /*The last segment*/ - int offset; /*How far into the first segment this record starts*/ + short state; /*What state we're in*/ +#define SSL_READ_NONE 1 +#define SSL_READ_HEADER 2 + int read_left; /*How many more bytes to read in this state*/ + int len; /*The length of the total record, including header*/ + UCHAR *data; /*The data for this record*/ + UCHAR *ptr; /*The data ptr*/ + int _allocated; /*The number of data bytes allocated for this record*/ + segment *q; /*The segments that match this record*/ + segment *q_last; /*The last segment*/ + int offset; /*How far into the first segment this record starts*/ } r_queue; typedef struct ssl_extensions_ { @@ -75,77 +74,75 @@ typedef struct ssl_extensions_ { } ssl_extensions; typedef struct ssl_obj_ { - tcp_conn *conn; - proto_obj *logger_obj; - int r_state; - int i_state; - int version; - UINT4 cipher_suite; + tcp_conn *conn; + proto_obj *logger_obj; + int r_state; + int i_state; + int version; + UINT4 cipher_suite; - char *client_name; - char *client_ip; - int client_port; - char *server_name; - char *server_ip; - int server_port; + char *client_name; + char *client_ip; + int client_port; + char *server_name; + char *server_ip; + int server_port; - struct SSL_CipherSuite_ *cs; - r_queue *i2r_queue; - r_queue *r2i_queue; - struct timeval time_start; - struct timeval time_last; - ssl_decode_ctx *ssl_ctx; - ssl_decoder *decoder; - ssl_extensions *extensions; + struct SSL_CipherSuite_ *cs; + r_queue *i2r_queue; + r_queue *r2i_queue; + struct timeval time_start; + struct timeval time_last; + ssl_decode_ctx *ssl_ctx; + ssl_decoder *decoder; + ssl_extensions *extensions; - int process_ciphertext; + int process_ciphertext; - /*Printing bookkeeping*/ - #define REC_PLAINTEXT 1 - #define REC_DECRYPTED_CIPHERTEXT 2 - #define REC_CIPHERTEXT 3 - int record_encryption; +/*Printing bookkeeping*/ +#define REC_PLAINTEXT 1 +#define REC_DECRYPTED_CIPHERTEXT 2 +#define REC_CIPHERTEXT 3 + int record_encryption; - int direction; /* The direction we're currently working in*/ - int record_count; - int indent_depth; - int indent_name_len; - struct json_object *cur_json_st; - char *cur_ja3_ec_str; - char *cur_ja3_ecp_str; + int direction; /* The direction we're currently working in*/ + int record_count; + int indent_depth; + int indent_name_len; + struct json_object *cur_json_st; + char *cur_ja3_ec_str; + char *cur_ja3_ecp_str; } ssl_obj; typedef struct decoder_ { - int type; - char *name; - int (*print) PROTO_LIST((ssl_obj *,int direction,segment *seg,Data *data)); + int type; + char *name; + int(*print) PROTO_LIST((ssl_obj *, int direction, segment *seg, Data *data)); } decoder; -#define SSL_NO_DATA 1 +#define SSL_NO_DATA 1 #define SSL_BAD_CONTENT_TYPE 2 -#define SSL_BAD_PMS 3 -#define SSL_CANT_DO_CIPHER 4 -#define SSL_NO_DECRYPT 5 -#define SSL_BAD_MAC 6 -#define SSL_BAD_DATA 7 +#define SSL_BAD_PMS 3 +#define SSL_CANT_DO_CIPHER 4 +#define SSL_NO_DECRYPT 5 +#define SSL_BAD_MAC 6 +#define SSL_BAD_DATA 7 /*SSL defines*/ -#define COMBINE(a,b) ((a<<8) | b) +#define COMBINE(a, b) ((a << 8) | b) #define SSL_HEADER_SIZE 5 -#define SSLV3_VERSION 0x300 -#define TLSV1_VERSION 0x301 -#define TLSV11_VERSION 0x302 -#define TLSV12_VERSION 0x303 -#define TLSV13_VERSION 0x304 +#define SSLV3_VERSION 0x300 +#define TLSV1_VERSION 0x301 +#define TLSV11_VERSION 0x302 +#define TLSV12_VERSION 0x303 +#define TLSV13_VERSION 0x304 /*State defines*/ -#define SSL_ST_SENT_NOTHING 0 -#define SSL_ST_HANDSHAKE 1 -#define SSL_ST_SENT_CHANGE_CIPHER_SPEC 2 +#define SSL_ST_SENT_NOTHING 0 +#define SSL_ST_HANDSHAKE 1 +#define SSL_ST_SENT_CHANGE_CIPHER_SPEC 2 #include "ssldecode.h" - #endif - diff --git a/ssl/ssl_rec.c b/ssl/ssl_rec.c index 14cf938..47a5c6e 100644 --- a/ssl/ssl_rec.c +++ b/ssl/ssl_rec.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssl_rec.c,v 1.3 2000/11/03 06:38:06 ekr Exp $ @@ -43,8 +44,6 @@ ekr@rtfm.com Wed Aug 18 15:46:57 1999 */ - - #include "network.h" #include "ssl_h.h" #include "sslprint.h" @@ -58,460 +57,453 @@ #include "ssldecode.h" #include "ssl_rec.h" - struct ssl_rec_decoder_ { - SSL_CipherSuite *cs; - Data *mac_key; - Data *implicit_iv; /* for AEAD ciphers */ - Data *write_key; /* for AEAD ciphers */ -#ifdef OPENSSL - EVP_CIPHER_CTX *evp; -#endif - UINT8 seq; -}; - -char *digests[]={ - "MD5", - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - NULL -}; - -char *ciphers[]={ - "DES", - "3DES", - "RC4", - "RC2", - "IDEA", - "AES128", - "AES256", - "CAMELLIA128", - "CAMELLIA256", - "SEED", - NULL, - "aes-128-gcm", - "aes-256-gcm", - "ChaCha20-Poly1305", - "aes-128-ccm", - "aes-128-ccm", // for ccm 8, uses the same cipher -}; - - -static int tls_check_mac PROTO_LIST((ssl_rec_decoder *d,int ct, - int ver,UCHAR *data,UINT4 datalen,UCHAR *iv,UINT4 ivlen,UCHAR *mac)); -static int fmt_seq PROTO_LIST((UINT4 num,UCHAR *buf)); - -int -ssl_create_rec_decoder (ssl_rec_decoder **dp, ssl_obj *ssl, UCHAR *mk, UCHAR *sk, UCHAR *iv) - { - int r,_status; - ssl_rec_decoder *dec=0; + SSL_CipherSuite *cs; + Data *mac_key; + Data *implicit_iv; /* for AEAD ciphers */ + Data *write_key; /* for AEAD ciphers */ #ifdef OPENSSL - const EVP_CIPHER *ciph=0; - int iv_len = ssl->version == TLSV13_VERSION?12:ssl->cs->block; - - /* Find the SSLeay cipher */ - if(ssl->cs->enc!=ENC_NULL){ - ciph=(EVP_CIPHER *)EVP_get_cipherbyname(ciphers[ssl->cs->enc-0x30]); - if(!ciph) - ABORT(R_INTERNAL); - } - else { - ciph=EVP_enc_null(); - } - - if(!(dec=(ssl_rec_decoder *)calloc(1,sizeof(ssl_rec_decoder)))) - ABORT(R_NO_MEMORY); - - dec->cs=ssl->cs; - - if((r=r_data_alloc(&dec->mac_key,ssl->cs->dig_len))) - ABORT(r); - - if((r=r_data_alloc(&dec->implicit_iv,iv_len))) - ABORT(r); - memcpy(dec->implicit_iv->data,iv, iv_len); - - if((r=r_data_create(&dec->write_key,sk,ssl->cs->eff_bits/8))) - ABORT(r); - - /* - This is necessary for AEAD ciphers, because we must wait to fully initialize the cipher - in order to include the implicit IV - */ - if(IS_AEAD_CIPHER(ssl->cs)){ - sk=NULL; - iv=NULL; - } - else - memcpy(dec->mac_key->data,mk,ssl->cs->dig_len); - - if(!(dec->evp=EVP_CIPHER_CTX_new())) - ABORT(R_NO_MEMORY); - EVP_CIPHER_CTX_init(dec->evp); - EVP_CipherInit(dec->evp,ciph,sk,iv,0); + EVP_CIPHER_CTX *evp; #endif - - *dp=dec; - _status=0; - abort: - if(_status){ - ssl_destroy_rec_decoder(&dec); - } - return(_status); + UINT8 seq; +}; + +char *digests[] = {"MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", NULL}; + +char *ciphers[] = { + "DES", "3DES", + "RC4", "RC2", + "IDEA", "AES128", + "AES256", "CAMELLIA128", + "CAMELLIA256", "SEED", + NULL, "aes-128-gcm", + "aes-256-gcm", "ChaCha20-Poly1305", + "aes-128-ccm", + "aes-128-ccm", // for ccm 8, uses the same cipher +}; + +static int tls_check_mac PROTO_LIST((ssl_rec_decoder * d, + int ct, + int ver, + UCHAR *data, + UINT4 datalen, + UCHAR *iv, + UINT4 ivlen, + UCHAR *mac)); +static int fmt_seq PROTO_LIST((UINT4 num, UCHAR *buf)); + +int ssl_create_rec_decoder(ssl_rec_decoder **dp, + ssl_obj *ssl, + UCHAR *mk, + UCHAR *sk, + UCHAR *iv) { + int r, _status; + ssl_rec_decoder *dec = 0; +#ifdef OPENSSL + const EVP_CIPHER *ciph = 0; + int iv_len = ssl->version == TLSV13_VERSION ? 12 : ssl->cs->block; + + /* Find the SSLeay cipher */ + if(ssl->cs->enc != ENC_NULL) { + ciph = (EVP_CIPHER *)EVP_get_cipherbyname(ciphers[ssl->cs->enc - 0x30]); + if(!ciph) + ABORT(R_INTERNAL); + } else { + ciph = EVP_enc_null(); } -int -ssl_destroy_rec_decoder (ssl_rec_decoder **dp) - { - ssl_rec_decoder *d; - - if(!dp || !*dp) - return(0); - d=*dp; + if(!(dec = (ssl_rec_decoder *)calloc(1, sizeof(ssl_rec_decoder)))) + ABORT(R_NO_MEMORY); - r_data_destroy(&d->mac_key); - r_data_destroy(&d->implicit_iv); - r_data_destroy(&d->write_key); -#ifdef OPENSSL - if(d->evp){ - EVP_CIPHER_CTX_free(d->evp); - } - free(*dp); -#endif + dec->cs = ssl->cs; - *dp=0; - return(0); + if((r = r_data_alloc(&dec->mac_key, ssl->cs->dig_len))) + ABORT(r); + + if((r = r_data_alloc(&dec->implicit_iv, iv_len))) + ABORT(r); + memcpy(dec->implicit_iv->data, iv, iv_len); + + if((r = r_data_create(&dec->write_key, sk, ssl->cs->eff_bits / 8))) + ABORT(r); + + /* + This is necessary for AEAD ciphers, because we must wait to fully + initialize the cipher in order to include the implicit IV + */ + if(IS_AEAD_CIPHER(ssl->cs)) { + sk = NULL; + iv = NULL; + } else + memcpy(dec->mac_key->data, mk, ssl->cs->dig_len); + + if(!(dec->evp = EVP_CIPHER_CTX_new())) + ABORT(R_NO_MEMORY); + EVP_CIPHER_CTX_init(dec->evp); + EVP_CipherInit(dec->evp, ciph, sk, iv, 0); +#endif + + *dp = dec; + _status = 0; +abort: + if(_status) { + ssl_destroy_rec_decoder(&dec); } - - -#define MSB(a) ((a>>8)&0xff) -#define LSB(a) (a&0xff) - -int -tls13_update_rec_key (ssl_rec_decoder *d, UCHAR *newkey, UCHAR *newiv) -{ - d->write_key->data = newkey; - d->implicit_iv->data = newiv; - d->seq = 0; + return (_status); } -int -tls13_decode_rec_data (ssl_obj *ssl, ssl_rec_decoder *d, int ct, int version, UCHAR *in, int inl, UCHAR *out, int *outl) - { - int pad,i; - int r,encpadl,x,_status=0; - UCHAR aad[5],aead_nonce[12], *tag; - int taglen = d->cs->enc==ENC_AES128_CCM_8?8:16; - CRDUMP("CipherText",in,inl); - CRDUMPD("KEY",d->write_key); - CRDUMPD("IV",d->implicit_iv); - if (!IS_AEAD_CIPHER(d->cs)){ - fprintf(stderr, "Non aead cipher in tls13\n"); - ABORT(-1); - } - memcpy(aead_nonce, d->implicit_iv->data, 12); - for (i = 0; i < 8; i++) { // AEAD NONCE according to RFC TLS1.3 - aead_nonce[12 - 1 - i] ^= ((d->seq >> (i * 8)) & 0xFF); - } - d->seq++; - CRDUMP("NONCE",aead_nonce,12); - tag = in+(inl-taglen); - CRDUMP("Tag", tag, taglen); +int ssl_destroy_rec_decoder(ssl_rec_decoder **dp) { + ssl_rec_decoder *d; - aad[0] = ct; - aad[1] = 0x03; - aad[2] = 0x03; - aad[3] = MSB(inl); - aad[4] = LSB(inl); - CRDUMP("AAD",aad,5); - inl-=taglen; + if(!dp || !*dp) + return (0); + d = *dp; - if (!EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)) { - fprintf(stderr, "Unable to set ivlen\n"); - ABORT(-1); - } + r_data_destroy(&d->mac_key); + r_data_destroy(&d->implicit_iv); + r_data_destroy(&d->write_key); +#ifdef OPENSSL + if(d->evp) { + EVP_CIPHER_CTX_free(d->evp); + } + free(*dp); +#endif - if (IS_CCM_CIPHER(d->cs) && !EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_TAG, taglen, tag)) { - fprintf(stderr, "Unable to set tag for ccm cipher\n"); - ABORT(-1); - } + *dp = 0; + return (0); +} - if(!EVP_DecryptInit_ex(d->evp,NULL,NULL,d->write_key->data,aead_nonce)){ - fprintf(stderr,"Unable to init evp1\n"); - ABORT(-1); - } +#define MSB(a) ((a >> 8) & 0xff) +#define LSB(a) (a & 0xff) - if (IS_CCM_CIPHER(d->cs) && !EVP_DecryptUpdate(d->evp,NULL,outl,NULL,inl)){ - fprintf(stderr,"Unable to update data length\n"); - ABORT(-1); - } +int tls13_update_rec_key(ssl_rec_decoder *d, UCHAR *newkey, UCHAR *newiv) { + d->write_key->data = newkey; + d->implicit_iv->data = newiv; + d->seq = 0; +} - if (!EVP_DecryptUpdate(d->evp,NULL,outl,aad,5)){ - fprintf(stderr,"Unable to update aad\n"); - ABORT(-1); - } +int tls13_decode_rec_data(ssl_obj *ssl, + ssl_rec_decoder *d, + int ct, + int version, + UCHAR *in, + int inl, + UCHAR *out, + int *outl) { + int pad, i; + int r, encpadl, x, _status = 0; + UCHAR aad[5], aead_nonce[12], *tag; + int taglen = d->cs->enc == ENC_AES128_CCM_8 ? 8 : 16; + CRDUMP("CipherText", in, inl); + CRDUMPD("KEY", d->write_key); + CRDUMPD("IV", d->implicit_iv); + if(!IS_AEAD_CIPHER(d->cs)) { + fprintf(stderr, "Non aead cipher in tls13\n"); + ABORT(-1); + } + memcpy(aead_nonce, d->implicit_iv->data, 12); + for(i = 0; i < 8; i++) { // AEAD NONCE according to RFC TLS1.3 + aead_nonce[12 - 1 - i] ^= ((d->seq >> (i * 8)) & 0xFF); + } + d->seq++; + CRDUMP("NONCE", aead_nonce, 12); + tag = in + (inl - taglen); + CRDUMP("Tag", tag, taglen); - CRDUMP("Real CipherText", in, inl); - if (!EVP_DecryptUpdate(d->evp,out,outl,in,inl)){ - fprintf(stderr,"Unable to update with CipherText\n"); - ABORT(-1); - } + aad[0] = ct; + aad[1] = 0x03; + aad[2] = 0x03; + aad[3] = MSB(inl); + aad[4] = LSB(inl); + CRDUMP("AAD", aad, 5); + inl -= taglen; - if (!IS_CCM_CIPHER(d->cs) && (!EVP_CIPHER_CTX_ctrl(d->evp,EVP_CTRL_GCM_SET_TAG,taglen,tag) || !EVP_DecryptFinal(d->evp,NULL,&x))) { - fprintf(stderr,"BAD MAC\n"); - ABORT(SSL_BAD_MAC); - } + if(!EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_IVLEN, 12, NULL)) { + fprintf(stderr, "Unable to set ivlen\n"); + ABORT(-1); + } + + if(IS_CCM_CIPHER(d->cs) && + !EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_AEAD_SET_TAG, taglen, tag)) { + fprintf(stderr, "Unable to set tag for ccm cipher\n"); + ABORT(-1); + } + + if(!EVP_DecryptInit_ex(d->evp, NULL, NULL, d->write_key->data, aead_nonce)) { + fprintf(stderr, "Unable to init evp1\n"); + ABORT(-1); + } + + if(IS_CCM_CIPHER(d->cs) && + !EVP_DecryptUpdate(d->evp, NULL, outl, NULL, inl)) { + fprintf(stderr, "Unable to update data length\n"); + ABORT(-1); + } + + if(!EVP_DecryptUpdate(d->evp, NULL, outl, aad, 5)) { + fprintf(stderr, "Unable to update aad\n"); + ABORT(-1); + } + + CRDUMP("Real CipherText", in, inl); + if(!EVP_DecryptUpdate(d->evp, out, outl, in, inl)) { + fprintf(stderr, "Unable to update with CipherText\n"); + ABORT(-1); + } + + if(!IS_CCM_CIPHER(d->cs) && + (!EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_GCM_SET_TAG, taglen, tag) || + !EVP_DecryptFinal(d->evp, NULL, &x))) { + fprintf(stderr, "BAD MAC\n"); + ABORT(SSL_BAD_MAC); + } abort: - ERR_print_errors_fp(stderr); - return _status; + ERR_print_errors_fp(stderr); + return _status; } -int -ssl_decode_rec_data (ssl_obj *ssl, ssl_rec_decoder *d, int ct, int version, UCHAR *in, int inl, UCHAR *out, int *outl) - { +int ssl_decode_rec_data(ssl_obj *ssl, + ssl_rec_decoder *d, + int ct, + int version, + UCHAR *in, + int inl, + UCHAR *out, + int *outl) { #ifdef OPENSSL - int pad; - int r,encpadl,x; - UCHAR *mac,aead_tag[13],aead_nonce[12]; - - CRDUMP("Ciphertext",in,inl); - if(IS_AEAD_CIPHER(d->cs)){ - memcpy(aead_nonce,d->implicit_iv->data,d->implicit_iv->len); - memcpy(aead_nonce+d->implicit_iv->len,in,12-d->implicit_iv->len); - in+=12-d->implicit_iv->len; - inl-=12-d->implicit_iv->len; + int pad; + int r, encpadl, x; + UCHAR *mac, aead_tag[13], aead_nonce[12]; - EVP_DecryptInit(d->evp, - NULL, - d->write_key->data, - aead_nonce); + CRDUMP("Ciphertext", in, inl); + if(IS_AEAD_CIPHER(d->cs)) { + memcpy(aead_nonce, d->implicit_iv->data, d->implicit_iv->len); + memcpy(aead_nonce + d->implicit_iv->len, in, 12 - d->implicit_iv->len); + in += 12 - d->implicit_iv->len; + inl -= 12 - d->implicit_iv->len; - /* - Then tag is always 16 bytes, as per: - https://tools.ietf.org/html/rfc5116#section-5.2 - */ - EVP_CIPHER_CTX_ctrl(d->evp,EVP_CTRL_GCM_SET_TAG,16,in+(inl-16)); - inl-=16; - - fmt_seq(d->seq,aead_tag); - d->seq++; - aead_tag[8]=ct; - aead_tag[9]=MSB(version); - aead_tag[10]=LSB(version); - aead_tag[11]=MSB(inl); - aead_tag[12]=LSB(inl); - - EVP_DecryptUpdate(d->evp,NULL,outl,aead_tag,13); - EVP_DecryptUpdate(d->evp,out,outl,in,inl); - - if (!(x=EVP_DecryptFinal(d->evp,NULL,&x))) - ERETURN(SSL_BAD_MAC); - } + EVP_DecryptInit(d->evp, NULL, d->write_key->data, aead_nonce); /* - Encrypt-then-MAC is not used with AEAD ciphers, as per: - https://tools.ietf.org/html/rfc7366#section-3 + Then tag is always 16 bytes, as per: + https://tools.ietf.org/html/rfc5116#section-5.2 */ - else if(ssl->extensions->encrypt_then_mac==2){ - *outl=inl; + EVP_CIPHER_CTX_ctrl(d->evp, EVP_CTRL_GCM_SET_TAG, 16, in + (inl - 16)); + inl -= 16; - /* First strip off the MAC */ - *outl-=d->cs->dig_len; - mac=in+(*outl); + fmt_seq(d->seq, aead_tag); + d->seq++; + aead_tag[8] = ct; + aead_tag[9] = MSB(version); + aead_tag[10] = LSB(version); + aead_tag[11] = MSB(inl); + aead_tag[12] = LSB(inl); - encpadl=*outl; - /* Now decrypt */ - EVP_Cipher(d->evp,out,in,*outl); - CRDUMP("Plaintext",out,*outl); + EVP_DecryptUpdate(d->evp, NULL, outl, aead_tag, 13); + EVP_DecryptUpdate(d->evp, out, outl, in, inl); - /* And then strip off the padding*/ - if(d->cs->block>1){ - pad=out[*outl-1]; - *outl-=(pad+1); + if(!(x = EVP_DecryptFinal(d->evp, NULL, &x))) + ERETURN(SSL_BAD_MAC); + } + + /* + Encrypt-then-MAC is not used with AEAD ciphers, as per: + https://tools.ietf.org/html/rfc7366#section-3 + */ + else if(ssl->extensions->encrypt_then_mac == 2) { + *outl = inl; + + /* First strip off the MAC */ + *outl -= d->cs->dig_len; + mac = in + (*outl); + + encpadl = *outl; + /* Now decrypt */ + EVP_Cipher(d->evp, out, in, *outl); + CRDUMP("Plaintext", out, *outl); + + /* And then strip off the padding*/ + if(d->cs->block > 1) { + pad = out[*outl - 1]; + *outl -= (pad + 1); + } + /* TLS 1.1 and beyond: remove explicit IV, only used with + * non-stream ciphers. */ + if(ssl->version >= 0x0302 && ssl->cs->block > 1) { + UINT4 blk = ssl->cs->block; + if(blk <= *outl) { + *outl -= blk; + memmove(out, out + blk, *outl); + } else { + DBG((0, "Block size greater than Plaintext!")); + ERETURN(SSL_BAD_MAC); } + + if((r = tls_check_mac(d, ct, version, in + blk, encpadl, in, blk, mac))) + ERETURN(r); + + } else if((r = tls_check_mac(d, ct, version, in, encpadl, NULL, 0, mac))) + ERETURN(r); + + } else { + /* First decrypt*/ + EVP_Cipher(d->evp, out, in, inl); + + CRDUMP("Plaintext", out, inl); + *outl = inl; + + /* Now strip off the padding*/ + if(d->cs->block > 1) { + pad = out[inl - 1]; + *outl -= (pad + 1); + } + + /* And the MAC */ + *outl -= d->cs->dig_len; + mac = out + (*outl); + CRDUMP("Record data", out, *outl); + + /* Now check the MAC */ + if(ssl->version == 0x300) { + if((r = ssl3_check_mac(d, ct, version, out, *outl, mac))) + ERETURN(r); + } else { /* TLS 1.1 and beyond: remove explicit IV, only used with * non-stream ciphers. */ - if (ssl->version>=0x0302 && ssl->cs->block > 1) { - UINT4 blk = ssl->cs->block; - if (blk <= *outl) { - *outl-=blk; - memmove(out, out+blk, *outl); - } - else { - DBG((0,"Block size greater than Plaintext!")); - ERETURN(SSL_BAD_MAC); - } - - if((r=tls_check_mac(d,ct,version,in+blk,encpadl,in,blk,mac))) - ERETURN(r); - + if(ssl->version >= 0x0302 && ssl->cs->block > 1) { + UINT4 blk = ssl->cs->block; + if(blk <= *outl) { + *outl -= blk; + memmove(out, out + blk, *outl); + } else { + DBG((0, "Block size greater than Plaintext!")); + ERETURN(SSL_BAD_MAC); + } } - else - if((r=tls_check_mac(d,ct,version,in,encpadl,NULL,0,mac))) - ERETURN(r); - + if((r = tls_check_mac(d, ct, version, out, *outl, NULL, 0, mac))) + ERETURN(r); } - else { - /* First decrypt*/ - EVP_Cipher(d->evp,out,in,inl); - - CRDUMP("Plaintext",out,inl); - *outl=inl; - - /* Now strip off the padding*/ - if(d->cs->block>1){ - pad=out[inl-1]; - *outl-=(pad+1); - } - - /* And the MAC */ - *outl-=d->cs->dig_len; - mac=out+(*outl); - CRDUMP("Record data",out,*outl); - - /* Now check the MAC */ - if(ssl->version==0x300){ - if((r=ssl3_check_mac(d,ct,version,out,*outl,mac))) - ERETURN(r); - } - else{ - /* TLS 1.1 and beyond: remove explicit IV, only used with - * non-stream ciphers. */ - if (ssl->version>=0x0302 && ssl->cs->block > 1) { - UINT4 blk = ssl->cs->block; - if (blk <= *outl) { - *outl-=blk; - memmove(out, out+blk, *outl); - } - else { - DBG((0,"Block size greater than Plaintext!")); - ERETURN(SSL_BAD_MAC); - } - } - if((r=tls_check_mac(d,ct,version,out,*outl,NULL,0,mac))) - ERETURN(r); - } - } -#endif - return(0); } - +#endif + return (0); +} #ifdef OPENSSL /* This should go to 2^128, but we're never really going to see more than 2^64, so we cheat*/ -static int -fmt_seq (UINT4 num, UCHAR *buf) - { - UINT4 netnum; - - memset(buf,0,8); - netnum=htonl(num); - memcpy(buf+4,&netnum,4); +static int fmt_seq(UINT4 num, UCHAR *buf) { + UINT4 netnum; - return(0); - } + memset(buf, 0, 8); + netnum = htonl(num); + memcpy(buf + 4, &netnum, 4); -static int -tls_check_mac (ssl_rec_decoder *d, int ct, int ver, UCHAR *data, UINT4 datalen, UCHAR *iv, UINT4 ivlen, UCHAR *mac) - { - HMAC_CTX *hm = HMAC_CTX_new(); - if(!hm) - ERETURN(R_NO_MEMORY); - const EVP_MD *md; - UINT4 l; - UCHAR buf[128]; - - md=EVP_get_digestbyname(digests[d->cs->dig-0x40]); - HMAC_Init_ex(hm,d->mac_key->data,d->mac_key->len,md,NULL); + return (0); +} - fmt_seq(d->seq,buf); - d->seq++; - HMAC_Update(hm,buf,8); - buf[0]=ct; - HMAC_Update(hm,buf,1); +static int tls_check_mac(ssl_rec_decoder *d, + int ct, + int ver, + UCHAR *data, + UINT4 datalen, + UCHAR *iv, + UINT4 ivlen, + UCHAR *mac) { + HMAC_CTX *hm = HMAC_CTX_new(); + if(!hm) + ERETURN(R_NO_MEMORY); + const EVP_MD *md; + UINT4 l; + UCHAR buf[128]; - buf[0]=MSB(ver); - buf[1]=LSB(ver); - HMAC_Update(hm,buf,2); + md = EVP_get_digestbyname(digests[d->cs->dig - 0x40]); + HMAC_Init_ex(hm, d->mac_key->data, d->mac_key->len, md, NULL); - buf[0]=MSB(datalen); - buf[1]=LSB(datalen); - HMAC_Update(hm,buf,2); + fmt_seq(d->seq, buf); + d->seq++; + HMAC_Update(hm, buf, 8); + buf[0] = ct; + HMAC_Update(hm, buf, 1); - /* for encrypt-then-mac with an explicit IV */ - if(ivlen && iv){ - HMAC_Update(hm,iv,ivlen); - HMAC_Update(hm,data,datalen-ivlen); - } - else - HMAC_Update(hm,data,datalen); - - HMAC_Final(hm,buf,&l); - if(memcmp(mac,buf,l)) - ERETURN(SSL_BAD_MAC); + buf[0] = MSB(ver); + buf[1] = LSB(ver); + HMAC_Update(hm, buf, 2); - HMAC_CTX_free(hm); - return(0); - } + buf[0] = MSB(datalen); + buf[1] = LSB(datalen); + HMAC_Update(hm, buf, 2); -int -ssl3_check_mac (ssl_rec_decoder *d, int ct, int ver, UCHAR *data, UINT4 datalen, UCHAR *mac) - { - EVP_MD_CTX *mc = EVP_MD_CTX_new(); - const EVP_MD *md; - UINT4 l; - UCHAR buf[64],dgst[20]; - int pad_ct; + /* for encrypt-then-mac with an explicit IV */ + if(ivlen && iv) { + HMAC_Update(hm, iv, ivlen); + HMAC_Update(hm, data, datalen - ivlen); + } else + HMAC_Update(hm, data, datalen); - pad_ct=(d->cs->dig==DIG_SHA)?40:48; - - md=EVP_get_digestbyname(digests[d->cs->dig-0x40]); - EVP_DigestInit(mc,md); + HMAC_Final(hm, buf, &l); + if(memcmp(mac, buf, l)) + ERETURN(SSL_BAD_MAC); - EVP_DigestUpdate(mc,d->mac_key->data,d->mac_key->len); + HMAC_CTX_free(hm); + return (0); +} - memset(buf,0x36,pad_ct); - EVP_DigestUpdate(mc,buf,pad_ct); +int ssl3_check_mac(ssl_rec_decoder *d, + int ct, + int ver, + UCHAR *data, + UINT4 datalen, + UCHAR *mac) { + EVP_MD_CTX *mc = EVP_MD_CTX_new(); + const EVP_MD *md; + UINT4 l; + UCHAR buf[64], dgst[20]; + int pad_ct; - fmt_seq(d->seq,buf); - d->seq++; - EVP_DigestUpdate(mc,buf,8); + pad_ct = (d->cs->dig == DIG_SHA) ? 40 : 48; - buf[0]=ct; - EVP_DigestUpdate(mc,buf,1); - - buf[0]=MSB(datalen); - buf[1]=LSB(datalen); - EVP_DigestUpdate(mc,buf,2); + md = EVP_get_digestbyname(digests[d->cs->dig - 0x40]); + EVP_DigestInit(mc, md); - EVP_DigestUpdate(mc,data,datalen); + EVP_DigestUpdate(mc, d->mac_key->data, d->mac_key->len); - EVP_DigestFinal(mc,dgst,&l); - - EVP_DigestInit(mc,md); + memset(buf, 0x36, pad_ct); + EVP_DigestUpdate(mc, buf, pad_ct); - EVP_DigestUpdate(mc,d->mac_key->data,d->mac_key->len); - - memset(buf,0x5c,pad_ct); - EVP_DigestUpdate(mc,buf,pad_ct); + fmt_seq(d->seq, buf); + d->seq++; + EVP_DigestUpdate(mc, buf, 8); - EVP_DigestUpdate(mc,dgst,l); + buf[0] = ct; + EVP_DigestUpdate(mc, buf, 1); - EVP_DigestFinal(mc,dgst,&l); + buf[0] = MSB(datalen); + buf[1] = LSB(datalen); + EVP_DigestUpdate(mc, buf, 2); - if(memcmp(mac,dgst,l)) - ERETURN(SSL_BAD_MAC); + EVP_DigestUpdate(mc, data, datalen); - EVP_MD_CTX_free(mc); + EVP_DigestFinal(mc, dgst, &l); - return(0); - } - -#endif + EVP_DigestInit(mc, md); + + EVP_DigestUpdate(mc, d->mac_key->data, d->mac_key->len); + + memset(buf, 0x5c, pad_ct); + EVP_DigestUpdate(mc, buf, pad_ct); + + EVP_DigestUpdate(mc, dgst, l); + + EVP_DigestFinal(mc, dgst, &l); + + if(memcmp(mac, dgst, l)) + ERETURN(SSL_BAD_MAC); + + EVP_MD_CTX_free(mc); + + return (0); +} + +#endif diff --git a/ssl/ssl_rec.h b/ssl/ssl_rec.h index 3d2738a..87b066f 100644 --- a/ssl/ssl_rec.h +++ b/ssl/ssl_rec.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssl_rec.h,v 1.2 2000/10/17 16:10:02 ekr Exp $ @@ -43,24 +44,43 @@ ekr@rtfm.com Wed Aug 18 16:16:23 1999 */ - #ifndef _ssl_rec_h #define _ssl_rec_h typedef struct ssl_rec_decoder_ ssl_rec_decoder; -int ssl_destroy_rec_decoder PROTO_LIST((ssl_rec_decoder **dp)); -int ssl_create_rec_decoder PROTO_LIST((ssl_rec_decoder **dp, - ssl_obj *ssl,UCHAR *mk,UCHAR *sk,UCHAR *iv)); -int ssl_decode_rec_data PROTO_LIST((ssl_obj *ssl,ssl_rec_decoder *d, - int ct,int version,UCHAR *in,int inl,UCHAR *out,int *outl)); -int tls13_decode_rec_data PROTO_LIST((ssl_obj *ssl,ssl_rec_decoder *d,int ct,int version,UCHAR *in,int inl,UCHAR *out,int *outl)); -int tls13_update_rec_key PROTO_LIST((ssl_rec_decoder *d,UCHAR *newkey, UCHAR *newiv)); +int ssl_destroy_rec_decoder PROTO_LIST((ssl_rec_decoder * *dp)); +int ssl_create_rec_decoder PROTO_LIST( + (ssl_rec_decoder * *dp, ssl_obj *ssl, UCHAR *mk, UCHAR *sk, UCHAR *iv)); +int ssl_decode_rec_data PROTO_LIST((ssl_obj * ssl, + ssl_rec_decoder *d, + int ct, + int version, + UCHAR *in, + int inl, + UCHAR *out, + int *outl)); +int tls13_decode_rec_data PROTO_LIST((ssl_obj * ssl, + ssl_rec_decoder *d, + int ct, + int version, + UCHAR *in, + int inl, + UCHAR *out, + int *outl)); +int tls13_update_rec_key PROTO_LIST((ssl_rec_decoder * d, + UCHAR *newkey, + UCHAR *newiv)); -int ssl3_check_mac(ssl_rec_decoder *d, int ct, int ver, UCHAR *data, - UINT4 datalen, UCHAR *mac); +int ssl3_check_mac(ssl_rec_decoder *d, + int ct, + int ver, + UCHAR *data, + UINT4 datalen, + UCHAR *mac); -#define IS_AEAD_CIPHER(cs) (cs->enc==0x3b||cs->enc==0x3c||cs->enc==0x3d||cs->enc==0x3e||cs->enc==0x3f) -#define IS_CCM_CIPHER(cs) (cs->enc==0x3e||cs->enc==0x3f) +#define IS_AEAD_CIPHER(cs) \ + (cs->enc == 0x3b || cs->enc == 0x3c || cs->enc == 0x3d || cs->enc == 0x3e || \ + cs->enc == 0x3f) +#define IS_CCM_CIPHER(cs) (cs->enc == 0x3e || cs->enc == 0x3f) #endif - diff --git a/ssl/sslciphers.h b/ssl/sslciphers.h index 9a1cfcc..718251c 100644 --- a/ssl/sslciphers.h +++ b/ssl/sslciphers.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: sslciphers.h,v 1.3 2002/08/17 01:33:17 ekr Exp $ @@ -43,55 +44,52 @@ ekr@rtfm.com Tue Mar 30 18:11:55 1999 */ - #ifndef _sslciphers_h #define _sslciphers_h typedef struct SSL_CipherSuite_ { - int number; - int kex; - int sig; - int enc; - int block; - int bits; - int eff_bits; - int dig; - int dig_len; - int export; + int number; + int kex; + int sig; + int enc; + int block; + int bits; + int eff_bits; + int dig; + int dig_len; + int export; } SSL_CipherSuite; -#define KEX_RSA 0x10 -#define KEX_DH 0x11 +#define KEX_RSA 0x10 +#define KEX_DH 0x11 -#define SIG_RSA 0x20 -#define SIG_DSS 0x21 -#define SIG_NONE 0x22 +#define SIG_RSA 0x20 +#define SIG_DSS 0x21 +#define SIG_NONE 0x22 -#define ENC_DES 0x30 -#define ENC_3DES 0x31 -#define ENC_RC4 0x32 -#define ENC_RC2 0x33 -#define ENC_IDEA 0x34 -#define ENC_AES128 0x35 -#define ENC_AES256 0x36 -#define ENC_CAMELLIA128 0x37 -#define ENC_CAMELLIA256 0x38 -#define ENC_SEED 0x39 -#define ENC_NULL 0x3a -#define ENC_AES128_GCM 0x3b -#define ENC_AES256_GCM 0x3c -#define ENC_CHACHA20_POLY1305 0x3d -#define ENC_AES128_CCM 0x3e -#define ENC_AES128_CCM_8 0x3f +#define ENC_DES 0x30 +#define ENC_3DES 0x31 +#define ENC_RC4 0x32 +#define ENC_RC2 0x33 +#define ENC_IDEA 0x34 +#define ENC_AES128 0x35 +#define ENC_AES256 0x36 +#define ENC_CAMELLIA128 0x37 +#define ENC_CAMELLIA256 0x38 +#define ENC_SEED 0x39 +#define ENC_NULL 0x3a +#define ENC_AES128_GCM 0x3b +#define ENC_AES256_GCM 0x3c +#define ENC_CHACHA20_POLY1305 0x3d +#define ENC_AES128_CCM 0x3e +#define ENC_AES128_CCM_8 0x3f -#define DIG_MD5 0x40 -#define DIG_SHA 0x41 -#define DIG_SHA224 0x42 /* Not sure why EKR didn't follow RFC for */ -#define DIG_SHA256 0x43 /* these values, but whatever, just adding on */ -#define DIG_SHA384 0x44 -#define DIG_SHA512 0x45 - -int ssl_find_cipher PROTO_LIST((int num,SSL_CipherSuite **cs)); +#define DIG_MD5 0x40 +#define DIG_SHA 0x41 +#define DIG_SHA224 0x42 /* Not sure why EKR didn't follow RFC for */ +#define DIG_SHA256 0x43 /* these values, but whatever, just adding on */ +#define DIG_SHA384 0x44 +#define DIG_SHA512 0x45 +int ssl_find_cipher PROTO_LIST((int num, SSL_CipherSuite **cs)); #endif - diff --git a/ssl/ssldecode.c b/ssl/ssldecode.c index 7bfb4b2..d963cab 100644 --- a/ssl/ssldecode.c +++ b/ssl/ssldecode.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssldecode.c,v 1.9 2002/08/17 01:33:17 ekr Exp $ @@ -60,12 +61,12 @@ #include "ssl_rec.h" #include "r_assoc.h" -#define PRF(ssl,secret,usage,rnd1,rnd2,out) (ssl->version==SSLV3_VERSION)? \ - ssl3_prf(ssl,secret,usage,rnd1,rnd2,out): \ - ((ssl->version == TLSV12_VERSION) ? \ - tls12_prf(ssl,secret,usage,rnd1,rnd2,out): \ - tls_prf(ssl,secret,usage,rnd1,rnd2,out)) - +#define PRF(ssl, secret, usage, rnd1, rnd2, out) \ + (ssl->version == SSLV3_VERSION) \ + ? ssl3_prf(ssl, secret, usage, rnd1, rnd2, out) \ + : ((ssl->version == TLSV12_VERSION) \ + ? tls12_prf(ssl, secret, usage, rnd1, rnd2, out) \ + : tls_prf(ssl, secret, usage, rnd1, rnd2, out)) static char *ssl_password; @@ -73,1277 +74,1297 @@ extern char *digests[]; extern UINT4 SSL_print_flags; struct ssl_decode_ctx_ { -#ifdef OPENSSL - SSL_CTX *ssl_ctx; - SSL *ssl; - r_assoc *session_cache; - FILE *ssl_key_log_file; +#ifdef OPENSSL + SSL_CTX *ssl_ctx; + SSL *ssl; + r_assoc *session_cache; + FILE *ssl_key_log_file; #else - char dummy; /* Some compilers (Win32) don't like empty - structs */ -#endif + char dummy; /* Some compilers (Win32) don't like empty + structs */ +#endif }; struct ssl_decoder_ { - ssl_decode_ctx *ctx; - Data *session_id; - SSL_CipherSuite *cs; - Data *client_random; - Data *server_random; - int ephemeral_rsa; - Data *PMS; - Data *MS; - Data *SHTS;//Server Handshake traffic secret - Data *CHTS;//Client Handshake traffic secret - Data *STS;//Server traffic Secret - Data *CTS;//Client traffic secret - Data *handshake_messages; - Data *session_hash; - ssl_rec_decoder *c_to_s; - ssl_rec_decoder *s_to_c; - ssl_rec_decoder *c_to_s_n; - ssl_rec_decoder *s_to_c_n; + ssl_decode_ctx *ctx; + Data *session_id; + SSL_CipherSuite *cs; + Data *client_random; + Data *server_random; + int ephemeral_rsa; + Data *PMS; + Data *MS; + Data *SHTS; // Server Handshake traffic secret + Data *CHTS; // Client Handshake traffic secret + Data *STS; // Server traffic Secret + Data *CTS; // Client traffic secret + Data *handshake_messages; + Data *session_hash; + ssl_rec_decoder *c_to_s; + ssl_rec_decoder *s_to_c; + ssl_rec_decoder *c_to_s_n; + ssl_rec_decoder *s_to_c_n; }; - #ifdef OPENSSL -static int tls_P_hash PROTO_LIST((ssl_obj *ssl,Data *secret,Data *seed, - const EVP_MD *md,Data *out)); -static int tls12_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage, - Data *rnd1,Data *rnd2,Data *out)); -static int tls_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage, - Data *rnd1,Data *rnd2,Data *out)); -static int ssl3_prf PROTO_LIST((ssl_obj *ssl,Data *secret,char *usage, - Data *rnd1,Data *rnd2,Data *out)); -static int ssl3_generate_export_iv PROTO_LIST((ssl_obj *ssl, - Data *rnd1,Data *rnd2,Data *out)); -static int ssl_generate_keying_material PROTO_LIST((ssl_obj *ssl, - ssl_decoder *d)); -static int ssl_generate_session_hash PROTO_LIST((ssl_obj *ssl, - ssl_decoder *d)); -static int ssl_read_key_log_file PROTO_LIST((ssl_obj* obj,ssl_decoder *d)); +static int tls_P_hash PROTO_LIST( + (ssl_obj * ssl, Data *secret, Data *seed, const EVP_MD *md, Data *out)); +static int tls12_prf PROTO_LIST((ssl_obj * ssl, + Data *secret, + char *usage, + Data *rnd1, + Data *rnd2, + Data *out)); +static int tls_prf PROTO_LIST((ssl_obj * ssl, + Data *secret, + char *usage, + Data *rnd1, + Data *rnd2, + Data *out)); +static int ssl3_prf PROTO_LIST((ssl_obj * ssl, + Data *secret, + char *usage, + Data *rnd1, + Data *rnd2, + Data *out)); +static int ssl3_generate_export_iv + PROTO_LIST((ssl_obj * ssl, Data *rnd1, Data *rnd2, Data *out)); +static int ssl_generate_keying_material PROTO_LIST((ssl_obj * ssl, + ssl_decoder *d)); +static int ssl_generate_session_hash PROTO_LIST((ssl_obj * ssl, + ssl_decoder *d)); +static int ssl_read_key_log_file PROTO_LIST((ssl_obj * obj, ssl_decoder *d)); #endif -static int ssl_create_session_lookup_key PROTO_LIST((ssl_obj *ssl, - UCHAR *id,UINT4 idlen,UCHAR **keyp,UINT4 *keyl)); -int ssl_save_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d)); -int ssl_restore_session PROTO_LIST((ssl_obj *ssl,ssl_decoder *d)); +static int ssl_create_session_lookup_key PROTO_LIST( + (ssl_obj * ssl, UCHAR *id, UINT4 idlen, UCHAR **keyp, UINT4 *keyl)); +int ssl_save_session PROTO_LIST((ssl_obj * ssl, ssl_decoder *d)); +int ssl_restore_session PROTO_LIST((ssl_obj * ssl, ssl_decoder *d)); /*The password code is not thread safe*/ -static int password_cb(char *buf,int num,int rwflag,void *userdata) - { - if(numssl_ctx=SSL_CTX_new(SSLv23_server_method()))) - ABORT(R_NO_MEMORY); - if(keyfile){ - if(pass){ - ssl_password=pass; - SSL_CTX_set_default_passwd_cb(d->ssl_ctx,password_cb); - } +int ssl_decode_ctx_create(ssl_decode_ctx **dp, + char *keyfile, + char *pass, + char *keylogfile) { +#ifdef OPENSSL + ssl_decode_ctx *d = 0; + int _status; + + SSL_library_init(); + OpenSSL_add_all_algorithms(); + if(!(d = (ssl_decode_ctx *)malloc(sizeof(ssl_decode_ctx)))) + ABORT(R_NO_MEMORY); + if(!(d->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) + ABORT(R_NO_MEMORY); + if(keyfile) { + if(pass) { + ssl_password = pass; + SSL_CTX_set_default_passwd_cb(d->ssl_ctx, password_cb); + } #if 0 if(SSL_CTX_use_certificate_file(d->ssl_ctx,keyfile,SSL_FILETYPE_PEM)!=1){ fprintf(stderr,"Problem loading certificate file\n"); ABORT(R_INTERNAL); } -#endif - if(SSL_CTX_use_PrivateKey_file(d->ssl_ctx,keyfile,SSL_FILETYPE_PEM)!=1){ - fprintf(stderr,"Problem loading private key\n"); - ABORT(R_INTERNAL); - } - } - if(!(d->ssl=SSL_new(d->ssl_ctx))) - ABORT(R_NO_MEMORY); - - if(r_assoc_create(&d->session_cache)) - ABORT(R_NO_MEMORY); - - if (keylogfile) { - if(!(d->ssl_key_log_file=fopen(keylogfile, "r"))){ - fprintf(stderr,"Failed to open ssl key log file"); - ABORT(R_INTERNAL); - } - } else { - d->ssl_key_log_file = NULL; - } - - X509V3_add_standard_extensions(); - - *dp=d; - _status=0; - abort: - return(_status); -#else - return(0); #endif + if(SSL_CTX_use_PrivateKey_file(d->ssl_ctx, keyfile, SSL_FILETYPE_PEM) != + 1) { + fprintf(stderr, "Problem loading private key\n"); + ABORT(R_INTERNAL); + } + } + if(!(d->ssl = SSL_new(d->ssl_ctx))) + ABORT(R_NO_MEMORY); + + if(r_assoc_create(&d->session_cache)) + ABORT(R_NO_MEMORY); + + if(keylogfile) { + if(!(d->ssl_key_log_file = fopen(keylogfile, "r"))) { + fprintf(stderr, "Failed to open ssl key log file"); + ABORT(R_INTERNAL); + } + } else { + d->ssl_key_log_file = NULL; } -int -ssl_decode_ctx_destroy (ssl_decode_ctx **dp) - { -#ifdef OPENSSL - ssl_decode_ctx *d = *dp; - if (!d) return 0; - if(d->ssl_key_log_file) { - fclose(d->ssl_key_log_file); - } + X509V3_add_standard_extensions(); - 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 (ssl_decoder **dp, ssl_decode_ctx *ctx) - { - int _status; - - ssl_decoder *d=0; - -#ifdef OPENSSL - if(!(d=(ssl_decoder *)calloc(1,sizeof(ssl_decoder)))) - ABORT(R_NO_MEMORY); - d->ctx=ctx; - - *dp=d; - _status=0; - abort: - if(_status) - ssl_decoder_destroy(&d); - return(_status); + *dp = d; + _status = 0; +abort: + return (_status); #else + return (0); +#endif +} + +int ssl_decode_ctx_destroy(ssl_decode_ctx **dp) { +#ifdef OPENSSL + ssl_decode_ctx *d = *dp; + if(!d) return 0; + 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_destroy (ssl_decoder **dp) - { -#ifdef OPENSSL - ssl_decoder *d; +int ssl_decoder_create(ssl_decoder **dp, ssl_decode_ctx *ctx) { + int _status; - if(!dp || !*dp) - return(0); - d=*dp; - r_data_destroy(&d->client_random); - r_data_destroy(&d->server_random); - r_data_destroy(&d->session_id); - r_data_destroy(&d->PMS); - r_data_destroy(&d->MS); - r_data_destroy(&d->handshake_messages); - r_data_destroy(&d->session_hash); - ssl_destroy_rec_decoder(&d->c_to_s); - ssl_destroy_rec_decoder(&d->c_to_s_n); - ssl_destroy_rec_decoder(&d->s_to_c); - ssl_destroy_rec_decoder(&d->s_to_c_n); - free(d); - *dp=0; -#endif - return(0); - } + ssl_decoder *d = 0; -int -ssl_set_client_random (ssl_decoder *d, UCHAR *msg, int len) - { -#ifdef OPENSSL - int r; - - r_data_destroy(&d->client_random); - if((r=r_data_create(&d->client_random,msg,len))) - ERETURN(r); -#endif - return(0); - } - -int -ssl_set_server_random (ssl_decoder *d, UCHAR *msg, int len) - { -#ifdef OPENSSL - int r; +#ifdef OPENSSL + if(!(d = (ssl_decoder *)calloc(1, sizeof(ssl_decoder)))) + ABORT(R_NO_MEMORY); + d->ctx = ctx; - r_data_destroy(&d->server_random); - if((r=r_data_create(&d->server_random,msg,len))) - ERETURN(r); -#endif - return(0); - } - -int -ssl_set_client_session_id (ssl_decoder *d, UCHAR *msg, int len) - { -#ifdef OPENSSL - int r; - - if(len>0) { - r_data_destroy(&d->session_id); - if((r=r_data_create(&d->session_id,msg,len))) - ERETURN(r); - } -#endif - return(0); - } - -int -ssl_process_server_session_id (ssl_obj *ssl, ssl_decoder *d, UCHAR *msg, int len) - { -#ifdef OPENSSL - int r,_status; - Data idd; - int restored=0; - - INIT_DATA(idd,msg,len); - - if (ssl->version==TLSV13_VERSION){ - // No need to save/restore session in tls1.3 since the only way of decrypting is through log file - } else { - /* First check to see if the client tried to restore */ - if(d->session_id){ - /* Now check to see if we restored */ - if((r=r_data_compare(&idd,d->session_id))) - ABORT(r); - - /* Now try to look up the session. We may not be able - to find it if, for instance, the original session - was initiated with something other than static RSA */ - if((r=ssl_restore_session(ssl,d))) - ABORT(r); - - restored=1; - } - } - - _status=0; - abort: - if(!restored){ - /* Copy over the session ID */ - r_data_destroy(&d->session_id); - r_data_create(&d->session_id,msg,len); - } - return(_status); + *dp = d; + _status = 0; +abort: + if(_status) + ssl_decoder_destroy(&d); + return (_status); #else - return(0); -#endif + return 0; +#endif +} + +int ssl_decoder_destroy(ssl_decoder **dp) { +#ifdef OPENSSL + ssl_decoder *d; + + if(!dp || !*dp) + return (0); + d = *dp; + r_data_destroy(&d->client_random); + r_data_destroy(&d->server_random); + r_data_destroy(&d->session_id); + r_data_destroy(&d->PMS); + r_data_destroy(&d->MS); + r_data_destroy(&d->handshake_messages); + r_data_destroy(&d->session_hash); + ssl_destroy_rec_decoder(&d->c_to_s); + ssl_destroy_rec_decoder(&d->c_to_s_n); + ssl_destroy_rec_decoder(&d->s_to_c); + ssl_destroy_rec_decoder(&d->s_to_c_n); + free(d); + *dp = 0; +#endif + return (0); +} + +int ssl_set_client_random(ssl_decoder *d, UCHAR *msg, int len) { +#ifdef OPENSSL + int r; + + r_data_destroy(&d->client_random); + if((r = r_data_create(&d->client_random, msg, len))) + ERETURN(r); +#endif + return (0); +} + +int ssl_set_server_random(ssl_decoder *d, UCHAR *msg, int len) { +#ifdef OPENSSL + int r; + + r_data_destroy(&d->server_random); + if((r = r_data_create(&d->server_random, msg, len))) + ERETURN(r); +#endif + return (0); +} + +int ssl_set_client_session_id(ssl_decoder *d, UCHAR *msg, int len) { +#ifdef OPENSSL + int r; + + if(len > 0) { + r_data_destroy(&d->session_id); + if((r = r_data_create(&d->session_id, msg, len))) + ERETURN(r); + } +#endif + return (0); +} + +int ssl_process_server_session_id(ssl_obj *ssl, + ssl_decoder *d, + UCHAR *msg, + int len) { +#ifdef OPENSSL + int r, _status; + Data idd; + int restored = 0; + + INIT_DATA(idd, msg, len); + + if(ssl->version == TLSV13_VERSION) { + // No need to save/restore session in tls1.3 since the only way of + // decrypting is through log file + } else { + /* First check to see if the client tried to restore */ + if(d->session_id) { + /* Now check to see if we restored */ + if((r = r_data_compare(&idd, d->session_id))) + ABORT(r); + + /* Now try to look up the session. We may not be able + to find it if, for instance, the original session + was initiated with something other than static RSA */ + if((r = ssl_restore_session(ssl, d))) + ABORT(r); + + restored = 1; + } } -int -ssl_process_client_session_id (ssl_obj *ssl, ssl_decoder *d, UCHAR *msg, int len) - { -#ifdef OPENSSL - int _status; - - /* First check if the client set session id */ - //todo: check that session_id in decoder and msg are the same (and if not then take from msg?) - if(d->session_id) - { - /* Remove the master secret */ - //todo: better save and destroy only when successfully read key log - r_data_destroy(&d->MS); + _status = 0; +abort: + if(!restored) { + /* Copy over the session ID */ + r_data_destroy(&d->session_id); + r_data_create(&d->session_id, msg, len); + } + return (_status); +#else + return (0); +#endif +} - if(d->ctx->ssl_key_log_file && (ssl_read_key_log_file(ssl, d)==0) && d->MS) - { - //we found master secret for session in keylog - //try to save session - _status = ssl_save_session(ssl,d); - } - else - { - //just return error - _status = -1; - } - } - else - { +int ssl_process_client_session_id(ssl_obj *ssl, + ssl_decoder *d, + UCHAR *msg, + int len) { +#ifdef OPENSSL + int _status; + + /* First check if the client set session id */ + // todo: check that session_id in decoder and msg are the same (and if not + // then take from msg?) + if(d->session_id) { + /* Remove the master secret */ + // todo: better save and destroy only when successfully read key log + r_data_destroy(&d->MS); + + if(d->ctx->ssl_key_log_file && (ssl_read_key_log_file(ssl, d) == 0) && + d->MS) { + // we found master secret for session in keylog + // try to save session + _status = ssl_save_session(ssl, d); + } else { + // just return error _status = -1; } - return(_status); -#else - return(0); -#endif + } else { + _status = -1; } + return (_status); +#else + return (0); +#endif +} -int ssl_process_handshake_finished(ssl_obj* ssl,ssl_decoder *dec, Data *data){ - if (ssl->version==TLSV13_VERSION){ - if (ssl->direction==DIR_I2R){ // Change from handshake decoder to data traffic decoder +int ssl_process_handshake_finished(ssl_obj *ssl, ssl_decoder *dec, Data *data) { + if(ssl->version == TLSV13_VERSION) { + if(ssl->direction == + DIR_I2R) { // Change from handshake decoder to data traffic decoder dec->c_to_s = dec->c_to_s_n; dec->c_to_s_n = 0; - } else { + } else { dec->s_to_c = dec->s_to_c_n; dec->s_to_c_n = 0; } - } + } } -int -ssl_process_change_cipher_spec (ssl_obj *ssl, ssl_decoder *d, int direction) - { +int ssl_process_change_cipher_spec(ssl_obj *ssl, + ssl_decoder *d, + int direction) { #ifdef OPENSSL - if (ssl->version!=TLSV13_VERSION){ - if(direction==DIR_I2R){ - d->c_to_s=d->c_to_s_n; - d->c_to_s_n=0; - if(d->c_to_s) ssl->process_ciphertext |= direction; - } - else { - d->s_to_c=d->s_to_c_n; - d->s_to_c_n=0; - if(d->s_to_c) ssl->process_ciphertext |= direction; - } + if(ssl->version != TLSV13_VERSION) { + if(direction == DIR_I2R) { + d->c_to_s = d->c_to_s_n; + d->c_to_s_n = 0; + if(d->c_to_s) + ssl->process_ciphertext |= direction; + } else { + d->s_to_c = d->s_to_c_n; + d->s_to_c_n = 0; + if(d->s_to_c) + ssl->process_ciphertext |= direction; } -#endif - return(0); } -int -ssl_decode_record (ssl_obj *ssl, ssl_decoder *dec, int direction, int ct, int version, Data *d) - { - ssl_rec_decoder *rd; - UCHAR *out; - int outl; - int r,_status; - UINT4 state; - - if(dec) - rd=(direction==DIR_I2R)?dec->c_to_s:dec->s_to_c; - else - rd=0; - state=(direction==DIR_I2R)?ssl->i_state:ssl->r_state; - - if (ssl->version == TLSV13_VERSION && ct != 23) { // Only type 23 is encrypted in tls1.3 - ssl->record_encryption = REC_PLAINTEXT; - return 0; - } else if(!rd){ - if(state & SSL_ST_SENT_CHANGE_CIPHER_SPEC){ - ssl->record_encryption=REC_CIPHERTEXT; - return(SSL_NO_DECRYPT); - } - else { - ssl->record_encryption=REC_PLAINTEXT; - return(0); - } - } - - ssl->record_encryption=REC_CIPHERTEXT; -#ifdef OPENSSL - if(!(out=(UCHAR *)malloc(d->len))) - ABORT(R_NO_MEMORY); - - if (ssl->version==TLSV13_VERSION){ - r=tls13_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl); - } else { - r=ssl_decode_rec_data(ssl,rd,ct,version,d->data,d->len,out,&outl); - } - if(r) { - ABORT(r); - } - - memcpy(d->data,out,outl); - d->len=outl; - - ssl->record_encryption=REC_DECRYPTED_CIPHERTEXT; - - _status=0; - abort: - FREE(out); - return(_status); -#else - return(0); -#endif - } - -int -ssl_update_handshake_messages (ssl_obj *ssl, Data *data) - { -#ifdef OPENSSL - Data *hms; - UCHAR *d; - int l,r; - - hms = ssl->decoder->handshake_messages; - d = data->data-4; - l = data->len+4; - - if(hms){ - if(!(hms->data = realloc(hms->data,l+hms->len))) - ERETURN(R_NO_MEMORY); - - memcpy(hms->data+hms->len,d,l); - hms->len+=l; - } - else{ - if((r=r_data_create(&hms,d,l))) - ERETURN(r); - ssl->decoder->handshake_messages=hms; - } #endif - return(0); + return (0); +} +int ssl_decode_record(ssl_obj *ssl, + ssl_decoder *dec, + int direction, + int ct, + int version, + Data *d) { + ssl_rec_decoder *rd; + UCHAR *out; + int outl; + int r, _status; + UINT4 state; - } + if(dec) + rd = (direction == DIR_I2R) ? dec->c_to_s : dec->s_to_c; + else + rd = 0; + state = (direction == DIR_I2R) ? ssl->i_state : ssl->r_state; -static int -ssl_create_session_lookup_key (ssl_obj *ssl, UCHAR *id, UINT4 idlen, UCHAR **keyp, UINT4 *keyl) - { - UCHAR *key=0; - UINT4 l; - int _status; - - l=idlen+strlen(ssl->server_name)+idlen+15; /* HOST + PORT + id */ - - if(!(key=(UCHAR *)malloc(l))) - ABORT(R_NO_MEMORY); - *keyp=key; - - memcpy(key,id,idlen); - *keyl=idlen; - key+=idlen; - - snprintf((char *)key,l,"%s:%d",ssl->server_name,ssl->server_port); - *keyl+=strlen((char *)key); - - _status=0; - abort: - return(_status); - } - -/* Look up the session id in the session cache and generate - the appropriate keying material */ -int -ssl_restore_session (ssl_obj *ssl, ssl_decoder *d) - { - UCHAR *lookup_key=0; - void *msv; - Data *msd; - int lookup_key_len; - int r,_status; -#ifdef OPENSSL - if((r=ssl_create_session_lookup_key(ssl, - d->session_id->data,d->session_id->len,&lookup_key, - (UINT4 *) &lookup_key_len))) - ABORT(r); - if((r=r_assoc_fetch(d->ctx->session_cache,(char *) lookup_key,lookup_key_len, - &msv))) - ABORT(r); - msd=(Data *)msv; - if((r=r_data_create(&d->MS,msd->data,msd->len))) - ABORT(r); - CRDUMPD("Restored MS",d->MS); - - switch(ssl->version){ - case SSLV3_VERSION: - case TLSV1_VERSION: - case TLSV11_VERSION: - case TLSV12_VERSION: - if((r=ssl_generate_keying_material(ssl,d))) - ABORT(r); - break; - default: - ABORT(SSL_CANT_DO_CIPHER); + if(ssl->version == TLSV13_VERSION && + ct != 23) { // Only type 23 is encrypted in tls1.3 + ssl->record_encryption = REC_PLAINTEXT; + return 0; + } else if(!rd) { + if(state & SSL_ST_SENT_CHANGE_CIPHER_SPEC) { + ssl->record_encryption = REC_CIPHERTEXT; + return (SSL_NO_DECRYPT); + } else { + ssl->record_encryption = REC_PLAINTEXT; + return (0); } - - _status=0; - abort: - FREE(lookup_key); - return(_status); -#else - return(0); -#endif } + ssl->record_encryption = REC_CIPHERTEXT; +#ifdef OPENSSL + if(!(out = (UCHAR *)malloc(d->len))) + ABORT(R_NO_MEMORY); + + if(ssl->version == TLSV13_VERSION) { + r = tls13_decode_rec_data(ssl, rd, ct, version, d->data, d->len, out, + &outl); + } else { + r = ssl_decode_rec_data(ssl, rd, ct, version, d->data, d->len, out, &outl); + } + if(r) { + ABORT(r); + } + + memcpy(d->data, out, outl); + d->len = outl; + + ssl->record_encryption = REC_DECRYPTED_CIPHERTEXT; + + _status = 0; +abort: + FREE(out); + return (_status); +#else + return (0); +#endif +} + +int ssl_update_handshake_messages(ssl_obj *ssl, Data *data) { +#ifdef OPENSSL + Data *hms; + UCHAR *d; + int l, r; + + hms = ssl->decoder->handshake_messages; + d = data->data - 4; + l = data->len + 4; + + if(hms) { + if(!(hms->data = realloc(hms->data, l + hms->len))) + ERETURN(R_NO_MEMORY); + + memcpy(hms->data + hms->len, d, l); + hms->len += l; + } else { + if((r = r_data_create(&hms, d, l))) + ERETURN(r); + ssl->decoder->handshake_messages = hms; + } +#endif + return (0); +} + +static int ssl_create_session_lookup_key(ssl_obj *ssl, + UCHAR *id, + UINT4 idlen, + UCHAR **keyp, + UINT4 *keyl) { + UCHAR *key = 0; + UINT4 l; + int _status; + + l = idlen + strlen(ssl->server_name) + idlen + 15; /* HOST + PORT + id */ + + if(!(key = (UCHAR *)malloc(l))) + ABORT(R_NO_MEMORY); + *keyp = key; + + memcpy(key, id, idlen); + *keyl = idlen; + key += idlen; + + snprintf((char *)key, l, "%s:%d", ssl->server_name, ssl->server_port); + *keyl += strlen((char *)key); + + _status = 0; +abort: + return (_status); +} + /* Look up the session id in the session cache and generate the appropriate keying material */ -int -ssl_save_session (ssl_obj *ssl, ssl_decoder *d) - { -#ifdef OPENSSL - UCHAR *lookup_key=0; - Data *msd=0; - int lookup_key_len; - int r,_status; - - if((r=ssl_create_session_lookup_key(ssl,d->session_id->data, - d->session_id->len,&lookup_key, - (UINT4 *) &lookup_key_len))) - ABORT(r); - if((r=r_data_create(&msd,d->MS->data,d->MS->len))) - ABORT(r); - if((r=r_assoc_insert(d->ctx->session_cache,(char *)lookup_key,lookup_key_len, - (void *)msd,0,(int (*)(void *))r_data_zfree, - R_ASSOC_NEW | R_ASSOC_REPLACE))) - ABORT(r); - - _status=0; - abort: - if(_status){ - r_data_zfree(msd); - } - FREE(lookup_key); - return(_status); -#else - return(0); -#endif +int ssl_restore_session(ssl_obj *ssl, ssl_decoder *d) { + UCHAR *lookup_key = 0; + void *msv; + Data *msd; + int lookup_key_len; + int r, _status; +#ifdef OPENSSL + if((r = ssl_create_session_lookup_key(ssl, d->session_id->data, + d->session_id->len, &lookup_key, + (UINT4 *)&lookup_key_len))) + ABORT(r); + if((r = r_assoc_fetch(d->ctx->session_cache, (char *)lookup_key, + lookup_key_len, &msv))) + ABORT(r); + msd = (Data *)msv; + if((r = r_data_create(&d->MS, msd->data, msd->len))) + ABORT(r); + CRDUMPD("Restored MS", d->MS); + + switch(ssl->version) { + case SSLV3_VERSION: + case TLSV1_VERSION: + case TLSV11_VERSION: + case TLSV12_VERSION: + if((r = ssl_generate_keying_material(ssl, d))) + ABORT(r); + break; + default: + ABORT(SSL_CANT_DO_CIPHER); } + _status = 0; +abort: + FREE(lookup_key); + return (_status); +#else + return (0); +#endif +} + +/* Look up the session id in the session cache and generate + the appropriate keying material */ +int ssl_save_session(ssl_obj *ssl, ssl_decoder *d) { +#ifdef OPENSSL + UCHAR *lookup_key = 0; + Data *msd = 0; + int lookup_key_len; + int r, _status; + + if((r = ssl_create_session_lookup_key(ssl, d->session_id->data, + d->session_id->len, &lookup_key, + (UINT4 *)&lookup_key_len))) + ABORT(r); + if((r = r_data_create(&msd, d->MS->data, d->MS->len))) + ABORT(r); + if((r = r_assoc_insert(d->ctx->session_cache, (char *)lookup_key, + lookup_key_len, (void *)msd, 0, + (int (*)(void *))r_data_zfree, + R_ASSOC_NEW | R_ASSOC_REPLACE))) + ABORT(r); + + _status = 0; +abort: + if(_status) { + r_data_zfree(msd); + } + FREE(lookup_key); + return (_status); +#else + return (0); +#endif +} + /* This only works with RSA because the other cipher suites offer PFS. Yuck. */ -int -ssl_process_client_key_exchange (ssl_obj *ssl, ssl_decoder *d, UCHAR *msg, int len) - { +int ssl_process_client_key_exchange(ssl_obj *ssl, + ssl_decoder *d, + UCHAR *msg, + int len) { #ifdef OPENSSL - int r,_status; - int i; - EVP_PKEY *pk; - const BIGNUM *n; + int r, _status; + int i; + EVP_PKEY *pk; + const BIGNUM *n; - /* Remove the master secret if it was there - to force keying material regeneration in - case we're renegotiating */ - r_data_destroy(&d->MS); + /* Remove the master secret if it was there + to force keying material regeneration in + case we're renegotiating */ + r_data_destroy(&d->MS); - if(!d->ctx->ssl_key_log_file || - ssl_read_key_log_file(ssl,d) || - !d->MS){ - if(ssl->cs->kex!=KEX_RSA) - return(-1); + if(!d->ctx->ssl_key_log_file || ssl_read_key_log_file(ssl, d) || !d->MS) { + if(ssl->cs->kex != KEX_RSA) + return (-1); - if(d->ephemeral_rsa) - return(-1); + if(d->ephemeral_rsa) + return (-1); - pk=SSL_get_privatekey(d->ctx->ssl); - if(!pk) - return(-1); + pk = SSL_get_privatekey(d->ctx->ssl); + if(!pk) + return (-1); - if(EVP_PKEY_id(pk)!=EVP_PKEY_RSA) - return(-1); - - RSA_get0_key(EVP_PKEY_get0_RSA(pk), &n, NULL, NULL); - if((r=r_data_alloc(&d->PMS,BN_num_bytes(n)))) - ABORT(r); + if(EVP_PKEY_id(pk) != EVP_PKEY_RSA) + return (-1); - i=RSA_private_decrypt(len,msg,d->PMS->data, - EVP_PKEY_get0_RSA(pk),RSA_PKCS1_PADDING); - - if(i!=48) - ABORT(SSL_BAD_PMS); - - d->PMS->len=48; - - CRDUMPD("PMS",d->PMS); - } - - switch(ssl->version){ - case SSLV3_VERSION: - case TLSV1_VERSION: - case TLSV11_VERSION: - case TLSV12_VERSION: - if((r=ssl_generate_keying_material(ssl,d))) - ABORT(r); - break; - default: - ABORT(SSL_CANT_DO_CIPHER); - } - - - /* Now store the data in the session cache */ - if((r=ssl_save_session(ssl,d))) + RSA_get0_key(EVP_PKEY_get0_RSA(pk), &n, NULL, NULL); + if((r = r_data_alloc(&d->PMS, BN_num_bytes(n)))) ABORT(r); - - _status=0; - abort: - return(_status); -#else - return 0; -#endif - + + i = RSA_private_decrypt(len, msg, d->PMS->data, EVP_PKEY_get0_RSA(pk), + RSA_PKCS1_PADDING); + + if(i != 48) + ABORT(SSL_BAD_PMS); + + d->PMS->len = 48; + + CRDUMPD("PMS", d->PMS); } + switch(ssl->version) { + case SSLV3_VERSION: + case TLSV1_VERSION: + case TLSV11_VERSION: + case TLSV12_VERSION: + if((r = ssl_generate_keying_material(ssl, d))) + ABORT(r); + break; + default: + ABORT(SSL_CANT_DO_CIPHER); + } + + /* Now store the data in the session cache */ + if((r = ssl_save_session(ssl, d))) + ABORT(r); + + _status = 0; +abort: + return (_status); +#else + return 0; +#endif +} #ifdef OPENSSL static int tls_P_hash(ssl_obj *ssl, - Data *secret, - Data *seed, - const EVP_MD *md, - Data *out) - { - UCHAR *ptr=out->data; - int left=out->len; - int tocpy; - UCHAR *A; - UCHAR _A[128],tmp[128]; - unsigned int A_l,tmp_l; - HMAC_CTX *hm = HMAC_CTX_new(); + Data *secret, + Data *seed, + const EVP_MD *md, + Data *out) { + UCHAR *ptr = out->data; + int left = out->len; + int tocpy; + UCHAR *A; + UCHAR _A[128], tmp[128]; + unsigned int A_l, tmp_l; + HMAC_CTX *hm = HMAC_CTX_new(); - CRDUMPD("P_hash secret",secret); - CRDUMPD("P_hash seed",seed); - - A=seed->data; - A_l=seed->len; + CRDUMPD("P_hash secret", secret); + CRDUMPD("P_hash seed", seed); - while(left){ - HMAC_Init_ex(hm,secret->data,secret->len,md,NULL); - HMAC_Update(hm,A,A_l); - HMAC_Final(hm,_A,&A_l); - A=_A; + A = seed->data; + A_l = seed->len; - HMAC_Init_ex(hm,secret->data,secret->len,md,NULL); - HMAC_Update(hm,A,A_l); - HMAC_Update(hm,seed->data,seed->len); - HMAC_Final(hm,tmp,&tmp_l); + while(left) { + HMAC_Init_ex(hm, secret->data, secret->len, md, NULL); + HMAC_Update(hm, A, A_l); + HMAC_Final(hm, _A, &A_l); + A = _A; - tocpy=MIN(left,tmp_l); - memcpy(ptr,tmp,tocpy); - ptr+=tocpy; - left-=tocpy; - } - - HMAC_CTX_free(hm); - CRDUMPD("P_hash out",out); - - return (0); - } - - -static int -tls_prf (ssl_obj *ssl, Data *secret, char *usage, Data *rnd1, Data *rnd2, Data *out) - { - int r,_status; - Data *md5_out=0,*sha_out=0; - Data *seed; - UCHAR *ptr; - Data *S1=0,*S2=0; - int i,S_l; - - if((r=r_data_alloc(&md5_out,MAX(out->len,16)))) - ABORT(r); - if((r=r_data_alloc(&sha_out,MAX(out->len,20)))) - ABORT(r); - if((r=r_data_alloc(&seed,strlen(usage)+rnd1->len+rnd2->len))) - ABORT(r); - ptr=seed->data; - memcpy(ptr,usage,strlen(usage)); ptr+=strlen(usage); - memcpy(ptr,rnd1->data,rnd1->len); ptr+=rnd1->len; - memcpy(ptr,rnd2->data,rnd2->len); ptr+=rnd2->len; - - S_l=secret->len/2 + secret->len%2; - - if((r=r_data_alloc(&S1,S_l))) - ABORT(r); - if((r=r_data_alloc(&S2,S_l))) - ABORT(r); - - memcpy(S1->data,secret->data,S_l); - memcpy(S2->data,secret->data + (secret->len - S_l),S_l); - - if((r=tls_P_hash - (ssl,S1,seed,EVP_get_digestbyname("MD5"),md5_out))) - ABORT(r); - if((r=tls_P_hash(ssl,S2,seed,EVP_get_digestbyname("SHA1"),sha_out))) - ABORT(r); - - - for(i=0;ilen;i++) - out->data[i]=md5_out->data[i] ^ sha_out->data[i]; - - CRDUMPD("PRF out",out); - _status=0; - abort: - r_data_destroy(&md5_out); - r_data_destroy(&sha_out); - r_data_destroy(&seed); - r_data_destroy(&S1); - r_data_destroy(&S2); - return(_status); + HMAC_Init_ex(hm, secret->data, secret->len, md, NULL); + HMAC_Update(hm, A, A_l); + HMAC_Update(hm, seed->data, seed->len); + HMAC_Final(hm, tmp, &tmp_l); + tocpy = MIN(left, tmp_l); + memcpy(ptr, tmp, tocpy); + ptr += tocpy; + left -= tocpy; } -static int -tls12_prf (ssl_obj *ssl, Data *secret, char *usage, Data *rnd1, Data *rnd2, Data *out) + HMAC_CTX_free(hm); + CRDUMPD("P_hash out", out); - { - const EVP_MD *md; - int r,_status; - Data *sha_out=0; - Data *seed; - UCHAR *ptr; - int i, dgi; - - if((r=r_data_alloc(&sha_out,MAX(out->len,64)))) /* assume max SHA512 */ - ABORT(r); - if((r=r_data_alloc(&seed,strlen(usage)+rnd1->len+rnd2->len))) - ABORT(r); - ptr=seed->data; - memcpy(ptr,usage,strlen(usage)); ptr+=strlen(usage); - memcpy(ptr,rnd1->data,rnd1->len); ptr+=rnd1->len; - memcpy(ptr,rnd2->data,rnd2->len); ptr+=rnd2->len; - - /* Earlier versions of openssl didn't have SHA256 of course... */ - dgi = MAX(DIG_SHA256, ssl->cs->dig); - dgi-=0x40; - if ((md=EVP_get_digestbyname(digests[dgi])) == NULL) { - DBG((0,"Cannot get EVP for digest %s, openssl library current?", - digests[dgi])); - ERETURN(SSL_BAD_MAC); - } - if((r=tls_P_hash(ssl,secret,seed,md,sha_out))) - ABORT(r); - - for(i=0;ilen;i++) - out->data[i]=sha_out->data[i]; - - CRDUMPD("PRF out",out); - _status=0; - abort: - r_data_destroy(&sha_out); - r_data_destroy(&seed); - return(_status); - - } - -static int -ssl3_generate_export_iv (ssl_obj *ssl, Data *r1, Data *r2, Data *out) - { - MD5_CTX md5; - UCHAR tmp[16]; - - MD5_Init(&md5); - MD5_Update(&md5,r1->data,r1->len); - MD5_Update(&md5,r2->data,r2->len); - MD5_Final(tmp,&md5); - - memcpy(out->data,tmp,out->len); - - return(0); - } - -static int -ssl3_prf (ssl_obj *ssl, Data *secret, char *usage, Data *r1, Data *r2, Data *out) - { - MD5_CTX md5; - SHA_CTX sha; - Data *rnd1,*rnd2; - int off; - int i=0,j; - UCHAR buf[20]; - - rnd1=r1; rnd2=r2; - - CRDUMPD("Secret",secret); - CRDUMPD("RND1",rnd1); - CRDUMPD("RND2",rnd2); - - MD5_Init(&md5); - memset(&sha,0,sizeof(sha)); - SHA1_Init(&sha); - - for(off=0;offlen;off+=16){ - char outbuf[16]; - int tocpy; - i++; - - /* A, BB, CCC, ... */ - for(j=0;jdata,secret->len); - CRDUMPD("secret",secret); - - if(!strcmp(usage,"client write key") || !strcmp(usage,"server write key")){ - SHA1_Update(&sha,rnd2->data,rnd2->len); - CRDUMPD("rnd2",rnd2); - SHA1_Update(&sha,rnd1->data,rnd1->len); - CRDUMPD("rnd1",rnd1); - } - else{ - SHA1_Update(&sha,rnd1->data,rnd1->len); - CRDUMPD("rnd1",rnd1); - SHA1_Update(&sha,rnd2->data,rnd2->len); - CRDUMPD("rnd2",rnd2); - } - - SHA1_Final(buf,&sha); - CRDUMP("SHA out",buf,20); - - SHA1_Init(&sha); - - MD5_Update(&md5,secret->data,secret->len); - MD5_Update(&md5,buf,20); - MD5_Final((unsigned char *)outbuf,&md5); - tocpy=MIN(out->len-off,16); - memcpy(out->data+off,outbuf,tocpy); - CRDUMP("MD5 out",(UCHAR *)outbuf,16); - - MD5_Init(&md5); - } - - return(0); - } - -static int -ssl_generate_keying_material (ssl_obj *ssl, ssl_decoder *d) - { - Data *key_block=0,temp; - UCHAR _iv_c[8],_iv_s[8]; - UCHAR _key_c[16],_key_s[16]; - int needed; - int r,_status; - UCHAR *ptr,*c_wk,*s_wk,*c_mk=NULL,*s_mk=NULL,*c_iv=NULL,*s_iv=NULL; - - if(!d->MS){ - if((r=r_data_alloc(&d->MS,48))) - ABORT(r); - - if (ssl->extensions->extended_master_secret==2) { - if((r=ssl_generate_session_hash(ssl,d))) - ABORT(r); - - temp.len=0; - if((r=PRF(ssl,d->PMS,"extended master secret",d->session_hash,&temp, - d->MS))) - ABORT(r); - } - else - if((r=PRF(ssl,d->PMS,"master secret",d->client_random,d->server_random, - d->MS))) - ABORT(r); - - CRDUMPD("MS",d->MS); - } - - /* Compute the key block. First figure out how much data - we need*/ - /* Ideally find a cleaner way to check for AEAD cipher */ - needed=!IS_AEAD_CIPHER(ssl->cs)?ssl->cs->dig_len*2:0; - needed+=ssl->cs->bits / 4; - if(ssl->cs->block>1) needed+=ssl->cs->block*2; - - - if((r=r_data_alloc(&key_block,needed))) - ABORT(r); - if((r=PRF(ssl,d->MS,"key expansion",d->server_random,d->client_random, - key_block))) - ABORT(r); - - ptr=key_block->data; - /* Ideally find a cleaner way to check for AEAD cipher */ - if(!IS_AEAD_CIPHER(ssl->cs)){ - c_mk=ptr; ptr+=ssl->cs->dig_len; - s_mk=ptr; ptr+=ssl->cs->dig_len; - } - - c_wk=ptr; ptr+=ssl->cs->eff_bits/8; - s_wk=ptr; ptr+=ssl->cs->eff_bits/8; - - if(ssl->cs->block>1){ - c_iv=ptr; ptr+=ssl->cs->block; - s_iv=ptr; ptr+=ssl->cs->block; - } - - if(ssl->cs->export){ - Data iv_c,iv_s; - Data key_c,key_s; - Data k; - - if(ssl->cs->block>1){ - ATTACH_DATA(iv_c,_iv_c); - ATTACH_DATA(iv_s,_iv_s); - - if(ssl->version==SSLV3_VERSION){ - if((r=ssl3_generate_export_iv(ssl,d->client_random, - d->server_random,&iv_c))) - ABORT(r); - if((r=ssl3_generate_export_iv(ssl,d->server_random, - d->client_random,&iv_s))) - ABORT(r); - } - else{ - UCHAR _iv_block[16]; - Data iv_block; - Data key_null; - UCHAR _key_null; - - INIT_DATA(key_null,&_key_null,0); - - /* We only have room for 8 bit IVs, but that's - all we should need. This is a sanity check */ - if(ssl->cs->block>8) - ABORT(R_INTERNAL); - - ATTACH_DATA(iv_block,_iv_block); - - if((r=PRF(ssl,&key_null,"IV block",d->client_random, - d->server_random,&iv_block))) - ABORT(r); - - memcpy(_iv_c,iv_block.data,8); - memcpy(_iv_s,iv_block.data+8,8); - } - - c_iv=_iv_c; - s_iv=_iv_s; - } - - if(ssl->version==SSLV3_VERSION){ - MD5_CTX md5; - - MD5_Init(&md5); - MD5_Update(&md5,c_wk,ssl->cs->eff_bits/8); - MD5_Update(&md5,d->client_random->data,d->client_random->len); - MD5_Update(&md5,d->server_random->data,d->server_random->len); - MD5_Final(_key_c,&md5); - c_wk=_key_c; - - MD5_Init(&md5); - MD5_Update(&md5,s_wk,ssl->cs->eff_bits/8); - MD5_Update(&md5,d->server_random->data,d->server_random->len); - MD5_Update(&md5,d->client_random->data,d->client_random->len); - MD5_Final(_key_s,&md5); - s_wk=_key_s; - } - else{ - ATTACH_DATA(key_c,_key_c); - ATTACH_DATA(key_s,_key_s); - INIT_DATA(k,c_wk,ssl->cs->eff_bits/8); - if((r=PRF(ssl,&k,"client write key",d->client_random,d->server_random, - &key_c))) - ABORT(r); - c_wk=_key_c; - INIT_DATA(k,s_wk,ssl->cs->eff_bits/8); - if((r=PRF(ssl,&k,"server write key",d->client_random,d->server_random, - &key_s))) - ABORT(r); - s_wk=_key_s; - } - } - - if (!IS_AEAD_CIPHER(ssl->cs)){ - CRDUMP("Client MAC key",c_mk,ssl->cs->dig_len); - CRDUMP("Server MAC key",s_mk,ssl->cs->dig_len); - } - CRDUMP("Client Write key",c_wk,ssl->cs->bits/8); - CRDUMP("Server Write key",s_wk,ssl->cs->bits/8); - - if(ssl->cs->block>1){ - CRDUMP("Client Write IV",c_iv,ssl->cs->block); - CRDUMP("Server Write IV",s_iv,ssl->cs->block); - } - - if((r=ssl_create_rec_decoder(&d->c_to_s_n, - ssl,c_mk,c_wk,c_iv))) - ABORT(r); - if((r=ssl_create_rec_decoder(&d->s_to_c_n, - ssl,s_mk,s_wk,s_iv))) - ABORT(r); - - - _status=0; - abort: - if(key_block){ - r_data_zfree(key_block); - free(key_block); - } - return(_status); - } - -static int hkdf_expand_label(ssl_obj *ssl, - ssl_decoder *d, - Data *secret, - char *label, - Data *context, - uint16_t length, - UCHAR **out) - { - int r; - size_t outlen = length; - EVP_PKEY_CTX *pctx; - - pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); - - Data hkdf_label; - UCHAR *ptr; - - //Construct HkdfLabel - hkdf_label.data = ptr = malloc(512); - *(uint16_t*)ptr = ntohs(length); - ptr+=2; - *(uint8_t*)ptr++ = 6+(label?strlen(label):0); - memcpy(ptr, "tls13 ", 6); - ptr+=6; - if (label) { - memcpy(ptr, label, strlen(label)); - ptr+=strlen(label); - } - *(uint8_t*)ptr++ = context?context->len:0; - if (context) { - memcpy(ptr, context->data, context->len); - ptr+=context->len; - } - hkdf_label.len = ptr - hkdf_label.data; - CRDUMPD("hkdf_label", &hkdf_label); - // Load parameters - *out = malloc(length); - if (EVP_PKEY_derive_init(pctx) <= 0) { - fprintf(stderr, "EVP_PKEY_derive_init failed\n"); - } - /* Error */ - if (EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY)<=0) { - fprintf(stderr, "EVP_PKEY_CTX_hkdf_mode failed\n"); - goto abort; - } - if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_get_digestbyname(digests[ssl->cs->dig-0x40])) <= 0) { - fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); - goto abort; - } - if (EVP_PKEY_CTX_set1_hkdf_key(pctx, secret->data, secret->len) <= 0) { - fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); - goto abort; - } - if (EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdf_label.data, hkdf_label.len) <= 0) { - fprintf(stderr, "EVP_PKEY_CTX_add1_hkdf_info failed\n"); - goto abort; - } - if (EVP_PKEY_derive(pctx, *out, &outlen) <= 0) { - fprintf(stderr, "EVP_PKEY_derive failed\n"); - goto abort; - } - - CRDUMP("out_hkdf", *out, outlen); - return 0; -abort: - ERR_print_errors_fp(stderr); - return r; - } - -// Will update the keys for the particular direction -int -ssl_tls13_update_keying_material (ssl_obj *ssl, ssl_decoder *d, int direction) -{ - Data *secret; - ssl_rec_decoder *decoder; - UCHAR *newsecret; - UCHAR *newkey; - UCHAR *newiv; - - if (direction == DIR_I2R) { - secret = d->CTS; - decoder = d->c_to_s; - } else { - secret = d->STS; - decoder = d->s_to_c; - } - hkdf_expand_label(ssl, d, secret, "traffic upd", NULL, ssl->cs->dig_len, &newsecret); - secret->data = newsecret; - hkdf_expand_label(ssl, d, secret, "key", NULL, ssl->cs->eff_bits/8, &newkey); - hkdf_expand_label(ssl, d, secret, "iv", NULL, 12, &newiv); - tls13_update_rec_key(decoder,newkey,newiv); - - return 0; + return (0); } -int -ssl_tls13_generate_keying_material (ssl_obj *ssl, ssl_decoder *d) +static int tls_prf(ssl_obj *ssl, + Data *secret, + char *usage, + Data *rnd1, + Data *rnd2, + Data *out) { + int r, _status; + Data *md5_out = 0, *sha_out = 0; + Data *seed; + UCHAR *ptr; + Data *S1 = 0, *S2 = 0; + int i, S_l; + + if((r = r_data_alloc(&md5_out, MAX(out->len, 16)))) + ABORT(r); + if((r = r_data_alloc(&sha_out, MAX(out->len, 20)))) + ABORT(r); + if((r = r_data_alloc(&seed, strlen(usage) + rnd1->len + rnd2->len))) + ABORT(r); + ptr = seed->data; + memcpy(ptr, usage, strlen(usage)); + ptr += strlen(usage); + memcpy(ptr, rnd1->data, rnd1->len); + ptr += rnd1->len; + memcpy(ptr, rnd2->data, rnd2->len); + ptr += rnd2->len; + + S_l = secret->len / 2 + secret->len % 2; + + if((r = r_data_alloc(&S1, S_l))) + ABORT(r); + if((r = r_data_alloc(&S2, S_l))) + ABORT(r); + + memcpy(S1->data, secret->data, S_l); + memcpy(S2->data, secret->data + (secret->len - S_l), S_l); + + if((r = tls_P_hash(ssl, S1, seed, EVP_get_digestbyname("MD5"), md5_out))) + ABORT(r); + if((r = tls_P_hash(ssl, S2, seed, EVP_get_digestbyname("SHA1"), sha_out))) + ABORT(r); + + for(i = 0; i < out->len; i++) + out->data[i] = md5_out->data[i] ^ sha_out->data[i]; + + CRDUMPD("PRF out", out); + _status = 0; +abort: + r_data_destroy(&md5_out); + r_data_destroy(&sha_out); + r_data_destroy(&seed); + r_data_destroy(&S1); + r_data_destroy(&S2); + return (_status); +} + +static int tls12_prf(ssl_obj *ssl, + Data *secret, + char *usage, + Data *rnd1, + Data *rnd2, + Data *out) + { - int r,_status; + const EVP_MD *md; + int r, _status; + Data *sha_out = 0; + Data *seed; + UCHAR *ptr; + int i, dgi; + + if((r = r_data_alloc(&sha_out, MAX(out->len, 64)))) /* assume max SHA512 */ + ABORT(r); + if((r = r_data_alloc(&seed, strlen(usage) + rnd1->len + rnd2->len))) + ABORT(r); + ptr = seed->data; + memcpy(ptr, usage, strlen(usage)); + ptr += strlen(usage); + memcpy(ptr, rnd1->data, rnd1->len); + ptr += rnd1->len; + memcpy(ptr, rnd2->data, rnd2->len); + ptr += rnd2->len; + + /* Earlier versions of openssl didn't have SHA256 of course... */ + dgi = MAX(DIG_SHA256, ssl->cs->dig); + dgi -= 0x40; + if((md = EVP_get_digestbyname(digests[dgi])) == NULL) { + DBG((0, "Cannot get EVP for digest %s, openssl library current?", + digests[dgi])); + ERETURN(SSL_BAD_MAC); + } + if((r = tls_P_hash(ssl, secret, seed, md, sha_out))) + ABORT(r); + + for(i = 0; i < out->len; i++) + out->data[i] = sha_out->data[i]; + + CRDUMPD("PRF out", out); + _status = 0; +abort: + r_data_destroy(&sha_out); + r_data_destroy(&seed); + return (_status); +} + +static int ssl3_generate_export_iv(ssl_obj *ssl, + Data *r1, + Data *r2, + Data *out) { + MD5_CTX md5; + UCHAR tmp[16]; + + MD5_Init(&md5); + MD5_Update(&md5, r1->data, r1->len); + MD5_Update(&md5, r2->data, r2->len); + MD5_Final(tmp, &md5); + + memcpy(out->data, tmp, out->len); + + return (0); +} + +static int ssl3_prf(ssl_obj *ssl, + Data *secret, + char *usage, + Data *r1, + Data *r2, + Data *out) { + MD5_CTX md5; + SHA_CTX sha; + Data *rnd1, *rnd2; + int off; + int i = 0, j; + UCHAR buf[20]; + + rnd1 = r1; + rnd2 = r2; + + CRDUMPD("Secret", secret); + CRDUMPD("RND1", rnd1); + CRDUMPD("RND2", rnd2); + + MD5_Init(&md5); + memset(&sha, 0, sizeof(sha)); + SHA1_Init(&sha); + + for(off = 0; off < out->len; off += 16) { + char outbuf[16]; + int tocpy; + i++; + + /* A, BB, CCC, ... */ + for(j = 0; j < i; j++) { + buf[j] = 64 + i; + } + + SHA1_Update(&sha, buf, i); + CRDUMP("BUF", buf, i); + if(secret) + SHA1_Update(&sha, secret->data, secret->len); + CRDUMPD("secret", secret); + + if(!strcmp(usage, "client write key") || + !strcmp(usage, "server write key")) { + SHA1_Update(&sha, rnd2->data, rnd2->len); + CRDUMPD("rnd2", rnd2); + SHA1_Update(&sha, rnd1->data, rnd1->len); + CRDUMPD("rnd1", rnd1); + } else { + SHA1_Update(&sha, rnd1->data, rnd1->len); + CRDUMPD("rnd1", rnd1); + SHA1_Update(&sha, rnd2->data, rnd2->len); + CRDUMPD("rnd2", rnd2); + } + + SHA1_Final(buf, &sha); + CRDUMP("SHA out", buf, 20); + + SHA1_Init(&sha); + + MD5_Update(&md5, secret->data, secret->len); + MD5_Update(&md5, buf, 20); + MD5_Final((unsigned char *)outbuf, &md5); + tocpy = MIN(out->len - off, 16); + memcpy(out->data + off, outbuf, tocpy); + CRDUMP("MD5 out", (UCHAR *)outbuf, 16); + + MD5_Init(&md5); + } + + return (0); +} + +static int ssl_generate_keying_material(ssl_obj *ssl, ssl_decoder *d) { + Data *key_block = 0, temp; + UCHAR _iv_c[8], _iv_s[8]; + UCHAR _key_c[16], _key_s[16]; + int needed; + int r, _status; + UCHAR *ptr, *c_wk, *s_wk, *c_mk = NULL, *s_mk = NULL, *c_iv = NULL, + *s_iv = NULL; + + if(!d->MS) { + if((r = r_data_alloc(&d->MS, 48))) + ABORT(r); + + if(ssl->extensions->extended_master_secret == 2) { + if((r = ssl_generate_session_hash(ssl, d))) + ABORT(r); + + temp.len = 0; + if((r = PRF(ssl, d->PMS, "extended master secret", d->session_hash, &temp, + d->MS))) + ABORT(r); + } else if((r = PRF(ssl, d->PMS, "master secret", d->client_random, + d->server_random, d->MS))) + ABORT(r); + + CRDUMPD("MS", d->MS); + } + + /* Compute the key block. First figure out how much data + we need*/ + /* Ideally find a cleaner way to check for AEAD cipher */ + needed = !IS_AEAD_CIPHER(ssl->cs) ? ssl->cs->dig_len * 2 : 0; + needed += ssl->cs->bits / 4; + if(ssl->cs->block > 1) + needed += ssl->cs->block * 2; + + if((r = r_data_alloc(&key_block, needed))) + ABORT(r); + if((r = PRF(ssl, d->MS, "key expansion", d->server_random, d->client_random, + key_block))) + ABORT(r); + + ptr = key_block->data; + /* Ideally find a cleaner way to check for AEAD cipher */ + if(!IS_AEAD_CIPHER(ssl->cs)) { + c_mk = ptr; + ptr += ssl->cs->dig_len; + s_mk = ptr; + ptr += ssl->cs->dig_len; + } + + c_wk = ptr; + ptr += ssl->cs->eff_bits / 8; + s_wk = ptr; + ptr += ssl->cs->eff_bits / 8; + + if(ssl->cs->block > 1) { + c_iv = ptr; + ptr += ssl->cs->block; + s_iv = ptr; + ptr += ssl->cs->block; + } + + if(ssl->cs->export) { + Data iv_c, iv_s; + Data key_c, key_s; + Data k; + + if(ssl->cs->block > 1) { + ATTACH_DATA(iv_c, _iv_c); + ATTACH_DATA(iv_s, _iv_s); + + if(ssl->version == SSLV3_VERSION) { + if((r = ssl3_generate_export_iv(ssl, d->client_random, d->server_random, + &iv_c))) + ABORT(r); + if((r = ssl3_generate_export_iv(ssl, d->server_random, d->client_random, + &iv_s))) + ABORT(r); + } else { + UCHAR _iv_block[16]; + Data iv_block; + Data key_null; + UCHAR _key_null; + + INIT_DATA(key_null, &_key_null, 0); + + /* We only have room for 8 bit IVs, but that's + all we should need. This is a sanity check */ + if(ssl->cs->block > 8) + ABORT(R_INTERNAL); + + ATTACH_DATA(iv_block, _iv_block); + + if((r = PRF(ssl, &key_null, "IV block", d->client_random, + d->server_random, &iv_block))) + ABORT(r); + + memcpy(_iv_c, iv_block.data, 8); + memcpy(_iv_s, iv_block.data + 8, 8); + } + + c_iv = _iv_c; + s_iv = _iv_s; + } + + if(ssl->version == SSLV3_VERSION) { + MD5_CTX md5; + + MD5_Init(&md5); + MD5_Update(&md5, c_wk, ssl->cs->eff_bits / 8); + MD5_Update(&md5, d->client_random->data, d->client_random->len); + MD5_Update(&md5, d->server_random->data, d->server_random->len); + MD5_Final(_key_c, &md5); + c_wk = _key_c; + + MD5_Init(&md5); + MD5_Update(&md5, s_wk, ssl->cs->eff_bits / 8); + MD5_Update(&md5, d->server_random->data, d->server_random->len); + MD5_Update(&md5, d->client_random->data, d->client_random->len); + MD5_Final(_key_s, &md5); + s_wk = _key_s; + } else { + ATTACH_DATA(key_c, _key_c); + ATTACH_DATA(key_s, _key_s); + INIT_DATA(k, c_wk, ssl->cs->eff_bits / 8); + if((r = PRF(ssl, &k, "client write key", d->client_random, + d->server_random, &key_c))) + ABORT(r); + c_wk = _key_c; + INIT_DATA(k, s_wk, ssl->cs->eff_bits / 8); + if((r = PRF(ssl, &k, "server write key", d->client_random, + d->server_random, &key_s))) + ABORT(r); + s_wk = _key_s; + } + } + + if(!IS_AEAD_CIPHER(ssl->cs)) { + CRDUMP("Client MAC key", c_mk, ssl->cs->dig_len); + CRDUMP("Server MAC key", s_mk, ssl->cs->dig_len); + } + CRDUMP("Client Write key", c_wk, ssl->cs->bits / 8); + CRDUMP("Server Write key", s_wk, ssl->cs->bits / 8); + + if(ssl->cs->block > 1) { + CRDUMP("Client Write IV", c_iv, ssl->cs->block); + CRDUMP("Server Write IV", s_iv, ssl->cs->block); + } + + if((r = ssl_create_rec_decoder(&d->c_to_s_n, ssl, c_mk, c_wk, c_iv))) + ABORT(r); + if((r = ssl_create_rec_decoder(&d->s_to_c_n, ssl, s_mk, s_wk, s_iv))) + ABORT(r); + + _status = 0; +abort: + if(key_block) { + r_data_zfree(key_block); + free(key_block); + } + return (_status); +} + +static int hkdf_expand_label(ssl_obj *ssl, + ssl_decoder *d, + Data *secret, + char *label, + Data *context, + uint16_t length, + UCHAR **out) { + int r; + size_t outlen = length; + EVP_PKEY_CTX *pctx; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + + Data hkdf_label; + UCHAR *ptr; + + // Construct HkdfLabel + hkdf_label.data = ptr = malloc(512); + *(uint16_t *)ptr = ntohs(length); + ptr += 2; + *(uint8_t *)ptr++ = 6 + (label ? strlen(label) : 0); + memcpy(ptr, "tls13 ", 6); + ptr += 6; + if(label) { + memcpy(ptr, label, strlen(label)); + ptr += strlen(label); + } + *(uint8_t *)ptr++ = context ? context->len : 0; + if(context) { + memcpy(ptr, context->data, context->len); + ptr += context->len; + } + hkdf_label.len = ptr - hkdf_label.data; + CRDUMPD("hkdf_label", &hkdf_label); + // Load parameters + *out = malloc(length); + if(EVP_PKEY_derive_init(pctx) <= 0) { + fprintf(stderr, "EVP_PKEY_derive_init failed\n"); + } + /* Error */ + if(EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_hkdf_mode failed\n"); + goto abort; + } + if(EVP_PKEY_CTX_set_hkdf_md( + pctx, EVP_get_digestbyname(digests[ssl->cs->dig - 0x40])) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); + goto abort; + } + if(EVP_PKEY_CTX_set1_hkdf_key(pctx, secret->data, secret->len) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_set_hkdf_md failed\n"); + goto abort; + } + if(EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdf_label.data, hkdf_label.len) <= 0) { + fprintf(stderr, "EVP_PKEY_CTX_add1_hkdf_info failed\n"); + goto abort; + } + if(EVP_PKEY_derive(pctx, *out, &outlen) <= 0) { + fprintf(stderr, "EVP_PKEY_derive failed\n"); + goto abort; + } + + CRDUMP("out_hkdf", *out, outlen); + return 0; +abort: + ERR_print_errors_fp(stderr); + return r; +} + +// Will update the keys for the particular direction +int ssl_tls13_update_keying_material(ssl_obj *ssl, + ssl_decoder *d, + int direction) { + Data *secret; + ssl_rec_decoder *decoder; + UCHAR *newsecret; + UCHAR *newkey; + UCHAR *newiv; + + if(direction == DIR_I2R) { + secret = d->CTS; + decoder = d->c_to_s; + } else { + secret = d->STS; + decoder = d->s_to_c; + } + hkdf_expand_label(ssl, d, secret, "traffic upd", NULL, ssl->cs->dig_len, + &newsecret); + secret->data = newsecret; + hkdf_expand_label(ssl, d, secret, "key", NULL, ssl->cs->eff_bits / 8, + &newkey); + hkdf_expand_label(ssl, d, secret, "iv", NULL, 12, &newiv); + tls13_update_rec_key(decoder, newkey, newiv); + + return 0; +} + +int ssl_tls13_generate_keying_material(ssl_obj *ssl, ssl_decoder *d) { + int r, _status; Data out; - UCHAR *s_wk_h,*s_iv_h,*c_wk_h,*c_iv_h, - *s_wk,*s_iv,*c_wk,*c_iv; - if (!(d->ctx->ssl_key_log_file && ssl_read_key_log_file(ssl, d)==0 && - d->SHTS && d->CHTS && d->STS && d->CTS)){ - ABORT(-1); - } + UCHAR *s_wk_h, *s_iv_h, *c_wk_h, *c_iv_h, *s_wk, *s_iv, *c_wk, *c_iv; + if(!(d->ctx->ssl_key_log_file && ssl_read_key_log_file(ssl, d) == 0 && + d->SHTS && d->CHTS && d->STS && d->CTS)) { + ABORT(-1); + } // It is 12 for all ciphers - if (hkdf_expand_label(ssl, d, d->SHTS, "key", NULL, ssl->cs->eff_bits/8, &s_wk_h)) { - fprintf(stderr, "s_wk_h hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->SHTS, "key", NULL, ssl->cs->eff_bits / 8, + &s_wk_h)) { + fprintf(stderr, "s_wk_h hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->SHTS, "iv", NULL, 12, &s_iv_h)) { - fprintf(stderr, "s_iv_h hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->SHTS, "iv", NULL, 12, &s_iv_h)) { + fprintf(stderr, "s_iv_h hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->CHTS, "key", NULL, ssl->cs->eff_bits/8, &c_wk_h)) { - fprintf(stderr, "c_wk_h hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->CHTS, "key", NULL, ssl->cs->eff_bits / 8, + &c_wk_h)) { + fprintf(stderr, "c_wk_h hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->CHTS, "iv", NULL, 12, &c_iv_h)) { - fprintf(stderr, "c_iv_h hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->CHTS, "iv", NULL, 12, &c_iv_h)) { + fprintf(stderr, "c_iv_h hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->STS, "key", NULL, ssl->cs->eff_bits/8, &s_wk)) { - fprintf(stderr, "s_wk hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->STS, "key", NULL, ssl->cs->eff_bits / 8, + &s_wk)) { + fprintf(stderr, "s_wk hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->STS, "iv", NULL, 12, &s_iv)) { - fprintf(stderr, "s_iv hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->STS, "iv", NULL, 12, &s_iv)) { + fprintf(stderr, "s_iv hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->CTS, "key", NULL, ssl->cs->eff_bits/8, &c_wk)) { - fprintf(stderr, "c_wk hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->CTS, "key", NULL, ssl->cs->eff_bits / 8, + &c_wk)) { + fprintf(stderr, "c_wk hkdf_expand_label failed\n"); + goto abort; } - if (hkdf_expand_label(ssl, d, d->CTS, "iv", NULL, 12, &c_iv)) { - fprintf(stderr, "c_iv hkdf_expand_label failed\n"); - goto abort; + if(hkdf_expand_label(ssl, d, d->CTS, "iv", NULL, 12, &c_iv)) { + fprintf(stderr, "c_iv hkdf_expand_label failed\n"); + goto abort; } - CRDUMP("Server Handshake Write key", s_wk_h,ssl->cs->eff_bits/8 ); + CRDUMP("Server Handshake Write key", s_wk_h, ssl->cs->eff_bits / 8); CRDUMP("Server Handshake IV", s_iv_h, 12); - CRDUMP("Client Handshake Write key", c_wk_h, ssl->cs->eff_bits/8); - CRDUMP("Client Handshake IV", c_iv_h,12); - CRDUMP("Server Write key", s_wk,ssl->cs->eff_bits/8); - CRDUMP("Server IV", s_iv,12); - CRDUMP("Client Write key",c_wk, ssl->cs->eff_bits/8); - CRDUMP("Client IV", c_iv,12); - - if((r=ssl_create_rec_decoder(&d->c_to_s_n, - ssl,NULL,c_wk,c_iv))) + CRDUMP("Client Handshake Write key", c_wk_h, ssl->cs->eff_bits / 8); + CRDUMP("Client Handshake IV", c_iv_h, 12); + CRDUMP("Server Write key", s_wk, ssl->cs->eff_bits / 8); + CRDUMP("Server IV", s_iv, 12); + CRDUMP("Client Write key", c_wk, ssl->cs->eff_bits / 8); + CRDUMP("Client IV", c_iv, 12); + + if((r = ssl_create_rec_decoder(&d->c_to_s_n, ssl, NULL, c_wk, c_iv))) ABORT(r); - if((r=ssl_create_rec_decoder(&d->s_to_c_n, - ssl,NULL,s_wk,s_iv))) + if((r = ssl_create_rec_decoder(&d->s_to_c_n, ssl, NULL, s_wk, s_iv))) ABORT(r); - if((r=ssl_create_rec_decoder(&d->c_to_s, - ssl,NULL,c_wk_h,c_iv_h))) + if((r = ssl_create_rec_decoder(&d->c_to_s, ssl, NULL, c_wk_h, c_iv_h))) ABORT(r); - if((r=ssl_create_rec_decoder(&d->s_to_c, - ssl,NULL,s_wk_h,s_iv_h))) + if((r = ssl_create_rec_decoder(&d->s_to_c, ssl, NULL, s_wk_h, s_iv_h))) ABORT(r); return 0; abort: return r; } -static int -ssl_generate_session_hash (ssl_obj *ssl, ssl_decoder *d) - { - int r,_status,dgi; - unsigned int len; - const EVP_MD *md; - EVP_MD_CTX *dgictx = EVP_MD_CTX_create(); +static int ssl_generate_session_hash(ssl_obj *ssl, ssl_decoder *d) { + int r, _status, dgi; + unsigned int len; + const EVP_MD *md; + EVP_MD_CTX *dgictx = EVP_MD_CTX_create(); - if((r=r_data_alloc(&d->session_hash,EVP_MAX_MD_SIZE))) - ABORT(r); + if((r = r_data_alloc(&d->session_hash, EVP_MAX_MD_SIZE))) + ABORT(r); - switch(ssl->version){ - case TLSV12_VERSION: - dgi = MAX(DIG_SHA256,ssl->cs->dig)-0x40; - if ((md=EVP_get_digestbyname(digests[dgi])) == NULL) { - DBG((0,"Cannot get EVP for digest %s, openssl library current?", - digests[dgi])); - ERETURN(SSL_BAD_MAC); - } + switch(ssl->version) { + case TLSV12_VERSION: + dgi = MAX(DIG_SHA256, ssl->cs->dig) - 0x40; + if((md = EVP_get_digestbyname(digests[dgi])) == NULL) { + DBG((0, "Cannot get EVP for digest %s, openssl library current?", + digests[dgi])); + ERETURN(SSL_BAD_MAC); + } - EVP_DigestInit(dgictx,md); - EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages->len); - EVP_DigestFinal(dgictx,d->session_hash->data,(unsigned int *) &d->session_hash->len); + EVP_DigestInit(dgictx, md); + EVP_DigestUpdate(dgictx, d->handshake_messages->data, + d->handshake_messages->len); + EVP_DigestFinal(dgictx, d->session_hash->data, + (unsigned int *)&d->session_hash->len); - break; - case SSLV3_VERSION: - case TLSV1_VERSION: - case TLSV11_VERSION: - EVP_DigestInit(dgictx,EVP_get_digestbyname("MD5")); - EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages->len); - EVP_DigestFinal_ex(dgictx,d->session_hash->data,(unsigned int *) &d->session_hash->len); + break; + case SSLV3_VERSION: + case TLSV1_VERSION: + case TLSV11_VERSION: + EVP_DigestInit(dgictx, EVP_get_digestbyname("MD5")); + EVP_DigestUpdate(dgictx, d->handshake_messages->data, + d->handshake_messages->len); + EVP_DigestFinal_ex(dgictx, d->session_hash->data, + (unsigned int *)&d->session_hash->len); - EVP_DigestInit(dgictx,EVP_get_digestbyname("SHA1")); - EVP_DigestUpdate(dgictx,d->handshake_messages->data,d->handshake_messages->len); - EVP_DigestFinal(dgictx,d->session_hash->data+d->session_hash->len,&len); + EVP_DigestInit(dgictx, EVP_get_digestbyname("SHA1")); + EVP_DigestUpdate(dgictx, d->handshake_messages->data, + d->handshake_messages->len); + EVP_DigestFinal(dgictx, d->session_hash->data + d->session_hash->len, + &len); - d->session_hash->len+=len; - break; - default: - ABORT(SSL_CANT_DO_CIPHER); - } - - _status=0; - abort: - return(_status); + d->session_hash->len += len; + break; + default: + ABORT(SSL_CANT_DO_CIPHER); } + _status = 0; +abort: + return (_status); +} + static int read_hex_string(char *str, UCHAR *buf, int n) { unsigned int t; int i; - for (i = 0; i < n; i++) { - if (sscanf(str + i * 2, "%02x", &t) != 1) + for(i = 0; i < n; i++) { + if(sscanf(str + i * 2, "%02x", &t) != 1) return -1; buf[i] = (char)t; } return 0; } -static int -ssl_read_key_log_file (ssl_obj *ssl, ssl_decoder *d) - { - int r,_status,n,i; - unsigned int t; - size_t l=0; - char *line, *d_client_random, *label, *client_random, *secret; - if (ssl->version==TLSV13_VERSION && !ssl->cs)// ssl->cs is not set when called from ssl_process_client_session_id +static int ssl_read_key_log_file(ssl_obj *ssl, ssl_decoder *d) { + int r, _status, n, i; + unsigned int t; + size_t l = 0; + char *line, *d_client_random, *label, *client_random, *secret; + if(ssl->version == TLSV13_VERSION && + !ssl->cs) // ssl->cs is not set when called from + // ssl_process_client_session_id + ABORT(r); + if(!(d_client_random = malloc((d->client_random->len * 2) + 1))) + ABORT(r); + for(i = 0; i < d->client_random->len; i++) + if(snprintf(d_client_random + (i * 2), 3, "%02x", + d->client_random->data[i]) != 2) ABORT(r); - if (!(d_client_random = malloc((d->client_random->len * 2) + 1))) - ABORT(r); - for (i = 0; i < d->client_random->len; i++) - if (snprintf(d_client_random + (i * 2), 3, "%02x", d->client_random->data[i]) != 2) + while((n = getline(&line, &l, d->ctx->ssl_key_log_file)) != -1) { + if(line[n - 1] == '\n') + line[n - 1] = '\0'; + if(!(label = strtok(line, " "))) + continue; + if(!(client_random = strtok(NULL, " ")) || strlen(client_random) != 64 || + STRNICMP(client_random, d_client_random, 64)) + continue; + secret = strtok(NULL, " "); + if(!(secret) || + strlen(secret) != + (ssl->version == TLSV13_VERSION ? ssl->cs->dig_len * 2 : 96)) + continue; + if(!strncmp(label, "CLIENT_RANDOM", 13)) { + if((r = r_data_alloc(&d->MS, 48))) + ABORT(r); + if(read_hex_string(secret, d->MS->data, 48)) ABORT(r); - while ((n = getline(&line, &l, d->ctx->ssl_key_log_file)) != -1) { - if (line[n-1] =='\n') line[n-1] = '\0'; - if (!(label=strtok(line, " "))) continue; - if (!(client_random=strtok(NULL, " ")) || strlen(client_random)!=64 || STRNICMP(client_random, d_client_random, 64)) continue; - secret=strtok(NULL, " "); - if (!(secret) || strlen(secret)!=(ssl->version==TLSV13_VERSION?ssl->cs->dig_len*2:96)) continue; - if (!strncmp(label, "CLIENT_RANDOM", 13)) { - if ((r=r_data_alloc(&d->MS, 48))) - ABORT(r); - if (read_hex_string(secret, d->MS->data, 48)) - ABORT(r); - } - if (ssl->version!=TLSV13_VERSION) continue; - if (!strncmp(label, "SERVER_HANDSHAKE_TRAFFIC_SECRET", 31)){ - if ((r=r_data_alloc(&d->SHTS, ssl->cs->dig_len))) - ABORT(r); - if (read_hex_string(secret, d->SHTS->data, ssl->cs->dig_len)) - ABORT(r); - } else if (!strncmp(label, "CLIENT_HANDSHAKE_TRAFFIC_SECRET", 31)){ - if ((r=r_data_alloc(&d->CHTS, ssl->cs->dig_len))) - ABORT(r); - if (read_hex_string(secret, d->CHTS->data, ssl->cs->dig_len)) - ABORT(r); - } else if (!strncmp(label, "SERVER_TRAFFIC_SECRET_0", 23)){ - if ((r=r_data_alloc(&d->STS, ssl->cs->dig_len))) - ABORT(r); - if (read_hex_string(secret, d->STS->data, ssl->cs->dig_len)) - ABORT(r); - } else if (!strncmp(label, "CLIENT_TRAFFIC_SECRET_0", 23)){ - if ((r=r_data_alloc(&d->CTS, ssl->cs->dig_len))) - ABORT(r); - if (read_hex_string(secret, d->CTS->data, ssl->cs->dig_len)) - ABORT(r); - } - /* - Eventually add support for other labels defined here: - https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format - */ } - _status=0; - abort: - if (d->ctx->ssl_key_log_file != NULL) - fseek(d->ctx->ssl_key_log_file, 0, SEEK_SET); - return(_status); + if(ssl->version != TLSV13_VERSION) + continue; + if(!strncmp(label, "SERVER_HANDSHAKE_TRAFFIC_SECRET", 31)) { + if((r = r_data_alloc(&d->SHTS, ssl->cs->dig_len))) + ABORT(r); + if(read_hex_string(secret, d->SHTS->data, ssl->cs->dig_len)) + ABORT(r); + } else if(!strncmp(label, "CLIENT_HANDSHAKE_TRAFFIC_SECRET", 31)) { + if((r = r_data_alloc(&d->CHTS, ssl->cs->dig_len))) + ABORT(r); + if(read_hex_string(secret, d->CHTS->data, ssl->cs->dig_len)) + ABORT(r); + } else if(!strncmp(label, "SERVER_TRAFFIC_SECRET_0", 23)) { + if((r = r_data_alloc(&d->STS, ssl->cs->dig_len))) + ABORT(r); + if(read_hex_string(secret, d->STS->data, ssl->cs->dig_len)) + ABORT(r); + } else if(!strncmp(label, "CLIENT_TRAFFIC_SECRET_0", 23)) { + if((r = r_data_alloc(&d->CTS, ssl->cs->dig_len))) + ABORT(r); + if(read_hex_string(secret, d->CTS->data, ssl->cs->dig_len)) + ABORT(r); + } + /* + Eventually add support for other labels defined here: + https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format + */ } + _status = 0; +abort: + if(d->ctx->ssl_key_log_file != NULL) + fseek(d->ctx->ssl_key_log_file, 0, SEEK_SET); + return (_status); +} #endif diff --git a/ssl/ssldecode.h b/ssl/ssldecode.h index 15566bb..688085a 100644 --- a/ssl/ssldecode.h +++ b/ssl/ssldecode.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: ssldecode.h,v 1.3 2001/07/20 23:33:16 ekr Exp $ @@ -43,40 +44,56 @@ ekr@rtfm.com Thu Apr 1 15:02:02 1999 */ - #ifndef _ssldecode_h #define _ssldecode_h -#define CRDUMP(a,b,c) P_(P_CR) {Data d; d.data=b; d.len=c; exdump(ssl,a,&d); LF;} -#define CRDUMPD(a,b) P_(P_CR) {exdump(ssl,a,b);LF;} +#define CRDUMP(a, b, c) \ + P_(P_CR) { \ + Data d; \ + d.data = b; \ + d.len = c; \ + exdump(ssl, a, &d); \ + LF; \ + } +#define CRDUMPD(a, b) \ + P_(P_CR) { \ + exdump(ssl, a, b); \ + LF; \ + } -int ssl_decode_ctx_create PROTO_LIST((ssl_decode_ctx **ctx, - char *keyfile,char *password,char *keylogfile)); +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, - UCHAR *msg,int len)); -int ssl_set_server_random PROTO_LIST((ssl_decoder *dp, - UCHAR *msg,int len)); -int ssl_set_client_session_id PROTO_LIST((ssl_decoder *dp, - UCHAR *msg,int len)); -int ssl_process_server_session_id PROTO_LIST((ssl_obj *obj,ssl_decoder *dp, - UCHAR *msg,int len)); -int ssl_process_client_session_id PROTO_LIST((ssl_obj *obj,ssl_decoder *dp, - UCHAR *msg,int len)); -int ssl_process_client_key_exchange PROTO_LIST((struct ssl_obj_ *, - ssl_decoder *d,UCHAR *msg,int len)); -int ssl_process_change_cipher_spec PROTO_LIST((ssl_obj *ssl, - ssl_decoder *d,int direction)); -int ssl_update_handshake_messages PROTO_LIST((ssl_obj *ssl, - Data *data)); -int ssl_decode_record PROTO_LIST((ssl_obj *ssl,ssl_decoder *dec,int direction, - int ct,int version,Data *d)); -int ssl_tls13_generate_keying_material PROTO_LIST((ssl_obj *obj,ssl_decoder *dec)); -int ssl_process_handshake_finished PROTO_LIST((ssl_obj* ssl,ssl_decoder *dec, Data *data)); -int ssl_tls13_update_keying_material PROTO_LIST((ssl_obj *ssl,ssl_decoder *dec,int dir)); - +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, UCHAR *msg, int len)); +int ssl_set_server_random PROTO_LIST((ssl_decoder * dp, UCHAR *msg, int len)); +int ssl_set_client_session_id PROTO_LIST((ssl_decoder * dp, + UCHAR *msg, + int len)); +int ssl_process_server_session_id + PROTO_LIST((ssl_obj * obj, ssl_decoder *dp, UCHAR *msg, int len)); +int ssl_process_client_session_id + PROTO_LIST((ssl_obj * obj, ssl_decoder *dp, UCHAR *msg, int len)); +int ssl_process_client_key_exchange + PROTO_LIST((struct ssl_obj_ *, ssl_decoder *d, UCHAR *msg, int len)); +int ssl_process_change_cipher_spec PROTO_LIST((ssl_obj * ssl, + ssl_decoder *d, + int direction)); +int ssl_update_handshake_messages PROTO_LIST((ssl_obj * ssl, Data *data)); +int ssl_decode_record PROTO_LIST((ssl_obj * ssl, + ssl_decoder *dec, + int direction, + int ct, + int version, + Data *d)); +int ssl_tls13_generate_keying_material PROTO_LIST((ssl_obj * obj, + ssl_decoder *dec)); +int ssl_process_handshake_finished PROTO_LIST((ssl_obj * ssl, + ssl_decoder *dec, + Data *data)); +int ssl_tls13_update_keying_material PROTO_LIST((ssl_obj * ssl, + ssl_decoder *dec, + int dir)); #endif - diff --git a/ssl/sslprint.c b/ssl/sslprint.c index d3fbf90..94d0916 100644 --- a/ssl/sslprint.c +++ b/ssl/sslprint.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: sslprint.c,v 1.8 2002/08/17 01:33:17 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Tue Jan 12 18:06:39 1999 */ - #include #include #include @@ -56,571 +56,561 @@ extern decoder ContentType_decoder[]; extern decoder HandshakeType_decoder[]; +#define BYTES_NEEDED(x) \ + (x <= 255) ? 1 : ((x <= (1 << 16)) ? 2 : (x <= (1 << 24) ? 3 : 4)) -#define BYTES_NEEDED(x) (x<=255)?1:((x<=(1<<16))?2:(x<=(1<<24)?3:4)) +int process_beginning_plaintext(ssl_obj *ssl, segment *seg, int direction) { + Data d; + if(seg->len == 0) + return (SSL_NO_DATA); -int -process_beginning_plaintext (ssl_obj *ssl, segment *seg, int direction) - { - Data d; - if(seg->len==0) - return(SSL_NO_DATA); - - d.data=seg->data; - d.len=seg->len; + d.data = seg->data; + d.len = seg->len; - /* this looks like SSL data. Ignore it*/ - if(d.data[0]==0x16) - return(SSL_BAD_CONTENT_TYPE); + /* this looks like SSL data. Ignore it*/ + if(d.data[0] == 0x16) + return (SSL_BAD_CONTENT_TYPE); - if (logger) logger->vtbl->data(ssl->logger_obj,d.data,d.len,direction); + if(logger) + logger->vtbl->data(ssl->logger_obj, d.data, d.len, direction); - P_(P_AD){ - ssl_print_timestamp(ssl,&seg->p->ts); - - ssl_print_direction_indicator(ssl,direction); - - print_data(ssl,&d); - LF; - } - - return(0); - } + P_(P_AD) { + ssl_print_timestamp(ssl, &seg->p->ts); -int -process_v2_hello (ssl_obj *ssl, segment *seg) - { - int r; - int rec_len; - int _status; - UINT4 cs_len; - UINT4 sid_len; - UINT4 chall_len; - UINT4 ver; - Data d; - Data chall; - UCHAR random[32]; - - if(seg->len==0) - ABORT(SSL_NO_DATA); + ssl_print_direction_indicator(ssl, direction); - d.data=seg->data; - d.len=seg->len; - - /* First check the message length. */ - if(d.len<4) - 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*/ - ABORT(SSL_BAD_CONTENT_TYPE); - - /* If msg_type==1 then we've got a v2 message (or trash)*/ - if(*d.data++!=1) - ABORT(SSL_BAD_CONTENT_TYPE); - d.len--; - - SSL_DECODE_UINT16_ABORT(ssl,"Version number",P_DC,&d,&ver); - /* We can't handle real v2 clients*/ - if(ver<=2){ - explain(ssl,"Version 2 Client.\n"); - 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; - - P_(P_HL) { - explain(ssl,"Version %d.%d ",(ver>>8)&0xff, - ver&0xff); - LF; - } - SSL_DECODE_UINT16_ABORT(ssl,"cipher_spec_length",P_DC,&d,&cs_len); - SSL_DECODE_UINT16_ABORT(ssl,"session_id_length",P_DC,&d,&sid_len); - SSL_DECODE_UINT16_ABORT(ssl,"challenge_length",P_DC,&d,&chall_len); - - if(cs_len%3){ - fprintf(stderr,"Bad cipher spec length %d\n",cs_len); - ABORT(SSL_BAD_DATA); - } - P_(P_HL){ - explain(ssl,"cipher suites\n"); - } - - for(;cs_len;cs_len-=3){ - UINT4 val; - - SSL_DECODE_UINT24_ABORT(ssl,0,0,&d,&val); - ssl_print_cipher_suite(ssl,ver,P_HL,val); - P_(P_HL){ - explain(ssl,"\n"); - } - } - - if(sid_len!=0){ - fprintf(stderr,"Session ID field should be zero length\n"); - ABORT(SSL_BAD_DATA); - } - - if(chall_len<16 || chall_len>32){ - fprintf(stderr,"Invalid challenge length %d\n",chall_len); - ABORT(SSL_BAD_DATA); - } - - SSL_DECODE_OPAQUE_ARRAY_ABORT(ssl,0,chall_len, - 0,&d,&chall); - P_(P_DC){ - exdump(ssl,"Challenge",&chall); - } - - memset(random,0,32); - memcpy(random+(32-chall_len),chall.data,chall_len); - - ssl_set_client_random(ssl->decoder,random,32); - ssl->i_state=SSL_ST_HANDSHAKE; - - P_(SSL_PRINT_HEXDUMP){ - Data d; - - INIT_DATA(d,seg->data,seg->len); - exdump(ssl,"Packet data",&d); - LF;LF; - } - - INDENT_POP; - - _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_obj *ssl, decoder *dtable, int value, int dir, segment *seg, Data *data) - { - while(dtable && dtable->type!=-1 && dtable->name!=NULL){ - if(dtable->type == value){ - INDENT_INCR; - explain(ssl,"%s",dtable->name); - if(dtable->print) { - INDENT_INCR; - dtable->print(ssl,dir,seg,data); - INDENT_POP; - } - INDENT_POP; - return(0); - } - dtable++; - } - - ERETURN(R_NOT_FOUND); - } - -int -ssl_expand_record (ssl_obj *ssl, segment *q, int direction, UCHAR *data, int len) - { - int r; - Data d; - UINT4 ct,vermaj,vermin,length; - int version; - char verstr[8]; - char enumstr[20]; - struct json_object *jobj; - jobj = ssl->cur_json_st; - - d.data=data; - d.len=len; - - /*This should be mapped to an enum*/ - SSL_DECODE_UINT8(ssl,0,0,&d,&ct); - SSL_DECODE_UINT8(ssl,0,0,&d,&vermaj); - SSL_DECODE_UINT8(ssl,0,0,&d,&vermin); - SSL_DECODE_UINT16(ssl,0,0,&d,&length); - - if(d.len!=length){ - explain(ssl," Short record: %u bytes available (expecting: %u)\n",length,d.len); - return(0); - } - version = ssl->version ? ssl->version : (vermaj*256+vermin); - - P_(P_RH){ - explain(ssl," V%d.%d(%d)",(version>>8)&0xff,version&0xff,length); - json_object_object_add(jobj, "record_len", json_object_new_int(length)); - snprintf(verstr,8,"%d.%d",(version>>8)&0xff,version&0xff); - json_object_object_add(jobj, "record_ver", json_object_new_string(verstr)); - } - - r = ssl_decode_record(ssl, ssl->decoder, direction, ct, version, &d); - if(r==SSL_BAD_MAC){ - explain(ssl," bad MAC\n"); - return(0); - } - - if(r){ - if(!(SSL_print_flags & SSL_PRINT_JSON)) - if((r=ssl_print_enum(ssl,0,ContentType_decoder,ct))) { - printf(" unknown record type: %d\n", ct); - ERETURN(r); - } - 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)) - LF; - } - else{ - //try to save unencrypted data to logger - //we must save record with type "application_data" (this is unencrypted data) - if (ct==23){ - if (logger) { - logger->vtbl->data(ssl->logger_obj,d.data,d.len,direction); - } - if (ssl->version==TLSV13_VERSION){ - ct = d.data[--d.len]; // In TLS 1.3 ct is stored in the end for encrypted records - } - } - if((r=ssl_decode_switch(ssl,ContentType_decoder,ct,direction,q, &d))) { - if(!(SSL_print_flags & SSL_PRINT_JSON)) - printf(" unknown record type: %d\n", ct); - ERETURN(r); - } - } - - return(0); - } - -int -ssl_decode_uintX (ssl_obj *ssl, char *name, int size, UINT4 p, Data *data, UINT4 *x) - { - UINT4 v=0; - UINT4 _x; - - if(!x) x=&_x; - - if(size>data->len){ - fprintf(stderr,"Short read: %d bytes available (expecting %d)\n", - data->len,size); - ERETURN(R_EOD); - } - - while(size--){ - v<<=8; - v|=*(data->data)++; - data->len--; - } - - P_(p){ - explain(ssl,"%s = %d\n",name,*x); - } - *x=v; - return(0); - } - -int -ssl_decode_opaque_array (ssl_obj *ssl, char *name, int size, UINT4 p, Data *data, Data *x) - { - UINT4 len; - char n[1000]; - int r; - Data _x; - - if(!x) x=&_x; - - sprintf(n,"%s (length)",name?name:""); - if(size<0){ - size*=-1; - if((r=ssl_decode_uintX(ssl,n,BYTES_NEEDED(size),P_DC,data,&len))) - ERETURN(r); - } - else{ - len=size; - } - - if(len>data->len){ - fprintf(stderr,"Not enough data. Found %d bytes (expecting %d)\n", - data->len,size); - ERETURN(R_EOD); - } - - x->data=data->data; - x->len=len; - data->data+=len; - data->len-=len; - - P_(p){ - exdump(ssl,name,x); - } - - return(0); - } - -int -ssl_lookup_enum (ssl_obj *ssl, decoder *dtable, UINT4 val, char **ptr) - { - while(dtable && dtable->type!=-1){ - if(dtable->type == val){ - *ptr=dtable->name; - return(0); - } - dtable++; - } - - return(R_NOT_FOUND); - } - -int -ssl_decode_enum (ssl_obj *ssl, char *name, int size, decoder *dtable, UINT4 p, Data *data, UINT4 *x) - { - int r; - UINT4 _x; - - if(!x) x=&_x; - - if((r=ssl_decode_uintX(ssl,name,size,0,data,x))) - ERETURN(r); - - P_(p){ - if(!(SSL_print_flags & SSL_PRINT_JSON)) - if((r=ssl_print_enum(ssl,name,dtable,*x))) - ERETURN(r); - } - - return(0); - } - -int -ssl_print_enum (ssl_obj *ssl, char *name, decoder *dtable, UINT4 value) - { - - if(name) explain(ssl,"%s ",name); - INDENT; - - while(dtable && dtable->type!=-1){ - if(dtable->type == value){ - INDENT_INCR; - explain(ssl,"%s",dtable->name); - INDENT_POP; - return(0); - } - dtable++; - } + print_data(ssl, &d); LF; - return(R_NOT_FOUND); } -int -ssl_get_enum_str (ssl_obj *ssl, char *outstr, decoder *dtable, UINT4 value) - { - while(dtable && dtable->type!=-1){ - if(dtable->type == value){ - strncpy(outstr, dtable->name, 20); - return(0); - } - dtable++; - } - return(R_NOT_FOUND); + return (0); +} + +int process_v2_hello(ssl_obj *ssl, segment *seg) { + int r; + int rec_len; + int _status; + UINT4 cs_len; + UINT4 sid_len; + UINT4 chall_len; + UINT4 ver; + Data d; + Data chall; + UCHAR random[32]; + + if(seg->len == 0) + ABORT(SSL_NO_DATA); + + d.data = seg->data; + d.len = seg->len; + + /* First check the message length. */ + if(d.len < 4) + 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*/ + ABORT(SSL_BAD_CONTENT_TYPE); + + /* If msg_type==1 then we've got a v2 message (or trash)*/ + if(*d.data++ != 1) + ABORT(SSL_BAD_CONTENT_TYPE); + d.len--; + + SSL_DECODE_UINT16_ABORT(ssl, "Version number", P_DC, &d, &ver); + /* We can't handle real v2 clients*/ + if(ver <= 2) { + explain(ssl, "Version 2 Client.\n"); + ABORT(SSL_BAD_DATA); } -int explain(ssl_obj *ssl,char *format,...) - { - va_list ap; - if(!(SSL_print_flags & SSL_PRINT_JSON)) { - va_start(ap,format); + 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")); - P_(P_NR){ - if(ssl->record_encryption==REC_DECRYPTED_CIPHERTEXT) - printf("\\f(CI"); - else - printf("\\fC"); - } - INDENT; + INDENT_INCR; - vprintf(format,ap); - va_end(ap); - } - return(0); + P_(P_HL) { + explain(ssl, "Version %d.%d ", (ver >> 8) & 0xff, ver & 0xff); + LF; + } + SSL_DECODE_UINT16_ABORT(ssl, "cipher_spec_length", P_DC, &d, &cs_len); + SSL_DECODE_UINT16_ABORT(ssl, "session_id_length", P_DC, &d, &sid_len); + SSL_DECODE_UINT16_ABORT(ssl, "challenge_length", P_DC, &d, &chall_len); + + if(cs_len % 3) { + fprintf(stderr, "Bad cipher spec length %d\n", cs_len); + ABORT(SSL_BAD_DATA); + } + P_(P_HL) { explain(ssl, "cipher suites\n"); } + + for(; cs_len; cs_len -= 3) { + UINT4 val; + + SSL_DECODE_UINT24_ABORT(ssl, 0, 0, &d, &val); + ssl_print_cipher_suite(ssl, ver, P_HL, val); + P_(P_HL) { explain(ssl, "\n"); } } -int -exdump (ssl_obj *ssl, char *name, Data *data) - { - int i; - if(!(SSL_print_flags & SSL_PRINT_JSON)) { - if(name){ - explain(ssl,"%s[%d]=\n",name,data->len); + if(sid_len != 0) { + fprintf(stderr, "Session ID field should be zero length\n"); + ABORT(SSL_BAD_DATA); + } + + if(chall_len < 16 || chall_len > 32) { + fprintf(stderr, "Invalid challenge length %d\n", chall_len); + ABORT(SSL_BAD_DATA); + } + + SSL_DECODE_OPAQUE_ARRAY_ABORT(ssl, 0, chall_len, 0, &d, &chall); + P_(P_DC) { exdump(ssl, "Challenge", &chall); } + + memset(random, 0, 32); + memcpy(random + (32 - chall_len), chall.data, chall_len); + + ssl_set_client_random(ssl->decoder, random, 32); + ssl->i_state = SSL_ST_HANDSHAKE; + + P_(SSL_PRINT_HEXDUMP) { + Data d; + + INIT_DATA(d, seg->data, seg->len); + exdump(ssl, "Packet data", &d); + LF; + LF; + } + + INDENT_POP; + + _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_obj *ssl, + decoder *dtable, + int value, + int dir, + segment *seg, + Data *data) { + while(dtable && dtable->type != -1 && dtable->name != NULL) { + if(dtable->type == value) { + INDENT_INCR; + explain(ssl, "%s", dtable->name); + if(dtable->print) { INDENT_INCR; + dtable->print(ssl, dir, seg, data); + INDENT_POP; } - P_(P_NR){ - printf("\\f(CB"); - } - for(i=0;ilen;i++){ + INDENT_POP; + return (0); + } + dtable++; + } - if(!i) INDENT; + ERETURN(R_NOT_FOUND); +} - if((data->len>8) && i && !(i%16)){ - LF; INDENT; - } - printf("%.2x ",data->data[i]&255); +int ssl_expand_record(ssl_obj *ssl, + segment *q, + int direction, + UCHAR *data, + int len) { + int r; + Data d; + UINT4 ct, vermaj, vermin, length; + int version; + char verstr[8]; + char enumstr[20]; + struct json_object *jobj; + jobj = ssl->cur_json_st; + + d.data = data; + d.len = len; + + /*This should be mapped to an enum*/ + SSL_DECODE_UINT8(ssl, 0, 0, &d, &ct); + SSL_DECODE_UINT8(ssl, 0, 0, &d, &vermaj); + SSL_DECODE_UINT8(ssl, 0, 0, &d, &vermin); + SSL_DECODE_UINT16(ssl, 0, 0, &d, &length); + + if(d.len != length) { + explain(ssl, " Short record: %u bytes available (expecting: %u)\n", length, + d.len); + return (0); + } + version = ssl->version ? ssl->version : (vermaj * 256 + vermin); + + P_(P_RH) { + explain(ssl, " V%d.%d(%d)", (version >> 8) & 0xff, version & 0xff, length); + json_object_object_add(jobj, "record_len", json_object_new_int(length)); + snprintf(verstr, 8, "%d.%d", (version >> 8) & 0xff, version & 0xff); + json_object_object_add(jobj, "record_ver", json_object_new_string(verstr)); + } + + r = ssl_decode_record(ssl, ssl->decoder, direction, ct, version, &d); + if(r == SSL_BAD_MAC) { + explain(ssl, " bad MAC\n"); + return (0); + } + + if(r) { + if(!(SSL_print_flags & SSL_PRINT_JSON)) + if((r = ssl_print_enum(ssl, 0, ContentType_decoder, ct))) { + printf(" unknown record type: %d\n", ct); + ERETURN(r); } - P_(P_NR){ - printf("\\fR"); - } - if(name) INDENT_POP; + 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)) LF; - } - return(0); - } - -int -exstr (ssl_obj *ssl, char *outstr, Data *data) - { - int i; - - char *ptr = outstr; - for(i=0;ilen;i++){ - sprintf(ptr, "%.2x",data->data[i]&255); - ptr+=2; - if(ilen - 1) { - sprintf(ptr, ":"); - ++ptr; + } else { + // try to save unencrypted data to logger + // we must save record with type "application_data" (this is unencrypted + // data) + if(ct == 23) { + if(logger) { + logger->vtbl->data(ssl->logger_obj, d.data, d.len, direction); + } + if(ssl->version == TLSV13_VERSION) { + ct = d.data[--d.len]; // In TLS 1.3 ct is stored in the end for + // encrypted records } } - - return(0); + if((r = ssl_decode_switch(ssl, ContentType_decoder, ct, direction, q, + &d))) { + if(!(SSL_print_flags & SSL_PRINT_JSON)) + printf(" unknown record type: %d\n", ct); + ERETURN(r); + } } -int -combodump (ssl_obj *ssl, char *name, Data *data) - { - UCHAR *ptr=data->data; - int len=data->len; + return (0); +} - if(name){ - explain(ssl,"%s[%d]=\n",name,data->len); +int ssl_decode_uintX(ssl_obj *ssl, + char *name, + int size, + UINT4 p, + Data *data, + UINT4 *x) { + UINT4 v = 0; + UINT4 _x; + + if(!x) + x = &_x; + + if(size > data->len) { + fprintf(stderr, "Short read: %d bytes available (expecting %d)\n", + data->len, size); + ERETURN(R_EOD); + } + + while(size--) { + v <<= 8; + v |= *(data->data)++; + data->len--; + } + + P_(p) { explain(ssl, "%s = %d\n", name, *x); } + *x = v; + return (0); +} + +int ssl_decode_opaque_array(ssl_obj *ssl, + char *name, + int size, + UINT4 p, + Data *data, + Data *x) { + UINT4 len; + char n[1000]; + int r; + Data _x; + + if(!x) + x = &_x; + + sprintf(n, "%s (length)", name ? name : ""); + if(size < 0) { + size *= -1; + if((r = ssl_decode_uintX(ssl, n, BYTES_NEEDED(size), P_DC, data, &len))) + ERETURN(r); + } else { + len = size; + } + + if(len > data->len) { + fprintf(stderr, "Not enough data. Found %d bytes (expecting %d)\n", + data->len, size); + ERETURN(R_EOD); + } + + x->data = data->data; + x->len = len; + data->data += len; + data->len -= len; + + P_(p) { exdump(ssl, name, x); } + + return (0); +} + +int ssl_lookup_enum(ssl_obj *ssl, decoder *dtable, UINT4 val, char **ptr) { + while(dtable && dtable->type != -1) { + if(dtable->type == val) { + *ptr = dtable->name; + return (0); + } + dtable++; + } + + return (R_NOT_FOUND); +} + +int ssl_decode_enum(ssl_obj *ssl, + char *name, + int size, + decoder *dtable, + UINT4 p, + Data *data, + UINT4 *x) { + int r; + UINT4 _x; + + if(!x) + x = &_x; + + if((r = ssl_decode_uintX(ssl, name, size, 0, data, x))) + ERETURN(r); + + P_(p) { + if(!(SSL_print_flags & SSL_PRINT_JSON)) + if((r = ssl_print_enum(ssl, name, dtable, *x))) + ERETURN(r); + } + + return (0); +} + +int ssl_print_enum(ssl_obj *ssl, char *name, decoder *dtable, UINT4 value) { + if(name) + explain(ssl, "%s ", name); + INDENT; + + while(dtable && dtable->type != -1) { + if(dtable->type == value) { + INDENT_INCR; + explain(ssl, "%s", dtable->name); + INDENT_POP; + return (0); + } + dtable++; + } + LF; + return (R_NOT_FOUND); +} + +int ssl_get_enum_str(ssl_obj *ssl, char *outstr, decoder *dtable, UINT4 value) { + while(dtable && dtable->type != -1) { + if(dtable->type == value) { + strncpy(outstr, dtable->name, 20); + return (0); + } + dtable++; + } + return (R_NOT_FOUND); +} + +int explain(ssl_obj *ssl, char *format, ...) { + va_list ap; + if(!(SSL_print_flags & SSL_PRINT_JSON)) { + va_start(ap, format); + + P_(P_NR) { + if(ssl->record_encryption == REC_DECRYPTED_CIPHERTEXT) + printf("\\f(CI"); + else + printf("\\fC"); + } + INDENT; + + vprintf(format, ap); + va_end(ap); + } + return (0); +} + +int exdump(ssl_obj *ssl, char *name, Data *data) { + int i; + if(!(SSL_print_flags & SSL_PRINT_JSON)) { + if(name) { + explain(ssl, "%s[%d]=\n", name, data->len); INDENT_INCR; } - while(len){ - int i; - int bytes=MIN(len,16); + P_(P_NR) { printf("\\f(CB"); } + for(i = 0; i < data->len; i++) { + if(!i) + INDENT; - INDENT; - - P_(P_NR){ - if(ssl->record_encryption==REC_DECRYPTED_CIPHERTEXT) - printf("\\f[CBI]"); - else - printf("\\f(CB"); + if((data->len > 8) && i && !(i % 16)) { + LF; + INDENT; } - - for(i=0;irecord_encryption==REC_DECRYPTED_CIPHERTEXT) - printf("\\f[CI]"); - else - printf("\\f(C"); - } - - for(i=0;idata[i] & 255); } - P_(P_NR){ - printf("\\fR"); - } - if(name) INDENT_POP; - return(0); - } - -int -print_data (ssl_obj *ssl, Data *d) - { - int i,bit8=0; - + P_(P_NR) { printf("\\fR"); } + if(name) + INDENT_POP; LF; - for(i=0;ilen;i++){ - if(d->data[i] == 0 || (!isprint(d->data[i]) && !strchr("\r\n\t",d->data[i]))){ - bit8=1; - break; - } - } - - if(bit8){ - INDENT; - printf("---------------------------------------------------------------\n"); - P_(P_HO){ - exdump(ssl,0,d); - } - else{ - combodump(ssl,0,d); - } - INDENT; - printf("---------------------------------------------------------------\n"); - - } - else{ - int nl=1; - INDENT; - printf("---------------------------------------------------------------\n"); - if(SSL_print_flags & SSL_PRINT_NROFF){ - if(ssl->process_ciphertext & ssl->direction) - printf("\\f[CI]"); - else - printf("\\f(C"); - } - - INDENT; - for(i=0;ilen;i++){ - /* Escape leading . */ - if(nl==1 && (SSL_print_flags & SSL_PRINT_NROFF) && (d->data[i]=='.')) - printf("\\&"); - nl=0; - - putchar(d->data[i]); - if(d->data[i]=='\n') {nl=1;INDENT;} - } - printf("---------------------------------------------------------------\n"); - if(SSL_print_flags & SSL_PRINT_NROFF){ - printf("\\f(R"); - } - } - - return(0); } -int -ssl_print_direction_indicator (ssl_obj *ssl, int dir) - { - struct json_object *jobj; + return (0); +} + +int exstr(ssl_obj *ssl, char *outstr, Data *data) { + int i; + + char *ptr = outstr; + for(i = 0; i < data->len; i++) { + sprintf(ptr, "%.2x", data->data[i] & 255); + ptr += 2; + if(i < data->len - 1) { + sprintf(ptr, ":"); + ++ptr; + } + } + + return (0); +} + +int combodump(ssl_obj *ssl, char *name, Data *data) { + UCHAR *ptr = data->data; + int len = data->len; + + if(name) { + explain(ssl, "%s[%d]=\n", name, data->len); + INDENT_INCR; + } + while(len) { + int i; + int bytes = MIN(len, 16); + + INDENT; + + P_(P_NR) { + if(ssl->record_encryption == REC_DECRYPTED_CIPHERTEXT) + printf("\\f[CBI]"); + else + printf("\\f(CB"); + } + + for(i = 0; i < bytes; i++) + printf("%.2x ", ptr[i] & 255); + /* Fill */ + for(i = 0; i < (16 - bytes); i++) + printf(" "); + printf(" "); + + P_(P_NR) { + if(ssl->record_encryption == REC_DECRYPTED_CIPHERTEXT) + printf("\\f[CI]"); + else + printf("\\f(C"); + } + + for(i = 0; i < bytes; i++) { + if(isprint(ptr[i])) + printf("%c", ptr[i]); + else + printf("."); + } + LF; + + len -= bytes; + ptr += bytes; + } + P_(P_NR) { printf("\\fR"); } + if(name) + INDENT_POP; + return (0); +} + +int print_data(ssl_obj *ssl, Data *d) { + int i, bit8 = 0; + + LF; + for(i = 0; i < d->len; i++) { + if(d->data[i] == 0 || + (!isprint(d->data[i]) && !strchr("\r\n\t", d->data[i]))) { + bit8 = 1; + break; + } + } + + if(bit8) { + INDENT; + printf("---------------------------------------------------------------\n"); + P_(P_HO) { exdump(ssl, 0, d); } + else { + combodump(ssl, 0, d); + } + INDENT; + printf("---------------------------------------------------------------\n"); + + } else { + int nl = 1; + INDENT; + printf("---------------------------------------------------------------\n"); + if(SSL_print_flags & SSL_PRINT_NROFF) { + if(ssl->process_ciphertext & ssl->direction) + printf("\\f[CI]"); + else + printf("\\f(C"); + } + + INDENT; + for(i = 0; i < d->len; i++) { + /* Escape leading . */ + if(nl == 1 && (SSL_print_flags & SSL_PRINT_NROFF) && (d->data[i] == '.')) + printf("\\&"); + nl = 0; + + putchar(d->data[i]); + if(d->data[i] == '\n') { + nl = 1; + INDENT; + } + } + printf("---------------------------------------------------------------\n"); + if(SSL_print_flags & SSL_PRINT_NROFF) { + printf("\\f(R"); + } + } + + return (0); +} +int ssl_print_direction_indicator(ssl_obj *ssl, int dir) { + struct json_object *jobj; #if 0 if(dir==DIR_I2R){ explain(ssl,"%s(%d) > %s>%d", @@ -632,124 +622,124 @@ ssl_print_direction_indicator (ssl_obj *ssl, int dir) } #else - jobj = ssl->cur_json_st; - - if(dir==DIR_I2R){ - explain(ssl,"C>S"); - if(jobj) { - json_object_object_add(jobj, "src_name", json_object_new_string(ssl->client_name)); - json_object_object_add(jobj, "src_ip", json_object_new_string(ssl->client_ip)); - json_object_object_add(jobj, "src_port", json_object_new_int(ssl->client_port)); - json_object_object_add(jobj, "dst_name", json_object_new_string(ssl->server_name)); - json_object_object_add(jobj, "dst_ip", json_object_new_string(ssl->server_ip)); - json_object_object_add(jobj, "dst_port", json_object_new_int(ssl->server_port)); - } - } - else{ - explain(ssl,"S>C"); - if(jobj) { - json_object_object_add(jobj, "src_name", json_object_new_string(ssl->server_name)); - json_object_object_add(jobj, "src_ip", json_object_new_string(ssl->server_ip)); - json_object_object_add(jobj, "src_port", json_object_new_int(ssl->server_port)); - json_object_object_add(jobj, "dst_name", json_object_new_string(ssl->client_name)); - json_object_object_add(jobj, "dst_ip", json_object_new_string(ssl->client_ip)); - json_object_object_add(jobj, "dst_port", json_object_new_int(ssl->client_port)); - } - } -#endif - - return(0); - } - -int -ssl_print_timestamp (ssl_obj *ssl, struct timeval *ts) - { - struct timeval dt; - int r; - - char ts_str[40]; - struct json_object *jobj; - jobj = ssl->cur_json_st; + jobj = ssl->cur_json_st; + if(dir == DIR_I2R) { + explain(ssl, "C>S"); if(jobj) { - snprintf(ts_str,40, "%lld%c%4.4lld",(long long)ts->tv_sec,'.',(long long)ts->tv_usec/100); - json_object *j_ts_str = json_object_new_string(ts_str); - json_object_object_add(jobj, "timestamp", j_ts_str); + json_object_object_add(jobj, "src_name", + json_object_new_string(ssl->client_name)); + json_object_object_add(jobj, "src_ip", + json_object_new_string(ssl->client_ip)); + json_object_object_add(jobj, "src_port", + json_object_new_int(ssl->client_port)); + json_object_object_add(jobj, "dst_name", + json_object_new_string(ssl->server_name)); + json_object_object_add(jobj, "dst_ip", + json_object_new_string(ssl->server_ip)); + json_object_object_add(jobj, "dst_port", + json_object_new_int(ssl->server_port)); } - if(SSL_print_flags & SSL_PRINT_TIMESTAMP_ABSOLUTE) { - if(!(SSL_print_flags & SSL_PRINT_JSON)) - explain(ssl,"%lld%c%4.4lld ",(long long)ts->tv_sec,'.',(long long)ts->tv_usec/100); - } - else{ - if((r=timestamp_diff(ts,&ssl->time_start,&dt))) - ERETURN(r); - if(!(SSL_print_flags & SSL_PRINT_JSON)) - explain(ssl,"%lld%c%4.4lld ",(long long)dt.tv_sec,'.',(long long)dt.tv_usec/100); - } - - if((r=timestamp_diff(ts,&ssl->time_last,&dt))){ - ERETURN(r); + } else { + explain(ssl, "S>C"); + if(jobj) { + json_object_object_add(jobj, "src_name", + json_object_new_string(ssl->server_name)); + json_object_object_add(jobj, "src_ip", + json_object_new_string(ssl->server_ip)); + json_object_object_add(jobj, "src_port", + json_object_new_int(ssl->server_port)); + json_object_object_add(jobj, "dst_name", + json_object_new_string(ssl->client_name)); + json_object_object_add(jobj, "dst_ip", + json_object_new_string(ssl->client_ip)); + json_object_object_add(jobj, "dst_port", + json_object_new_int(ssl->client_port)); } + } +#endif + + return (0); +} + +int ssl_print_timestamp(ssl_obj *ssl, struct timeval *ts) { + struct timeval dt; + int r; + + char ts_str[40]; + struct json_object *jobj; + jobj = ssl->cur_json_st; + + if(jobj) { + snprintf(ts_str, 40, "%lld%c%4.4lld", (long long)ts->tv_sec, '.', + (long long)ts->tv_usec / 100); + json_object *j_ts_str = json_object_new_string(ts_str); + json_object_object_add(jobj, "timestamp", j_ts_str); + } + if(SSL_print_flags & SSL_PRINT_TIMESTAMP_ABSOLUTE) { if(!(SSL_print_flags & SSL_PRINT_JSON)) - explain(ssl,"(%lld%c%4.4lld) ",(long long)dt.tv_sec,'.',(long long)dt.tv_usec/100); - - memcpy(&ssl->time_last,ts,sizeof(struct timeval)); - - return(0); + explain(ssl, "%lld%c%4.4lld ", (long long)ts->tv_sec, '.', + (long long)ts->tv_usec / 100); + } else { + if((r = timestamp_diff(ts, &ssl->time_start, &dt))) + ERETURN(r); + if(!(SSL_print_flags & SSL_PRINT_JSON)) + explain(ssl, "%lld%c%4.4lld ", (long long)dt.tv_sec, '.', + (long long)dt.tv_usec / 100); } + if((r = timestamp_diff(ts, &ssl->time_last, &dt))) { + ERETURN(r); + } + if(!(SSL_print_flags & SSL_PRINT_JSON)) + explain(ssl, "(%lld%c%4.4lld) ", (long long)dt.tv_sec, '.', + (long long)dt.tv_usec / 100); -int -ssl_print_record_num (ssl_obj *ssl) - { - struct json_object *jobj; - jobj = ssl->cur_json_st; + memcpy(&ssl->time_last, ts, sizeof(struct timeval)); - ssl->record_count++; - if(!(SSL_print_flags & SSL_PRINT_JSON)) { - if(SSL_print_flags & SSL_PRINT_NROFF){ - printf("\\fI%d %d\\fR %s", - ssl->conn->conn_number, - ssl->record_count,ssl->record_count<10?" ":""); - } - else{ - printf("%d %d %s",ssl->conn->conn_number, - ssl->record_count,ssl->record_count<10?" ":""); - } + return (0); +} + +int ssl_print_record_num(ssl_obj *ssl) { + struct json_object *jobj; + jobj = ssl->cur_json_st; + + ssl->record_count++; + if(!(SSL_print_flags & SSL_PRINT_JSON)) { + if(SSL_print_flags & SSL_PRINT_NROFF) { + printf("\\fI%d %d\\fR %s", ssl->conn->conn_number, ssl->record_count, + ssl->record_count < 10 ? " " : ""); + } else { + printf("%d %d %s", ssl->conn->conn_number, ssl->record_count, + ssl->record_count < 10 ? " " : ""); } - json_object_object_add(jobj, "connection_number", json_object_new_int(ssl->conn->conn_number)); - json_object_object_add(jobj, "record_count", json_object_new_int(ssl->record_count)); - - return(0); } + json_object_object_add(jobj, "connection_number", + json_object_new_int(ssl->conn->conn_number)); + json_object_object_add(jobj, "record_count", + json_object_new_int(ssl->record_count)); -int -ssl_print_cipher_suite (ssl_obj *ssl, int version, int p, UINT4 val) - { - char *str; - char *prefix=version<=0x300?"SSL_":"TLS_"; - int r; - - P_(p){ - if((r=ssl_lookup_enum(ssl,cipher_suite_decoder,val,&str))){ - explain(ssl,"Unknown value 0x%x",val); - return(0); - } + return (0); +} - /* Now the tricky bit. If the cipher suite begins with TLS_ - and the version is SSLv3 then we replace it with SSL_*/ - if(!strncmp(str,"TLS_",4)){ - explain(ssl,"%s%s",prefix,str+4); - } - else{ - explain(ssl,"%s",str); - } +int ssl_print_cipher_suite(ssl_obj *ssl, int version, int p, UINT4 val) { + char *str; + char *prefix = version <= 0x300 ? "SSL_" : "TLS_"; + int r; + + P_(p) { + if((r = ssl_lookup_enum(ssl, cipher_suite_decoder, val, &str))) { + explain(ssl, "Unknown value 0x%x", val); + return (0); + } + + /* Now the tricky bit. If the cipher suite begins with TLS_ + and the version is SSLv3 then we replace it with SSL_*/ + if(!strncmp(str, "TLS_", 4)) { + explain(ssl, "%s%s", prefix, str + 4); + } else { + explain(ssl, "%s", str); } - return(0); } - - - - - - + return (0); +} diff --git a/ssl/sslprint.h b/ssl/sslprint.h index e180abe..6953645 100644 --- a/ssl/sslprint.h +++ b/ssl/sslprint.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: sslprint.h,v 1.3 2000/11/03 06:38:06 ekr Exp $ @@ -43,66 +44,104 @@ ekr@rtfm.com Wed Feb 10 15:34:14 1999 */ - #ifndef _sslprint_h #define _sslprint_h #include "ssl_analyze.h" #include "ssl_h.h" -int ssl_expand_record PROTO_LIST((ssl_obj *ssl, - segment *q,int direction,UCHAR *data,int len)); -int ssl_decode_switch PROTO_LIST((ssl_obj *ssl, - decoder *dtable,int value,int dir,segment *seg,Data *data)); -int ssl_decode_uintX PROTO_LIST((ssl_obj *ssl,char *name,int size, - UINT4 print,Data *data,UINT4 *x)); -int ssl_decode_opaque_array PROTO_LIST((ssl_obj *ssl,char *name,int size, - UINT4 print,Data *data,Data *x)); -int ssl_decode_enum PROTO_LIST((ssl_obj *ssl,char *name, - int size,decoder *decode,UINT4 p,Data *data, - UINT4 *x)); -int ssl_lookup_enum PROTO_LIST((ssl_obj *ssl,decoder *dtable, - UINT4 val,char **ptr)); -int ssl_print_enum PROTO_LIST((ssl_obj *obj,char *name, - decoder *decode,UINT4 value)); -int ssl_get_enum_str PROTO_LIST((ssl_obj *obj,char *outstr, - decoder *decode,UINT4 value)); -int print_data PROTO_LIST((ssl_obj *ssl,Data *d)); -int process_v2_hello PROTO_LIST((ssl_obj *ssl,segment *seg)); -int process_beginning_plaintext PROTO_LIST((ssl_obj *ssl, - segment *seg,int direction)); -int ssl_print_direction_indicator PROTO_LIST((ssl_obj *ssl,int dir)); -int ssl_print_timestamp PROTO_LIST((ssl_obj *ssl,struct timeval *ts)); -int ssl_print_record_num PROTO_LIST((ssl_obj *ssl)); -int ssl_print_cipher_suite PROTO_LIST((ssl_obj *ssl,int version,int p, - UINT4 val)); +int ssl_expand_record PROTO_LIST( + (ssl_obj * ssl, segment *q, int direction, UCHAR *data, int len)); +int ssl_decode_switch PROTO_LIST((ssl_obj * ssl, + decoder *dtable, + int value, + int dir, + segment *seg, + Data *data)); +int ssl_decode_uintX PROTO_LIST( + (ssl_obj * ssl, char *name, int size, UINT4 print, Data *data, UINT4 *x)); +int ssl_decode_opaque_array PROTO_LIST( + (ssl_obj * ssl, char *name, int size, UINT4 print, Data *data, Data *x)); +int ssl_decode_enum PROTO_LIST((ssl_obj * ssl, + char *name, + int size, + decoder *decode, + UINT4 p, + Data *data, + UINT4 *x)); +int ssl_lookup_enum + PROTO_LIST((ssl_obj * ssl, decoder *dtable, UINT4 val, char **ptr)); +int ssl_print_enum + PROTO_LIST((ssl_obj * obj, char *name, decoder *decode, UINT4 value)); +int ssl_get_enum_str + PROTO_LIST((ssl_obj * obj, char *outstr, decoder *decode, UINT4 value)); +int print_data PROTO_LIST((ssl_obj * ssl, Data *d)); +int process_v2_hello PROTO_LIST((ssl_obj * ssl, segment *seg)); +int process_beginning_plaintext PROTO_LIST((ssl_obj * ssl, + segment *seg, + int direction)); +int ssl_print_direction_indicator PROTO_LIST((ssl_obj * ssl, int dir)); +int ssl_print_timestamp PROTO_LIST((ssl_obj * ssl, struct timeval *ts)); +int ssl_print_record_num PROTO_LIST((ssl_obj * ssl)); +int ssl_print_cipher_suite + PROTO_LIST((ssl_obj * ssl, int version, int p, UINT4 val)); -int explain PROTO_LIST((ssl_obj *ssl,char *format,...)); -int exdump PROTO_LIST((ssl_obj *ssl,char *name,Data *data)); -int exstr PROTO_LIST((ssl_obj *ssl,char *name,Data *data)); +int explain PROTO_LIST((ssl_obj * ssl, char *format, ...)); +int exdump PROTO_LIST((ssl_obj * ssl, char *name, Data *data)); +int exstr PROTO_LIST((ssl_obj * ssl, char *name, Data *data)); +#define SSL_DECODE_UINT8(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 1, b, c, d))) \ + ERETURN(r) +#define SSL_DECODE_UINT16(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 2, b, c, d))) \ + ERETURN(r) +#define SSL_DECODE_UINT24(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 3, b, c, d))) \ + ERETURN(r) +#define SSL_DECODE_UINT32(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 4, b, c, d))) \ + ERETURN(r) +#define SSL_DECODE_OPAQUE_ARRAY(a, n, b, c, d, e) \ + if((r = ssl_decode_opaque_array(a, n, b, c, d, e))) \ + ERETURN(r) +#define SSL_DECODE_ENUM(a, b, c, d, e, f, g) \ + if((r = ssl_decode_enum(a, b, c, d, e, f, g))) \ + ERETURN(r) +#define SSL_DECODE_UINT8_ABORT(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 1, b, c, d))) \ + ABORT(r) +#define SSL_DECODE_UINT16_ABORT(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 2, b, c, d))) \ + ABORT(r) +#define SSL_DECODE_UINT24_ABORT(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 3, b, c, d))) \ + ABORT(r) +#define SSL_DECODE_UINT32_ABORT(a, n, b, c, d) \ + if((r = ssl_decode_uintX(a, n, 4, b, c, d))) \ + ABORT(r) +#define SSL_DECODE_OPAQUE_ARRAY_ABORT(a, n, b, c, d, e) \ + if((r = ssl_decode_opaque_array(a, n, b, c, d, e))) \ + ABORT(r) +#define SSL_DECODE_ENUM_ABORT(a, b, c, d, e, f, g) \ + if((r = ssl_decode_enum(a, b, c, d, e, f, g))) \ + ABORT(r) +#define P_(p) if((p == SSL_PRINT_ALL) || (p & SSL_print_flags)) -#define SSL_DECODE_UINT8(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,1,b,c,d))) ERETURN(r) -#define SSL_DECODE_UINT16(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,2,b,c,d))) ERETURN(r) -#define SSL_DECODE_UINT24(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,3,b,c,d))) ERETURN(r) -#define SSL_DECODE_UINT32(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,4,b,c,d))) ERETURN(r) -#define SSL_DECODE_OPAQUE_ARRAY(a,n,b,c,d,e) if((r=ssl_decode_opaque_array(a,n,b,c,d,e))) ERETURN(r) -#define SSL_DECODE_ENUM(a,b,c,d,e,f,g) if((r=ssl_decode_enum(a,b,c,d,e,f,g))) ERETURN(r) -#define SSL_DECODE_UINT8_ABORT(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,1,b,c,d))) ABORT(r) -#define SSL_DECODE_UINT16_ABORT(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,2,b,c,d))) ABORT(r) -#define SSL_DECODE_UINT24_ABORT(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,3,b,c,d))) ABORT(r) -#define SSL_DECODE_UINT32_ABORT(a,n,b,c,d) if((r=ssl_decode_uintX(a,n,4,b,c,d))) ABORT(r) -#define SSL_DECODE_OPAQUE_ARRAY_ABORT(a,n,b,c,d,e) if((r=ssl_decode_opaque_array(a,n,b,c,d,e))) ABORT(r) -#define SSL_DECODE_ENUM_ABORT(a,b,c,d,e,f,g) if((r=ssl_decode_enum(a,b,c,d,e,f,g))) ABORT(r) -#define P_(p) if((p==SSL_PRINT_ALL) || (p & SSL_print_flags)) - -#define INDENT if(!(NET_print_flags & NET_PRINT_JSON)) do {int i; for(i=0;i<(ssl->indent_depth + ssl->indent_name_len);i++) printf("%s",SSL_print_flags & SSL_PRINT_NROFF?" ":" ");} while(0) -#define INDENT_INCR ssl->indent_depth+=2 -#define INDENT_POP ssl->indent_depth-=2 +#define INDENT \ + if(!(NET_print_flags & NET_PRINT_JSON)) \ + do { \ + int i; \ + for(i = 0; i < (ssl->indent_depth + ssl->indent_name_len); i++) \ + printf("%s", SSL_print_flags &SSL_PRINT_NROFF ? " " : " "); \ + } while(0) +#define INDENT_INCR ssl->indent_depth += 2 +#define INDENT_POP ssl->indent_depth -= 2 #define INDENT_NAME(x) ssl->indent_name_len += strlen(x) -#define INDENT_NAME_POP ssl->indent_name_len=0 +#define INDENT_NAME_POP ssl->indent_name_len = 0 #define LINE_LEFT (80-(ssl->indent_name_len + ssl->indent_depth) -#define LF if(!(NET_print_flags & NET_PRINT_JSON)) printf("\n") - -#endif +#define LF \ + if(!(NET_print_flags & NET_PRINT_JSON)) \ + printf("\n") +#endif diff --git a/ssl/sslxprint.c b/ssl/sslxprint.c index 6d79e9e..ec1068e 100644 --- a/ssl/sslxprint.c +++ b/ssl/sslxprint.c @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: sslxprint.c,v 1.3 2000/11/03 06:38:06 ekr Exp $ @@ -43,7 +44,6 @@ ekr@rtfm.com Thu Mar 25 21:17:16 1999 */ - #include #include "network.h" #include "ssl_h.h" @@ -57,201 +57,195 @@ #define BUFSIZE 1024 -static int sslx__print_dn PROTO_LIST((ssl_obj *ssl,char *x)); +static int sslx__print_dn PROTO_LIST((ssl_obj * ssl, char *x)); #ifdef OPENSSL -static int sslx__print_serial PROTO_LIST((ssl_obj *ssl,ASN1_INTEGER *a)); +static int sslx__print_serial PROTO_LIST((ssl_obj * ssl, ASN1_INTEGER *a)); #endif -int -sslx_print_certificate (ssl_obj *ssl, Data *data, int pf) - { -#ifdef OPENSSL - X509 *x=0; - ASN1_INTEGER *a; -#endif - UCHAR *d; - int _status; - struct json_object *cert_obj; - -#ifdef OPENSSL - P_(P_ASN){ - char buf[BUFSIZE]; - int ext; - char *b64_cert; - - char *serial_str = NULL; - Data data_tmp; - - struct json_object *jobj; - jobj = ssl->cur_json_st; - - cert_obj = json_object_new_object(); - - d=data->data; - - if(!(b64_cert=(char *)calloc(1,sizeof(char) * ((((data->len) + 3 - 1)/3) * 4 + 1)))) - ABORT(R_NO_MEMORY); - - EVP_EncodeBlock((unsigned char *)b64_cert, d, data->len); - json_object_object_add(cert_obj, "cert_der", json_object_new_string(b64_cert)); - free(b64_cert); - - if(!(x=d2i_X509(0,(const unsigned char **) &d,data->len))){ - explain(ssl,"Bad certificate"); - ABORT(R_BAD_DATA); - } - X509_NAME_oneline(X509_get_subject_name(x),buf, - BUFSIZE); - explain(ssl,"Subject\n"); - INDENT_INCR; - json_object_object_add(cert_obj, "cert_subject", json_object_new_string(buf)); - sslx__print_dn(ssl,buf); - INDENT_POP; - X509_NAME_oneline(X509_get_issuer_name(x),buf, - BUFSIZE); - explain(ssl,"Issuer\n"); - INDENT_INCR; - json_object_object_add(cert_obj, "cert_issuer", json_object_new_string(buf)); - sslx__print_dn(ssl,buf); - INDENT_POP; - a=X509_get_serialNumber(x); - explain(ssl,"Serial "); - if(!(serial_str=(char *)calloc(1,sizeof(char) * (a->length * 3)))) - ABORT(R_NO_MEMORY); - INIT_DATA(data_tmp,a->data,a->length); - exstr(ssl, serial_str, &data_tmp); - json_object_object_add(cert_obj, "cert_serial", json_object_new_string(serial_str)); - free(serial_str); - sslx__print_serial(ssl,a); - - ext=X509_get_ext_count(x); - if(ext>0){ - int i,j; - UCHAR buf[1024]; - - explain(ssl,"Extensions\n"); - INDENT_INCR; - for(i=0;iprocess_ciphertext&ssl->direction) - printf("\\f(CI"); - else - printf("\\fC"); - - INDENT_INCR; - INDENT; - if(!X509V3_EXT_print_fp(stdout,ex,0,0)){ - printf("Hex value"); - } - INDENT_POP; - explain(ssl,"\n"); - } - } - INDENT_POP; - - } - else{ +int sslx_print_certificate(ssl_obj *ssl, Data *data, int pf) { +#ifdef OPENSSL + X509 *x = 0; + ASN1_INTEGER *a; #endif - P_(pf){ - exdump(ssl,"certificate",data); - } -#ifdef OPENSSL - } + UCHAR *d; + int _status; + struct json_object *cert_obj; - struct json_object *certs_array; - json_object_object_get_ex(jobj, "cert_chain", &certs_array); - json_object_array_add(certs_array,cert_obj); +#ifdef OPENSSL + P_(P_ASN) { + char buf[BUFSIZE]; + int ext; + char *b64_cert; + + char *serial_str = NULL; + Data data_tmp; + + struct json_object *jobj; + jobj = ssl->cur_json_st; + + cert_obj = json_object_new_object(); + + d = data->data; + + if(!(b64_cert = (char *)calloc( + 1, sizeof(char) * ((((data->len) + 3 - 1) / 3) * 4 + 1)))) + ABORT(R_NO_MEMORY); + + EVP_EncodeBlock((unsigned char *)b64_cert, d, data->len); + json_object_object_add(cert_obj, "cert_der", + json_object_new_string(b64_cert)); + free(b64_cert); + + if(!(x = d2i_X509(0, (const unsigned char **)&d, data->len))) { + explain(ssl, "Bad certificate"); + ABORT(R_BAD_DATA); } -#endif + X509_NAME_oneline(X509_get_subject_name(x), buf, BUFSIZE); + explain(ssl, "Subject\n"); + INDENT_INCR; + json_object_object_add(cert_obj, "cert_subject", + json_object_new_string(buf)); + sslx__print_dn(ssl, buf); + INDENT_POP; + X509_NAME_oneline(X509_get_issuer_name(x), buf, BUFSIZE); + explain(ssl, "Issuer\n"); + INDENT_INCR; + json_object_object_add(cert_obj, "cert_issuer", + json_object_new_string(buf)); + sslx__print_dn(ssl, buf); + INDENT_POP; + a = X509_get_serialNumber(x); + explain(ssl, "Serial "); + if(!(serial_str = (char *)calloc(1, sizeof(char) * (a->length * 3)))) + ABORT(R_NO_MEMORY); + INIT_DATA(data_tmp, a->data, a->length); + exstr(ssl, serial_str, &data_tmp); + json_object_object_add(cert_obj, "cert_serial", + json_object_new_string(serial_str)); + free(serial_str); + sslx__print_serial(ssl, a); - _status=0; - abort: -#ifdef OPENSSL - if(x) X509_free(x); -#endif - if(_status && cert_obj) json_object_put(cert_obj); - return(_status); - } + ext = X509_get_ext_count(x); + if(ext > 0) { + int i, j; + UCHAR buf[1024]; -int -sslx_print_dn (ssl_obj *ssl, Data *data, int pf) - { - UCHAR buf[BUFSIZE]; - int _status; - UCHAR *d=data->data; -#ifdef OPENSSL - X509_NAME *n=0; -#endif - - P_(pf){ -#ifdef OPENSSL - P_(P_ASN){ - if(!(n=d2i_X509_NAME(0,(const unsigned char **) &d,data->len))) - ABORT(R_BAD_DATA); - X509_NAME_oneline(n,(char *)buf,BUFSIZE); - sslx__print_dn(ssl,(char *)buf); - } - else{ -#endif - exdump(ssl,0,data); -#ifdef OPENSSL + explain(ssl, "Extensions\n"); + INDENT_INCR; + for(i = 0; i < ext; i++) { + X509_EXTENSION *ex; + ASN1_OBJECT *obj; + + ex = X509_get_ext(x, i); + obj = X509_EXTENSION_get_object(ex); + i2t_ASN1_OBJECT((char *)buf, sizeof(buf), obj); + + explain(ssl, "Extension: %s\n", buf); + j = X509_EXTENSION_get_critical(ex); + if(j) { + INDENT; + explain(ssl, "Critical\n"); + } + if(SSL_print_flags & SSL_PRINT_NROFF) { + if(ssl->process_ciphertext & ssl->direction) + printf("\\f(CI"); + else + printf("\\fC"); + + INDENT_INCR; + INDENT; + if(!X509V3_EXT_print_fp(stdout, ex, 0, 0)) { + printf("Hex value"); + } + INDENT_POP; + explain(ssl, "\n"); + } } + INDENT_POP; + + } else { #endif + P_(pf) { exdump(ssl, "certificate", data); } +#ifdef OPENSSL } - _status=0; - abort: -#ifdef OPENSSL + struct json_object *certs_array; + json_object_object_get_ex(jobj, "cert_chain", &certs_array); + json_object_array_add(certs_array, cert_obj); + } +#endif + + _status = 0; +abort: +#ifdef OPENSSL + if(x) + X509_free(x); +#endif + if(_status && cert_obj) + json_object_put(cert_obj); + return (_status); +} + +int sslx_print_dn(ssl_obj *ssl, Data *data, int pf) { + UCHAR buf[BUFSIZE]; + int _status; + UCHAR *d = data->data; +#ifdef OPENSSL + X509_NAME *n = 0; +#endif + + P_(pf){ +#ifdef OPENSSL + P_(P_ASN){if(!(n = d2i_X509_NAME(0, (const unsigned char **)&d, + data->len))) ABORT(R_BAD_DATA); + X509_NAME_oneline(n, (char *)buf, BUFSIZE); + sslx__print_dn(ssl, (char *)buf); +} +else { +#endif + exdump(ssl, 0, data); +#ifdef OPENSSL +} +#endif +} + +_status = 0; +abort : +#ifdef OPENSSL if(n) X509_NAME_free(n); -#endif - return(_status); - } +#endif +return (_status); +} -static int -sslx__print_dn (ssl_obj *ssl, char *x) - { - char *slash; +static int sslx__print_dn(ssl_obj *ssl, char *x) { + char *slash; - if(*x=='/') x++; - - while (x){ - if((slash=strchr(x,'/'))){ - *slash=0; - } + if(*x == '/') + x++; - explain(ssl,"%s\n",x); + while(x) { + if((slash = strchr(x, '/'))) { + *slash = 0; + } - x=slash?slash+1:0; - }; + explain(ssl, "%s\n", x); - return(0); - } + x = slash ? slash + 1 : 0; + }; + + return (0); +} #ifdef OPENSSL -static int -sslx__print_serial (ssl_obj *ssl, ASN1_INTEGER *a) - { - Data d; - - if(a->length==0) - printf("0"); +static int sslx__print_serial(ssl_obj *ssl, ASN1_INTEGER *a) { + Data d; - INIT_DATA(d,a->data,a->length); - exdump(ssl,0,&d); + if(a->length == 0) + printf("0"); - return(0); - } + INIT_DATA(d, a->data, a->length); + exdump(ssl, 0, &d); + + return (0); +} #endif diff --git a/ssl/sslxprint.h b/ssl/sslxprint.h index 5d44876..a559cdb 100644 --- a/ssl/sslxprint.h +++ b/ssl/sslxprint.h @@ -18,7 +18,7 @@ documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - + This product includes software developed by Eric Rescorla for RTFM, Inc. @@ -35,7 +35,8 @@ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMAGE. + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH + DAMAGE. $Id: sslxprint.h,v 1.2 2000/10/17 16:10:02 ekr Exp $ @@ -43,12 +44,10 @@ ekr@rtfm.com Thu Mar 25 21:23:34 1999 */ - #ifndef _sslxprint_h #define _sslxprint_h -int sslx_print_certificate PROTO_LIST((ssl_obj *ssl,Data *data,int pf)); -int sslx_print_dn PROTO_LIST((ssl_obj *ssl,Data *data,int pf)); +int sslx_print_certificate PROTO_LIST((ssl_obj * ssl, Data *data, int pf)); +int sslx_print_dn PROTO_LIST((ssl_obj * ssl, Data *data, int pf)); #endif -