mirror of
https://github.com/adulau/ssldump.git
synced 2024-11-07 12:06:27 +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:
|
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
|
./autogen.sh
|
||||||
./configure --prefix=/usr/local
|
./configure --prefix=/usr/local
|
||||||
make
|
make
|
||||||
|
@ -45,7 +45,7 @@ make
|
||||||
|
|
||||||
On Fedora, Centos & RHEL:
|
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
|
./autogen.sh
|
||||||
./configure --prefix=/usr/local
|
./configure --prefix=/usr/local
|
||||||
make
|
make
|
||||||
|
|
|
@ -135,6 +135,7 @@ int network_process_packet(handler,timestamp,data,length)
|
||||||
p.len = ntohs(p.ip->ip_len);
|
p.len = ntohs(p.ip->ip_len);
|
||||||
|
|
||||||
if(p.len > length) {
|
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");
|
printf("Malformed packet, size from IP header is larger than size reported by libpcap, skipping ...\n");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,5 +106,6 @@ extern UINT4 NET_print_flags;
|
||||||
#define NET_PRINT_TYPESET 2
|
#define NET_PRINT_TYPESET 2
|
||||||
#define NET_PRINT_ACKS 4
|
#define NET_PRINT_ACKS 4
|
||||||
#define NET_PRINT_NO_RESOLVE 8
|
#define NET_PRINT_NO_RESOLVE 8
|
||||||
|
#define NET_PRINT_JSON 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ void sig_handler(int sig)
|
||||||
logger->vtbl->deinit();
|
logger->vtbl->deinit();
|
||||||
|
|
||||||
freed_conn = destroy_all_conn();
|
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);
|
printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn);
|
||||||
|
|
||||||
if(p)
|
if(p)
|
||||||
|
@ -258,7 +258,7 @@ void pcap_cb(ptr,hdr,data)
|
||||||
if(packet_cnt == conn_freq) {
|
if(packet_cnt == conn_freq) {
|
||||||
packet_cnt = 0;
|
packet_cnt = 0;
|
||||||
memcpy(&last_packet_seen_time,&hdr->ts,sizeof(struct timeval));
|
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);
|
printf("%d inactive connection(s) cleaned from connection pool\n", cleaned_conn);
|
||||||
} else {
|
} else {
|
||||||
packet_cnt++;
|
packet_cnt++;
|
||||||
|
@ -310,7 +310,7 @@ int main(argc,argv)
|
||||||
|
|
||||||
signal(SIGINT,sig_handler);
|
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){
|
switch(c){
|
||||||
case 'v':
|
case 'v':
|
||||||
print_version();
|
print_version();
|
||||||
|
@ -328,6 +328,10 @@ int main(argc,argv)
|
||||||
/*Kludge*/
|
/*Kludge*/
|
||||||
SSL_print_flags |= SSL_PRINT_NROFF;
|
SSL_print_flags |= SSL_PRINT_NROFF;
|
||||||
break;
|
break;
|
||||||
|
case 'j':
|
||||||
|
NET_print_flags |= NET_PRINT_JSON;
|
||||||
|
SSL_print_flags |= SSL_PRINT_JSON;
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
NET_print_flags |= NET_PRINT_ACKS;
|
NET_print_flags |= NET_PRINT_ACKS;
|
||||||
break;
|
break;
|
||||||
|
@ -472,6 +476,7 @@ int main(argc,argv)
|
||||||
|
|
||||||
pcap_if_type=pcap_datalink(p);
|
pcap_if_type=pcap_datalink(p);
|
||||||
|
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON))
|
||||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||||
printf("\n.nf\n.ps -2\n");
|
printf("\n.nf\n.ps -2\n");
|
||||||
|
|
||||||
|
@ -480,11 +485,12 @@ int main(argc,argv)
|
||||||
|
|
||||||
pcap_loop(p,-1,pcap_cb,(u_char *)n);
|
pcap_loop(p,-1,pcap_cb,(u_char *)n);
|
||||||
|
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON))
|
||||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||||
printf("\n.ps\n.fi\n");
|
printf("\n.ps\n.fi\n");
|
||||||
|
|
||||||
freed_conn = destroy_all_conn();
|
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);
|
printf("Cleaned %d remaining connection(s) from connection pool\n", freed_conn);
|
||||||
|
|
||||||
pcap_close(p);
|
pcap_close(p);
|
||||||
|
|
|
@ -74,13 +74,13 @@ int exdump(name,data)
|
||||||
for(i=0;i<data->len;i++){
|
for(i=0;i<data->len;i++){
|
||||||
if(!i && (data->len>8)) INDENT;
|
if(!i && (data->len>8)) INDENT;
|
||||||
if((data->len>8) && i && !(i%12)){
|
if((data->len>8) && i && !(i%12)){
|
||||||
printf("\n"); INDENT;
|
LF;INDENT;
|
||||||
}
|
}
|
||||||
printf("%.2x ",data->data[i]&255);
|
printf("%.2x ",data->data[i]&255);
|
||||||
}
|
}
|
||||||
if(name) INDENT_POP;
|
if(name) INDENT_POP;
|
||||||
if(data->len>8 && i%12)
|
if(data->len>8 && i%12)
|
||||||
printf("\n");
|
LF;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ int process_tcp_packet(handler,ctx,p)
|
||||||
conn->i2r.ack=ntohl(p->tcp->th_ack)+1;
|
conn->i2r.ack=ntohl(p->tcp->th_ack)+1;
|
||||||
lookuphostname(&conn->i_addr,&sn);
|
lookuphostname(&conn->i_addr,&sn);
|
||||||
lookuphostname(&conn->r_addr,&dn);
|
lookuphostname(&conn->r_addr,&dn);
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON)) {
|
||||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||||
printf("\\fC");
|
printf("\\fC");
|
||||||
printf("New TCP connection #%d: %s(%d) <-> %s(%d)\n",
|
printf("New TCP connection #%d: %s(%d) <-> %s(%d)\n",
|
||||||
|
@ -138,7 +139,7 @@ int process_tcp_packet(handler,ctx,p)
|
||||||
dn,conn->r_port);
|
dn,conn->r_port);
|
||||||
if(NET_print_flags & NET_PRINT_TYPESET)
|
if(NET_print_flags & NET_PRINT_TYPESET)
|
||||||
printf("\\fR");
|
printf("\\fR");
|
||||||
|
}
|
||||||
conn->state=TCP_STATE_ESTABLISHED;
|
conn->state=TCP_STATE_ESTABLISHED;
|
||||||
free(sn);
|
free(sn);
|
||||||
free(dn);
|
free(dn);
|
||||||
|
@ -240,6 +241,7 @@ static int process_data_segment(conn,handler,p,stream,direction)
|
||||||
l=p->len - p->tcp->th_off * 4;
|
l=p->len - p->tcp->th_off * 4;
|
||||||
|
|
||||||
if(l < 0) {
|
if(l < 0) {
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON))
|
||||||
printf("Malformed packet, computed TCP segment size is negative, skipping ...\n");
|
printf("Malformed packet, computed TCP segment size is negative, skipping ...\n");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -400,6 +402,7 @@ static int print_tcp_packet(p)
|
||||||
lookuphostname(&p->ip->ip_src,&src);
|
lookuphostname(&p->ip->ip_src,&src);
|
||||||
lookuphostname(&p->ip->ip_dst,&dst);
|
lookuphostname(&p->ip->ip_dst,&dst);
|
||||||
|
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON)) {
|
||||||
printf("TCP: %s(%d) -> %s(%d) ",
|
printf("TCP: %s(%d) -> %s(%d) ",
|
||||||
src,
|
src,
|
||||||
ntohs(p->tcp->th_sport),
|
ntohs(p->tcp->th_sport),
|
||||||
|
@ -425,7 +428,7 @@ static int print_tcp_packet(p)
|
||||||
printf("URG ");
|
printf("URG ");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
}
|
||||||
free(src);
|
free(src);
|
||||||
free(dst);
|
free(dst);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
123
ssl/ssl.enums.c
123
ssl/ssl.enums.c
|
@ -1,3 +1,4 @@
|
||||||
|
#include <json-c/json.h>
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "ssl_h.h"
|
#include "ssl_h.h"
|
||||||
#include "sslprint.h"
|
#include "sslprint.h"
|
||||||
|
@ -15,6 +16,10 @@ static int decode_ContentType_ChangeCipherSpec(ssl,dir,seg,data)
|
||||||
Data *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);
|
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;
|
ssl->r_state=SSL_ST_SENT_CHANGE_CIPHER_SPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
LF;
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,9 +42,10 @@ static int decode_ContentType_Alert(ssl,dir,seg,data)
|
||||||
{
|
{
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
struct json_object *jobj;
|
||||||
|
|
||||||
if(ssl->record_encryption==REC_CIPHERTEXT){
|
if(ssl->record_encryption==REC_CIPHERTEXT){
|
||||||
printf("\n");
|
LF;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,17 +55,20 @@ static int decode_ContentType_Alert(ssl,dir,seg,data)
|
||||||
ERETURN(R_EOD);
|
ERETURN(R_EOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jobj = ssl->cur_json_st;
|
||||||
|
json_object_object_add(jobj, "msg_type", json_object_new_string("Alert"));
|
||||||
|
|
||||||
P_(P_HL){
|
P_(P_HL){
|
||||||
printf("\n");
|
LF;
|
||||||
SSL_DECODE_ENUM(ssl,"level",1,AlertLevel_decoder,P_HL,data,0);
|
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);
|
SSL_DECODE_ENUM(ssl,"value",1,AlertDescription_decoder,P_HL,data,0);
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SSL_DECODE_ENUM(ssl,0,1,AlertLevel_decoder,SSL_PRINT_ALL,data,0);
|
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);
|
SSL_DECODE_ENUM(ssl,0,1,AlertDescription_decoder,SSL_PRINT_ALL,data,0);
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
@ -77,9 +86,10 @@ static int decode_ContentType_Handshake(ssl,dir,seg,data)
|
||||||
UINT4 t,l;
|
UINT4 t,l;
|
||||||
int rs=0;
|
int rs=0;
|
||||||
Data d;
|
Data d;
|
||||||
|
struct json_object *jobj;
|
||||||
|
|
||||||
if(ssl->record_encryption==REC_CIPHERTEXT){
|
if(ssl->record_encryption==REC_CIPHERTEXT){
|
||||||
printf("\n");
|
LF;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,13 +103,16 @@ static int decode_ContentType_Handshake(ssl,dir,seg,data)
|
||||||
ERETURN(R_EOD);
|
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.data=data->data;
|
||||||
d.len=l;
|
d.len=l;
|
||||||
data->len-=l;
|
data->len-=l;
|
||||||
data->data+=l;
|
data->data+=l;
|
||||||
P_(P_HL){
|
P_(P_HL){
|
||||||
if(!rs){
|
if(!rs){
|
||||||
printf("\n");
|
LF;
|
||||||
rs=1;
|
rs=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +131,9 @@ static int decode_ContentType_application_data(ssl,dir,seg,data)
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
Data d;
|
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);
|
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);
|
print_data(ssl,&d);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
@ -160,9 +176,12 @@ static int decode_HandshakeType_HelloRequest(ssl,dir,seg,data)
|
||||||
segment *seg;
|
segment *seg;
|
||||||
Data *data;
|
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);
|
return(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -173,6 +192,9 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
||||||
Data *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;
|
UINT4 vj,vn,cs,cslen,complen,comp,odd,exlen,ex;
|
||||||
Data session_id,random;
|
Data session_id,random;
|
||||||
|
@ -182,13 +204,13 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
||||||
extern decoder compression_method_decoder[];
|
extern decoder compression_method_decoder[];
|
||||||
extern decoder extension_decoder[];
|
extern decoder extension_decoder[];
|
||||||
|
|
||||||
printf("\n");
|
LF;
|
||||||
ssl_update_handshake_messages(ssl,data);
|
ssl_update_handshake_messages(ssl,data);
|
||||||
SSL_DECODE_UINT8(ssl,0,0,data,&vj);
|
SSL_DECODE_UINT8(ssl,0,0,data,&vj);
|
||||||
SSL_DECODE_UINT8(ssl,0,0,data,&vn);
|
SSL_DECODE_UINT8(ssl,0,0,data,&vn);
|
||||||
|
|
||||||
P_(P_HL) {explain(ssl,"Version %d.%d ",vj,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_DECODE_OPAQUE_ARRAY(ssl,"random",32,P_ND,data,&random);
|
||||||
|
@ -219,7 +241,7 @@ static int decode_HandshakeType_ClientHello(ssl,dir,seg,data)
|
||||||
ssl_decode_enum(ssl,0,2,cipher_suite_decoder,
|
ssl_decode_enum(ssl,0,2,cipher_suite_decoder,
|
||||||
0,data,&cs);
|
0,data,&cs);
|
||||||
ssl_print_cipher_suite(ssl,(vj<<8)|vn,P_HL,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");
|
explain(ssl,"compression methods\n");
|
||||||
for(;complen;complen--){
|
for(;complen;complen--){
|
||||||
SSL_DECODE_ENUM(ssl,0,1,compression_method_decoder,P_HL,data,&comp);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -263,14 +285,18 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data)
|
||||||
|
|
||||||
extern decoder extension_decoder[];
|
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_update_handshake_messages(ssl,data);
|
||||||
SSL_DECODE_UINT8(ssl,0,0,data,&vj);
|
SSL_DECODE_UINT8(ssl,0,0,data,&vj);
|
||||||
SSL_DECODE_UINT8(ssl,0,0,data,&vn);
|
SSL_DECODE_UINT8(ssl,0,0,data,&vn);
|
||||||
|
|
||||||
ssl->version=vj*256+vn;
|
ssl->version=vj*256+vn;
|
||||||
P_(P_HL) {explain(ssl,"Version %d.%d ",vj,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,
|
ssl_process_server_session_id(ssl,ssl->decoder,session_id.data,
|
||||||
session_id.len);
|
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);
|
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);
|
SSL_DECODE_UINT16(ssl,"extensions len",0,data,&exlen);
|
||||||
if (exlen) {
|
if (exlen) {
|
||||||
|
@ -304,7 +330,7 @@ static int decode_HandshakeType_ServerHello(ssl,dir,seg,data)
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,10 +349,16 @@ static int decode_HandshakeType_Certificate(ssl,dir,seg,data)
|
||||||
Data cert;
|
Data cert;
|
||||||
int r;
|
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_update_handshake_messages(ssl,data);
|
||||||
SSL_DECODE_UINT24(ssl,"certificates len",0,data,&len);
|
SSL_DECODE_UINT24(ssl,"certificates len",0,data,&len);
|
||||||
|
|
||||||
|
json_object_object_add(jobj, "cert_chain", json_object_new_array());
|
||||||
|
|
||||||
while(len){
|
while(len){
|
||||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate",-((1<<23)-1),
|
SSL_DECODE_OPAQUE_ARRAY(ssl,"certificate",-((1<<23)-1),
|
||||||
0,data,&cert);
|
0,data,&cert);
|
||||||
|
@ -347,7 +379,11 @@ static int decode_HandshakeType_ServerKeyExchange(ssl,dir,seg,data)
|
||||||
|
|
||||||
int r;
|
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);
|
ssl_update_handshake_messages(ssl,data);
|
||||||
if(ssl->cs){
|
if(ssl->cs){
|
||||||
P_(P_ND){
|
P_(P_ND){
|
||||||
|
@ -385,14 +421,18 @@ static int decode_HandshakeType_CertificateRequest(ssl,dir,seg,data)
|
||||||
Data ca;
|
Data ca;
|
||||||
int r;
|
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_update_handshake_messages(ssl,data);
|
||||||
SSL_DECODE_UINT8(ssl,"certificate_types len",0,data,&len);
|
SSL_DECODE_UINT8(ssl,"certificate_types len",0,data,&len);
|
||||||
for(;len;len--){
|
for(;len;len--){
|
||||||
SSL_DECODE_ENUM(ssl,"certificate_types",1,
|
SSL_DECODE_ENUM(ssl,"certificate_types",1,
|
||||||
client_certificate_type_decoder, P_HL,data,0);
|
client_certificate_type_decoder, P_HL,data,0);
|
||||||
P_(P_HL){
|
P_(P_HL){
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -416,8 +456,11 @@ static int decode_HandshakeType_ServerHelloDone(ssl,dir,seg,data)
|
||||||
Data *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);
|
ssl_update_handshake_messages(ssl,data);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
@ -431,7 +474,12 @@ static int decode_HandshakeType_CertificateVerify(ssl,dir,seg,data)
|
||||||
|
|
||||||
|
|
||||||
int r;
|
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_update_handshake_messages(ssl,data);
|
||||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"Signature",-((1<<15)-1),P_HL,data,0);
|
SSL_DECODE_OPAQUE_ARRAY(ssl,"Signature",-((1<<15)-1),P_HL,data,0);
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -448,7 +496,11 @@ static int decode_HandshakeType_ClientKeyExchange(ssl,dir,seg,data)
|
||||||
int r;
|
int r;
|
||||||
Data pms;
|
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);
|
ssl_update_handshake_messages(ssl,data);
|
||||||
if(ssl->cs){
|
if(ssl->cs){
|
||||||
switch(ssl->cs->kex){
|
switch(ssl->cs->kex){
|
||||||
|
@ -486,7 +538,11 @@ static int decode_HandshakeType_Finished(ssl,dir,seg,data)
|
||||||
|
|
||||||
int r;
|
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){
|
switch(ssl->version){
|
||||||
case 0x300:
|
case 0x300:
|
||||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"md5_hash",16,P_ND,data,0);
|
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:
|
case 0x301:
|
||||||
SSL_DECODE_OPAQUE_ARRAY(ssl,"verify_data",12,P_ND,data,0);
|
SSL_DECODE_OPAQUE_ARRAY(ssl,"verify_data",12,P_ND,data,0);
|
||||||
P_(P_ND)
|
P_(P_ND)
|
||||||
printf("\n");
|
LF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2124,6 +2180,9 @@ static int decode_AlertLevel_warning(ssl,dir,seg,data)
|
||||||
segment *seg;
|
segment *seg;
|
||||||
Data *data;
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
static int decode_AlertLevel_fatal(ssl,dir,seg,data)
|
static int decode_AlertLevel_fatal(ssl,dir,seg,data)
|
||||||
|
@ -2132,6 +2191,9 @@ static int decode_AlertLevel_fatal(ssl,dir,seg,data)
|
||||||
segment *seg;
|
segment *seg;
|
||||||
Data *data;
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
decoder AlertLevel_decoder[]={
|
decoder AlertLevel_decoder[]={
|
||||||
|
@ -2530,7 +2592,7 @@ static int decode_extension_server_name(ssl,dir,seg,data)
|
||||||
|
|
||||||
if(dir==DIR_I2R){
|
if(dir==DIR_I2R){
|
||||||
SSL_DECODE_UINT16(ssl,"server name list length",0,data,&l);
|
SSL_DECODE_UINT16(ssl,"server name list length",0,data,&l);
|
||||||
printf("\n");
|
LF;
|
||||||
while(l) {
|
while(l) {
|
||||||
p=data->len;
|
p=data->len;
|
||||||
SSL_DECODE_UINT8(ssl, "server name type", 0, data, &t);
|
SSL_DECODE_UINT8(ssl, "server name type", 0, data, &t);
|
||||||
|
@ -2896,6 +2958,7 @@ static int decode_server_name_type_host_name(ssl,dir,seg,data)
|
||||||
int r;
|
int r;
|
||||||
UINT4 l;
|
UINT4 l;
|
||||||
SSL_DECODE_UINT16(ssl,"server name length",0,data,&l);
|
SSL_DECODE_UINT16(ssl,"server name length",0,data,&l);
|
||||||
|
if(!(NET_print_flags & NET_PRINT_JSON))
|
||||||
printf(": %.*s",l,data->data);
|
printf(": %.*s",l,data->data);
|
||||||
|
|
||||||
/* Possibly use data->data to set/modify ssl->server_name */
|
/* Possibly use data->data to set/modify ssl->server_name */
|
||||||
|
|
|
@ -44,7 +44,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "sslprint.h"
|
#include "sslprint.h"
|
||||||
|
@ -246,8 +247,14 @@ static int create_ssl_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn,
|
||||||
ABORT(r);
|
ABORT(r);
|
||||||
|
|
||||||
lookuphostname(i_addr,&obj->client_name);
|
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;
|
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->server_port=r_port;
|
||||||
|
|
||||||
obj->i_state=SSL_ST_SENT_NOTHING;
|
obj->i_state=SSL_ST_SENT_NOTHING;
|
||||||
|
@ -574,6 +581,8 @@ static int print_ssl_record(obj,direction,q,data,len)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
obj->cur_json_st = json_object_new_object();
|
||||||
|
|
||||||
if((r=print_ssl_header(obj,direction,q,data,len)))
|
if((r=print_ssl_header(obj,direction,q,data,len)))
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
|
|
||||||
|
@ -583,9 +592,14 @@ static int print_ssl_record(obj,direction,q,data,len)
|
||||||
|
|
||||||
INIT_DATA(d,data,len);
|
INIT_DATA(d,data,len);
|
||||||
exdump(obj,"Packet data",&d);
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,8 +623,7 @@ int close_ssl_analyzer(_obj,p,dir)
|
||||||
ssl_print_timestamp(ssl,&p->ts);
|
ssl_print_timestamp(ssl,&p->ts);
|
||||||
ssl_print_direction_indicator(ssl,dir);
|
ssl_print_direction_indicator(ssl,dir);
|
||||||
explain(ssl," TCP %s",what);
|
explain(ssl," TCP %s",what);
|
||||||
printf("\n");
|
LF;
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ extern proto_mod ssl_mod;
|
||||||
#define P_TSA (1<<12)
|
#define P_TSA (1<<12)
|
||||||
#define P_QT (1<<13)
|
#define P_QT (1<<13)
|
||||||
#define P_HO (1<<14)
|
#define P_HO (1<<14)
|
||||||
|
#define P_JS (1<<15)
|
||||||
|
|
||||||
#define SSL_PRINT_TIMESTAMP (1) /*Timestamp records*/
|
#define SSL_PRINT_TIMESTAMP (1) /*Timestamp records*/
|
||||||
#define SSL_PRINT_HEXDUMP (1<<2) /*Print the whole record in hex*/
|
#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_TIMESTAMP_ABSOLUTE (P_TSA)
|
||||||
#define SSL_PRINT_QUIET (P_QT)
|
#define SSL_PRINT_QUIET (P_QT)
|
||||||
#define SSL_PRINT_HEX_ONLY (P_HO)
|
#define SSL_PRINT_HEX_ONLY (P_HO)
|
||||||
|
#define SSL_PRINT_JSON (P_JS)
|
||||||
#define SSL_PRINT_ALL 0xfffffff
|
#define SSL_PRINT_ALL 0xfffffff
|
||||||
|
|
||||||
extern UINT4 SSL_print_flags;
|
extern UINT4 SSL_print_flags;
|
||||||
|
|
|
@ -81,8 +81,10 @@ typedef struct ssl_obj_ {
|
||||||
UINT4 cipher_suite;
|
UINT4 cipher_suite;
|
||||||
|
|
||||||
char *client_name;
|
char *client_name;
|
||||||
|
char *client_ip;
|
||||||
int client_port;
|
int client_port;
|
||||||
char *server_name;
|
char *server_name;
|
||||||
|
char *server_ip;
|
||||||
int server_port;
|
int server_port;
|
||||||
|
|
||||||
struct SSL_CipherSuite_ *cs;
|
struct SSL_CipherSuite_ *cs;
|
||||||
|
@ -106,6 +108,7 @@ typedef struct ssl_obj_ {
|
||||||
int record_count;
|
int record_count;
|
||||||
int indent_depth;
|
int indent_depth;
|
||||||
int indent_name_len;
|
int indent_name_len;
|
||||||
|
struct json_object *cur_json_st;
|
||||||
} ssl_obj;
|
} ssl_obj;
|
||||||
|
|
||||||
typedef struct decoder_ {
|
typedef struct decoder_ {
|
||||||
|
|
|
@ -47,8 +47,8 @@
|
||||||
#ifndef _ssldecode_h
|
#ifndef _ssldecode_h
|
||||||
#define _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 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);printf("\n");}
|
#define CRDUMPD(a,b) P_(P_CR) {exdump(ssl,a,b);LF;}
|
||||||
|
|
||||||
int ssl_decode_ctx_create PROTO_LIST((ssl_decode_ctx **ctx,
|
int ssl_decode_ctx_create PROTO_LIST((ssl_decode_ctx **ctx,
|
||||||
char *keyfile,char *password,char *keylogfile));
|
char *keyfile,char *password,char *keylogfile));
|
||||||
|
|
118
ssl/sslprint.c
118
ssl/sslprint.c
|
@ -44,7 +44,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
@ -83,7 +83,7 @@ int process_beginning_plaintext(ssl,seg,direction)
|
||||||
ssl_print_direction_indicator(ssl,direction);
|
ssl_print_direction_indicator(ssl,direction);
|
||||||
|
|
||||||
print_data(ssl,&d);
|
print_data(ssl,&d);
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
@ -140,7 +140,7 @@ int process_v2_hello(ssl,seg)
|
||||||
P_(P_HL) {
|
P_(P_HL) {
|
||||||
explain(ssl,"Version %d.%d ",(ver>>8)&0xff,
|
explain(ssl,"Version %d.%d ",(ver>>8)&0xff,
|
||||||
ver&0xff);
|
ver&0xff);
|
||||||
printf("\n");
|
LF;
|
||||||
}
|
}
|
||||||
SSL_DECODE_UINT16(ssl,"cipher_spec_length",P_DC,&d,&cs_len);
|
SSL_DECODE_UINT16(ssl,"cipher_spec_length",P_DC,&d,&cs_len);
|
||||||
SSL_DECODE_UINT16(ssl,"session_id_length",P_DC,&d,&sid_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);
|
INIT_DATA(d,seg->data,seg->len);
|
||||||
exdump(ssl,"Packet data",&d);
|
exdump(ssl,"Packet data",&d);
|
||||||
printf("\n\n");
|
LF;LF;
|
||||||
}
|
}
|
||||||
|
|
||||||
INDENT_POP;
|
INDENT_POP;
|
||||||
|
@ -235,6 +235,11 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
||||||
Data d;
|
Data d;
|
||||||
UINT4 ct,vermaj,vermin,length;
|
UINT4 ct,vermaj,vermin,length;
|
||||||
int version;
|
int version;
|
||||||
|
char verstr[4];
|
||||||
|
char enumstr[20];
|
||||||
|
struct json_object *jobj;
|
||||||
|
jobj = ssl->cur_json_st;
|
||||||
|
|
||||||
d.data=data;
|
d.data=data;
|
||||||
d.len=len;
|
d.len=len;
|
||||||
|
|
||||||
|
@ -251,9 +256,11 @@ int ssl_expand_record(ssl,q,direction,data,len)
|
||||||
|
|
||||||
P_(P_RH){
|
P_(P_RH){
|
||||||
explain(ssl," V%d.%d(%d)",vermaj,vermin,length);
|
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;
|
version=vermaj*256+vermin;
|
||||||
|
|
||||||
r=ssl_decode_record(ssl,ssl->decoder,direction,ct,version,&d);
|
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){
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
if((r=ssl_print_enum(ssl,0,ContentType_decoder,ct))) {
|
if((r=ssl_print_enum(ssl,0,ContentType_decoder,ct))) {
|
||||||
printf(" unknown record type: %d\n", ct);
|
printf(" unknown record type: %d\n", ct);
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
}
|
}
|
||||||
printf("\n");
|
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{
|
else{
|
||||||
//try to save unencrypted data to logger
|
//try to save unencrypted data to logger
|
||||||
|
@ -276,6 +288,7 @@ 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 ((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))) {
|
if((r=ssl_decode_switch(ssl,ContentType_decoder,data[0],direction,q, &d))) {
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
printf(" unknown record type: %d\n", ct);
|
printf(" unknown record type: %d\n", ct);
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
}
|
}
|
||||||
|
@ -394,6 +407,7 @@ int ssl_decode_enum(ssl,name,size,dtable,p,data,x)
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
|
|
||||||
P_(p){
|
P_(p){
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
if((r=ssl_print_enum(ssl,name,dtable,*x)))
|
if((r=ssl_print_enum(ssl,name,dtable,*x)))
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
}
|
}
|
||||||
|
@ -407,6 +421,7 @@ int ssl_print_enum(ssl,name,dtable,value)
|
||||||
decoder *dtable;
|
decoder *dtable;
|
||||||
UINT4 value;
|
UINT4 value;
|
||||||
{
|
{
|
||||||
|
|
||||||
if(name) explain(ssl,"%s ",name);
|
if(name) explain(ssl,"%s ",name);
|
||||||
INDENT;
|
INDENT;
|
||||||
|
|
||||||
|
@ -419,14 +434,30 @@ int ssl_print_enum(ssl,name,dtable,value)
|
||||||
}
|
}
|
||||||
dtable++;
|
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);
|
return(R_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
int explain(ssl_obj *ssl,char *format,...)
|
int explain(ssl_obj *ssl,char *format,...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON)) {
|
||||||
va_start(ap,format);
|
va_start(ap,format);
|
||||||
|
|
||||||
P_(P_NR){
|
P_(P_NR){
|
||||||
|
@ -439,6 +470,7 @@ int explain(ssl_obj *ssl,char *format,...)
|
||||||
|
|
||||||
vprintf(format,ap);
|
vprintf(format,ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +480,7 @@ int exdump(ssl,name,data)
|
||||||
Data *data;
|
Data *data;
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON)) {
|
||||||
if(name){
|
if(name){
|
||||||
explain(ssl,"%s[%d]=\n",name,data->len);
|
explain(ssl,"%s[%d]=\n",name,data->len);
|
||||||
INDENT_INCR;
|
INDENT_INCR;
|
||||||
|
@ -461,7 +493,7 @@ int exdump(ssl,name,data)
|
||||||
if(!i) INDENT;
|
if(!i) INDENT;
|
||||||
|
|
||||||
if((data->len>8) && i && !(i%16)){
|
if((data->len>8) && i && !(i%16)){
|
||||||
printf("\n"); INDENT;
|
LF; INDENT;
|
||||||
}
|
}
|
||||||
printf("%.2x ",data->data[i]&255);
|
printf("%.2x ",data->data[i]&255);
|
||||||
}
|
}
|
||||||
|
@ -469,7 +501,28 @@ int exdump(ssl,name,data)
|
||||||
printf("\\fR");
|
printf("\\fR");
|
||||||
}
|
}
|
||||||
if(name) INDENT_POP;
|
if(name) INDENT_POP;
|
||||||
printf("\n");
|
LF;
|
||||||
|
}
|
||||||
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +571,7 @@ int combodump(ssl,name,data)
|
||||||
else
|
else
|
||||||
printf(".");
|
printf(".");
|
||||||
}
|
}
|
||||||
printf("\n");
|
LF;
|
||||||
|
|
||||||
len-=bytes;
|
len-=bytes;
|
||||||
ptr+=bytes;
|
ptr+=bytes;
|
||||||
|
@ -536,7 +589,7 @@ int print_data(ssl,d)
|
||||||
{
|
{
|
||||||
int i,bit8=0;
|
int i,bit8=0;
|
||||||
|
|
||||||
printf("\n");
|
LF;
|
||||||
for(i=0;i<d->len;i++){
|
for(i=0;i<d->len;i++){
|
||||||
if(d->data[i] == 0 || (!isprint(d->data[i]) && !strchr("\r\n\t",d->data[i]))){
|
if(d->data[i] == 0 || (!isprint(d->data[i]) && !strchr("\r\n\t",d->data[i]))){
|
||||||
bit8=1;
|
bit8=1;
|
||||||
|
@ -590,6 +643,7 @@ int ssl_print_direction_indicator(ssl,dir)
|
||||||
ssl_obj *ssl;
|
ssl_obj *ssl;
|
||||||
int dir;
|
int dir;
|
||||||
{
|
{
|
||||||
|
struct json_object *jobj;
|
||||||
#if 0
|
#if 0
|
||||||
if(dir==DIR_I2R){
|
if(dir==DIR_I2R){
|
||||||
explain(ssl,"%s(%d) > %s>%d",
|
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);
|
ssl->client_name,ssl->client_port,ssl->server_name,ssl->server_port);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
jobj = ssl->cur_json_st;
|
||||||
|
|
||||||
if(dir==DIR_I2R){
|
if(dir==DIR_I2R){
|
||||||
explain(ssl,"C>S");
|
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{
|
else{
|
||||||
explain(ssl,"S>C");
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -618,18 +691,30 @@ int ssl_print_timestamp(ssl,ts)
|
||||||
struct timeval dt;
|
struct timeval dt;
|
||||||
int r;
|
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) {
|
if(SSL_print_flags & SSL_PRINT_TIMESTAMP_ABSOLUTE) {
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
explain(ssl,"%d%c%4.4d ",ts->tv_sec,'.',ts->tv_usec/100);
|
explain(ssl,"%d%c%4.4d ",ts->tv_sec,'.',ts->tv_usec/100);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if((r=timestamp_diff(ts,&ssl->time_start,&dt)))
|
if((r=timestamp_diff(ts,&ssl->time_start,&dt)))
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
explain(ssl,"%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100);
|
explain(ssl,"%d%c%4.4d ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((r=timestamp_diff(ts,&ssl->time_last,&dt))){
|
if((r=timestamp_diff(ts,&ssl->time_last,&dt))){
|
||||||
ERETURN(r);
|
ERETURN(r);
|
||||||
}
|
}
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
explain(ssl,"(%d%c%4.4d) ",dt.tv_sec,'.',dt.tv_usec/100);
|
explain(ssl,"(%d%c%4.4d) ",dt.tv_sec,'.',dt.tv_usec/100);
|
||||||
|
|
||||||
memcpy(&ssl->time_last,ts,sizeof(struct timeval));
|
memcpy(&ssl->time_last,ts,sizeof(struct timeval));
|
||||||
|
@ -641,7 +726,11 @@ int ssl_print_timestamp(ssl,ts)
|
||||||
int ssl_print_record_num(ssl)
|
int ssl_print_record_num(ssl)
|
||||||
ssl_obj *ssl;
|
ssl_obj *ssl;
|
||||||
{
|
{
|
||||||
|
struct json_object *jobj;
|
||||||
|
jobj = ssl->cur_json_st;
|
||||||
|
|
||||||
ssl->record_count++;
|
ssl->record_count++;
|
||||||
|
if(!(SSL_print_flags & SSL_PRINT_JSON))
|
||||||
if(SSL_print_flags & SSL_PRINT_NROFF){
|
if(SSL_print_flags & SSL_PRINT_NROFF){
|
||||||
printf("\\fI%d %d\\fR %s",
|
printf("\\fI%d %d\\fR %s",
|
||||||
ssl->conn->conn_number,
|
ssl->conn->conn_number,
|
||||||
|
@ -652,6 +741,9 @@ int ssl_print_record_num(ssl)
|
||||||
ssl->record_count,ssl->record_count<10?" ":"");
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ int ssl_lookup_enum PROTO_LIST((ssl_obj *ssl,decoder *dtable,
|
||||||
UINT4 val,char **ptr));
|
UINT4 val,char **ptr));
|
||||||
int ssl_print_enum PROTO_LIST((ssl_obj *obj,char *name,
|
int ssl_print_enum PROTO_LIST((ssl_obj *obj,char *name,
|
||||||
decoder *decode,UINT4 value));
|
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 print_data PROTO_LIST((ssl_obj *ssl,Data *d));
|
||||||
int process_v2_hello PROTO_LIST((ssl_obj *ssl,segment *seg));
|
int process_v2_hello PROTO_LIST((ssl_obj *ssl,segment *seg));
|
||||||
int process_beginning_plaintext PROTO_LIST((ssl_obj *ssl,
|
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 explain PROTO_LIST((ssl_obj *ssl,char *format,...));
|
||||||
int exdump PROTO_LIST((ssl_obj *ssl,char *name,Data *data));
|
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_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 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 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_INCR ssl->indent_depth+=2
|
||||||
#define INDENT_POP ssl->indent_depth-=2
|
#define INDENT_POP ssl->indent_depth-=2
|
||||||
#define INDENT_NAME(x) ssl->indent_name_len += strlen(x)
|
#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 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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <json-c/json.h>
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "ssl_h.h"
|
#include "ssl_h.h"
|
||||||
#include "sslprint.h"
|
#include "sslprint.h"
|
||||||
|
@ -78,9 +78,25 @@ int sslx_print_certificate(ssl,data,pf)
|
||||||
P_(P_ASN){
|
P_(P_ASN){
|
||||||
char buf[BUFSIZE];
|
char buf[BUFSIZE];
|
||||||
int ext;
|
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;
|
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))){
|
if(!(x=d2i_X509(0,(const unsigned char **) &d,data->len))){
|
||||||
explain(ssl,"Bad certificate");
|
explain(ssl,"Bad certificate");
|
||||||
ABORT(R_BAD_DATA);
|
ABORT(R_BAD_DATA);
|
||||||
|
@ -89,16 +105,24 @@ int sslx_print_certificate(ssl,data,pf)
|
||||||
BUFSIZE);
|
BUFSIZE);
|
||||||
explain(ssl,"Subject\n");
|
explain(ssl,"Subject\n");
|
||||||
INDENT_INCR;
|
INDENT_INCR;
|
||||||
|
json_object_object_add(cert_obj, "cert_subject", json_object_new_string(buf));
|
||||||
sslx__print_dn(ssl,buf);
|
sslx__print_dn(ssl,buf);
|
||||||
INDENT_POP;
|
INDENT_POP;
|
||||||
X509_NAME_oneline(X509_get_issuer_name(x),buf,
|
X509_NAME_oneline(X509_get_issuer_name(x),buf,
|
||||||
BUFSIZE);
|
BUFSIZE);
|
||||||
explain(ssl,"Issuer\n");
|
explain(ssl,"Issuer\n");
|
||||||
INDENT_INCR;
|
INDENT_INCR;
|
||||||
|
json_object_object_add(cert_obj, "cert_issuer", json_object_new_string(buf));
|
||||||
sslx__print_dn(ssl,buf);
|
sslx__print_dn(ssl,buf);
|
||||||
INDENT_POP;
|
INDENT_POP;
|
||||||
a=X509_get_serialNumber(x);
|
a=X509_get_serialNumber(x);
|
||||||
explain(ssl,"Serial ");
|
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);
|
sslx__print_serial(ssl,a);
|
||||||
|
|
||||||
ext=X509_get_ext_count(x);
|
ext=X509_get_ext_count(x);
|
||||||
|
@ -147,6 +171,10 @@ int sslx_print_certificate(ssl,data,pf)
|
||||||
}
|
}
|
||||||
#ifdef OPENSSL
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
164
ssldump.1
164
ssldump.1
|
@ -61,8 +61,7 @@ ssldump \- dump SSL traffic on a network
|
||||||
.na
|
.na
|
||||||
.B ssldump
|
.B ssldump
|
||||||
[
|
[
|
||||||
.B \-vTshVq
|
.B \-aAdeFHjnNPqtTvxXy
|
||||||
.B \-aAdeHnNqTxXvy
|
|
||||||
] [
|
] [
|
||||||
.B \-i
|
.B \-i
|
||||||
.I interface
|
.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
|
it will also decrypt the connections and display the application
|
||||||
data traffic.
|
data traffic.
|
||||||
.LP
|
.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
|
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
|
transmission so you may have trouble using it with network taps such
|
||||||
as SunOS nit that don't permit you to see transmitted data.
|
as SunOS nit that don't permit you to see transmitted data.
|
||||||
.B Under SunOS with nit or bpf:
|
.B Under SunOS with nit or bpf:
|
||||||
To run
|
To run
|
||||||
.I tcpdump
|
.I ssldump
|
||||||
you must have read access to
|
you must have read access to
|
||||||
.I /dev/nit
|
.I /dev/nit
|
||||||
or
|
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
|
Once the super-user has enabled promiscuous-mode operation using
|
||||||
.IR pfconfig (8),
|
.IR pfconfig (8),
|
||||||
any user may run
|
any user may run
|
||||||
.BR ssldump
|
.I ssldump
|
||||||
.B Under BSD:
|
.B Under BSD:
|
||||||
You must have read access to
|
You must have read access to
|
||||||
.IR /dev/bpf* .
|
.IR /dev/bpf* .
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-a
|
.B \-a
|
||||||
Print bare TCP ACKs (useful for observing Nagle behavior)
|
Print bare TCP ACKs (useful for observing Nagle behavior).
|
||||||
.TP
|
.TP
|
||||||
.B \-A
|
.B \-A
|
||||||
Print all record fields (by default ssldump chooses
|
Print all record fields (by default \fIssldump\fP chooses
|
||||||
the most interesting fields)
|
the most interesting fields).
|
||||||
.TP
|
.TP
|
||||||
.B \-d
|
.B \-d
|
||||||
Display the application data traffic. This usually means
|
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.
|
application data traffic \fIbefore\fP the SSL session initiates.
|
||||||
This allows you to see HTTPS CONNECT behavior as well as
|
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
|
whether plaintext is traffic before the initiation of an
|
||||||
SSL connection or just a regular TCP connection, this allows
|
SSL connection or just a regular TCP connection, this allows
|
||||||
you to use ssldump to sniff any TCP connection.
|
you to use \fIssldump\fP to sniff any TCP connection.
|
||||||
ssldump will automatically detect ASCII data and display it
|
\fIssldump\fP will automatically detect ASCII data and display it
|
||||||
directly to the screen. non-ASCII data is displayed as hex
|
directly to the screen. non-ASCII data is displayed as hex
|
||||||
dumps. See also -X.
|
dumps. See also -X.
|
||||||
.TP
|
.TP
|
||||||
.B \-e
|
.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
|
.TP
|
||||||
.B \-H
|
.B \-H
|
||||||
Print the full SSL packet header.
|
Print the full SSL packet header.
|
||||||
.TP
|
.TP
|
||||||
|
.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
|
.B \-n
|
||||||
Don't try to resolve host names from IP addresses
|
Don't try to resolve host names from IP addresses.
|
||||||
.TP
|
.TP
|
||||||
.B \-N
|
.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.
|
certificates and DNs.
|
||||||
.TP
|
.TP
|
||||||
.B \-p
|
.BI \-p " password"
|
||||||
Use \fIpassword\fP as the SSL keyfile password.
|
Use \fIpassword\fP as the SSL keyfile password.
|
||||||
.TP
|
.TP
|
||||||
.B \-P
|
.B \-P
|
||||||
|
@ -183,55 +201,13 @@ Don't put the interface into promiscuous mode.
|
||||||
.B \-q
|
.B \-q
|
||||||
Don't decode any record fields beyond a single summary line. (quiet mode).
|
Don't decode any record fields beyond a single summary line. (quiet mode).
|
||||||
.TP
|
.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"
|
.BI \-r " file"
|
||||||
Read data from \fIfile\fP instead of from the network.
|
Read data from \fIfile\fP instead of from the network.
|
||||||
The old -f option still works but is deprecated and will
|
The old -f option still works but is deprecated and will
|
||||||
probably be removed with the next version.
|
probably be removed with the next version.
|
||||||
.TP
|
.TP
|
||||||
.BI \-S " [ " crypto " | " d " | " ht " | " H " ]"
|
.BI \-S " [ " crypto " | " d " | " ht " | " H " ]"
|
||||||
Specify SSL flags to ssldump. These flags include:
|
Specify SSL flags to \fIssldump\fP. These flags include:
|
||||||
.RS
|
.RS
|
||||||
.TP
|
.TP
|
||||||
.I crypto
|
.I crypto
|
||||||
|
@ -247,17 +223,40 @@ Print the handshake type.
|
||||||
Print handshake type and highlights.
|
Print handshake type and highlights.
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.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"
|
.BI \-w " outputpcap"
|
||||||
Use \fIoutputpcap\fP as the destination for decrypted packets.
|
Use \fIoutputpcap\fP as the destination for decrypted packets.
|
||||||
.TP
|
.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
|
\fIexpression\fP
|
||||||
.RS
|
.RS
|
||||||
Selects what packets ssldump will examine. Technically speaking,
|
Selects what packets \fIssldump\fP will examine. Technically speaking,
|
||||||
ssldump supports the full expression syntax from PCAP and tcpdump.
|
\fIssldump\fP supports the full expression syntax from PCAP and tcpdump.
|
||||||
In fact, the description here is cribbed from the tcpdump man
|
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
|
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.
|
don't result in incomplete TCP streams are listed here.
|
||||||
.LP
|
.LP
|
||||||
The \fIexpression\fP consists of one or more
|
The \fIexpression\fP consists of one or more
|
||||||
|
@ -431,29 +430,36 @@ which should not be confused with
|
||||||
.fi
|
.fi
|
||||||
.in -.5i
|
.in -.5i
|
||||||
.LP
|
.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.
|
or as multiple arguments, whichever is more convenient.
|
||||||
Generally, if the expression contains Shell metacharacters, it is
|
Generally, if the expression contains Shell metacharacters, it is
|
||||||
easier to pass it as a single, quoted argument.
|
easier to pass it as a single, quoted argument.
|
||||||
Multiple arguments are concatenated with spaces before being parsed.
|
Multiple arguments are concatenated with spaces before being parsed.
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.LP
|
.LP
|
||||||
To listen to traffic on interface \fIle0\fP port \fI443\fP
|
To listen to traffic on interface \fIle0\fP port \fI443\fP:
|
||||||
.RS
|
.RS
|
||||||
.nf
|
.nf
|
||||||
\fBssldump -i le0 port 443\fP
|
\fBssldump -i le0 port 443\fP
|
||||||
.fi
|
.fi
|
||||||
.RE
|
.RE
|
||||||
.LP
|
.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
|
.RS
|
||||||
.nf
|
.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
|
.fi
|
||||||
.RE
|
.RE
|
||||||
.LP
|
.LP
|
||||||
To decrypt traffic to host \fIromeo\fR
|
To decrypt traffic to host \fIromeo\fR
|
||||||
\fIserver.pem\fR and the password \fIfoobar\fR
|
\fIserver.pem\fR and the password \fIfoobar\fR:
|
||||||
.RS
|
.RS
|
||||||
.nf
|
.nf
|
||||||
\fBssldump -Ad -k ~/server.pem -p foobar -i le0 host romeo
|
\fBssldump -Ad -k ~/server.pem -p foobar -i le0 host romeo
|
||||||
|
@ -463,7 +469,7 @@ To decrypt traffic to host \fIromeo\fR
|
||||||
.LP
|
.LP
|
||||||
All output is printed to standard out.
|
All output is printed to standard out.
|
||||||
.LP
|
.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
|
like the following
|
||||||
.nf
|
.nf
|
||||||
.LP
|
.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
|
The next field in the record line is the direction that the record
|
||||||
was going. \fIC>S\fR indicates records transmitted from client to
|
was going. \fIC>S\fR indicates records transmitted from client to
|
||||||
server and \fIS>C\fR indicates records transmitted from server to client.
|
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).
|
is the SSL client (this is nearly always correct).
|
||||||
.LP
|
.LP
|
||||||
The next field is the record type, one of \fIHandshake\fR, \fIIAlert\fR,
|
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
|
may print record-specific data on the rest of the line. For \fIHandshake\fR
|
||||||
records, it prints the handshake message. Thus, this record is
|
records, it prints the handshake message. Thus, this record is
|
||||||
a \fICertificate\fR message.
|
a \fICertificate\fR message.
|
||||||
.LP
|
.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:
|
are the ones that have proven to be most useful for debugging:
|
||||||
.LP
|
.LP
|
||||||
.nf
|
.nf
|
||||||
|
@ -525,16 +531,16 @@ flags.
|
||||||
.LP
|
.LP
|
||||||
.SH DECRYPTION
|
.SH DECRYPTION
|
||||||
.LP
|
.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:
|
conditions are met:
|
||||||
.RS
|
.RS
|
||||||
.nf
|
.nf
|
||||||
1. ssldump has the keys.
|
1. \fIssldump\fP has the keys.
|
||||||
2. Static RSA was used.
|
2. Static RSA was used.
|
||||||
.fi
|
.fi
|
||||||
.RE
|
.RE
|
||||||
In any other case, once encryption starts,
|
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.
|
record type. Consider the following section of a trace.
|
||||||
.LP
|
.LP
|
||||||
.nf
|
.nf
|
||||||
|
@ -553,7 +559,7 @@ record type. Consider the following section of a trace.
|
||||||
Note that the \fIClientKeyExchange\fR message type is printed
|
Note that the \fIClientKeyExchange\fR message type is printed
|
||||||
but the rest of the \fIHandshake\fR messages do not have
|
but the rest of the \fIHandshake\fR messages do not have
|
||||||
types. These are the \fIFinished\fR messages, but because they
|
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,
|
Similarly, had the \fIAlert\fR in record 14 happened during the handshake,
|
||||||
it's type and level would have been printed. However, since it
|
it's type and level would have been printed. However, since it
|
||||||
is encrypted we can only tell that it is an alert.
|
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
|
Support is provided for only for Ethernet and loopback interfaces
|
||||||
because that's all that I have. If you have another kind of network
|
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
|
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
|
.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.
|
resumed sessions.
|
||||||
.LP
|
.LP
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
@ -580,4 +586,4 @@ resumed sessions.
|
||||||
.LP
|
.LP
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
.LP
|
.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