"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ssl/ssl_analyze.c" between
ssldump-0.9b3.tar.gz and ssldump-1.3.tar.gz

About: ssldump is an SSLv3/TLS network protocol analyzer.

ssl_analyze.c  (ssldump-0.9b3):ssl_analyze.c  (ssldump-1.3)
skipping to change at line 44 skipping to change at line 44
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMA GE. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY SUCH DAMA GE.
$Id: ssl_analyze.c,v 1.8 2002/01/21 18:46:13 ekr Exp $ $Id: ssl_analyze.c,v 1.8 2002/01/21 18:46:13 ekr Exp $
ekr@rtfm.com Fri Jan 8 14:07:05 1999 ekr@rtfm.com Fri Jan 8 14:07:05 1999
*/ */
static char *RCSSTRING="$Id: ssl_analyze.c,v 1.8 2002/01/21 18:46:13 ekr Exp $"; #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"
#include "ssl_h.h" #include "ssl_h.h"
#include "ssl_analyze.h" #include "ssl_analyze.h"
/*UINT4 SSL_print_flags=P_HL| P_ND;*/ /*UINT4 SSL_print_flags=P_HL| P_ND;*/
UINT4 SSL_print_flags = 1 | P_HT | P_HL; UINT4 SSL_print_flags = 1 | P_HT | P_HL;
static int parse_ssl_flags PROTO_LIST((char *str)); static int parse_ssl_flags PROTO_LIST((char *str));
static int create_ssl_ctx PROTO_LIST((void *handle,proto_ctx **ctxp)); static int create_ssl_ctx PROTO_LIST((void *handle,proto_ctx **ctxp));
static int create_ssl_analyzer PROTO_LIST((void *handle, static int create_ssl_analyzer PROTO_LIST((void *handle,
proto_ctx *ctx,tcp_conn *conn,proto_obj **objp, proto_ctx *ctx,tcp_conn *conn,proto_obj **objp,
struct in_addr *i_addr,u_short i_port, struct in_addr *i_addr,u_short i_port,
struct in_addr *r_addr,u_short r_port, struct timeval *base_time)); struct in_addr *r_addr,u_short r_port, struct timeval *base_time));
static int destroy_ssl_ctx PROTO_LIST((void *handle,proto_ctx **ctxp));
static int destroy_ssl_analyzer PROTO_LIST((proto_obj **objp)); static int destroy_ssl_analyzer PROTO_LIST((proto_obj **objp));
static int read_ssl_record PROTO_LIST((ssl_obj *obj,r_queue *q,segment *seg, static int read_ssl_record PROTO_LIST((ssl_obj *obj,r_queue *q,segment *seg,
int offset,segment **lastp,int *offsetp)); int offset,segment **lastp,int *offsetp));
static int read_data PROTO_LIST((r_queue *q,segment *seg,int offset, static int read_data PROTO_LIST((r_queue *q,segment *seg,int offset,
segment **lastp,int *offsetp)); segment **lastp,int *offsetp));
static int data_ssl_analyzer PROTO_LIST((proto_obj *_obj,segment *seg, static int data_ssl_analyzer PROTO_LIST((proto_obj *_obj,segment *seg,
int direction)); int direction));
int close_ssl_analyzer PROTO_LIST((proto_obj *_obj,packet *p,int direction)); int close_ssl_analyzer PROTO_LIST((proto_obj *_obj,packet *p,int direction));
static int create_r_queue PROTO_LIST((r_queue **qp)); static int create_r_queue PROTO_LIST((r_queue **qp));
static int free_r_queue PROTO_LIST((r_queue *q)); static int free_r_queue PROTO_LIST((r_queue *q));
static int print_ssl_record PROTO_LIST((ssl_obj *obj,int direction, static int print_ssl_record PROTO_LIST((ssl_obj *obj,int direction,
segment *q,UCHAR *data,int len)); segment *q,UCHAR *data,int len));
char *SSL_keyfile=0; char *SSL_keyfile=0;
char *SSL_password=0; char *SSL_password=0;
char *SSL_keylogfile=0;
#define NEGATE 0x800000 #define NEGATE 0x800000
typedef struct { typedef struct {
int ch; int ch;
char *name; char *name;
UINT4 flag; UINT4 flag;
} flag_struct; } flag_struct;
flag_struct flags[]={ flag_struct flags[]={
skipping to change at line 133 skipping to change at line 135
'A', 'A',
"all", "all",
SSL_PRINT_ALL_FIELDS SSL_PRINT_ALL_FIELDS
}, },
{ {
0, 0,
"d", "d",
SSL_PRINT_DECODE SSL_PRINT_DECODE
}, },
{ {
0, 'y',
"nroff", "nroff",
SSL_PRINT_NROFF SSL_PRINT_NROFF
}, },
{ {
'N', 'N',
"asn", "asn",
SSL_PRINT_DECODE_ASN1 SSL_PRINT_DECODE_ASN1
}, },
{ {
0, 0,
skipping to change at line 187 skipping to change at line 189
static int parse_ssl_flags(str) static int parse_ssl_flags(str)
char *str; char *str;
{ {
char *x,*y; char *x,*y;
flag_struct *fl; flag_struct *fl;
int bang; int bang;
y=str; y=str;
while(x=strtok(y,",")){ while((x=strtok(y,","))){
y=0; y=0;
if(*x=='!'){ if(*x=='!'){
bang=1; bang=1;
x++; x++;
} }
else else
bang=0; bang=0;
for(fl=flags;fl->name;fl++){ for(fl=flags;fl->name;fl++){
if(!strcmp(x,fl->name)){ if(!strcmp(x,fl->name)){
skipping to change at line 218 skipping to change at line 220
return(0); return(0);
} }
static int create_ssl_ctx(handle,ctxp) static int create_ssl_ctx(handle,ctxp)
void *handle; void *handle;
proto_ctx **ctxp; proto_ctx **ctxp;
{ {
ssl_decode_ctx *ctx=0; ssl_decode_ctx *ctx=0;
int r,_status; int r,_status;
if(r=ssl_decode_ctx_create(&ctx,SSL_keyfile,SSL_password)) if((r=ssl_decode_ctx_create(&ctx,SSL_keyfile,SSL_password,SSL_keylogfile)))
ABORT(r); ABORT(r);
*ctxp=(proto_ctx *)ctx; *ctxp=(proto_ctx *)ctx;
_status=0; _status=0;
abort: abort:
return(_status); return(_status);
} }
static int create_ssl_analyzer(handle,ctx,conn,objp,i_addr,i_port,r_addr,r_port, base_time) static int destroy_ssl_ctx(handle,ctxp)
void *handle; void *handle;
proto_ctx *ctx; proto_ctx **ctxp;
tcp_conn *conn; {
proto_obj **objp; ssl_decode_ctx *ctx=0;
struct in_addr *i_addr; ctx=(ssl_decode_ctx *) *ctxp;
u_short i_port; ssl_decode_ctx_destroy(&ctx);
struct in_addr *r_addr; return 0;
u_short r_port; }
struct timeval *base_time;
static int create_ssl_analyzer(void *handle, proto_ctx *ctx, tcp_conn *conn,
proto_obj **objp, struct in_addr *i_addr, u_short i_port, struct in_addr *r_ad
dr,
u_short r_port, struct timeval *base_time)
{ {
int r,_status; int r,_status;
ssl_obj *obj=0; ssl_obj *obj=0;
if(!(obj=(ssl_obj *)calloc(sizeof(ssl_obj),1))) if(!(obj=(ssl_obj *)calloc(1,sizeof(ssl_obj))))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
obj->ssl_ctx=(ssl_decode_ctx *)ctx; obj->ssl_ctx=(ssl_decode_ctx *)ctx;
obj->conn=conn; obj->conn=conn;
if(r=create_r_queue(&obj->r2i_queue)) if((r=create_r_queue(&obj->r2i_queue)))
ABORT(r); ABORT(r);
if(r=create_r_queue(&obj->i2r_queue)) if((r=create_r_queue(&obj->i2r_queue)))
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;
obj->r_state=SSL_ST_HANDSHAKE; obj->r_state=SSL_ST_HANDSHAKE;
memcpy(&obj->time_start,base_time,sizeof(struct timeval)); memcpy(&obj->time_start,base_time,sizeof(struct timeval));
memcpy(&obj->time_last,base_time,sizeof(struct timeval)); memcpy(&obj->time_last,base_time,sizeof(struct timeval));
if(r=ssl_decoder_create(&obj->decoder,obj->ssl_ctx)) if((r=ssl_decoder_create(&obj->decoder,obj->ssl_ctx)))
ABORT(r); ABORT(r);
if (!(obj->extensions=malloc(sizeof(ssl_extensions))))
ABORT(R_NO_MEMORY);
*objp=(proto_obj *)obj; *objp=(proto_obj *)obj;
_status=0; _status=0;
//check logger...
if (logger) _status=logger->vtbl->create(&obj->logger_obj,i_addr,i_port,r_ad
dr,r_port,base_time);
abort: abort:
if(_status){ if(_status){
destroy_ssl_analyzer((proto_obj **)&obj); destroy_ssl_analyzer((proto_obj **)&obj);
} }
return(_status); return(_status);
} }
static int destroy_ssl_analyzer(objp) static int destroy_ssl_analyzer(objp)
proto_obj **objp; proto_obj **objp;
{ {
ssl_obj *obj; ssl_obj *obj;
if(!objp || !*objp) if(!objp || !*objp)
return(0); return(0);
obj=(ssl_obj *)*objp; obj=(ssl_obj *)*objp;
DBG((0,"Destroying SSL analyzer")); DBG((0,"Destroying SSL analyzer"));
//check logger...
if (logger) logger->vtbl->destroy(&obj->logger_obj);
free_r_queue(obj->i2r_queue); free_r_queue(obj->i2r_queue);
free_r_queue(obj->r2i_queue); free_r_queue(obj->r2i_queue);
ssl_decoder_destroy(&obj->decoder); ssl_decoder_destroy(&obj->decoder);
free(obj->client_name); free(obj->client_name);
free(obj->client_ip);
free(obj->server_name); free(obj->server_name);
free(obj->server_ip);
free(obj->extensions);
free(*objp); free(*objp);
*objp=0; *objp=0;
return(0); return(0);
} }
static int free_r_queue(q) static int free_r_queue(q)
r_queue *q; r_queue *q;
{ {
FREE(q->data); FREE(q->data);
skipping to change at line 313 skipping to change at line 337
free(q); free(q);
return(0); return(0);
} }
static int create_r_queue(qp) static int create_r_queue(qp)
r_queue **qp; r_queue **qp;
{ {
r_queue *q=0; r_queue *q=0;
int _status; int _status;
if(!(q=(r_queue *)calloc(sizeof(r_queue),1))) if(!(q=(r_queue *)calloc(1,sizeof(r_queue))))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
if(!(q->data=(UCHAR *)malloc(SSL_HEADER_SIZE))) if(!(q->data=(UCHAR *)malloc(SSL_HEADER_SIZE)))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
q->ptr=q->data; q->ptr=q->data;
q->_allocated=SSL_HEADER_SIZE; q->_allocated=SSL_HEADER_SIZE;
q->len=0; q->len=0;
q->state=SSL_READ_NONE; q->state=SSL_READ_NONE;
*qp=q; *qp=q;
skipping to change at line 346 skipping to change at line 370
int offset; int offset;
segment **lastp; segment **lastp;
int *offsetp; int *offsetp;
{ {
segment *last=seg; segment *last=seg;
int rec_len,r,_status; int rec_len,r,_status;
switch(q->state){ switch(q->state){
case SSL_READ_NONE: case SSL_READ_NONE:
q->read_left=SSL_HEADER_SIZE; if (SSL_HEADER_SIZE<q->len)
if(r=read_data(q,seg,offset,&last,&offset)) ABORT(-1);
q->read_left=SSL_HEADER_SIZE-q->len;
if((r=read_data(q,seg,offset,&last,&offset)))
ABORT(r); ABORT(r);
q->state=SSL_READ_HEADER; q->state=SSL_READ_HEADER;
switch(q->data[0]){ switch(q->data[0]){
case 20: case 20:
case 21: case 21:
case 22: case 22:
case 23: case 23:
break; break;
default: default:
printf("Unknown SSL content type %d\n",q->data[0] & 255); DBG((0,"Unknown SSL content type %d for segment %u:%u(%u)",
ABORT(R_INTERNAL); q->data[0] & 255,seg->s_seq,seg->s_seq+seg->len,seg->len));
} }
rec_len=COMBINE(q->data[3],q->data[4]); rec_len=COMBINE(q->data[3],q->data[4]);
/* SSL v3.0 spec says a record may not exceed 2**14 + 2048 == 18432 */
if(rec_len > 18432)
ABORT(R_INTERNAL);
/*Expand the buffer*/ /*Expand the buffer*/
if(q->_allocated<(rec_len+SSL_HEADER_SIZE)){ if(q->_allocated<(rec_len+SSL_HEADER_SIZE)){
if(!(q->data=realloc(q->data,rec_len+5))) if(!(q->data=realloc(q->data,rec_len+5)))
ABORT(R_NO_MEMORY); ABORT(R_NO_MEMORY);
q->_allocated=rec_len+SSL_HEADER_SIZE; q->_allocated=rec_len+SSL_HEADER_SIZE;
q->ptr=q->data+SSL_HEADER_SIZE;
}; };
q->ptr=q->data+SSL_HEADER_SIZE;
q->read_left=rec_len; q->read_left=rec_len;
case SSL_READ_HEADER: case SSL_READ_HEADER:
if(r=read_data(q,last,offset,&last,&offset)) if((r=read_data(q,last,offset,&last,&offset)))
ABORT(r); ABORT(r);
break; break;
default: default:
ABORT(R_INTERNAL); ABORT(R_INTERNAL);
} }
q->state=SSL_READ_NONE; q->state=SSL_READ_NONE;
/*Whew. If we get here, we've managed to read a whole record*/ /*Whew. If we get here, we've managed to read a whole record*/
*lastp=last; *lastp=last;
*offsetp=offset; *offsetp=offset;
skipping to change at line 424 skipping to change at line 454
q->ptr+=tocpy; q->ptr+=tocpy;
q->len+=tocpy; q->len+=tocpy;
#ifdef DEBUG #ifdef DEBUG
bread+=tocpy; bread+=tocpy;
#endif #endif
if(!q->read_left) if(!q->read_left)
break; break;
}; };
if(q->read_left){ if(q->read_left){
if(r=copy_tcp_segment_queue(&q->q,seg)) if((r=copy_tcp_segment_queue(&q->q,seg)))
ABORT(r); ABORT(r);
return(SSL_NO_DATA); return(SSL_NO_DATA);
} }
if(seg && tocpy==(seg->len - offset)){ if(seg && tocpy==(seg->len - offset)){
*lastp=0; *lastp=0;
*offsetp=0; *offsetp=0;
} }
else{ else{
*lastp=seg; *lastp=seg;
skipping to change at line 454 skipping to change at line 484
return(_status); return(_status);
} }
static int data_ssl_analyzer(_obj,seg,direction) static int data_ssl_analyzer(_obj,seg,direction)
proto_obj *_obj; proto_obj *_obj;
segment *seg; segment *seg;
int direction; int direction;
{ {
int _status,r; int _status,r;
r_queue *q; r_queue *q;
segment *last,*q_next,*assembled; segment *last,*q_next=NULL,*assembled;
ssl_obj *ssl=(ssl_obj *)_obj; ssl_obj *ssl=(ssl_obj *)_obj;
int offset=0; int offset=0;
q=direction==DIR_R2I?ssl->r2i_queue:ssl->i2r_queue; q=direction==DIR_R2I?ssl->r2i_queue:ssl->i2r_queue;
/* Handle SSLv2 backwards compat client hello /* Handle SSLv2 backwards compat client hello
This is sloppy because we'll assume that it's This is sloppy because we'll assume that it's
all in one TCP segment -- an assumption we make all in one TCP segment -- an assumption we make
nowhere else in the code nowhere else in the code
*/ */
skipping to change at line 501 skipping to change at line 531
} }
if(q->q_last){ if(q->q_last){
q->q_last->next=seg; q->q_last->next=seg;
assembled=q->q; assembled=q->q;
} }
else else
assembled=seg; assembled=seg;
ssl->direction=direction; ssl->direction=direction;
if(r=print_ssl_record(ssl,direction,assembled,q->data,q->len)) if((r=print_ssl_record(ssl,direction,assembled,q->data,q->len)))
ABORT(r); ABORT(r);
/*Now reset things, so we can read another record*/ /*Now reset things, so we can read another record*/
if(q){ if(q){
if(q->q_last) q->q_last->next=0; if(q->q_last) q->q_last->next=0;
if(last) if(last)
last->next=q_next; last->next=q_next;
free_tcp_segment_queue(q->q); free_tcp_segment_queue(q->q);
q->q=0;q->q_last=0;q->offset=0;q->len=0;q->ptr=q->data; q->q=0;q->q_last=0;q->offset=0;q->len=0;q->ptr=q->data;
q->state=SSL_READ_NONE; q->state=SSL_READ_NONE;
skipping to change at line 533 skipping to change at line 563
} }
static int print_ssl_header(obj,direction,q,data,len) static int print_ssl_header(obj,direction,q,data,len)
ssl_obj *obj; ssl_obj *obj;
int direction; int direction;
segment *q; segment *q;
UCHAR *data; UCHAR *data;
int len; int len;
{ {
int ct=0; int ct=0;
int r;
segment *s; segment *s;
struct timeval dt;
ssl_print_record_num(obj); ssl_print_record_num(obj);
if(SSL_print_flags & SSL_PRINT_TIMESTAMP){ if(SSL_print_flags & SSL_PRINT_TIMESTAMP){
for(s=q;s;s=s->next) ct++; for(s=q;s;s=s->next) ct++;
for(s=q;s;s=s->next){ for(s=q;s;s=s->next){
ssl_print_timestamp(obj,&s->p->ts); ssl_print_timestamp(obj,&s->p->ts);
if(s->next) if(s->next)
skipping to change at line 564 skipping to change at line 592
static int print_ssl_record(obj,direction,q,data,len) static int print_ssl_record(obj,direction,q,data,len)
ssl_obj *obj; ssl_obj *obj;
int direction; int direction;
segment *q; segment *q;
UCHAR *data; UCHAR *data;
int len; int len;
{ {
int r; int r;
if(r=print_ssl_header(obj,direction,q,data,len)) obj->cur_json_st = json_object_new_object();
if((r=print_ssl_header(obj,direction,q,data,len)))
ERETURN(r); ERETURN(r);
ssl_expand_record(obj,q,direction,data,len); ssl_expand_record(obj,q,direction,data,len);
if(SSL_print_flags & SSL_PRINT_HEXDUMP){ if(SSL_print_flags & SSL_PRINT_HEXDUMP){
Data d; Data d;
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);
} }
int close_ssl_analyzer(_obj,p,dir) int close_ssl_analyzer(_obj,p,dir)
proto_obj *_obj; proto_obj *_obj;
packet *p; packet *p;
int dir; int dir;
{ {
ssl_obj *ssl=(ssl_obj *)_obj; ssl_obj *ssl=(ssl_obj *)_obj;
char *what; char *what;
if(p->tcp->th_flags & TH_RST) if(p->tcp->th_flags & TH_RST)
what="RST"; what="RST";
else else
what="FIN"; what="FIN";
//check logger...
if (logger) logger->vtbl->close(ssl->logger_obj,NULL,0,dir);
explain(ssl,"%d ",ssl->conn->conn_number); explain(ssl,"%d ",ssl->conn->conn_number);
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);
} }
static struct proto_mod_vtbl_ ssl_vtbl ={ static struct proto_mod_vtbl_ ssl_vtbl ={
parse_ssl_flags, parse_ssl_flags,
parse_ssl_flag, parse_ssl_flag,
create_ssl_ctx, create_ssl_ctx,
create_ssl_analyzer, create_ssl_analyzer,
destroy_ssl_ctx,
destroy_ssl_analyzer, destroy_ssl_analyzer,
data_ssl_analyzer, data_ssl_analyzer,
close_ssl_analyzer, close_ssl_analyzer,
}; };
struct proto_mod_ ssl_mod = { struct proto_mod_ ssl_mod = {
0, 0,
&ssl_vtbl &ssl_vtbl
}; };
 End of changes. 37 change blocks. 
34 lines changed or deleted 74 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)