GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-radius.c Lines: 0 69 0.0 %
Date: 2017-11-07 Branches: 0 44 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-radius.c,v 1.11 2015/11/16 00:16:39 mmcc Exp $	*/
2
3
/*
4
 * Copyright (c) 1997 Thomas H. Ptacek. All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 *
28
 */
29
30
#include <sys/types.h>
31
#include <netinet/in.h>
32
#include <arpa/inet.h>
33
34
#include <stdio.h>
35
#include <string.h>
36
37
/* RADIUS support for tcpdump, Thomas Ptacek <tqbf@enteract.com> */
38
39
#include "interface.h"
40
#include "radius.h"
41
42
static void r_print_att(int code, int len, const u_char *val);
43
static void r_print_int(int code, int len, const u_char *val);
44
static void r_print_address(int code, int len, const u_char *val);
45
static void r_print_string(int code, int len, const u_char *val);
46
static void r_print_hex(int code, int len, const u_char *val);
47
48
/* --------------------------------------------------------------- */
49
50
struct radius_ctable {
51
	int code;
52
	char *name;
53
};
54
55
/* map opcodes to strings */
56
57
#define DEFINED_OPCODES		11
58
59
static struct radius_ctable radius_codes[] = {
60
	{ -1, 					NULL	},
61
	{ RADIUS_CODE_ACCESS_REQUEST,		"Axs?"	},
62
	{ RADIUS_CODE_ACCESS_ACCEPT,		"Axs+"	},
63
	{ RADIUS_CODE_ACCESS_REJECT,		"Axs-"	},
64
	{ RADIUS_CODE_ACCOUNT_REQUEST,		"Act?"	},
65
	{ RADIUS_CODE_ACCOUNT_RESPONSE,		"Act+"	},
66
	{ RADIUS_CODE_ACCOUNT_STATUS,		"ActSt"	},
67
	{ RADIUS_CODE_PASSCHG_REQUEST,		"Pchg?"	},
68
	{ RADIUS_CODE_PASSCHG_ACCEPT,		"Pchg+"	},
69
	{ RADIUS_CODE_PASSCHG_REJECT,		"Pchg-"	},
70
	{ RADIUS_CODE_ACCOUNT_MESSAGE,		"ActMg"	},
71
	{ RADIUS_CODE_ACCESS_CHALLENGE,		"Axs!"	},
72
	{ -1,					NULL	}
73
};
74
75
/* --------------------------------------------------------------- */
76
77
#define MAX_VALUES 20
78
79
struct radius_atable {
80
	int code;
81
	int encoding;
82
	char *name;
83
	char *values[MAX_VALUES];
84
};
85
86
/* map attributes to strings */
87
88
/* the right way to do this is probably to read these values out
89
 * of the actual RADIUS dictionary; this would require the machine
90
 * running tcpdump to have that file installed, and it's not my
91
 * program, so I'm not going to introduce new dependencies. Oh well.
92
 */
