File: [local] / src / usr.sbin / tcpdump / print-radius.c (download)
Revision 1.8, Tue May 23 21:57:15 2006 UTC (18 years ago) by stevesk
Branch: MAIN
CVS Tags: OPENBSD_5_0_BASE, OPENBSD_5_0, OPENBSD_4_9_BASE, OPENBSD_4_9, OPENBSD_4_8_BASE, OPENBSD_4_8, OPENBSD_4_7_BASE, OPENBSD_4_7, OPENBSD_4_6_BASE, OPENBSD_4_6, OPENBSD_4_5_BASE, OPENBSD_4_5, OPENBSD_4_4_BASE, OPENBSD_4_4, OPENBSD_4_3_BASE, OPENBSD_4_3, OPENBSD_4_2_BASE, OPENBSD_4_2, OPENBSD_4_1_BASE, OPENBSD_4_1, OPENBSD_4_0_BASE, OPENBSD_4_0 Changes since 1.7: +7 -4 lines
clean an XXX and don't print preceding ',' on first attribute; ok
canacar@
|
/* $OpenBSD: print-radius.c,v 1.8 2006/05/23 21:57:15 stevesk Exp $ */
/*
* Copyright (c) 1997 Thomas H. Ptacek. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
/* RADIUS support for tcpdump, Thomas Ptacek <tqbf@enteract.com> */
#include "interface.h"
#include "radius.h"
static void r_print_att(int code, int len, const u_char *val);
static void r_print_int(int code, int len, const u_char *val);
static void r_print_address(int code, int len, const u_char *val);
static void r_print_string(int code, int len, const u_char *val);
static void r_print_hex(int code, int len, const u_char *val);
/* --------------------------------------------------------------- */
struct radius_ctable {
int code;
char *name;
};
/* map opcodes to strings */
#define DEFINED_OPCODES 11
static struct radius_ctable radius_codes[] = {
{ -1, NULL },
{ RADIUS_CODE_ACCESS_REQUEST, "Axs?" },
{ RADIUS_CODE_ACCESS_ACCEPT, "Axs+" },
{ RADIUS_CODE_ACCESS_REJECT, "Axs-" },
{ RADIUS_CODE_ACCOUNT_REQUEST, "Act?" },
{ RADIUS_CODE_ACCOUNT_RESPONSE, "Act+" },
{ RADIUS_CODE_ACCOUNT_STATUS, "ActSt" },
{ RADIUS_CODE_PASSCHG_REQUEST, "Pchg?" },
{ RADIUS_CODE_PASSCHG_ACCEPT, "Pchg+" },
{ RADIUS_CODE_PASSCHG_REJECT, "Pchg-" },
{ RADIUS_CODE_ACCOUNT_MESSAGE, "ActMg" },
{ RADIUS_CODE_ACCESS_CHALLENGE, "Axs!" },
{ -1, NULL }
};
/* --------------------------------------------------------------- */
#define MAX_VALUES 20
struct radius_atable {
int code;
int encoding;
char *name;
char *values[MAX_VALUES];
};
/* map attributes to strings */
/* the right way to do this is probably to read these values out
* of the actual RADIUS dictionary; this would require the machine
* running tcpdump to have that file installed, and it's not my
* program, so I'm not going to introduce new dependencies. Oh well.
*/
static struct radius_atable radius_atts[] = {
{ RADIUS_ATT_USER_NAME, RD_STRING, "Name", { NULL } },
{ RADIUS_ATT_PASSWORD, RD_HEX, "Pass", { NULL } },
{ RADIUS_ATT_CHAP_PASS, RD_HEX, "CPass", { NULL } },
{ RADIUS_ATT_NAS_IP, RD_ADDRESS, "NAS-IP", { NULL } },
{ RADIUS_ATT_NAS_PORT, RD_INT, "NAS-Pt", { NULL } },
{ RADIUS_ATT_USER_SERVICE, RD_INT, "USvc",
{ "", "Login", "Framed", "DB-Lgn", "DB-Frm", "Out", "Shell", NULL } },
{ RADIUS_ATT_PROTOCOL, RD_INT, "FProt",
{ "", "PPP", "SLIP", NULL } },
{ RADIUS_ATT_FRAMED_ADDRESS, RD_ADDRESS, "F-IP", { NULL } },
{ RADIUS_ATT_NETMASK, RD_ADDRESS, "F-Msk", { NULL } },
{ RADIUS_ATT_ROUTING, RD_INT, "F-Rtg", { NULL } },
{ RADIUS_ATT_FILTER, RD_STRING, "FltID", { NULL } },
{ RADIUS_ATT_MTU, RD_INT, "F-MTU", { NULL } },
{ RADIUS_ATT_COMPRESSION, RD_INT, "F-Comp", { NULL } },
{ RADIUS_ATT_LOGIN_HOST, RD_ADDRESS, "L-Hst", { NULL } },
{ RADIUS_ATT_LOGIN_SERVICE, RD_INT, "L-Svc",
{ "", "Telnt", "Rlog", "Clear", "PortM", NULL } },
{ RADIUS_ATT_LOGIN_TCP_PORT, RD_INT, "L-Pt", { NULL } },
{ RADIUS_ATT_OLD_PASSWORD, RD_HEX, "OPass", { NULL } },
{ RADIUS_ATT_PORT_MESSAGE, RD_STRING, "PMsg", { NULL } },
{ RADIUS_ATT_DIALBACK_NO, RD_STRING, "DB#", { NULL } },
{ RADIUS_ATT_DIALBACK_NAME, RD_STRING, "DBNm", { NULL } },
{ RADIUS_ATT_EXPIRATION, RD_DATE, "PExp", { NULL } },
{ RADIUS_ATT_FRAMED_ROUTE, RD_STRING, "F-Rt", { NULL } },
{ RADIUS_ATT_FRAMED_IPX, RD_ADDRESS, "F-IPX", { NULL } },
{ RADIUS_ATT_CHALLENGE_STATE, RD_STRING, "CState", { NULL } },
{ RADIUS_ATT_CLASS, RD_STRING, "Class", { NULL } },
{ RADIUS_ATT_VENDOR_SPECIFIC, RD_HEX, "Vendor", { NULL } },
{ RADIUS_ATT_SESSION_TIMEOUT, RD_INT, "S-TO", { NULL } },
{ RADIUS_ATT_IDLE_TIMEOUT, RD_INT, "I-TO", { NULL } },
{ RADIUS_ATT_TERMINATE_ACTION, RD_INT, "TermAct", { NULL } },
{ RADIUS_ATT_CALLED_ID, RD_STRING, "Callee", { NULL } },
{ RADIUS_ATT_CALLER_ID, RD_STRING, "Caller", { NULL } },
{ RADIUS_ATT_STATUS_TYPE, RD_INT, "Stat",
{ "", "Start", "Stop", NULL } },
{ -1, -1, NULL, { NULL } }
};
typedef void (*aselector)(int code, int len, const u_char *data);
aselector atselector[] = {
r_print_hex,
r_print_int,
r_print_int,
r_print_address,
r_print_string,
r_print_hex
};
static void r_print_att(int code, int len, const u_char *data) {
struct radius_atable *atp;
int i;
for(atp = radius_atts; atp->code != -1; atp++)
if(atp->code == code)
break;
if(atp->code == -1) {
if(vflag > 1) {
fprintf(stdout, " %d =", code);
atselector[RD_HEX](code, len, data);
} else
fprintf(stdout, " %d", code);
return;
}
fprintf(stdout, " %s =", atp->name);
if(atp->encoding == RD_INT && *atp->values) {
u_int32_t k = ntohl((*(int *)data));
for(i = 0; atp->values[i] != NULL; i++)
/* SHOOT ME */ ;
if(k < i) {
fprintf(stdout, " %s",
atp->values[k]);
return;
}
}
atselector[atp->encoding](code, len, data);
}
static void r_print_int(int code, int len, const u_char *data) {
if(len < 4) {
fputs(" ?", stdout);
return;
}
fprintf(stdout, " %d", ntohl((*(int *)data)));
}
static void r_print_address(int code, int len, const u_char *data) {
if(len < 4) {
fputs(" ?", stdout);
return;
}
fprintf(stdout, " %s", inet_ntoa((*(struct in_addr *)data)));
}
static void r_print_string(int code, int len, const u_char *data) {
char string[128];
if(!len) {
fputs(" ?", stdout);
return;
}
if(len > 127)
len = 127;
memset(string, 0, 128);
memcpy(string, data, len);
fprintf(stdout, " %s", string);
}
static void r_print_hex(int code, int len, const u_char *data) {
int i;
/* excuse me */
fputs(" [", stdout);
for(i = 0; i < len; i++)
fprintf(stdout, "%x", data[i]);
fputc(']', stdout);
}
void radius_print(register const u_char *data, u_int len) {
const struct radius_header *rhp;
const u_char *pp;
int first, l, ac, al;
if(len < sizeof(struct radius_header)) {
fputs(" [|radius]", stdout);
return;
}
rhp = (struct radius_header *) data;
if(rhp->code > DEFINED_OPCODES ||
rhp->code < 1)
fprintf(stdout, " Code:%d id:%x [%d]",
rhp->code, rhp->id, ntohs(rhp->len));
else
fprintf(stdout, " %s id:%x [%d]",
radius_codes[rhp->code].name,
rhp->id, ntohs(rhp->len));
if(ntohs(rhp->len) > len) {
fputs(" [|radius]", stdout);
return;
}
l = len - RADFIXEDSZ;
if(!l)
return;
else
pp = data + RADFIXEDSZ;
first = 1;
while(l) {
if(!first)
fputc(',', stdout);
else
first = 0;
ac = *pp++;
al = *pp++;
if(al > l || al < 2) {
fputs(" [|radius]", stdout);
return;
}
al -= 2;
r_print_att(ac, al, pp);
pp += al; l -= al + 2;
}
}