/*
* $Id: dump.c,v 1.7 2006/12/13 01:11:37 heas Exp $
*
* Copyright (c) 1995-1998 by Cisco systems, Inc.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that this
* copyright and permission notice appear on all copies of the
* software and supporting documentation, the name of Cisco Systems,
* Inc. not be used in advertising or publicity pertaining to
* distribution of the program without specific prior permission, and
* notice be given in supporting documentation that modification,
* copying and distribution is by permission of Cisco Systems, Inc.
*
* Cisco Systems, Inc. makes no representations about the suitability
* of this software for any purpose. THIS SOFTWARE IS PROVIDED ``AS
* IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "tac_plus.h"
/* Routines for dumping packets to stderr */
char *
summarise_outgoing_packet_type(u_char *pak)
{
HDR *hdr;
struct authen_reply *authen;
struct author_reply *author;
char *p;
hdr = (HDR *) pak;
switch (hdr->type) {
case TAC_PLUS_AUTHEN:
authen = (struct authen_reply *) (pak + TAC_PLUS_HDR_SIZE);
switch (authen->status) {
case TAC_PLUS_AUTHEN_STATUS_PASS:
p = "AUTHEN/SUCCEED";
break;
case TAC_PLUS_AUTHEN_STATUS_FAIL:
p = "AUTHEN/FAIL";
break;
case TAC_PLUS_AUTHEN_STATUS_GETDATA:
p = "AUTHEN/GETDATA";
break;
case TAC_PLUS_AUTHEN_STATUS_GETUSER:
p = "AUTHEN/GETUSER";
break;
case TAC_PLUS_AUTHEN_STATUS_GETPASS:
p = "AUTHEN/GETPASS";
break;
case TAC_PLUS_AUTHEN_STATUS_ERROR:
p = "AUTHEN/ERROR";
break;
default:
p = "AUTHEN/UNKNOWN";
break;
}
break;
case TAC_PLUS_AUTHOR:
author = (struct author_reply *) (pak + TAC_PLUS_HDR_SIZE);
switch (author->status) {
case AUTHOR_STATUS_PASS_ADD:
p = "AUTHOR/PASS_ADD";
break;
case AUTHOR_STATUS_FAIL:
p = "AUTHOR/FAIL";
break;
case AUTHOR_STATUS_PASS_REPL:
p = "AUTHOR/PASS_REPL";
break;
case AUTHOR_STATUS_ERROR:
p = "AUTHOR/ERROR";
break;
default:
p = "AUTHOR/UNKNOWN";
break;
}
break;
case TAC_PLUS_ACCT:
p = "ACCT";
break;
default:
p = "UNKNOWN";
break;
}
return(p);
}
void
dump_header(u_char *pak)
{
HDR *hdr;
u_char *data;
hdr = (HDR *) pak;
report(LOG_DEBUG, "PACKET: key=%s", session.key ? session.key : "<NULL>");
report(LOG_DEBUG, "version %d (0x%x), type %d, seq no %d, encryption %d",
hdr->version, hdr->version,
hdr->type, hdr->seq_no, hdr->encryption);
report(LOG_DEBUG, "session_id %u (0x%x), Data length %d (0x%x)",
ntohl(hdr->session_id), ntohl(hdr->session_id),
ntohl(hdr->datalength), ntohl(hdr->datalength));
report(LOG_DEBUG, "End header");
if (debug & DEBUG_HEX_FLAG) {
report(LOG_DEBUG, "Packet body hex dump:");
data = (u_char *) (pak + TAC_PLUS_HDR_SIZE);
report_hex(LOG_DEBUG, data, ntohl(hdr->datalength));
}
}
/* Dump packets originated by a NAS */
void
dump_nas_pak(u_char *pak)
{
struct authen_start *start;
struct authen_cont *cont;
struct author *author;
struct acct *acct;
int i;
HDR *hdr;
u_char *p, *argsizep;
int seq;
dump_header(pak);
hdr = (HDR *) pak;
seq = hdr->seq_no;
if (seq % 2 != 1) {
report(LOG_DEBUG, "nas packets should be odd numbered seq=%d",
seq);
exit(1);
}
switch (hdr->type) {
case TAC_PLUS_AUTHEN:
start = (struct authen_start *) (pak + TAC_PLUS_HDR_SIZE);
switch (hdr->seq_no) {
case 1:
report(LOG_DEBUG, "type=AUTHEN/START, priv_lvl = %d",
start->priv_lvl);
switch (start->action) {
case TAC_PLUS_AUTHEN_LOGIN:
report(LOG_DEBUG, "action=login");
break;
case TAC_PLUS_AUTHEN_CHPASS:
report(LOG_DEBUG, "action=chpass");
break;
case TAC_PLUS_AUTHEN_SENDPASS:
report(LOG_DEBUG, "action=sendpass");
break;
case TAC_PLUS_AUTHEN_SENDAUTH:
report(LOG_DEBUG, "action=sendauth");
break;
default:
report(LOG_DEBUG, "action=UNKNOWN %d", start->action);
break;
}
switch(start->authen_type) {
case TAC_PLUS_AUTHEN_TYPE_ASCII:
report(LOG_DEBUG, "authen_type=ascii");
break;
case TAC_PLUS_AUTHEN_TYPE_PAP:
report(LOG_DEBUG, "authen_type=pap");
break;
case TAC_PLUS_AUTHEN_TYPE_CHAP:
report(LOG_DEBUG, "authen_type=chap");
break;
case TAC_PLUS_AUTHEN_TYPE_ARAP:
report(LOG_DEBUG, "authen_type=arap");
break;
default:
report(LOG_DEBUG, "authen_type=unknown %d", start->authen_type);
break;
}
switch(start->service) {
case TAC_PLUS_AUTHEN_SVC_LOGIN:
report(LOG_DEBUG, "service=login");
break;
case TAC_PLUS_AUTHEN_SVC_ENABLE:
report(LOG_DEBUG, "service=enable");
break;
case TAC_PLUS_AUTHEN_SVC_PPP:
report(LOG_DEBUG, "service=ppp");
break;
case TAC_PLUS_AUTHEN_SVC_ARAP:
report(LOG_DEBUG, "service=arap");
break;
case TAC_PLUS_AUTHEN_SVC_PT:
report(LOG_DEBUG, "service=pt");
break;
case TAC_PLUS_AUTHEN_SVC_RCMD:
report(LOG_DEBUG, "service=rcmd");
break;
case TAC_PLUS_AUTHEN_SVC_X25:
report(LOG_DEBUG, "service=x25");
break;
case TAC_PLUS_AUTHEN_SVC_NASI:
report(LOG_DEBUG, "service=nasi");
break;
default:
report(LOG_DEBUG, "service=unknown %d", start->service);
break;
}
report(LOG_DEBUG,
"user_len=%d port_len=%d (0x%x), rem_addr_len=%d (0x%x)",
start->user_len, start->port_len, start->port_len,
start->rem_addr_len, start->rem_addr_len);
report(LOG_DEBUG, "data_len=%d", start->data_len);
/* start of variable length data is here */
p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHEN_START_FIXED_FIELDS_SIZE;
report(LOG_DEBUG, "User: ");
report_string(LOG_DEBUG, p, start->user_len);
p += start->user_len;
report(LOG_DEBUG, "port: ");
report_string(LOG_DEBUG, p, start->port_len);
p += start->port_len;
report(LOG_DEBUG, "rem_addr: ");
report_string(LOG_DEBUG, p, start->rem_addr_len);
p += start->rem_addr_len;
report(LOG_DEBUG, "data: ");
report_string(LOG_DEBUG, p, start->data_len);
report(LOG_DEBUG, "End packet");
return;
default:
cont = (struct authen_cont *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "type=AUTHEN/CONT");
report(LOG_DEBUG, "user_msg_len %d (0x%x), user_data_len %d (0x%x)",
cont->user_msg_len, cont->user_msg_len,
cont->user_data_len, cont->user_data_len);
report(LOG_DEBUG, "flags=0x%x", cont->flags);
/* start of variable length data is here */
p = pak + TAC_PLUS_HDR_SIZE +
TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE;
report(LOG_DEBUG, "User msg: ");
report_string(LOG_DEBUG, p, cont->user_msg_len);
p += cont->user_msg_len;
report(LOG_DEBUG, "User data: ");
report_string(LOG_DEBUG, p, cont->user_data_len);
report(LOG_DEBUG, "End packet");
return;
}
case TAC_PLUS_AUTHOR:
author = (struct author *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "type=AUTHOR, priv_lvl=%d, authen=%d",
author->priv_lvl,
author->authen_type);
switch(author->authen_method) {
case AUTHEN_METH_NONE:
report(LOG_DEBUG, "method=none");
break;
case AUTHEN_METH_KRB5:
report(LOG_DEBUG, "method=krb5");
break;
case AUTHEN_METH_LINE:
report(LOG_DEBUG, "method=line");
break;
case AUTHEN_METH_ENABLE:
report(LOG_DEBUG, "method=enable");
break;
case AUTHEN_METH_LOCAL:
report(LOG_DEBUG, "method=local");
break;
case AUTHEN_METH_TACACSPLUS:
report(LOG_DEBUG, "method=tacacs+");
break;
case AUTHEN_METH_RCMD:
report(LOG_DEBUG, "method=rcmd");
break;
default:
report(LOG_DEBUG, "method=unknown %d", author->authen_method);
break;
}
report(LOG_DEBUG, "svc=%d user_len=%d port_len=%d rem_addr_len=%d",
author->service, author->user_len,
author->port_len, author->rem_addr_len);
report(LOG_DEBUG, "arg_cnt=%d", author->arg_cnt);
/* variable length data start here */
p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE;
argsizep = p;
p += author->arg_cnt;
report(LOG_DEBUG, "User: ");
report_string(LOG_DEBUG, p, author->user_len);
p += author->user_len;
report(LOG_DEBUG, "port: ");
report_string(LOG_DEBUG, p, author->port_len);
p += author->port_len;
report(LOG_DEBUG, "rem_addr: ");
report_string(LOG_DEBUG, p, author->rem_addr_len);
p += author->rem_addr_len;
for (i = 0; i < (int) author->arg_cnt; i++) {
report(LOG_DEBUG, "arg[%d]: size=%d ", i, *argsizep);
report_string(LOG_DEBUG, p, *argsizep);
p += *argsizep;
argsizep++;
}
break;
case TAC_PLUS_ACCT:
acct = (struct acct *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "ACCT, flags=0x%x method=%d priv_lvl=%d",
acct->flags, acct->authen_method, acct->priv_lvl);
report(LOG_DEBUG, "type=%d svc=%d",
acct->authen_type, acct->authen_service);
report(LOG_DEBUG, "user_len=%d port_len=%d rem_addr_len=%d",
acct->user_len, acct->port_len, acct->rem_addr_len);
report(LOG_DEBUG, "arg_cnt=%d", acct->arg_cnt);
p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE;
argsizep = p;
p += acct->arg_cnt;
report(LOG_DEBUG, "User: ");
report_string(LOG_DEBUG, p, acct->user_len);
p += acct->user_len;
report(LOG_DEBUG, "port: ");
report_string(LOG_DEBUG, p, acct->port_len);
p += acct->port_len;
report(LOG_DEBUG, "rem_addr: ");
report_string(LOG_DEBUG, p, acct->rem_addr_len);
p += acct->rem_addr_len;
for (i = 0; i < (int) acct->arg_cnt; i++) {
report(LOG_DEBUG, "arg[%d]: size=%d ", i, *argsizep);
report_string(LOG_DEBUG, p, *argsizep);
p += *argsizep;
argsizep++;
}
break;
default:
report(LOG_DEBUG, "dump_nas_pak: unrecognized header type %d", hdr->type);
}
report(LOG_DEBUG, "End packet");
}
/* Dump packets originated by Tacacsd */
void
dump_tacacs_pak(u_char *pak)
{
struct authen_reply *authen;
struct author_reply *author;
struct acct_reply *acct;
HDR *hdr;
u_char *p, *argsizep;
int i;
int seq;
dump_header(pak);
hdr = (HDR *) pak;
seq = hdr->seq_no;
if (seq % 2 != 0) {
report(LOG_ERR, "%s: Bad sequence number %d should be even",
session.peer, seq);
tac_exit(1);
}
switch (hdr->type) {
case TAC_PLUS_AUTHEN:
authen = (struct authen_reply *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "type=AUTHEN status=%d (%s) flags=0x%x",
authen->status, summarise_outgoing_packet_type(pak),
authen->flags);
report(LOG_DEBUG, "msg_len=%d, data_len=%d",
authen->msg_len, authen->data_len);
/* start of variable length data is here */
p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHEN_REPLY_FIXED_FIELDS_SIZE;
report(LOG_DEBUG, "msg: ");
report_string(LOG_DEBUG, p, authen->msg_len);
p += authen->msg_len;
report(LOG_DEBUG, "data: ");
report_string(LOG_DEBUG, p, authen->data_len);
report(LOG_DEBUG, "End packet");
return;
case TAC_PLUS_AUTHOR:
author = (struct author_reply *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "type=AUTHOR/REPLY status=%d (%s) ",
author->status, summarise_outgoing_packet_type(pak));
report(LOG_DEBUG, "msg_len=%d, data_len=%d arg_cnt=%d",
author->msg_len, author->data_len, author->arg_cnt);
/* start of variable length data is here */
p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE;
/* arg sizes come next */
argsizep = p;
p += author->arg_cnt;
report(LOG_DEBUG, "msg: ");
report_string(LOG_DEBUG, p, author->msg_len);
p += author->msg_len;
report(LOG_DEBUG, "data: ");
report_string(LOG_DEBUG, p, author->data_len);
p += author->data_len;
/* args follow */
for (i = 0; i < (int) author->arg_cnt; i++) {
int size = argsizep[i];
report(LOG_DEBUG, "arg[%d] size=%d ", i, size);
report_string(LOG_DEBUG, p, size);
p += size;
}
break;
case TAC_PLUS_ACCT:
acct = (struct acct_reply *) (pak + TAC_PLUS_HDR_SIZE);
report(LOG_DEBUG, "ACCT/REPLY status=%d", acct->status);
report(LOG_DEBUG, "msg_len=%d data_len=%d",
acct->msg_len, acct->data_len);
p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REPLY_FIXED_FIELDS_SIZE;
report(LOG_DEBUG, "msg: ");
report_string(LOG_DEBUG, p, acct->msg_len);
p += acct->msg_len;
report(LOG_DEBUG, "data: ");
report_string(LOG_DEBUG, p, acct->data_len);
break;
default:
report(LOG_DEBUG, "dump_tacacs_pak: unrecognized header type %d",
hdr->type);
}
report(LOG_DEBUG, "End packet");
}
/* summarise packet types for logging routines. */
char *
summarise_incoming_packet_type(u_char *pak)
{
HDR *hdr;
char *p;
hdr = (HDR *) pak;
switch (hdr->type) {
case TAC_PLUS_AUTHEN:
switch (hdr->seq_no) {
case 1:
p = "AUTHEN/START";
break;
default:
p = "AUTHEN/CONT";
break;
}
return(p);
case TAC_PLUS_AUTHOR:
p = "AUTHOR";
break;
case TAC_PLUS_ACCT:
p = "ACCT";
break;
default:
p = "UNKNOWN";
break;
}
return(p);
}
syntax highlighted by Code2HTML, v. 0.9.1