93
94
static struct radius_atable radius_atts[] = {
95
96
{ RADIUS_ATT_USER_NAME, 	RD_STRING, 	"Name", 	{ NULL } },
97
{ RADIUS_ATT_PASSWORD, 		RD_HEX, 	"Pass", 	{ NULL } },
98
{ RADIUS_ATT_CHAP_PASS, 	RD_HEX, 	"CPass",	{ NULL } },
99
{ RADIUS_ATT_NAS_IP, 		RD_ADDRESS, 	"NAS-IP", 	{ NULL } },
100
{ RADIUS_ATT_NAS_PORT, 		RD_INT, 	"NAS-Pt", 	{ NULL } },
101
102
{ RADIUS_ATT_USER_SERVICE, 	RD_INT, 	"USvc",
103
{ "", "Login", "Framed", "DB-Lgn", "DB-Frm", "Out", "Shell", NULL } },
104
105
{ RADIUS_ATT_PROTOCOL, 		RD_INT, 	"FProt",
106
{ "", "PPP", "SLIP", NULL } },
107
108
{ RADIUS_ATT_FRAMED_ADDRESS, 	RD_ADDRESS, 	"F-IP", 	{ NULL } },
109
{ RADIUS_ATT_NETMASK, 		RD_ADDRESS, 	"F-Msk", 	{ NULL } },
110
{ RADIUS_ATT_ROUTING, 		RD_INT, 	"F-Rtg", 	{ NULL } },
111
{ RADIUS_ATT_FILTER, 		RD_STRING, 	"FltID", 	{ NULL } },
112
{ RADIUS_ATT_MTU, 		RD_INT, 	"F-MTU", 	{ NULL } },
113
{ RADIUS_ATT_COMPRESSION, 	RD_INT, 	"F-Comp", 	{ NULL } },
114
{ RADIUS_ATT_LOGIN_HOST, 	RD_ADDRESS, 	"L-Hst", 	{ NULL } },
115
116
{ RADIUS_ATT_LOGIN_SERVICE, 	RD_INT, 	"L-Svc",
117
{ "", "Telnt", "Rlog", "Clear", "PortM", NULL }				},
118
119
{ RADIUS_ATT_LOGIN_TCP_PORT, 	RD_INT, 	"L-Pt", 	{ NULL } },
120
{ RADIUS_ATT_OLD_PASSWORD, 	RD_HEX, 	"OPass", 	{ NULL } },
121
{ RADIUS_ATT_PORT_MESSAGE, 	RD_STRING, 	"PMsg", 	{ NULL } },
122
{ RADIUS_ATT_DIALBACK_NO, 	RD_STRING, 	"DB#", 		{ NULL } },
123
{ RADIUS_ATT_DIALBACK_NAME, 	RD_STRING, 	"DBNm", 	{ NULL } },
124
{ RADIUS_ATT_EXPIRATION, 	RD_DATE, 	"PExp", 	{ NULL } },
125
{ RADIUS_ATT_FRAMED_ROUTE, 	RD_STRING, 	"F-Rt", 	{ NULL } },
126
{ RADIUS_ATT_FRAMED_IPX, 	RD_ADDRESS, 	"F-IPX", 	{ NULL } },
127
{ RADIUS_ATT_CHALLENGE_STATE, 	RD_STRING, 	"CState", 	{ NULL } },
128
{ RADIUS_ATT_CLASS, 		RD_STRING, 	"Class", 	{ NULL } },
129
{ RADIUS_ATT_VENDOR_SPECIFIC, 	RD_HEX, 	"Vendor", 	{ NULL } },
130
{ RADIUS_ATT_SESSION_TIMEOUT, 	RD_INT, 	"S-TO", 	{ NULL } },
131
{ RADIUS_ATT_IDLE_TIMEOUT, 	RD_INT, 	"I-TO", 	{ NULL } },
132
{ RADIUS_ATT_TERMINATE_ACTION, 	RD_INT, 	"TermAct", 	{ NULL } },
133
{ RADIUS_ATT_CALLED_ID, 	RD_STRING, 	"Callee", 	{ NULL } },
134
{ RADIUS_ATT_CALLER_ID, 	RD_STRING, 	"Caller", 	{ NULL } },
135
136
{ RADIUS_ATT_STATUS_TYPE, 	RD_INT, 	"Stat",
137
{ "", "Start", "Stop", NULL }					},
138
139
{ -1,				-1,		NULL, 		{ NULL } }
140
141
};
142
143
typedef void (*aselector)(int code, int len, const u_char *data);
144
aselector atselector[] = {
145
	r_print_hex,
146
	r_print_int,
147
	r_print_int,
148
	r_print_address,
149
	r_print_string,
150
	r_print_hex
151
};
152
153
static void r_print_att(int code, int len, const u_char *data) {
154
	struct radius_atable *atp;
155
	int i;
156
157
	for(atp = radius_atts; atp->code != -1; atp++)
158
		if(atp->code == code)
159
			break;
160
161
	if(atp->code == -1) {
162
		if(vflag > 1) {
163
			fprintf(stdout, " %d =", code);
164
			atselector[RD_HEX](code, len, data);
165
		} else
166
			fprintf(stdout, " %d", code);
167
168
		return;
169
	}
170
171
	fprintf(stdout, " %s =", atp->name);
172
173
	if(atp->encoding == RD_INT && *atp->values) {
174
		u_int32_t k = ntohl((*(int *)data));
175
176
		for(i = 0; atp->values[i] != NULL; i++)
177
			/* SHOOT ME */ ;
178
179
		if(k < i) {
180
			fprintf(stdout, " %s",
181
				atp->values[k]);
182
			return;
183
		}
184
	}
185
186
	atselector[atp->encoding](code, len, data);
187
}
188
189
static void r_print_int(int code, int len, const u_char *data) {
190
	if(len < 4) {
191
		fputs(" ?", stdout);
192
		return;
193
	}
194
195
	fprintf(stdout, " %d", ntohl((*(int *)data)));
196
}
197
198
static void r_print_address(int code, int len, const u_char *data) {
199
	if(len < 4) {
200
		fputs(" ?", stdout);
201
		return;
202
	}
203
204
	fprintf(stdout, " %s", inet_ntoa((*(struct in_addr *)data)));
205
}
206
207
static void r_print_string(int code, int len, const u_char *data) {
208
	char string[128];
209
210
	if(!len) {
211
		fputs(" ?", stdout);
212
		return;
213
	}
214
215
	if(len > 127)
216
		len = 127;
217
218
	memset(string, 0, 128);
219
	memcpy(string, data, len);
220
221
	fprintf(stdout, " ");
222
	safeputs(string);
223
}
224
225
static void r_print_hex(int code, int len, const u_char *data) {
226
	int i;
227
228
	/* excuse me */
229
230
	fputs(" [", stdout);
231
232
	for(i = 0; i < len; i++)
233
		fprintf(stdout, "%02x", data[i]);
234
235
	fputc(']', stdout);
236
}
237
238
void radius_print(const u_char *data, u_int len) {
239
	const struct radius_header *rhp;
240
	const u_char *pp;
241
	int first, l, ac, al;
242
243
	if(len < sizeof(struct radius_header)) {
244
		fputs(" [|radius]", stdout);
245
		return;
246
	}
247
248
	rhp = (struct radius_header *) data;
249
250
	if(rhp->code > DEFINED_OPCODES ||
251
	   rhp->code < 1)
252
		fprintf(stdout, " Code:%d id:%x [%d]",
253
		rhp->code, rhp->id, ntohs(rhp->len));
254
	else
255
		fprintf(stdout, " %s id:%x [%d]",
256
			radius_codes[rhp->code].name,
257
			rhp->id, ntohs(rhp->len));
258
259
	if(ntohs(rhp->len) > len) {
260
		fputs(" [|radius]", stdout);
261
		return;
262
	}
263
264
	l = len - RADFIXEDSZ;
265
	if(!l)
266
		return;
267
	else
268
		pp = data + RADFIXEDSZ;
269
270
	first = 1;
271
	while(l) {
272
		if(!first)
273
			fputc(',', stdout);
274
		else
275
			first = 0;
276
277
		ac = *pp++;
278
		al = *pp++;
279
280
		if(al > l || al < 2) {
281
			fputs(" [|radius]", stdout);
282
			return;
283
		}
284
285
		al -= 2;
286
287
		r_print_att(ac, al, pp);
288
289
		pp += al; l -= al + 2;
290
	}
291
}