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