Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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