mirror of
https://github.com/adulau/ssldump.git
synced 2024-12-22 16:05:58 +00:00
First import of the JSON output code (https://github.com/adulau/ssldump/issues/41)
This commit is contained in:
parent
28b4915099
commit
d0ca1a8adc
15 changed files with 454 additions and 233 deletions
|
@ -36,7 +36,7 @@ Additional back-end code available is in the [crl-monitor ](https://github.com/a
|
|||
|
||||
On Debian & Ubuntu:
|
||||
```
|
||||
apt install build-essential autoconf libssl-dev libpcap-dev libnet1-dev
|
||||
apt install build-essential autoconf libssl-dev libpcap-dev libnet1-dev libjson-c-dev
|
||||
./autogen.sh
|
||||
./configure --prefix=/usr/local
|
||||
make
|
||||
|
@ -45,7 +45,7 @@ make
|
|||
|
||||
On Fedora, Centos & RHEL:
|
||||
```
|
||||
dnf install autoconf automake gcc make openssl-devel libpcap-devel libnet-devel
|
||||
dnf install autoconf automake gcc make openssl-devel libpcap-devel libnet-devel json-c-devel
|
||||
./autogen.sh
|
||||
./configure --prefix=/usr/local
|
||||
make
|
||||
|
|
|
@ -135,8 +135,9 @@ int network_process_packet(handler,timestamp,data,length)
|
|||
p.len = ntohs(p.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);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (p.len == 0) {
|
||||
|
|
|
@ -106,5 +106,6 @@ extern UINT4 NET_print_flags;
|
|||
#define NET_PRINT_TYPESET 2
|
||||
#define NET_PRINT_ACKS 4
|
||||
#define NET_PRINT_NO_RESOLVE 8
|
||||
#define NET_PRINT_JSON 16
|
||||
#endif
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ void sig_handler(int sig)
|
|||
logger->vtbl->deinit();
|
||||
|
||||
freed_conn = destroy_all_conn();
|
||||
if(freed_conn)
|
||||
if(freed_conn && !(NET_print_flags & NET_PRINT_JSON))
|
||||
printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn);
|
||||
|
||||
if(p)
|
||||
|
@ -258,7 +258,7 @@ void pcap_cb(ptr,hdr,data)
|
|||
if(packet_cnt == conn_freq) {
|
||||
packet_cnt = 0;
|
||||
memcpy(&last_packet_seen_time,&hdr->ts,sizeof(struct timeval));
|
||||
if((cleaned_conn = clean_old_conn()))
|
||||
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++;
|
||||
|
@ -310,7 +310,7 @@ int main(argc,argv)
|
|||
|
||||
signal(SIGINT,sig_handler);
|
||||
|
||||
while((c=getopt(argc,argv,"vr:F:f:S:yTt:ai:k:l:w:p:nsAxXhHVNdqem:P"))!=EOF){
|
||||
while((c=getopt(argc,argv,"vr:F:f:S:jyTt:ai:k:l:w:p:nsAxXhHVNdqem:P"))!=EOF){
|
||||
switch(c){
|
||||
case 'v':
|
||||
print_version();
|
||||
|
@ -328,6 +328,10 @@ int main(argc,argv)
|
|||
/*Kludge*/
|
||||
SSL_print_flags |= SSL_PRINT_NROFF;
|
||||
break;
|
||||
case 'j':
|
||||
NET_print_flags |= NET_PRINT_JSON;
|
||||
SSL_print_flags |= SSL_PRINT_JSON;
|
||||
break;
|
||||
case 'a':
|
||||
NET_print_flags |= NET_PRINT_ACKS;
|
||||
break;
|
||||
|
@ -471,20 +475,22 @@ int main(argc,argv)
|
|||
}
|
||||
|
||||
pcap_if_type=pcap_datalink(p);
|
||||
|
||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||
printf("\n.nf\n.ps -2\n");
|
||||
|
||||
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_TYPESET)
|
||||
printf("\n.ps\n.fi\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)
|
||||
if(freed_conn && !(NET_print_flags & NET_PRINT_JSON))
|
||||
printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn);
|
||||
|
||||
pcap_close(p);
|
||||
|
|
|
@ -74,13 +74,13 @@ int exdump(name,data)
|
|||
for(i=0;i<data->len;i++){
|
||||
if(!i && (data->len>8)) INDENT;
|
||||
if((data->len>8) && i && !(i%12)){
|
||||
printf("\n"); INDENT;
|
||||
LF;INDENT;
|
||||
}
|
||||
printf("%.2x ",data->data[i]&255);
|
||||
}
|
||||
if(name) INDENT_POP;
|
||||
if(data->len>8 && i%12)
|
||||
printf("\n");
|
||||
LF;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -130,15 +130,16 @@ int process_tcp_packet(handler,ctx,p)
|
|||
conn->i2r.ack=ntohl(p->tcp->th_ack)+1;
|
||||
lookuphostname(&conn->i_addr,&sn);
|
||||
lookuphostname(&conn->r_addr,&dn);
|
||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||
printf("\\fC");
|
||||
printf("New TCP connection #%d: %s(%d) <-> %s(%d)\n",
|
||||
conn->conn_number,
|
||||
sn,conn->i_port,
|
||||
dn,conn->r_port);
|
||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||
printf("\\fR");
|
||||
|
||||
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,
|
||||
sn,conn->i_port,
|
||||
dn,conn->r_port);
|
||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||
printf("\\fR");
|
||||
}
|
||||
conn->state=TCP_STATE_ESTABLISHED;
|
||||
free(sn);
|
||||
free(dn);
|
||||
|
@ -240,7 +241,8 @@ static int process_data_segment(conn,handler,p,stream,direction)
|
|||
l=p->len - p->tcp->th_off * 4;
|
||||
|
||||
if(l < 0) {
|
||||
printf("Malformed packet, computed TCP segment size is negative, skipping ...\n");
|
||||
if(!(NET_print_flags & NET_PRINT_JSON))
|
||||
printf("Malformed packet, computed TCP segment size is negative, skipping ...\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -400,32 +402,33 @@ static int print_tcp_packet(p)
|
|||
lookuphostname(&p->ip->ip_src,&src);
|
||||
lookuphostname(&p->ip->ip_dst,&dst);
|
||||
|
||||
printf("TCP: %s(%d) -> %s(%d) ",
|
||||
src,
|
||||
ntohs(p->tcp->th_sport),
|
||||
dst,
|
||||
ntohs(p->tcp->th_dport));
|
||||
if(!(NET_print_flags & NET_PRINT_JSON)) {
|
||||
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);
|
||||
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_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");
|
||||
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);
|
||||
|
|
127
ssl/ssl.enums.c
127
ssl/ssl.enums.c
|
@ -1,3 +1,4 @@
|
|||
#include <json-c/json.h>
|
||||
#include "network.h"
|
||||
#include "ssl_h.h"
|
||||
#include "sslprint.h"
|
||||
|
@ -15,6 +16,10 @@ static int decode_ContentType_ChangeCipherSpec(ssl,dir,seg,data)
|
|||
Data *data;
|
||||
{
|
||||
|
||||
struct json_object *jobj;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -25,7 +30,7 @@ static int decode_ContentType_ChangeCipherSpec(ssl,dir,seg,data)
|
|||
ssl->r_state=SSL_ST_SENT_CHANGE_CIPHER_SPEC;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
LF;
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
@ -37,9 +42,10 @@ static int decode_ContentType_Alert(ssl,dir,seg,data)
|
|||
{
|
||||
|
||||
int r;
|
||||
struct json_object *jobj;
|
||||
|
||||
if(ssl->record_encryption==REC_CIPHERTEXT){
|
||||
printf("\n");
|
||||
LF;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -49,17 +55,20 @@ static int decode_ContentType_Alert(ssl,dir,seg,data)
|
|||
ERETURN(R_EOD);
|
||||
}
|
||||
|
||||
jobj = ssl->cur_json_st;
|
||||
json_object_object_add(jobj, "msg_type", json_object_new_string("Alert"));
|
||||
|
||||
P_(P_HL){
|
||||
printf("\n");
|
||||
LF;
|
||||
SSL_DECODE_ENUM(ssl,"level",1,AlertLevel_decoder,P_HL,data,0);
|
||||
printf("\n");
|
||||
LF;
|
||||
SSL_DECODE_ENUM(ssl,"value",1,AlertDescription_decoder,P_HL,data,0);
|
||||
printf("\n");
|
||||
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);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
return(0);
|
||||
|
||||
|
@ -77,9 +86,10 @@ static int decode_ContentType_Handshake(ssl,dir,seg,data)
|
|||
UINT4 t,l;
|
||||
int rs=0;
|
||||
Data d;
|
||||
struct json_object *jobj;
|
||||
|
||||
if(ssl->record_encryption==REC_CIPHERTEXT){
|
||||
printf("\n");
|
||||
LF;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -93,13 +103,16 @@ static int decode_ContentType_Handshake(ssl,dir,seg,data)
|
|||
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){
|
||||
printf("\n");
|
||||
LF;
|
||||
rs=1;
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +131,9 @@ static int decode_ContentType_application_data(ssl,dir,seg,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);
|
||||
|
||||
|
@ -125,7 +141,7 @@ static int decode_ContentType_application_data(ssl,dir,seg,data)
|
|||
print_data(ssl,&d);
|
||||
}
|
||||
else {
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
return(0);
|
||||
|
||||
|
@ -160,9 +176,12 @@ static int decode_HandshakeType_HelloRequest(ssl,dir,seg,data)
|
|||
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"));
|
||||
|
||||
|
||||
printf("\n");
|
||||
LF;
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
@ -173,6 +192,9 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
|||
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;
|
||||
|
@ -182,14 +204,14 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
|||
extern decoder compression_method_decoder[];
|
||||
extern decoder extension_decoder[];
|
||||
|
||||
printf("\n");
|
||||
LF;
|
||||
ssl_update_handshake_messages(ssl,data);
|
||||
SSL_DECODE_UINT8(ssl,0,0,data,&vj);
|
||||
SSL_DECODE_UINT8(ssl,0,0,data,&vn);
|
||||
|
||||
P_(P_HL) {explain(ssl,"Version %d.%d ",vj,vn);
|
||||
printf("\n");
|
||||
}
|
||||
LF;
|
||||
}
|
||||
|
||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"random",32,P_ND,data,&random);
|
||||
ssl_set_client_random(ssl->decoder,random.data,random.len);
|
||||
|
@ -219,7 +241,7 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
|||
ssl_decode_enum(ssl,0,2,cipher_suite_decoder,
|
||||
0,data,&cs);
|
||||
ssl_print_cipher_suite(ssl,(vj<<8)|vn,P_HL,cs);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +250,7 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
|||
explain(ssl,"compression methods\n");
|
||||
for(;complen;complen--){
|
||||
SSL_DECODE_ENUM(ssl,0,1,compression_method_decoder,P_HL,data,&comp);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +266,7 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
|
@ -263,14 +285,18 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data)
|
|||
|
||||
extern decoder extension_decoder[];
|
||||
|
||||
printf("\n");
|
||||
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);
|
||||
|
||||
ssl->version=vj*256+vn;
|
||||
P_(P_HL) {explain(ssl,"Version %d.%d ",vj,vn);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
|
||||
|
||||
|
@ -288,9 +314,9 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data)
|
|||
ssl_process_server_session_id(ssl,ssl->decoder,session_id.data,
|
||||
session_id.len);
|
||||
|
||||
P_(P_HL) printf("\n");
|
||||
P_(P_HL) LF;
|
||||
SSL_DECODE_ENUM(ssl,"compressionMethod",1,compression_method_decoder,P_HL,data,0);
|
||||
P_(P_HL) printf("\n");
|
||||
P_(P_HL) LF;
|
||||
|
||||
SSL_DECODE_UINT16(ssl,"extensions len",0,data,&exlen);
|
||||
if (exlen) {
|
||||
|
@ -304,7 +330,7 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,10 +349,16 @@ static int decode_HandshakeType_Certificate(ssl,dir,seg,data)
|
|||
Data cert;
|
||||
int r;
|
||||
|
||||
printf("\n");
|
||||
struct json_object *jobj;
|
||||
jobj = ssl->cur_json_st;
|
||||
json_object_object_add(jobj, "handshake_type", json_object_new_string("Certificate"));
|
||||
|
||||
LF;
|
||||
ssl_update_handshake_messages(ssl,data);
|
||||
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);
|
||||
|
@ -347,7 +379,11 @@ static int decode_HandshakeType_ServerKeyExchange(ssl,dir,seg,data)
|
|||
|
||||
int r;
|
||||
|
||||
printf("\n");
|
||||
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){
|
||||
|
@ -385,14 +421,18 @@ static int decode_HandshakeType_CertificateRequest(ssl,dir,seg,data)
|
|||
Data ca;
|
||||
int r;
|
||||
|
||||
printf("\n");
|
||||
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){
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -416,8 +456,11 @@ static int decode_HandshakeType_ServerHelloDone(ssl,dir,seg,data)
|
|||
Data *data;
|
||||
{
|
||||
|
||||
struct json_object *jobj;
|
||||
jobj = ssl->cur_json_st;
|
||||
json_object_object_add(jobj, "handshake_type", json_object_new_string("ServerHelloDone"));
|
||||
|
||||
printf("\n");
|
||||
LF;
|
||||
ssl_update_handshake_messages(ssl,data);
|
||||
return(0);
|
||||
|
||||
|
@ -431,7 +474,12 @@ static int decode_HandshakeType_CertificateVerify(ssl,dir,seg,data)
|
|||
|
||||
|
||||
int r;
|
||||
printf("\n");
|
||||
|
||||
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);
|
||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"Signature",-((1<<15)-1),P_HL,data,0);
|
||||
return(0);
|
||||
|
@ -448,7 +496,11 @@ static int decode_HandshakeType_ClientKeyExchange(ssl,dir,seg,data)
|
|||
int r;
|
||||
Data pms;
|
||||
|
||||
printf("\n");
|
||||
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){
|
||||
|
@ -486,7 +538,11 @@ static int decode_HandshakeType_Finished(ssl,dir,seg,data)
|
|||
|
||||
int r;
|
||||
|
||||
printf("\n");
|
||||
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);
|
||||
|
@ -496,7 +552,7 @@ static int decode_HandshakeType_Finished(ssl,dir,seg,data)
|
|||
case 0x301:
|
||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"verify_data",12,P_ND,data,0);
|
||||
P_(P_ND)
|
||||
printf("\n");
|
||||
LF;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2124,6 +2180,9 @@ static int decode_AlertLevel_warning(ssl,dir,seg,data)
|
|||
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,dir,seg,data)
|
||||
|
@ -2132,6 +2191,9 @@ static int decode_AlertLevel_fatal(ssl,dir,seg,data)
|
|||
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[]={
|
||||
|
@ -2530,7 +2592,7 @@ static int decode_extension_server_name(ssl,dir,seg,data)
|
|||
|
||||
if(dir==DIR_I2R){
|
||||
SSL_DECODE_UINT16(ssl,"server name list length",0,data,&l);
|
||||
printf("\n");
|
||||
LF;
|
||||
while(l) {
|
||||
p=data->len;
|
||||
SSL_DECODE_UINT8(ssl, "server name type", 0, data, &t);
|
||||
|
@ -2896,7 +2958,8 @@ static int decode_server_name_type_host_name(ssl,dir,seg,data)
|
|||
int r;
|
||||
UINT4 l;
|
||||
SSL_DECODE_UINT16(ssl,"server name length",0,data,&l);
|
||||
printf(": %.*s",l,data->data);
|
||||
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)
|
||||
|
|
|
@ -44,7 +44,8 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "network.h"
|
||||
#include "debug.h"
|
||||
#include "sslprint.h"
|
||||
|
@ -246,8 +247,14 @@ static int create_ssl_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn,
|
|||
ABORT(r);
|
||||
|
||||
lookuphostname(i_addr,&obj->client_name);
|
||||
if(!(obj->client_ip=(char *)calloc(1,INET_ADDRSTRLEN)))
|
||||
ABORT(R_NO_MEMORY);
|
||||
inet_ntop(AF_INET, i_addr, obj->client_ip, INET_ADDRSTRLEN);
|
||||
obj->client_port=i_port;
|
||||
lookuphostname(r_addr,&obj->server_name);
|
||||
lookuphostname(r_addr,&obj->server_name);
|
||||
if(!(obj->server_ip=(char *)calloc(1,INET_ADDRSTRLEN)))
|
||||
ABORT(R_NO_MEMORY);
|
||||
inet_ntop(AF_INET, r_addr, obj->server_ip, INET_ADDRSTRLEN);
|
||||
obj->server_port=r_port;
|
||||
|
||||
obj->i_state=SSL_ST_SENT_NOTHING;
|
||||
|
@ -573,7 +580,9 @@ static int print_ssl_record(obj,direction,q,data,len)
|
|||
int len;
|
||||
{
|
||||
int r;
|
||||
|
||||
|
||||
obj->cur_json_st = json_object_new_object();
|
||||
|
||||
if((r=print_ssl_header(obj,direction,q,data,len)))
|
||||
ERETURN(r);
|
||||
|
||||
|
@ -583,8 +592,13 @@ static int print_ssl_record(obj,direction,q,data,len)
|
|||
|
||||
INIT_DATA(d,data,len);
|
||||
exdump(obj,"Packet data",&d);
|
||||
printf("\n\n");
|
||||
LF;LF;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -609,8 +623,7 @@ int close_ssl_analyzer(_obj,p,dir)
|
|||
ssl_print_timestamp(ssl,&p->ts);
|
||||
ssl_print_direction_indicator(ssl,dir);
|
||||
explain(ssl," TCP %s",what);
|
||||
printf("\n");
|
||||
|
||||
LF;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ extern proto_mod ssl_mod;
|
|||
#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*/
|
||||
|
@ -77,6 +78,7 @@ extern proto_mod ssl_mod;
|
|||
#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;
|
||||
|
|
|
@ -81,8 +81,10 @@ typedef struct ssl_obj_ {
|
|||
UINT4 cipher_suite;
|
||||
|
||||
char *client_name;
|
||||
char *client_ip;
|
||||
int client_port;
|
||||
char *server_name;
|
||||
char *server_ip;
|
||||
int server_port;
|
||||
|
||||
struct SSL_CipherSuite_ *cs;
|
||||
|
@ -106,6 +108,7 @@ typedef struct ssl_obj_ {
|
|||
int record_count;
|
||||
int indent_depth;
|
||||
int indent_name_len;
|
||||
struct json_object *cur_json_st;
|
||||
} ssl_obj;
|
||||
|
||||
typedef struct decoder_ {
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
#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); printf("\n");}
|
||||
#define CRDUMPD(a,b) P_(P_CR) {exdump(ssl,a,b);printf("\n");}
|
||||
#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));
|
||||
|
|
214
ssl/sslprint.c
214
ssl/sslprint.c
|
@ -44,7 +44,7 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include "network.h"
|
||||
|
@ -83,7 +83,7 @@ int process_beginning_plaintext(ssl,seg,direction)
|
|||
ssl_print_direction_indicator(ssl,direction);
|
||||
|
||||
print_data(ssl,&d);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
@ -140,7 +140,7 @@ int process_v2_hello(ssl,seg)
|
|||
P_(P_HL) {
|
||||
explain(ssl,"Version %d.%d ",(ver>>8)&0xff,
|
||||
ver&0xff);
|
||||
printf("\n");
|
||||
LF;
|
||||
}
|
||||
SSL_DECODE_UINT16(ssl,"cipher_spec_length",P_DC,&d,&cs_len);
|
||||
SSL_DECODE_UINT16(ssl,"session_id_length",P_DC,&d,&sid_len);
|
||||
|
@ -191,7 +191,7 @@ int process_v2_hello(ssl,seg)
|
|||
|
||||
INIT_DATA(d,seg->data,seg->len);
|
||||
exdump(ssl,"Packet data",&d);
|
||||
printf("\n\n");
|
||||
LF;LF;
|
||||
}
|
||||
|
||||
INDENT_POP;
|
||||
|
@ -235,6 +235,11 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
|||
Data d;
|
||||
UINT4 ct,vermaj,vermin,length;
|
||||
int version;
|
||||
char verstr[4];
|
||||
char enumstr[20];
|
||||
struct json_object *jobj;
|
||||
jobj = ssl->cur_json_st;
|
||||
|
||||
d.data=data;
|
||||
d.len=len;
|
||||
|
||||
|
@ -251,9 +256,11 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
|||
|
||||
P_(P_RH){
|
||||
explain(ssl," V%d.%d(%d)",vermaj,vermin,length);
|
||||
json_object_object_add(jobj, "record_len", json_object_new_int(length));
|
||||
snprintf(verstr,4,"%d.%d",vermaj,vermin);
|
||||
json_object_object_add(jobj, "record_ver", json_object_new_string(verstr));
|
||||
}
|
||||
|
||||
|
||||
version=vermaj*256+vermin;
|
||||
|
||||
r=ssl_decode_record(ssl,ssl->decoder,direction,ct,version,&d);
|
||||
|
@ -264,11 +271,16 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
|||
}
|
||||
|
||||
if(r){
|
||||
if((r=ssl_print_enum(ssl,0,ContentType_decoder,ct))) {
|
||||
printf(" unknown record type: %d\n", ct);
|
||||
ERETURN(r);
|
||||
}
|
||||
printf("\n");
|
||||
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);
|
||||
}
|
||||
ssl_get_enum_str(ssl,enumstr,ContentType_decoder,ct);
|
||||
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
|
||||
|
@ -276,7 +288,8 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
|||
if ((ct == 23) && (logger)) logger->vtbl->data(ssl->logger_obj,d.data,d.len,direction);
|
||||
|
||||
if((r=ssl_decode_switch(ssl,ContentType_decoder,data[0],direction,q, &d))) {
|
||||
printf(" unknown record type: %d\n", ct);
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||
printf(" unknown record type: %d\n", ct);
|
||||
ERETURN(r);
|
||||
}
|
||||
}
|
||||
|
@ -394,8 +407,9 @@ int ssl_decode_enum(ssl,name,size,dtable,p,data,x)
|
|||
ERETURN(r);
|
||||
|
||||
P_(p){
|
||||
if((r=ssl_print_enum(ssl,name,dtable,*x)))
|
||||
ERETURN(r);
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||
if((r=ssl_print_enum(ssl,name,dtable,*x)))
|
||||
ERETURN(r);
|
||||
}
|
||||
|
||||
return(0);
|
||||
|
@ -407,6 +421,7 @@ int ssl_print_enum(ssl,name,dtable,value)
|
|||
decoder *dtable;
|
||||
UINT4 value;
|
||||
{
|
||||
|
||||
if(name) explain(ssl,"%s ",name);
|
||||
INDENT;
|
||||
|
||||
|
@ -419,26 +434,43 @@ int ssl_print_enum(ssl,name,dtable,value)
|
|||
}
|
||||
dtable++;
|
||||
}
|
||||
printf("\n");
|
||||
LF;
|
||||
return(R_NOT_FOUND);
|
||||
}
|
||||
|
||||
int ssl_get_enum_str(ssl,outstr,dtable,value)
|
||||
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);
|
||||
|
||||
va_start(ap,format);
|
||||
P_(P_NR){
|
||||
if(ssl->record_encryption==REC_DECRYPTED_CIPHERTEXT)
|
||||
printf("\\f(CI");
|
||||
else
|
||||
printf("\\fC");
|
||||
}
|
||||
INDENT;
|
||||
|
||||
P_(P_NR){
|
||||
if(ssl->record_encryption==REC_DECRYPTED_CIPHERTEXT)
|
||||
printf("\\f(CI");
|
||||
else
|
||||
printf("\\fC");
|
||||
vprintf(format,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
INDENT;
|
||||
|
||||
vprintf(format,ap);
|
||||
va_end(ap);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -448,31 +480,52 @@ int exdump(ssl,name,data)
|
|||
Data *data;
|
||||
{
|
||||
int i;
|
||||
|
||||
if(name){
|
||||
explain(ssl,"%s[%d]=\n",name,data->len);
|
||||
INDENT_INCR;
|
||||
}
|
||||
P_(P_NR){
|
||||
printf("\\f(CB");
|
||||
}
|
||||
for(i=0;i<data->len;i++){
|
||||
|
||||
if(!i) INDENT;
|
||||
|
||||
if((data->len>8) && i && !(i%16)){
|
||||
printf("\n"); INDENT;
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON)) {
|
||||
if(name){
|
||||
explain(ssl,"%s[%d]=\n",name,data->len);
|
||||
INDENT_INCR;
|
||||
}
|
||||
printf("%.2x ",data->data[i]&255);
|
||||
P_(P_NR){
|
||||
printf("\\f(CB");
|
||||
}
|
||||
for(i=0;i<data->len;i++){
|
||||
|
||||
if(!i) INDENT;
|
||||
|
||||
if((data->len>8) && i && !(i%16)){
|
||||
LF; INDENT;
|
||||
}
|
||||
printf("%.2x ",data->data[i]&255);
|
||||
}
|
||||
P_(P_NR){
|
||||
printf("\\fR");
|
||||
}
|
||||
if(name) INDENT_POP;
|
||||
LF;
|
||||
}
|
||||
P_(P_NR){
|
||||
printf("\\fR");
|
||||
}
|
||||
if(name) INDENT_POP;
|
||||
printf("\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int exstr(ssl,outstr,data)
|
||||
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,name,data)
|
||||
ssl_obj *ssl;
|
||||
char *name;
|
||||
|
@ -518,7 +571,7 @@ int combodump(ssl,name,data)
|
|||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("\n");
|
||||
LF;
|
||||
|
||||
len-=bytes;
|
||||
ptr+=bytes;
|
||||
|
@ -536,7 +589,7 @@ int print_data(ssl,d)
|
|||
{
|
||||
int i,bit8=0;
|
||||
|
||||
printf("\n");
|
||||
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;
|
||||
|
@ -590,6 +643,7 @@ int ssl_print_direction_indicator(ssl,dir)
|
|||
ssl_obj *ssl;
|
||||
int dir;
|
||||
{
|
||||
struct json_object *jobj;
|
||||
#if 0
|
||||
if(dir==DIR_I2R){
|
||||
explain(ssl,"%s(%d) > %s>%d",
|
||||
|
@ -600,11 +654,30 @@ int ssl_print_direction_indicator(ssl,dir)
|
|||
ssl->client_name,ssl->client_port,ssl->server_name,ssl->server_port);
|
||||
}
|
||||
#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
|
||||
|
||||
|
@ -617,23 +690,35 @@ int ssl_print_timestamp(ssl,ts)
|
|||
{
|
||||
struct timeval dt;
|
||||
int r;
|
||||
|
||||
|
||||
char ts_str[16];
|
||||
struct json_object *jobj;
|
||||
jobj = ssl->cur_json_st;
|
||||
|
||||
if(jobj) {
|
||||
snprintf(ts_str,16, "%d%c%4.4d",ts->tv_sec,'.',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) {
|
||||
explain(ssl,"%d%c%4.4d ",ts->tv_sec,'.',ts->tv_usec/100);
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||
explain(ssl,"%d%c%4.4d ",ts->tv_sec,'.',ts->tv_usec/100);
|
||||
}
|
||||
else{
|
||||
if((r=timestamp_diff(ts,&ssl->time_start,&dt)))
|
||||
ERETURN(r);
|
||||
explain(ssl,"%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||
explain(ssl,"%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||
}
|
||||
|
||||
if((r=timestamp_diff(ts,&ssl->time_last,&dt))){
|
||||
ERETURN(r);
|
||||
}
|
||||
explain(ssl,"(%d%c%4.4d) ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||
explain(ssl,"(%d%c%4.4d) ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||
|
||||
memcpy(&ssl->time_last,ts,sizeof(struct timeval));
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -641,16 +726,23 @@ int ssl_print_timestamp(ssl,ts)
|
|||
int ssl_print_record_num(ssl)
|
||||
ssl_obj *ssl;
|
||||
{
|
||||
struct json_object *jobj;
|
||||
jobj = ssl->cur_json_st;
|
||||
|
||||
ssl->record_count++;
|
||||
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?" ":"");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ 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,
|
||||
|
@ -77,6 +79,7 @@ int ssl_print_cipher_suite PROTO_LIST((ssl_obj *ssl,int version,int p,
|
|||
|
||||
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)
|
||||
|
@ -87,13 +90,13 @@ int exdump PROTO_LIST((ssl_obj *ssl,char *name,Data *data));
|
|||
#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 P_(p) if((p==SSL_PRINT_ALL) || (p & SSL_print_flags))
|
||||
|
||||
#define INDENT 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 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 LINE_LEFT (80-(ssl->indent_name_len + ssl->indent_depth)
|
||||
#define LF printf("\n")
|
||||
#define LF if(!(NET_print_flags & NET_PRINT_JSON)) printf("\n")
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
*/
|
||||
|
||||
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include "network.h"
|
||||
#include "ssl_h.h"
|
||||
#include "sslprint.h"
|
||||
|
@ -78,9 +78,25 @@ int sslx_print_certificate(ssl,data,pf)
|
|||
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;
|
||||
|
||||
struct json_object *cert_obj;
|
||||
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));
|
||||
|
||||
if(!(x=d2i_X509(0,(const unsigned char **) &d,data->len))){
|
||||
explain(ssl,"Bad certificate");
|
||||
ABORT(R_BAD_DATA);
|
||||
|
@ -89,16 +105,24 @@ int sslx_print_certificate(ssl,data,pf)
|
|||
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));
|
||||
|
||||
sslx__print_serial(ssl,a);
|
||||
|
||||
ext=X509_get_ext_count(x);
|
||||
|
@ -147,6 +171,10 @@ int sslx_print_certificate(ssl,data,pf)
|
|||
}
|
||||
#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
|
||||
|
||||
|
|
168
ssldump.1
168
ssldump.1
|
@ -61,8 +61,7 @@ ssldump \- dump SSL traffic on a network
|
|||
.na
|
||||
.B ssldump
|
||||
[
|
||||
.B \-vTshVq
|
||||
.B \-aAdeHnNqTxXvy
|
||||
.B \-aAdeFHjnNPqtTvxXy
|
||||
] [
|
||||
.B \-i
|
||||
.I interface
|
||||
|
@ -110,14 +109,14 @@ form to stdout. If provided with the appropriate keying material,
|
|||
it will also decrypt the connections and display the application
|
||||
data traffic.
|
||||
.LP
|
||||
ssldump has been tested on FreeBSD, Linux, Solaris, and HP/UX. Since
|
||||
\fIssldump\fP has been tested on FreeBSD, Linux, Solaris, and HP/UX. Since
|
||||
it's based on PCAP, it should work on most platforms. However, unlike
|
||||
tcpdump, ssldump needs to be able to see both sides of the data
|
||||
tcpdump, \fIssldump\fP needs to be able to see both sides of the data
|
||||
transmission so you may have trouble using it with network taps such
|
||||
as SunOS nit that don't permit you to see transmitted data.
|
||||
.B Under SunOS with nit or bpf:
|
||||
To run
|
||||
.I tcpdump
|
||||
.I ssldump
|
||||
you must have read access to
|
||||
.I /dev/nit
|
||||
or
|
||||
|
@ -135,46 +134,65 @@ You must be root or it must be installed setuid to root.
|
|||
Once the super-user has enabled promiscuous-mode operation using
|
||||
.IR pfconfig (8),
|
||||
any user may run
|
||||
.BR ssldump
|
||||
.I ssldump
|
||||
.B Under BSD:
|
||||
You must have read access to
|
||||
.IR /dev/bpf* .
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-a
|
||||
Print bare TCP ACKs (useful for observing Nagle behavior)
|
||||
Print bare TCP ACKs (useful for observing Nagle behavior).
|
||||
.TP
|
||||
.B \-A
|
||||
Print all record fields (by default ssldump chooses
|
||||
the most interesting fields)
|
||||
Print all record fields (by default \fIssldump\fP chooses
|
||||
the most interesting fields).
|
||||
.TP
|
||||
.B \-d
|
||||
Display the application data traffic. This usually means
|
||||
decrypting it, but when -d is used ssldump will also decode
|
||||
decrypting it, but when -d is used \fIssldump\fP will also decode
|
||||
application data traffic \fIbefore\fP the SSL session initiates.
|
||||
This allows you to see HTTPS CONNECT behavior as well as
|
||||
SMTP STARTTLS. As a side effect, since ssldump can't tell
|
||||
SMTP STARTTLS. As a side effect, since \fIssldump\fP can't tell
|
||||
whether plaintext is traffic before the initiation of an
|
||||
SSL connection or just a regular TCP connection, this allows
|
||||
you to use ssldump to sniff any TCP connection.
|
||||
ssldump will automatically detect ASCII data and display it
|
||||
you to use \fIssldump\fP to sniff any TCP connection.
|
||||
\fIssldump\fP will automatically detect ASCII data and display it
|
||||
directly to the screen. non-ASCII data is displayed as hex
|
||||
dumps. See also -X.
|
||||
.TP
|
||||
.B \-e
|
||||
Print absolute timestamps instead of relative timestamps
|
||||
Print absolute timestamps instead of relative timestamps.
|
||||
.TP
|
||||
.B \-F
|
||||
Specify the number of packets after which a connection pool cleaning is performed (in packets, default: 100).
|
||||
.TP
|
||||
.B \-H
|
||||
Print the full SSL packet header.
|
||||
.TP
|
||||
.B \-n
|
||||
Don't try to resolve host names from IP addresses
|
||||
.BI \-i " interface"
|
||||
Use \fIinterface\fP as the network interface on which to sniff SSL/TLS
|
||||
traffic.
|
||||
.TP
|
||||
.B \-j
|
||||
Switch output format to JSON. Only stdout is affected by this toggle.
|
||||
.TP
|
||||
.BI \-k " keyfile"
|
||||
Use \fIkeyfile\fP as the location of the SSL keyfile (OpenSSL format)
|
||||
Previous versions of \fIssldump\fP automatically looked in ./server.pem.
|
||||
Now you must specify your keyfile every time.
|
||||
.TP
|
||||
.BI \-l " sslkeylogfile"
|
||||
Use \fIsslkeylogfile\fP as the location of the SSLKEYLOGFILE
|
||||
(https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format).
|
||||
.TP
|
||||
.B \-n
|
||||
Don't try to resolve host names from IP addresses.
|
||||
.TP
|
||||
.B \-N
|
||||
Attempt to parse ASN.1 when it appears, such as in
|
||||
Attempt to parse ASN.1 when it appears, such as in
|
||||
certificates and DNs.
|
||||
.TP
|
||||
.B \-p
|
||||
.BI \-p " password"
|
||||
Use \fIpassword\fP as the SSL keyfile password.
|
||||
.TP
|
||||
.B \-P
|
||||
|
@ -183,55 +201,13 @@ Don't put the interface into promiscuous mode.
|
|||
.B \-q
|
||||
Don't decode any record fields beyond a single summary line. (quiet mode).
|
||||
.TP
|
||||
.B \-T
|
||||
Print the TCP headers.
|
||||
.TP
|
||||
.B \-v
|
||||
Display version and copyright information.
|
||||
.TP
|
||||
.B \-t
|
||||
Specify the TTL for inactive connections referenced in the connection pool (in seconds, default: 100).
|
||||
.TP
|
||||
.B \-F
|
||||
Specify the number of packets after which a connection pool cleaning is performed (in packets, default: 100).
|
||||
.TP
|
||||
.B \-x
|
||||
Print each record in hex, as well as decoding it.
|
||||
.TP
|
||||
.B \-X
|
||||
When the -d option is used, binary data is automatically printed
|
||||
in two columns with a hex dump on the left and the printable characters
|
||||
on the right. -X suppresses the display of the printable characters,
|
||||
thus making it easier to cut and paste the hex data into some other
|
||||
program.
|
||||
.TP
|
||||
.B \-y
|
||||
Decorate the output for processing with nroff/troff. Not very
|
||||
useful for the average user.
|
||||
.TP
|
||||
.BI \-i " interface"
|
||||
Use \fIinterface\fP as the network interface on which to sniff SSL/TLS
|
||||
traffic.
|
||||
.TP
|
||||
.BI \-k " keyfile"
|
||||
Use \fIkeyfile\fP as the location of the SSL keyfile (OpenSSL format)
|
||||
Previous versions of ssldump automatically looked in ./server.pem.
|
||||
Now you must specify your keyfile every time.
|
||||
.TP
|
||||
.BI \-l " sslkeylogfile"
|
||||
Use \fIsslkeylogfile\fP as the location of the SSLKEYLOGFILE
|
||||
(https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format)
|
||||
.TP
|
||||
.BI \-p " password"
|
||||
Use \fIpassword\fP as the SSL keyfile password.
|
||||
.TP
|
||||
.BI \-r " file"
|
||||
Read data from \fIfile\fP instead of from the network.
|
||||
The old -f option still works but is deprecated and will
|
||||
probably be removed with the next version.
|
||||
.TP
|
||||
.BI \-S " [ " crypto " | " d " | " ht " | " H " ]"
|
||||
Specify SSL flags to ssldump. These flags include:
|
||||
Specify SSL flags to \fIssldump\fP. These flags include:
|
||||
.RS
|
||||
.TP
|
||||
.I crypto
|
||||
|
@ -247,17 +223,40 @@ Print the handshake type.
|
|||
Print handshake type and highlights.
|
||||
.RE
|
||||
.TP
|
||||
.B \-t
|
||||
Specify the TTL for inactive connections referenced in the connection pool (in seconds, default: 100).
|
||||
.TP
|
||||
.B \-T
|
||||
Print the TCP headers.
|
||||
.TP
|
||||
.B \-v
|
||||
Display version and copyright information.
|
||||
.TP
|
||||
.BI \-w " outputpcap"
|
||||
Use \fIoutputpcap\fP as the destination for decrypted packets.
|
||||
.TP
|
||||
.B \-x
|
||||
Print each record in hex, as well as decoding it.
|
||||
.TP
|
||||
.B \-X
|
||||
When the -d option is used, binary data is automatically printed
|
||||
in two columns with a hex dump on the left and the printable characters
|
||||
on the right. -X suppresses the display of the printable characters,
|
||||
thus making it easier to cut and paste the hex data into some other
|
||||
program.
|
||||
.TP
|
||||
.B \-y
|
||||
Decorate the output for processing with nroff/troff. Not very
|
||||
useful for the average user.
|
||||
.TP
|
||||
\fIexpression\fP
|
||||
.RS
|
||||
Selects what packets ssldump will examine. Technically speaking,
|
||||
ssldump supports the full expression syntax from PCAP and tcpdump.
|
||||
Selects what packets \fIssldump\fP will examine. Technically speaking,
|
||||
\fIssldump\fP supports the full expression syntax from PCAP and tcpdump.
|
||||
In fact, the description here is cribbed from the tcpdump man
|
||||
page. However, since ssldump needs to examine full TCP streams,
|
||||
page. However, since \fIssldump\fP needs to examine full TCP streams,
|
||||
most of the tcpdump expressions will select traffic mixes
|
||||
that ssldump will simply ignore. Only the expressions which
|
||||
that \fIssldump\fP will simply ignore. Only the expressions which
|
||||
don't result in incomplete TCP streams are listed here.
|
||||
.LP
|
||||
The \fIexpression\fP consists of one or more
|
||||
|
@ -431,29 +430,36 @@ which should not be confused with
|
|||
.fi
|
||||
.in -.5i
|
||||
.LP
|
||||
Expression arguments can be passed to ssldump as either a single argument
|
||||
Expression arguments can be passed to \fIssldump\fP as either a single argument
|
||||
or as multiple arguments, whichever is more convenient.
|
||||
Generally, if the expression contains Shell metacharacters, it is
|
||||
easier to pass it as a single, quoted argument.
|
||||
Multiple arguments are concatenated with spaces before being parsed.
|
||||
.SH EXAMPLES
|
||||
.LP
|
||||
To listen to traffic on interface \fIle0\fP port \fI443\fP
|
||||
To listen to traffic on interface \fIle0\fP port \fI443\fP:
|
||||
.RS
|
||||
.nf
|
||||
\fBssldump -i le0 port 443\fP
|
||||
.fi
|
||||
.RE
|
||||
.LP
|
||||
To listen to traffic to the server \fIromeo\fP on port \fI443\fP.
|
||||
To listen to traffic to the server \fIromeo\fP on port \fI443\fP:
|
||||
.RS
|
||||
.nf
|
||||
\fBssldump -i le0 port 443 and host romeo\fP
|
||||
\fBssldump -i le0 port 443 and host romeo\fP:
|
||||
.fi
|
||||
.RE
|
||||
.LP
|
||||
To switch output format to JSON:
|
||||
.RS
|
||||
.nf
|
||||
\fBssldump -ANH -j -i le0 port 443 and host romeo\fP
|
||||
.fi
|
||||
.RE
|
||||
.LP
|
||||
To decrypt traffic to host \fIromeo\fR
|
||||
\fIserver.pem\fR and the password \fIfoobar\fR
|
||||
\fIserver.pem\fR and the password \fIfoobar\fR:
|
||||
.RS
|
||||
.nf
|
||||
\fBssldump -Ad -k ~/server.pem -p foobar -i le0 host romeo
|
||||
|
@ -463,7 +469,7 @@ To decrypt traffic to host \fIromeo\fR
|
|||
.LP
|
||||
All output is printed to standard out.
|
||||
.LP
|
||||
ssldump prints an indication of every new TCP connection using a line
|
||||
\fIssldump\fP prints an indication of every new TCP connection using a line
|
||||
like the following
|
||||
.nf
|
||||
.LP
|
||||
|
@ -493,16 +499,16 @@ the time since the previous record. Both are in seconds.
|
|||
The next field in the record line is the direction that the record
|
||||
was going. \fIC>S\fR indicates records transmitted from client to
|
||||
server and \fIS>C\fR indicates records transmitted from server to client.
|
||||
ssldump assumes that the host to transmit the first SYN
|
||||
\fIssldump\fP assumes that the host to transmit the first SYN
|
||||
is the SSL client (this is nearly always correct).
|
||||
.LP
|
||||
The next field is the record type, one of \fIHandshake\fR, \fIIAlert\fR,
|
||||
\fIChangeCipherSpec\fR, or \fIapplication_data\fR. Finally, ssldump
|
||||
\fIChangeCipherSpec\fR, or \fIapplication_data\fR. Finally, \fIssldump\fP
|
||||
may print record-specific data on the rest of the line. For \fIHandshake\fR
|
||||
records, it prints the handshake message. Thus, this record is
|
||||
a \fICertificate\fR message.
|
||||
.LP
|
||||
ssldump chooses certain record types for further decoding. These
|
||||
\fIssldump\fP chooses certain record types for further decoding. These
|
||||
are the ones that have proven to be most useful for debugging:
|
||||
.LP
|
||||
.nf
|
||||
|
@ -525,16 +531,16 @@ flags.
|
|||
.LP
|
||||
.SH DECRYPTION
|
||||
.LP
|
||||
ssldump can decrypt traffic between two hosts if the following two
|
||||
\fIssldump\fP can decrypt traffic between two hosts if the following two
|
||||
conditions are met:
|
||||
.RS
|
||||
.nf
|
||||
1. ssldump has the keys.
|
||||
1. \fIssldump\fP has the keys.
|
||||
2. Static RSA was used.
|
||||
.fi
|
||||
.RE
|
||||
In any other case, once encryption starts,
|
||||
ssldump will only be able to determine the
|
||||
\fIssldump\fP will only be able to determine the
|
||||
record type. Consider the following section of a trace.
|
||||
.LP
|
||||
.nf
|
||||
|
@ -553,7 +559,7 @@ record type. Consider the following section of a trace.
|
|||
Note that the \fIClientKeyExchange\fR message type is printed
|
||||
but the rest of the \fIHandshake\fR messages do not have
|
||||
types. These are the \fIFinished\fR messages, but because they
|
||||
are encrypted ssldump only knows that they are of type \fIHandshake\fR.
|
||||
are encrypted \fIssldump\fP only knows that they are of type \fIHandshake\fR.
|
||||
Similarly, had the \fIAlert\fR in record 14 happened during the handshake,
|
||||
it's type and level would have been printed. However, since it
|
||||
is encrypted we can only tell that it is an alert.
|
||||
|
@ -569,9 +575,9 @@ implemented. In practice, this turns out not to be much of a problem.
|
|||
Support is provided for only for Ethernet and loopback interfaces
|
||||
because that's all that I have. If you have another kind of network
|
||||
you will need to modify pcap_cb in base/pcap-snoop.c. If you have
|
||||
direct experience with ssldump on other networks, please send me patches.
|
||||
direct experience with \fIssldump\fP on other networks, please send me patches.
|
||||
.LP
|
||||
ssldump doesn't implement session caching and therefore can't decrypt
|
||||
\fIssldump\fP doesn't implement session caching and therefore can't decrypt
|
||||
resumed sessions.
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
|
@ -580,4 +586,4 @@ resumed sessions.
|
|||
.LP
|
||||
.SH AUTHOR
|
||||
.LP
|
||||
ssldump was written by Eric Rescorla <ekr@rtfm.com>.
|
||||
\fIssldump\fP was written by Eric Rescorla <ekr@rtfm.com>.
|
||||
|
|
Loading…
Reference in a new issue