xref: /plan9/sys/src/cmd/ip/snoopy/eap.c (revision ed397113cdcf7aafea372b730bbcd17b05ee3f60)
1*ed397113SDavid du Colombier #include <u.h>
2*ed397113SDavid du Colombier #include <libc.h>
3*ed397113SDavid du Colombier #include <ip.h>
4*ed397113SDavid du Colombier #include "dat.h"
5*ed397113SDavid du Colombier #include "protos.h"
6*ed397113SDavid du Colombier 
7*ed397113SDavid du Colombier typedef struct Hdr	Hdr;
8*ed397113SDavid du Colombier struct Hdr
9*ed397113SDavid du Colombier {
10*ed397113SDavid du Colombier 	uchar	code;
11*ed397113SDavid du Colombier 	uchar	id;
12*ed397113SDavid du Colombier 	uchar	len[2];	/* length including this header */
13*ed397113SDavid du Colombier 
14*ed397113SDavid du Colombier 	uchar	tp;	/* optional, only for Request/Response */
15*ed397113SDavid du Colombier };
16*ed397113SDavid du Colombier 
17*ed397113SDavid du Colombier enum
18*ed397113SDavid du Colombier {
19*ed397113SDavid du Colombier 	EAPHDR=	4,	/* sizeof(code)+sizeof(id)+sizeof(len) */
20*ed397113SDavid du Colombier 	TPHDR= 1,	/* sizeof(tp) */
21*ed397113SDavid du Colombier 
22*ed397113SDavid du Colombier 	/* eap types */
23*ed397113SDavid du Colombier 	Request = 1,
24*ed397113SDavid du Colombier 	Response,
25*ed397113SDavid du Colombier 	Success,
26*ed397113SDavid du Colombier 	Fail,
27*ed397113SDavid du Colombier 
28*ed397113SDavid du Colombier 	/* eap request/response sub-types */
29*ed397113SDavid du Colombier 	Identity = 1,		/* Identity */
30*ed397113SDavid du Colombier 	Notify,		/* Notification */
31*ed397113SDavid du Colombier 	Nak,			/* Nak (Response only) */
32*ed397113SDavid du Colombier 	Md5,		/* MD5-challenge */
33*ed397113SDavid du Colombier 	Otp,			/* one time password */
34*ed397113SDavid du Colombier 	Gtc,			/* generic token card */
35*ed397113SDavid du Colombier 	Ttls = 21,		/* tunneled TLS */
36*ed397113SDavid du Colombier 	Xpnd = 254,	/* expanded types */
37*ed397113SDavid du Colombier 	Xprm,		/* experimental use */
38*ed397113SDavid du Colombier };
39*ed397113SDavid du Colombier 
40*ed397113SDavid du Colombier enum
41*ed397113SDavid du Colombier {
42*ed397113SDavid du Colombier 	Ot,
43*ed397113SDavid du Colombier };
44*ed397113SDavid du Colombier 
45*ed397113SDavid du Colombier static Mux p_mux[] =
46*ed397113SDavid du Colombier {
47*ed397113SDavid du Colombier 	{ "eap_identity", Identity, },
48*ed397113SDavid du Colombier 	{ "eap_notify", Notify, },
49*ed397113SDavid du Colombier 	{ "eap_nak", Nak, },
50*ed397113SDavid du Colombier 	{ "eap_md5", Md5, },
51*ed397113SDavid du Colombier 	{ "eap_otp", Otp, },
52*ed397113SDavid du Colombier 	{ "eap_gtc", Gtc, },
53*ed397113SDavid du Colombier 	{ "ttls", Ttls, },
54*ed397113SDavid du Colombier 	{ "eap_xpnd", Xpnd, },
55*ed397113SDavid du Colombier 	{ "eap_xprm", Xprm, },
56*ed397113SDavid du Colombier 	{ 0 }
57*ed397113SDavid du Colombier };
58*ed397113SDavid du Colombier 
59*ed397113SDavid du Colombier static char *eapsubtype[256] =
60*ed397113SDavid du Colombier {
61*ed397113SDavid du Colombier [Identity]	"Identity",
62*ed397113SDavid du Colombier [Notify]	"Notify",
63*ed397113SDavid du Colombier [Nak]		"Nak",
64*ed397113SDavid du Colombier [Md5]	"Md5",
65*ed397113SDavid du Colombier [Otp]		"Otp",
66*ed397113SDavid du Colombier [Gtc]		"Gtc",
67*ed397113SDavid du Colombier [Ttls]		"Ttls",
68*ed397113SDavid du Colombier [Xpnd]	"Xpnd",
69*ed397113SDavid du Colombier [Xprm]	"Xprm",
70*ed397113SDavid du Colombier };
71*ed397113SDavid du Colombier 
72*ed397113SDavid du Colombier 
73*ed397113SDavid du Colombier static void
p_compile(Filter * f)74*ed397113SDavid du Colombier p_compile(Filter *f)
75*ed397113SDavid du Colombier {
76*ed397113SDavid du Colombier 	Mux *m;
77*ed397113SDavid du Colombier 
78*ed397113SDavid du Colombier 	for(m = p_mux; m->name != nil; m++)
79*ed397113SDavid du Colombier 		if(strcmp(f->s, m->name) == 0){
80*ed397113SDavid du Colombier 			f->pr = m->pr;
81*ed397113SDavid du Colombier 			f->ulv = m->val;
82*ed397113SDavid du Colombier 			f->subop = Ot;
83*ed397113SDavid du Colombier 			return;
84*ed397113SDavid du Colombier 		}
85*ed397113SDavid du Colombier 	sysfatal("unknown eap field or type: %s", f->s);
86*ed397113SDavid du Colombier }
87*ed397113SDavid du Colombier 
88*ed397113SDavid du Colombier static int
p_filter(Filter * f,Msg * m)89*ed397113SDavid du Colombier p_filter(Filter *f, Msg *m)
90*ed397113SDavid du Colombier {
91*ed397113SDavid du Colombier 	Hdr *h;
92*ed397113SDavid du Colombier 	int len;
93*ed397113SDavid du Colombier 
94*ed397113SDavid du Colombier 	if(f->subop != Ot)
95*ed397113SDavid du Colombier 		return 0;
96*ed397113SDavid du Colombier 
97*ed397113SDavid du Colombier 	if(m->pe - m->ps < EAPHDR)
98*ed397113SDavid du Colombier 		return -1;
99*ed397113SDavid du Colombier 
100*ed397113SDavid du Colombier 	h = (Hdr*)m->ps;
101*ed397113SDavid du Colombier 
102*ed397113SDavid du Colombier 	/* truncate the message if there's extra */
103*ed397113SDavid du Colombier 	/* len includes header */
104*ed397113SDavid du Colombier 	len = NetS(h->len);
105*ed397113SDavid du Colombier 	if(m->ps+len < m->pe)
106*ed397113SDavid du Colombier 		m->pe = m->ps+len;
107*ed397113SDavid du Colombier 	else if(m->ps+len > m->pe)
108*ed397113SDavid du Colombier 		return -1;
109*ed397113SDavid du Colombier 	m->ps += EAPHDR;
110*ed397113SDavid du Colombier 
111*ed397113SDavid du Colombier 	if(h->code != Request && h->code != Response)
112*ed397113SDavid du Colombier 		return 0;
113*ed397113SDavid du Colombier 	m->ps += TPHDR;
114*ed397113SDavid du Colombier 
115*ed397113SDavid du Colombier 	if(h->tp == f->ulv)
116*ed397113SDavid du Colombier 		return 1;
117*ed397113SDavid du Colombier 
118*ed397113SDavid du Colombier 	return 0;
119*ed397113SDavid du Colombier }
120*ed397113SDavid du Colombier 
121*ed397113SDavid du Colombier static char*
op(int i)122*ed397113SDavid du Colombier op(int i)
123*ed397113SDavid du Colombier {
124*ed397113SDavid du Colombier 	static char x[20];
125*ed397113SDavid du Colombier 
126*ed397113SDavid du Colombier 	switch(i){
127*ed397113SDavid du Colombier 	case Request:
128*ed397113SDavid du Colombier 		return "Request";
129*ed397113SDavid du Colombier 	case Response:
130*ed397113SDavid du Colombier 		return "Response";
131*ed397113SDavid du Colombier 	case Success:
132*ed397113SDavid du Colombier 		return "Success";
133*ed397113SDavid du Colombier 	case Fail:
134*ed397113SDavid du Colombier 		return "Fail";
135*ed397113SDavid du Colombier 	default:
136*ed397113SDavid du Colombier 		sprint(x, "%1d", i);
137*ed397113SDavid du Colombier 		return x;
138*ed397113SDavid du Colombier 	}
139*ed397113SDavid du Colombier }
140*ed397113SDavid du Colombier 
141*ed397113SDavid du Colombier static char*
subop(uchar val)142*ed397113SDavid du Colombier subop(uchar val)
143*ed397113SDavid du Colombier {
144*ed397113SDavid du Colombier 	static char x[20], *p;
145*ed397113SDavid du Colombier 
146*ed397113SDavid du Colombier 	p = eapsubtype[val];
147*ed397113SDavid du Colombier 	if(p != nil)
148*ed397113SDavid du Colombier 		return p;
149*ed397113SDavid du Colombier 	else {
150*ed397113SDavid du Colombier 		sprint(x, "%1d", val);
151*ed397113SDavid du Colombier 		return x;
152*ed397113SDavid du Colombier 	}
153*ed397113SDavid du Colombier }
154*ed397113SDavid du Colombier 
155*ed397113SDavid du Colombier static int
p_seprint(Msg * m)156*ed397113SDavid du Colombier p_seprint(Msg *m)
157*ed397113SDavid du Colombier {
158*ed397113SDavid du Colombier 	Hdr *h;
159*ed397113SDavid du Colombier 	int len;
160*ed397113SDavid du Colombier 	char *p, *e;
161*ed397113SDavid du Colombier 
162*ed397113SDavid du Colombier 	if(m->pe - m->ps < EAPHDR)
163*ed397113SDavid du Colombier 		return -1;
164*ed397113SDavid du Colombier 
165*ed397113SDavid du Colombier 	p = m->p;
166*ed397113SDavid du Colombier 	e = m->e;
167*ed397113SDavid du Colombier 	h = (Hdr*)m->ps;
168*ed397113SDavid du Colombier 
169*ed397113SDavid du Colombier 	/* resize packet (should already be done by eapol) */
170*ed397113SDavid du Colombier 	/* len includes header */
171*ed397113SDavid du Colombier 	len = NetS(h->len);
172*ed397113SDavid du Colombier 	if(m->ps+len < m->pe)
173*ed397113SDavid du Colombier 		m->pe = m->ps+len;
174*ed397113SDavid du Colombier 	else if(m->ps+len > m->pe)
175*ed397113SDavid du Colombier 		return -1;
176*ed397113SDavid du Colombier 	m->ps += EAPHDR;
177*ed397113SDavid du Colombier 
178*ed397113SDavid du Colombier 	p = seprint(p, e, "id=%1d code=%s", h->id, op(h->code));
179*ed397113SDavid du Colombier 	switch(h->code) {
180*ed397113SDavid du Colombier 	case Request:
181*ed397113SDavid du Colombier 	case Response:
182*ed397113SDavid du Colombier 		m->ps += TPHDR;
183*ed397113SDavid du Colombier 		p = seprint(p, e, " type=%s", subop(h->tp));
184*ed397113SDavid du Colombier 		/* special case needed to print eap_notify notification as unicode */
185*ed397113SDavid du Colombier 		demux(p_mux, h->tp, h->tp, m, &dump);
186*ed397113SDavid du Colombier 		break;
187*ed397113SDavid du Colombier 	default:
188*ed397113SDavid du Colombier 		demux(p_mux, 0, 0, m, &dump);
189*ed397113SDavid du Colombier 		break;
190*ed397113SDavid du Colombier 	}
191*ed397113SDavid du Colombier 	m->p = seprint(p, e, " len=%1d", len);
192*ed397113SDavid du Colombier 	return 0;
193*ed397113SDavid du Colombier }
194*ed397113SDavid du Colombier 
195*ed397113SDavid du Colombier static int
p_seprintidentity(Msg * m)196*ed397113SDavid du Colombier p_seprintidentity(Msg *m)
197*ed397113SDavid du Colombier {
198*ed397113SDavid du Colombier 	char *ps, *pe, *z;
199*ed397113SDavid du Colombier 	int len;
200*ed397113SDavid du Colombier 
201*ed397113SDavid du Colombier 	m->pr = nil;
202*ed397113SDavid du Colombier 	ps = (char*)m->ps;
203*ed397113SDavid du Colombier 	pe = (char*)m->pe;
204*ed397113SDavid du Colombier 
205*ed397113SDavid du Colombier 	/* we would like to do this depending on the 'context':
206*ed397113SDavid du Colombier 	 *  - one for eap_identity request and
207*ed397113SDavid du Colombier 	 *  - one for eap_identity response
208*ed397113SDavid du Colombier 	 * but we've lost the context, or haven't we?
209*ed397113SDavid du Colombier 	 * so we treat them the same, so we might erroneously
210*ed397113SDavid du Colombier 	 * print a response as if it was a request. too bad. - axel
211*ed397113SDavid du Colombier 	 */
212*ed397113SDavid du Colombier 	for (z=ps; *z != '\0' && z+1 < pe; z++)
213*ed397113SDavid du Colombier 		;
214*ed397113SDavid du Colombier 	if (*z == '\0' && z+1 < pe) {
215*ed397113SDavid du Colombier 		m->p = seprint(m->p, m->e, "prompt=(%s)", ps);
216*ed397113SDavid du Colombier 		len = pe - (z+1);
217*ed397113SDavid du Colombier 		m->p = seprint(m->p, m->e, " options=(%.*s)", len, z+1);
218*ed397113SDavid du Colombier 	} else {
219*ed397113SDavid du Colombier 		len = pe - ps;
220*ed397113SDavid du Colombier 		m->p = seprint(m->p, m->e, "%.*s", len, ps);
221*ed397113SDavid du Colombier 	}
222*ed397113SDavid du Colombier 	return 0;
223*ed397113SDavid du Colombier }
224*ed397113SDavid du Colombier 
225*ed397113SDavid du Colombier Proto eap =
226*ed397113SDavid du Colombier {
227*ed397113SDavid du Colombier 	"eap",
228*ed397113SDavid du Colombier 	p_compile,
229*ed397113SDavid du Colombier 	p_filter,
230*ed397113SDavid du Colombier 	p_seprint,
231*ed397113SDavid du Colombier 	p_mux,
232*ed397113SDavid du Colombier 	"%lud",
233*ed397113SDavid du Colombier 	nil,
234*ed397113SDavid du Colombier 	defaultframer,
235*ed397113SDavid du Colombier };
236*ed397113SDavid du Colombier 
237*ed397113SDavid du Colombier Proto eap_identity =
238*ed397113SDavid du Colombier {
239*ed397113SDavid du Colombier 	"eap_identity",
240*ed397113SDavid du Colombier 	p_compile,
241*ed397113SDavid du Colombier 	p_filter,
242*ed397113SDavid du Colombier 	p_seprintidentity,
243*ed397113SDavid du Colombier 	nil,
244*ed397113SDavid du Colombier 	nil,
245*ed397113SDavid du Colombier 	nil,
246*ed397113SDavid du Colombier 	defaultframer,
247*ed397113SDavid du Colombier };
248