]>
Commit | Line | Data |
---|---|---|
0bc5d371 MT |
1 | diff -Naur ppp-2.4.5/README.eap-tls ppp-2.4.5-eaptls-mppe-0.99/README.eap-tls |
2 | --- ppp-2.4.5/README.eap-tls 1970-01-01 01:00:00.000000000 +0100 | |
3 | +++ ppp-2.4.5-eaptls-mppe-0.99/README.eap-tls 2010-10-01 15:17:54.205272328 +0200 | |
4 | @@ -0,0 +1,169 @@ | |
5 | +EAP-TLS authentication support for PPP | |
6 | +====================================== | |
7 | + | |
8 | +1. Intro | |
9 | + | |
10 | + The Extensible Authentication Protocol (EAP; RFC 3748) is a | |
11 | + security protocol that can be used with PPP. It provides a means | |
12 | + to plug in multiple optional authentication methods. | |
13 | + | |
14 | + Transport Level Security (TLS; RFC 2246) provides for mutual | |
15 | + authentication, integrity-protected ciphersuite negotiation and | |
16 | + key exchange between two endpoints. It also provides for optional | |
17 | + MPPE encryption. | |
18 | + | |
19 | + EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets, | |
20 | + allowing TLS mutual authentication to be used as a generic EAP | |
21 | + mechanism. It also provides optional encryption using the MPPE | |
22 | + protocol. | |
23 | + | |
24 | + This patch provide EAP-TLS support to pppd. | |
25 | + This authentication method can be used in both client or server | |
26 | + mode. | |
27 | + | |
28 | +2. Building | |
29 | + | |
30 | + To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org) | |
31 | + is required. Any version from 0.9.7 should work. | |
32 | + | |
33 | + Configure, compile, and install as usual. | |
34 | + | |
35 | +3. Configuration | |
36 | + | |
37 | + On the client side there are two ways to configure EAP-TLS: | |
38 | + | |
39 | + 1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters | |
40 | + | |
41 | + 2. edit the /etc/ppp/eaptls-client file. | |
42 | + Insert a line for each system with which you use EAP-TLS. | |
43 | + The line is composed of this fields separated by tab: | |
44 | + | |
45 | + - Client name | |
46 | + The name used by the client for authentication, can be * | |
47 | + - Server name | |
48 | + The name of the server, can be * | |
49 | + - Client certificate file | |
50 | + The file containing the certificate chain for the | |
51 | + client in PEM format | |
52 | + - Server certificate file | |
53 | + If you want to specify the certificate that the | |
54 | + server is allowed to use, put the certificate file name. | |
55 | + Else put a dash '-'. | |
56 | + - CA certificate file | |
57 | + The file containing the trusted CA certificates in PEM | |
58 | + format. | |
59 | + - Client private key file | |
60 | + The file containing the client private key in PEM format. | |
61 | + | |
62 | + | |
63 | + On the server side edit the /etc/ppp/eaptls-server file. | |
64 | + Insert a line for each system with which you use EAP-TLS. | |
65 | + The line is composed of this fields separated by tab: | |
66 | + | |
67 | + - Client name | |
68 | + The name used by the client for authentication, can be * | |
69 | + - Server name | |
70 | + The name of the server, can be * | |
71 | + - Client certificate file | |
72 | + If you want to specify the certificate that the | |
73 | + client is allowed to use, put the certificate file name. | |
74 | + Else put a dash '-'. | |
75 | + - Server certificate file | |
76 | + The file containing the certificate chain for the | |
77 | + server in PEM format | |
78 | + - CA certificate file | |
79 | + The file containing the trusted CA certificates in PEM | |
80 | + format. | |
81 | + - Client private key file | |
82 | + The file containing the server private key in PEM format. | |
83 | + - addresses | |
84 | + A list of IP addresses the client is allowed to use. | |
85 | + | |
86 | + | |
87 | + OpenSSL engine support is included starting with v0.95 of this patch. | |
88 | + Currently the only engine tested is the 'pkcs11' engine (hardware token | |
89 | + support). To use the 'pksc11' engine: | |
90 | + - Use a special private key fileiname in the /etc/ppp/eaptls-client file: | |
91 | + <engine>:<identifier> | |
92 | + e.g. | |
93 | + pkcs11:123456 | |
94 | + | |
95 | + - The certificate can also be loaded from the 'pkcs11' engine using | |
96 | + a special client certificate filename in the /etc/ppp/eaptls-client file: | |
97 | + <engine>:<identifier> | |
98 | + e.g. | |
99 | + pkcs11:123456 | |
100 | + | |
101 | + - Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior | |
102 | + to starting 'pppd'. A sample openssl.cnf file is | |
103 | + | |
104 | + openssl_conf = openssl_def | |
105 | + | |
106 | + [ openssl_def ] | |
107 | + engines = engine_section | |
108 | + | |
109 | + [ engine_section ] | |
110 | + pkcs11 = pkcs11_section | |
111 | + | |
112 | + [ pkcs11_section ] | |
113 | + engine_id = pkcs11 | |
114 | + dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so | |
115 | + MODULE_PATH = /usr/lib64/libeTPkcs11.so | |
116 | + init = 0 | |
117 | + | |
118 | + - There are two ways to specify a password/PIN for the PKCS11 engine: | |
119 | + - inside the openssl.cnf file using | |
120 | + PIN = your-secret-pin | |
121 | + Note The keyword 'PIN' is case sensitive! | |
122 | + - Using the 'password' in the ppp options file. | |
123 | + From v0.97 of the eap-tls patch the password can also be supplied | |
124 | + using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c | |
125 | + for an example). | |
126 | + | |
127 | + | |
128 | +4. Options | |
129 | + | |
130 | + These pppd options are available: | |
131 | + | |
132 | + ca <ca-file> | |
133 | + Use the CA public certificate found in <ca-file> in PEM format | |
134 | + cert <cert-file> | |
135 | + Use the client public certificate found in <cert-file> in PEM format | |
136 | + or in engine:engine_id format | |
137 | + key <key-file> | |
138 | + Use the client private key found in <key-file> in PEM format | |
139 | + or in engine:engine_id format | |
140 | + crl-dir <dir> | |
141 | + Use CRL files from dir. It contains CRL files in PEM | |
142 | + format and each file contains a CRL. The files are looked up | |
143 | + by the issuer name hash value. Use the c_rehash utility | |
144 | + to create necessary links. | |
145 | + need-peer-eap | |
146 | + If the peer doesn't ask us to authenticate or doesn't use eap | |
147 | + to authenticate us, disconnect. | |
148 | + | |
149 | + Note: | |
150 | + password-encrypted certificates can be used as of v0.94 of this | |
151 | + patch. The password for the eap-tls.key file is specified using | |
152 | + the regular | |
153 | + password .... | |
154 | + statement in the ppp options file, or by using the appropriate | |
155 | + plugin which supplies a 'eaptls_passwd_hook' routine. | |
156 | + | |
157 | +5. Connecting | |
158 | + | |
159 | + If you're setting up a pppd server, edit the EAP-TLS configuration file | |
160 | + as written above and then run pppd with the 'auth' option to authenticate | |
161 | + the client. The EAP-TLS method will be used if the other eap methods can't | |
162 | + be used (no secrets). | |
163 | + | |
164 | + If you're setting up a client, edit the configuration file and then run | |
165 | + pppd with 'remotename' option to specify the server name. Add the | |
166 | + 'need-peer-eap' option if you want to be sure the peer ask you to | |
167 | + authenticate (and to use eap) and to disconnect if it doesn't. | |
168 | + | |
169 | +6. Notes | |
170 | + | |
171 | + This is experimental code. | |
172 | + Send suggestions and comments to Jan Just Keijser <janjust@nikhef.nl> | |
173 | + | |
174 | diff -Naur ppp-2.4.5/etc.ppp/eaptls-client ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-client | |
175 | --- ppp-2.4.5/etc.ppp/eaptls-client 1970-01-01 01:00:00.000000000 +0100 | |
176 | +++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-client 2010-10-01 15:17:54.205272328 +0200 | |
177 | @@ -0,0 +1,10 @@ | |
178 | +# Parameters for authentication using EAP-TLS (client) | |
179 | + | |
180 | +# client name (can be *) | |
181 | +# server name (can be *) | |
182 | +# client certificate file (required) | |
183 | +# server certificate file (optional, if unused put '-') | |
184 | +# CA certificate file (required) | |
185 | +# client private key file (required) | |
186 | + | |
187 | +#client server /root/cert/client.crt - /root/cert/ca.crt /root/cert/client.key | |
188 | diff -Naur ppp-2.4.5/etc.ppp/eaptls-server ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-server | |
189 | --- ppp-2.4.5/etc.ppp/eaptls-server 1970-01-01 01:00:00.000000000 +0100 | |
190 | +++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-server 2010-10-01 15:17:54.205272328 +0200 | |
191 | @@ -0,0 +1,11 @@ | |
192 | +# Parameters for authentication using EAP-TLS (server) | |
193 | + | |
194 | +# client name (can be *) | |
195 | +# server name (can be *) | |
196 | +# client certificate file (optional, if unused put '-') | |
197 | +# server certificate file (required) | |
198 | +# CA certificate file (required) | |
199 | +# server private key file (required) | |
200 | +# allowed addresses (required, can be *) | |
201 | + | |
202 | +#client server - /root/cert/server.crt /root/cert/ca.crt /root/cert/server.key 192.168.1.0/24 | |
203 | diff -Naur ppp-2.4.5/etc.ppp/openssl.cnf ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/openssl.cnf | |
204 | --- ppp-2.4.5/etc.ppp/openssl.cnf 1970-01-01 01:00:00.000000000 +0100 | |
205 | +++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/openssl.cnf 2010-10-01 15:17:54.206272162 +0200 | |
206 | @@ -0,0 +1,14 @@ | |
207 | +openssl_conf = openssl_def | |
208 | + | |
209 | +[ openssl_def ] | |
210 | +engines = engine_section | |
211 | + | |
212 | +[ engine_section ] | |
213 | +pkcs11 = pkcs11_section | |
214 | + | |
215 | +[ pkcs11_section ] | |
216 | +engine_id = pkcs11 | |
217 | +dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so | |
218 | +MODULE_PATH = /usr/lib64/libeTPkcs11.so | |
219 | +init = 0 | |
220 | + | |
221 | diff -Naur ppp-2.4.5/linux/Makefile.top ppp-2.4.5-eaptls-mppe-0.99/linux/Makefile.top | |
222 | --- ppp-2.4.5/linux/Makefile.top 2009-11-16 23:26:07.000000000 +0100 | |
223 | +++ ppp-2.4.5-eaptls-mppe-0.99/linux/Makefile.top 2010-10-01 15:17:54.206272162 +0200 | |
224 | @@ -26,7 +26,7 @@ | |
225 | cd pppdump; $(MAKE) $(MFLAGS) install | |
226 | ||
227 | install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ | |
228 | - $(ETCDIR)/chap-secrets | |
229 | + $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client | |
230 | ||
231 | install-devel: | |
232 | cd pppd; $(MAKE) $(MFLAGS) install-devel | |
233 | @@ -37,6 +37,10 @@ | |
234 | $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@ | |
235 | $(ETCDIR)/chap-secrets: | |
236 | $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@ | |
237 | +$(ETCDIR)/eaptls-server: | |
238 | + $(INSTALL) -c -m 600 etc.ppp/eaptls-server $@ | |
239 | +$(ETCDIR)/eaptls-client: | |
240 | + $(INSTALL) -c -m 600 etc.ppp/eaptls-client $@ | |
241 | ||
242 | $(BINDIR): | |
243 | $(INSTALL) -d -m 755 $@ | |
244 | diff -Naur ppp-2.4.5/pppd/Makefile.linux ppp-2.4.5-eaptls-mppe-0.99/pppd/Makefile.linux | |
245 | --- ppp-2.4.5/pppd/Makefile.linux 2009-11-16 23:26:07.000000000 +0100 | |
246 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/Makefile.linux 2010-10-01 15:17:54.207272272 +0200 | |
247 | @@ -73,6 +73,9 @@ | |
248 | # Enable EAP SRP-SHA1 authentication (requires libsrp) | |
249 | #USE_SRP=y | |
250 | ||
251 | +# Enable EAP-TLS authentication (requires libssl and libcurl) | |
252 | +USE_EAPTLS=y | |
253 | + | |
254 | MAXOCTETS=y | |
255 | ||
256 | INCLUDE_DIRS= -I../include | |
257 | @@ -112,6 +115,15 @@ | |
258 | PPPDOBJS += sha1.o | |
259 | endif | |
260 | ||
261 | +# EAP-TLS | |
262 | +ifdef USE_EAPTLS | |
263 | +CFLAGS += -DUSE_EAPTLS=1 -I/usr/kerberos/include | |
264 | +LIBS += -lssl -lcrypto | |
265 | +PPPDSRC += eap-tls.c | |
266 | +HEADERS += eap-tls.h | |
267 | +PPPDOBJS += eap-tls.o | |
268 | +endif | |
269 | + | |
270 | ifdef HAS_SHADOW | |
271 | CFLAGS += -DHAS_SHADOW | |
272 | #LIBS += -lshadow $(LIBS) | |
273 | diff -Naur ppp-2.4.5/pppd/auth.c ppp-2.4.5-eaptls-mppe-0.99/pppd/auth.c | |
274 | --- ppp-2.4.5/pppd/auth.c 2009-11-16 23:26:07.000000000 +0100 | |
275 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/auth.c 2010-10-01 15:17:54.210272021 +0200 | |
276 | @@ -109,6 +109,9 @@ | |
277 | #include "upap.h" | |
278 | #include "chap-new.h" | |
279 | #include "eap.h" | |
280 | +#ifdef USE_EAPTLS | |
281 | +#include "eap-tls.h" | |
282 | +#endif | |
283 | #ifdef CBCP_SUPPORT | |
284 | #include "cbcp.h" | |
285 | #endif | |
286 | @@ -183,6 +186,11 @@ | |
287 | /* Hook for a plugin to get the CHAP password for authenticating us */ | |
288 | int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; | |
289 | ||
290 | +#ifdef USE_EAPTLS | |
291 | +/* Hook for a plugin to get the EAP-TLS password for authenticating us */ | |
292 | +int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL; | |
293 | +#endif | |
294 | + | |
295 | /* Hook for a plugin to say whether it is OK if the peer | |
296 | refuses to authenticate. */ | |
297 | int (*null_auth_hook) __P((struct wordlist **paddrs, | |
298 | @@ -238,6 +246,13 @@ | |
299 | bool explicit_user = 0; /* Set if "user" option supplied */ | |
300 | bool explicit_passwd = 0; /* Set if "password" option supplied */ | |
301 | char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ | |
302 | +#ifdef USE_EAPTLS | |
303 | +char *cacert_file = NULL; /* CA certificate file (pem format) */ | |
304 | +char *cert_file = NULL; /* client certificate file (pem format) */ | |
305 | +char *privkey_file = NULL; /* client private key file (pem format) */ | |
306 | +char *crl_dir = NULL; /* directory containing CRL files */ | |
307 | +bool need_peer_eap = 0; /* Require peer to authenticate us */ | |
308 | +#endif | |
309 | ||
310 | static char *uafname; /* name of most recent +ua file */ | |
311 | ||
312 | @@ -254,6 +269,19 @@ | |
313 | static int have_chap_secret __P((char *, char *, int, int *)); | |
314 | static int have_srp_secret __P((char *client, char *server, int need_ip, | |
315 | int *lacks_ipp)); | |
316 | + | |
317 | +#ifdef USE_EAPTLS | |
318 | +static int have_eaptls_secret_server | |
319 | +__P((char *client, char *server, int need_ip, int *lacks_ipp)); | |
320 | +static int have_eaptls_secret_client __P((char *client, char *server)); | |
321 | +static int scan_authfile_eaptls __P((FILE * f, char *client, char *server, | |
322 | + char *cli_cert, char *serv_cert, | |
323 | + char *ca_cert, char *pk, | |
324 | + struct wordlist ** addrs, | |
325 | + struct wordlist ** opts, | |
326 | + char *filename, int flags)); | |
327 | +#endif | |
328 | + | |
329 | static int ip_addr_check __P((u_int32_t, struct permitted_ip *)); | |
330 | static int scan_authfile __P((FILE *, char *, char *, char *, | |
331 | struct wordlist **, struct wordlist **, | |
332 | @@ -401,6 +429,14 @@ | |
333 | "Set telephone number(s) which are allowed to connect", | |
334 | OPT_PRIV | OPT_A2LIST }, | |
335 | ||
336 | +#ifdef USE_EAPTLS | |
337 | + { "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" }, | |
338 | + { "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" }, | |
339 | + { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" }, | |
340 | + { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" }, | |
341 | + { "need-peer-eap", o_bool, &need_peer_eap, | |
342 | + "Require the peer to authenticate us", 1 }, | |
343 | +#endif /* USE_EAPTLS */ | |
344 | { NULL } | |
345 | }; | |
346 | ||
347 | @@ -731,6 +767,9 @@ | |
348 | lcp_options *wo = &lcp_wantoptions[unit]; | |
349 | lcp_options *go = &lcp_gotoptions[unit]; | |
350 | lcp_options *ho = &lcp_hisoptions[unit]; | |
351 | +#ifdef USE_EAPTLS | |
352 | + lcp_options *ao = &lcp_allowoptions[unit]; | |
353 | +#endif | |
354 | int i; | |
355 | struct protent *protp; | |
356 | ||
357 | @@ -765,6 +804,22 @@ | |
358 | } | |
359 | } | |
360 | ||
361 | +#ifdef USE_EAPTLS | |
362 | + if (need_peer_eap && !ao->neg_eap) { | |
363 | + warn("eap required to authenticate us but no suitable secrets"); | |
364 | + lcp_close(unit, "couldn't negotiate eap"); | |
365 | + status = EXIT_AUTH_TOPEER_FAILED; | |
366 | + return; | |
367 | + } | |
368 | + | |
369 | + if (need_peer_eap && !ho->neg_eap) { | |
370 | + warn("peer doesn't want to authenticate us with eap"); | |
371 | + lcp_close(unit, "couldn't negotiate eap"); | |
372 | + status = EXIT_PEER_AUTH_FAILED; | |
373 | + return; | |
374 | + } | |
375 | +#endif | |
376 | + | |
377 | new_phase(PHASE_AUTHENTICATE); | |
378 | auth = 0; | |
379 | if (go->neg_eap) { | |
380 | @@ -1278,6 +1333,15 @@ | |
381 | our_name, 1, &lacks_ip); | |
382 | } | |
383 | ||
384 | +#ifdef USE_EAPTLS | |
385 | + if (!can_auth && wo->neg_eap) { | |
386 | + can_auth = | |
387 | + have_eaptls_secret_server((explicit_remote ? remote_name : | |
388 | + NULL), our_name, 1, &lacks_ip); | |
389 | + | |
390 | + } | |
391 | +#endif | |
392 | + | |
393 | if (auth_required && !can_auth && noauth_addrs == NULL) { | |
394 | if (default_auth) { | |
395 | option_error( | |
396 | @@ -1332,7 +1396,11 @@ | |
397 | passwd[0] != 0 || | |
398 | (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, | |
399 | (explicit_remote? remote_name: NULL), 0, NULL))) || | |
400 | - have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); | |
401 | + have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL) | |
402 | +#ifdef USE_EAPTLS | |
403 | + || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL))) | |
404 | +#endif | |
405 | + ; | |
406 | ||
407 | hadchap = -1; | |
408 | if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) | |
409 | @@ -1347,8 +1415,14 @@ | |
410 | !have_chap_secret((explicit_remote? remote_name: NULL), our_name, | |
411 | 1, NULL))) && | |
412 | !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, | |
413 | - NULL)) | |
414 | + NULL) | |
415 | +#ifdef USE_EAPTLS | |
416 | + && !have_eaptls_secret_server((explicit_remote? remote_name: NULL), | |
417 | + our_name, 1, NULL) | |
418 | +#endif | |
419 | + ) | |
420 | go->neg_eap = 0; | |
421 | + | |
422 | } | |
423 | ||
424 | ||
425 | @@ -1706,6 +1780,7 @@ | |
426 | } | |
427 | ||
428 | ||
429 | + | |
430 | /* | |
431 | * get_secret - open the CHAP secret file and return the secret | |
432 | * for authenticating the given client on the given server. | |
433 | @@ -2358,3 +2433,335 @@ | |
434 | ||
435 | auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0); | |
436 | } | |
437 | + | |
438 | + | |
439 | +#ifdef USE_EAPTLS | |
440 | +static int | |
441 | +have_eaptls_secret_server(client, server, need_ip, lacks_ipp) | |
442 | + char *client; | |
443 | + char *server; | |
444 | + int need_ip; | |
445 | + int *lacks_ipp; | |
446 | +{ | |
447 | + FILE *f; | |
448 | + int ret; | |
449 | + char *filename; | |
450 | + struct wordlist *addrs; | |
451 | + char servcertfile[MAXWORDLEN]; | |
452 | + char clicertfile[MAXWORDLEN]; | |
453 | + char cacertfile[MAXWORDLEN]; | |
454 | + char pkfile[MAXWORDLEN]; | |
455 | + | |
456 | + filename = _PATH_EAPTLSSERVFILE; | |
457 | + f = fopen(filename, "r"); | |
458 | + if (f == NULL) | |
459 | + return 0; | |
460 | + | |
461 | + if (client != NULL && client[0] == 0) | |
462 | + client = NULL; | |
463 | + else if (server != NULL && server[0] == 0) | |
464 | + server = NULL; | |
465 | + | |
466 | + ret = | |
467 | + scan_authfile_eaptls(f, client, server, clicertfile, servcertfile, | |
468 | + cacertfile, pkfile, &addrs, NULL, filename, | |
469 | + 0); | |
470 | + | |
471 | + fclose(f); | |
472 | + | |
473 | +/* | |
474 | + if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile, | |
475 | + clicertfile, pkfile)) | |
476 | + ret = -1; | |
477 | +*/ | |
478 | + | |
479 | + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { | |
480 | + if (lacks_ipp != 0) | |
481 | + *lacks_ipp = 1; | |
482 | + ret = -1; | |
483 | + } | |
484 | + if (addrs != 0) | |
485 | + free_wordlist(addrs); | |
486 | + | |
487 | + return ret >= 0; | |
488 | +} | |
489 | + | |
490 | + | |
491 | +static int | |
492 | +have_eaptls_secret_client(client, server) | |
493 | + char *client; | |
494 | + char *server; | |
495 | +{ | |
496 | + FILE *f; | |
497 | + int ret; | |
498 | + char *filename; | |
499 | + struct wordlist *addrs = NULL; | |
500 | + char servcertfile[MAXWORDLEN]; | |
501 | + char clicertfile[MAXWORDLEN]; | |
502 | + char cacertfile[MAXWORDLEN]; | |
503 | + char pkfile[MAXWORDLEN]; | |
504 | + | |
505 | + if (client != NULL && client[0] == 0) | |
506 | + client = NULL; | |
507 | + else if (server != NULL && server[0] == 0) | |
508 | + server = NULL; | |
509 | + | |
510 | + if (cacert_file && cert_file && privkey_file) | |
511 | + return 1; | |
512 | + | |
513 | + filename = _PATH_EAPTLSCLIFILE; | |
514 | + f = fopen(filename, "r"); | |
515 | + if (f == NULL) | |
516 | + return 0; | |
517 | + | |
518 | + ret = | |
519 | + scan_authfile_eaptls(f, client, server, clicertfile, servcertfile, | |
520 | + cacertfile, pkfile, &addrs, NULL, filename, | |
521 | + 0); | |
522 | + fclose(f); | |
523 | + | |
524 | +/* | |
525 | + if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile, | |
526 | + servcertfile, pkfile)) | |
527 | + ret = -1; | |
528 | +*/ | |
529 | + | |
530 | + if (addrs != 0) | |
531 | + free_wordlist(addrs); | |
532 | + | |
533 | + return ret >= 0; | |
534 | +} | |
535 | + | |
536 | + | |
537 | +static int | |
538 | +scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk, | |
539 | + addrs, opts, filename, flags) | |
540 | + FILE *f; | |
541 | + char *client; | |
542 | + char *server; | |
543 | + char *cli_cert; | |
544 | + char *serv_cert; | |
545 | + char *ca_cert; | |
546 | + char *pk; | |
547 | + struct wordlist **addrs; | |
548 | + struct wordlist **opts; | |
549 | + char *filename; | |
550 | + int flags; | |
551 | +{ | |
552 | + int newline; | |
553 | + int got_flag, best_flag; | |
554 | + struct wordlist *ap, *addr_list, *alist, **app; | |
555 | + char word[MAXWORDLEN]; | |
556 | + | |
557 | + if (addrs != NULL) | |
558 | + *addrs = NULL; | |
559 | + if (opts != NULL) | |
560 | + *opts = NULL; | |
561 | + addr_list = NULL; | |
562 | + if (!getword(f, word, &newline, filename)) | |
563 | + return -1; /* file is empty??? */ | |
564 | + newline = 1; | |
565 | + best_flag = -1; | |
566 | + for (;;) { | |
567 | + /* | |
568 | + * Skip until we find a word at the start of a line. | |
569 | + */ | |
570 | + while (!newline && getword(f, word, &newline, filename)); | |
571 | + if (!newline) | |
572 | + break; /* got to end of file */ | |
573 | + | |
574 | + /* | |
575 | + * Got a client - check if it's a match or a wildcard. | |
576 | + */ | |
577 | + got_flag = 0; | |
578 | + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { | |
579 | + newline = 0; | |
580 | + continue; | |
581 | + } | |
582 | + if (!ISWILD(word)) | |
583 | + got_flag = NONWILD_CLIENT; | |
584 | + | |
585 | + /* | |
586 | + * Now get a server and check if it matches. | |
587 | + */ | |
588 | + if (!getword(f, word, &newline, filename)) | |
589 | + break; | |
590 | + if (newline) | |
591 | + continue; | |
592 | + if (!ISWILD(word)) { | |
593 | + if (server != NULL && strcmp(word, server) != 0) | |
594 | + continue; | |
595 | + got_flag |= NONWILD_SERVER; | |
596 | + } | |
597 | + | |
598 | + /* | |
599 | + * Got some sort of a match - see if it's better than what | |
600 | + * we have already. | |
601 | + */ | |
602 | + if (got_flag <= best_flag) | |
603 | + continue; | |
604 | + | |
605 | + /* | |
606 | + * Get the cli_cert | |
607 | + */ | |
608 | + if (!getword(f, word, &newline, filename)) | |
609 | + break; | |
610 | + if (newline) | |
611 | + continue; | |
612 | + if (strcmp(word, "-") != 0) { | |
613 | + strlcpy(cli_cert, word, MAXWORDLEN); | |
614 | + } else | |
615 | + cli_cert[0] = 0; | |
616 | + | |
617 | + /* | |
618 | + * Get serv_cert | |
619 | + */ | |
620 | + if (!getword(f, word, &newline, filename)) | |
621 | + break; | |
622 | + if (newline) | |
623 | + continue; | |
624 | + if (strcmp(word, "-") != 0) { | |
625 | + strlcpy(serv_cert, word, MAXWORDLEN); | |
626 | + } else | |
627 | + serv_cert[0] = 0; | |
628 | + | |
629 | + /* | |
630 | + * Get ca_cert | |
631 | + */ | |
632 | + if (!getword(f, word, &newline, filename)) | |
633 | + break; | |
634 | + if (newline) | |
635 | + continue; | |
636 | + strlcpy(ca_cert, word, MAXWORDLEN); | |
637 | + | |
638 | + /* | |
639 | + * Get pk | |
640 | + */ | |
641 | + if (!getword(f, word, &newline, filename)) | |
642 | + break; | |
643 | + if (newline) | |
644 | + continue; | |
645 | + strlcpy(pk, word, MAXWORDLEN); | |
646 | + | |
647 | + | |
648 | + /* | |
649 | + * Now read address authorization info and make a wordlist. | |
650 | + */ | |
651 | + app = &alist; | |
652 | + for (;;) { | |
653 | + if (!getword(f, word, &newline, filename) || newline) | |
654 | + break; | |
655 | + ap = (struct wordlist *) | |
656 | + malloc(sizeof(struct wordlist) + strlen(word) + 1); | |
657 | + if (ap == NULL) | |
658 | + novm("authorized addresses"); | |
659 | + ap->word = (char *) (ap + 1); | |
660 | + strcpy(ap->word, word); | |
661 | + *app = ap; | |
662 | + app = &ap->next; | |
663 | + } | |
664 | + *app = NULL; | |
665 | + /* | |
666 | + * This is the best so far; remember it. | |
667 | + */ | |
668 | + best_flag = got_flag; | |
669 | + if (addr_list) | |
670 | + free_wordlist(addr_list); | |
671 | + addr_list = alist; | |
672 | + | |
673 | + if (!newline) | |
674 | + break; | |
675 | + } | |
676 | + | |
677 | + /* scan for a -- word indicating the start of options */ | |
678 | + for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) | |
679 | + if (strcmp(ap->word, "--") == 0) | |
680 | + break; | |
681 | + /* ap = start of options */ | |
682 | + if (ap != NULL) { | |
683 | + ap = ap->next; /* first option */ | |
684 | + free(*app); /* free the "--" word */ | |
685 | + *app = NULL; /* terminate addr list */ | |
686 | + } | |
687 | + if (opts != NULL) | |
688 | + *opts = ap; | |
689 | + else if (ap != NULL) | |
690 | + free_wordlist(ap); | |
691 | + if (addrs != NULL) | |
692 | + *addrs = addr_list; | |
693 | + else if (addr_list != NULL) | |
694 | + free_wordlist(addr_list); | |
695 | + | |
696 | + return best_flag; | |
697 | +} | |
698 | + | |
699 | + | |
700 | +int | |
701 | +get_eaptls_secret(unit, client, server, clicertfile, servcertfile, | |
702 | + cacertfile, pkfile, am_server) | |
703 | + int unit; | |
704 | + char *client; | |
705 | + char *server; | |
706 | + char *clicertfile; | |
707 | + char *servcertfile; | |
708 | + char *cacertfile; | |
709 | + char *pkfile; | |
710 | + int am_server; | |
711 | +{ | |
712 | + FILE *fp; | |
713 | + int ret; | |
714 | + char *filename = NULL; | |
715 | + struct wordlist *addrs = NULL; | |
716 | + struct wordlist *opts = NULL; | |
717 | + | |
718 | + /* in client mode the ca+cert+privkey can also be specified as options */ | |
719 | + if (!am_server && cacert_file && cert_file && privkey_file ) | |
720 | + { | |
721 | + strlcpy( clicertfile, cert_file, MAXWORDLEN ); | |
722 | + strlcpy( cacertfile, cacert_file, MAXWORDLEN ); | |
723 | + strlcpy( pkfile, privkey_file, MAXWORDLEN ); | |
724 | + servcertfile[0] = '\0'; | |
725 | + } | |
726 | + else | |
727 | + { | |
728 | + filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE); | |
729 | + addrs = NULL; | |
730 | + | |
731 | + fp = fopen(filename, "r"); | |
732 | + if (fp == NULL) | |
733 | + { | |
734 | + error("Can't open eap-tls secret file %s: %m", filename); | |
735 | + return 0; | |
736 | + } | |
737 | + | |
738 | + check_access(fp, filename); | |
739 | + | |
740 | + ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile, | |
741 | + cacertfile, pkfile, &addrs, &opts, filename, 0); | |
742 | + | |
743 | + fclose(fp); | |
744 | + | |
745 | + if (ret < 0) return 0; | |
746 | + } | |
747 | + | |
748 | + if (eaptls_passwd_hook) | |
749 | + { | |
750 | + dbglog( "Calling eaptls password hook" ); | |
751 | + if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0) | |
752 | + { | |
753 | + error("Unable to obtain EAP-TLS password for %s (%s) from plugin", | |
754 | + client, pkfile); | |
755 | + return 0; | |
756 | + } | |
757 | + } | |
758 | + if (am_server) | |
759 | + set_allowed_addrs(unit, addrs, opts); | |
760 | + else if (opts != NULL) | |
761 | + free_wordlist(opts); | |
762 | + if (addrs != NULL) | |
763 | + free_wordlist(addrs); | |
764 | + | |
765 | + return 1; | |
766 | +} | |
767 | +#endif | |
768 | + | |
769 | diff -Naur ppp-2.4.5/pppd/ccp.c ppp-2.4.5-eaptls-mppe-0.99/pppd/ccp.c | |
770 | --- ppp-2.4.5/pppd/ccp.c 2009-11-16 23:26:07.000000000 +0100 | |
771 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/ccp.c 2010-10-01 15:17:54.211272258 +0200 | |
772 | @@ -540,6 +540,9 @@ | |
773 | if (go->mppe) { | |
774 | ccp_options *ao = &ccp_allowoptions[f->unit]; | |
775 | int auth_mschap_bits = auth_done[f->unit]; | |
776 | +#ifdef USE_EAPTLS | |
777 | + int auth_eap_bits = auth_done[f->unit]; | |
778 | +#endif | |
779 | int numbits; | |
780 | ||
781 | /* | |
782 | @@ -567,8 +570,23 @@ | |
783 | lcp_close(f->unit, "MPPE required but not available"); | |
784 | return; | |
785 | } | |
786 | + | |
787 | +#ifdef USE_EAPTLS | |
788 | + /* | |
789 | + * MPPE is also possible in combination with EAP-TLS. | |
790 | + * It is not possible to detect if we're doing EAP or EAP-TLS | |
791 | + * at this stage, hence we accept all forms of EAP. If TLS is | |
792 | + * not used then the MPPE keys will not be derived anyway. | |
793 | + */ | |
794 | + /* Leave only the eap auth bits set */ | |
795 | + auth_eap_bits &= (EAP_WITHPEER | EAP_PEER ); | |
796 | + | |
797 | + if ((numbits == 0) && (auth_eap_bits == 0)) { | |
798 | + error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed."); | |
799 | +#else | |
800 | if (!numbits) { | |
801 | - error("MPPE required, but MS-CHAP[v2] auth not performed."); | |
802 | + error("MPPE required, but MS-CHAP[v2] auth not performed."); | |
803 | +#endif | |
804 | lcp_close(f->unit, "MPPE required but not available"); | |
805 | return; | |
806 | } | |
807 | diff -Naur ppp-2.4.5/pppd/chap-md5.c ppp-2.4.5-eaptls-mppe-0.99/pppd/chap-md5.c | |
808 | --- ppp-2.4.5/pppd/chap-md5.c 2009-11-16 23:26:07.000000000 +0100 | |
809 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/chap-md5.c 2010-10-01 15:17:54.212272142 +0200 | |
810 | @@ -36,7 +36,11 @@ | |
811 | #include "chap-new.h" | |
812 | #include "chap-md5.h" | |
813 | #include "magic.h" | |
814 | +#ifdef USE_EAPTLS | |
815 | +#include "eap-tls.h" | |
816 | +#else | |
817 | #include "md5.h" | |
818 | +#endif /* USE_EAPTLS */ | |
819 | ||
820 | #define MD5_HASH_SIZE 16 | |
821 | #define MD5_MIN_CHALLENGE 16 | |
822 | diff -Naur ppp-2.4.5/pppd/eap-tls.c ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.c | |
823 | --- ppp-2.4.5/pppd/eap-tls.c 1970-01-01 01:00:00.000000000 +0100 | |
824 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.c 2010-10-05 15:12:45.881615580 +0200 | |
825 | @@ -0,0 +1,1174 @@ | |
826 | +/* | |
827 | + * eap-tls.c - EAP-TLS implementation for PPP | |
828 | + * | |
829 | + * Copyright (c) Beniamino Galvani 2005 All rights reserved. | |
830 | + * | |
831 | + * Redistribution and use in source and binary forms, with or without | |
832 | + * modification, are permitted provided that the following conditions | |
833 | + * are met: | |
834 | + * | |
835 | + * 1. Redistributions of source code must retain the above copyright | |
836 | + * notice, this list of conditions and the following disclaimer. | |
837 | + * | |
838 | + * 2. Redistributions in binary form must reproduce the above copyright | |
839 | + * notice, this list of conditions and the following disclaimer in | |
840 | + * the documentation and/or other materials provided with the | |
841 | + * distribution. | |
842 | + * | |
843 | + * 3. The name(s) of the authors of this software must not be used to | |
844 | + * endorse or promote products derived from this software without | |
845 | + * prior written permission. | |
846 | + * | |
847 | + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO | |
848 | + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
849 | + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |
850 | + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
851 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
852 | + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |
853 | + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
854 | + * | |
855 | + */ | |
856 | + | |
857 | +#include <string.h> | |
858 | +#include <unistd.h> | |
859 | +#include <sys/types.h> | |
860 | +#include <sys/stat.h> | |
861 | +#include <fcntl.h> | |
862 | + | |
863 | +#include <openssl/conf.h> | |
864 | +#include <openssl/engine.h> | |
865 | +#include <openssl/hmac.h> | |
866 | +#include <openssl/err.h> | |
867 | +#include <openssl/x509v3.h> | |
868 | + | |
869 | +#include "pppd.h" | |
870 | +#include "eap.h" | |
871 | +#include "eap-tls.h" | |
872 | +#include "fsm.h" | |
873 | +#include "lcp.h" | |
874 | +#include "pathnames.h" | |
875 | + | |
876 | +/* The openssl configuration file and engines can be loaded only once */ | |
877 | +static CONF *ssl_config = NULL; | |
878 | +static ENGINE *cert_engine = NULL; | |
879 | +static ENGINE *pkey_engine = NULL; | |
880 | + | |
881 | +#ifdef MPPE | |
882 | + | |
883 | +/* | |
884 | + * TLS PRF from RFC 2246 | |
885 | + */ | |
886 | +static void P_hash(const EVP_MD *evp_md, | |
887 | + const unsigned char *secret, unsigned int secret_len, | |
888 | + const unsigned char *seed, unsigned int seed_len, | |
889 | + unsigned char *out, unsigned int out_len) | |
890 | +{ | |
891 | + HMAC_CTX ctx_a, ctx_out; | |
892 | + unsigned char a[HMAC_MAX_MD_CBLOCK]; | |
893 | + unsigned int size; | |
894 | + | |
895 | + HMAC_CTX_init(&ctx_a); | |
896 | + HMAC_CTX_init(&ctx_out); | |
897 | + HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL); | |
898 | + HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL); | |
899 | + | |
900 | + size = HMAC_size(&ctx_out); | |
901 | + | |
902 | + /* Calculate A(1) */ | |
903 | + HMAC_Update(&ctx_a, seed, seed_len); | |
904 | + HMAC_Final(&ctx_a, a, NULL); | |
905 | + | |
906 | + while (1) { | |
907 | + /* Calculate next part of output */ | |
908 | + HMAC_Update(&ctx_out, a, size); | |
909 | + HMAC_Update(&ctx_out, seed, seed_len); | |
910 | + | |
911 | + /* Check if last part */ | |
912 | + if (out_len < size) { | |
913 | + HMAC_Final(&ctx_out, a, NULL); | |
914 | + memcpy(out, a, out_len); | |
915 | + break; | |
916 | + } | |
917 | + | |
918 | + /* Place digest in output buffer */ | |
919 | + HMAC_Final(&ctx_out, out, NULL); | |
920 | + HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL); | |
921 | + out += size; | |
922 | + out_len -= size; | |
923 | + | |
924 | + /* Calculate next A(i) */ | |
925 | + HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL); | |
926 | + HMAC_Update(&ctx_a, a, size); | |
927 | + HMAC_Final(&ctx_a, a, NULL); | |
928 | + } | |
929 | + | |
930 | + HMAC_CTX_cleanup(&ctx_a); | |
931 | + HMAC_CTX_cleanup(&ctx_out); | |
932 | + memset(a, 0, sizeof(a)); | |
933 | +} | |
934 | + | |
935 | +static void PRF(const unsigned char *secret, unsigned int secret_len, | |
936 | + const unsigned char *seed, unsigned int seed_len, | |
937 | + unsigned char *out, unsigned char *buf, unsigned int out_len) | |
938 | +{ | |
939 | + unsigned int i; | |
940 | + unsigned int len = (secret_len + 1) / 2; | |
941 | + const unsigned char *s1 = secret; | |
942 | + const unsigned char *s2 = secret + (secret_len - len); | |
943 | + | |
944 | + P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len); | |
945 | + P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len); | |
946 | + | |
947 | + for (i=0; i < out_len; i++) { | |
948 | + out[i] ^= buf[i]; | |
949 | + } | |
950 | +} | |
951 | + | |
952 | +#define EAPTLS_MPPE_KEY_LEN 32 | |
953 | + | |
954 | +/* | |
955 | + * Generate keys according to RFC 2716 and add to reply | |
956 | + */ | |
957 | +void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, | |
958 | + int client) | |
959 | +{ | |
960 | + unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN]; | |
961 | + unsigned char seed[64 + 2*SSL3_RANDOM_SIZE]; | |
962 | + unsigned char *p = seed; | |
963 | + SSL *s = ets->ssl; | |
964 | + size_t prf_size; | |
965 | + | |
966 | + prf_size = strlen(prf_label); | |
967 | + | |
968 | + memcpy(p, prf_label, prf_size); | |
969 | + p += prf_size; | |
970 | + | |
971 | + memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); | |
972 | + p += SSL3_RANDOM_SIZE; | |
973 | + prf_size += SSL3_RANDOM_SIZE; | |
974 | + | |
975 | + memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); | |
976 | + prf_size += SSL3_RANDOM_SIZE; | |
977 | + | |
978 | + PRF(s->session->master_key, s->session->master_key_length, | |
979 | + seed, prf_size, out, buf, sizeof(out)); | |
980 | + | |
981 | + /* | |
982 | + * We now have the master send and receive keys. | |
983 | + * From these, generate the session send and receive keys. | |
984 | + * (see RFC3079 / draft-ietf-pppext-mppe-keys-03.txt for details) | |
985 | + */ | |
986 | + if (client) | |
987 | + { | |
988 | + p = out; | |
989 | + BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); | |
990 | + p += EAPTLS_MPPE_KEY_LEN; | |
991 | + BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); | |
992 | + } | |
993 | + else | |
994 | + { | |
995 | + p = out; | |
996 | + BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); | |
997 | + p += EAPTLS_MPPE_KEY_LEN; | |
998 | + BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); | |
999 | + } | |
1000 | + | |
1001 | + mppe_keys_set = 1; | |
1002 | +} | |
1003 | + | |
1004 | +#endif | |
1005 | + | |
1006 | +void log_ssl_errors( void ) | |
1007 | +{ | |
1008 | + unsigned long ssl_err = ERR_get_error(); | |
1009 | + | |
1010 | + if (ssl_err != 0) | |
1011 | + dbglog("EAP-TLS SSL error stack:"); | |
1012 | + while (ssl_err != 0) { | |
1013 | + dbglog( ERR_error_string( ssl_err, NULL ) ); | |
1014 | + ssl_err = ERR_get_error(); | |
1015 | + } | |
1016 | +} | |
1017 | + | |
1018 | + | |
1019 | +int password_callback (char *buf, int size, int rwflag, void *u) | |
1020 | +{ | |
1021 | + if (buf) | |
1022 | + { | |
1023 | + strncpy (buf, passwd, size); | |
1024 | + return strlen (buf); | |
1025 | + } | |
1026 | + return 0; | |
1027 | +} | |
1028 | + | |
1029 | + | |
1030 | +CONF *eaptls_ssl_load_config( void ) | |
1031 | +{ | |
1032 | + CONF *config; | |
1033 | + int ret_code; | |
1034 | + long error_line = 33; | |
1035 | + | |
1036 | + config = NCONF_new( NULL ); | |
1037 | + dbglog( "Loading OpenSSL config file" ); | |
1038 | + ret_code = NCONF_load( config, _PATH_OPENSSLCONFFILE, &error_line ); | |
1039 | + if (ret_code == 0) | |
1040 | + { | |
1041 | + warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line ); | |
1042 | + NCONF_free( config ); | |
1043 | + config = NULL; | |
1044 | + ERR_clear_error(); | |
1045 | + } | |
1046 | + | |
1047 | + dbglog( "Loading OpenSSL built-ins" ); | |
1048 | + ENGINE_load_builtin_engines(); | |
1049 | + OPENSSL_load_builtin_modules(); | |
1050 | + | |
1051 | + dbglog( "Loading OpenSSL configured modules" ); | |
1052 | + if (CONF_modules_load( config, NULL, 0 ) <= 0 ) | |
1053 | + { | |
1054 | + warn( "EAP-TLS: Error loading OpenSSL modules" ); | |
1055 | + log_ssl_errors(); | |
1056 | + config = NULL; | |
1057 | + } | |
1058 | + | |
1059 | + return config; | |
1060 | +} | |
1061 | + | |
1062 | +ENGINE *eaptls_ssl_load_engine( char *engine_name ) | |
1063 | +{ | |
1064 | + ENGINE *e = NULL; | |
1065 | + | |
1066 | + dbglog( "Enabling OpenSSL auto engines" ); | |
1067 | + ENGINE_register_all_complete(); | |
1068 | + | |
1069 | + dbglog( "Loading OpenSSL '%s' engine support", engine_name ); | |
1070 | + e = ENGINE_by_id( engine_name ); | |
1071 | + if (!e) | |
1072 | + { | |
1073 | + dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name ); | |
1074 | + e = ENGINE_by_id( "dynamic" ); | |
1075 | + if (e) | |
1076 | + { | |
1077 | + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0) | |
1078 | + || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) | |
1079 | + { | |
1080 | + warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name ); | |
1081 | + log_ssl_errors(); | |
1082 | + ENGINE_free(e); | |
1083 | + e = NULL; | |
1084 | + } | |
1085 | + } | |
1086 | + else | |
1087 | + { | |
1088 | + warn( "EAP-TLS: Cannot load dynamic engine support" ); | |
1089 | + } | |
1090 | + } | |
1091 | + | |
1092 | + if (e) | |
1093 | + { | |
1094 | + dbglog( "Initialising engine" ); | |
1095 | + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) | |
1096 | + { | |
1097 | + warn( "EAP-TLS: Cannot use that engine" ); | |
1098 | + log_ssl_errors(); | |
1099 | + ENGINE_free(e); | |
1100 | + e = NULL; | |
1101 | + } | |
1102 | + } | |
1103 | + | |
1104 | + return e; | |
1105 | +} | |
1106 | + | |
1107 | +/* | |
1108 | + * Initialize the SSL stacks and tests if certificates, key and crl | |
1109 | + * for client or server use can be loaded. | |
1110 | + */ | |
1111 | +SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, | |
1112 | + char *certfile, char *peer_certfile, char *privkeyfile) | |
1113 | +{ | |
1114 | + char *cert_engine_name = NULL; | |
1115 | + char *cert_identifier = NULL; | |
1116 | + char *pkey_engine_name = NULL; | |
1117 | + char *pkey_identifier = NULL; | |
1118 | + SSL_CTX *ctx; | |
1119 | + X509_STORE *certstore; | |
1120 | + X509_LOOKUP *lookup; | |
1121 | + X509 *tmp; | |
1122 | + | |
1123 | + /* | |
1124 | + * Without these can't continue | |
1125 | + */ | |
1126 | + if (!cacertfile[0]) | |
1127 | + { | |
1128 | + error("EAP-TLS: CA certificate missing"); | |
1129 | + return NULL; | |
1130 | + } | |
1131 | + | |
1132 | + if (!certfile[0]) | |
1133 | + { | |
1134 | + error("EAP-TLS: User certificate missing"); | |
1135 | + return NULL; | |
1136 | + } | |
1137 | + | |
1138 | + if (!privkeyfile[0]) | |
1139 | + { | |
1140 | + error("EAP-TLS: User private key missing"); | |
1141 | + return NULL; | |
1142 | + } | |
1143 | + | |
1144 | + SSL_library_init(); | |
1145 | + SSL_load_error_strings(); | |
1146 | + | |
1147 | + ctx = SSL_CTX_new(TLSv1_method()); | |
1148 | + | |
1149 | + if (!ctx) { | |
1150 | + error("EAP-TLS: Cannot initialize SSL CTX context"); | |
1151 | + goto fail; | |
1152 | + } | |
1153 | + | |
1154 | + /* if the certificate filename is of the form engine:id. e.g. | |
1155 | + pkcs11:12345 | |
1156 | + then we try to load and use this engine. | |
1157 | + If the certificate filename starts with a / or . then we | |
1158 | + ALWAYS assume it is a file and not an engine/pkcs11 identifier | |
1159 | + */ | |
1160 | + if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL ) | |
1161 | + { | |
1162 | + cert_identifier = index( certfile, ':' ); | |
1163 | + | |
1164 | + if (cert_identifier) | |
1165 | + { | |
1166 | + cert_engine_name = certfile; | |
1167 | + *cert_identifier = '\0'; | |
1168 | + cert_identifier++; | |
1169 | + | |
1170 | + dbglog( "Found certificate engine '%s'", cert_engine_name ); | |
1171 | + dbglog( "Found certificate identifier '%s'", cert_identifier ); | |
1172 | + } | |
1173 | + } | |
1174 | + | |
1175 | + /* if the privatekey filename is of the form engine:id. e.g. | |
1176 | + pkcs11:12345 | |
1177 | + then we try to load and use this engine. | |
1178 | + If the privatekey filename starts with a / or . then we | |
1179 | + ALWAYS assume it is a file and not an engine/pkcs11 identifier | |
1180 | + */ | |
1181 | + if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL ) | |
1182 | + { | |
1183 | + pkey_identifier = index( privkeyfile, ':' ); | |
1184 | + | |
1185 | + if (pkey_identifier) | |
1186 | + { | |
1187 | + pkey_engine_name = privkeyfile; | |
1188 | + *pkey_identifier = '\0'; | |
1189 | + pkey_identifier++; | |
1190 | + | |
1191 | + dbglog( "Found privatekey engine '%s'", pkey_engine_name ); | |
1192 | + dbglog( "Found privatekey identifier '%s'", pkey_identifier ); | |
1193 | + } | |
1194 | + } | |
1195 | + | |
1196 | + if (cert_identifier && pkey_identifier) | |
1197 | + { | |
1198 | + if (strlen( cert_identifier ) == 0) | |
1199 | + { | |
1200 | + if (strlen( pkey_identifier ) == 0) | |
1201 | + error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" ); | |
1202 | + else | |
1203 | + { | |
1204 | + dbglog( "Substituting privatekey identifier for certificate identifier" ); | |
1205 | + cert_identifier = pkey_identifier; | |
1206 | + } | |
1207 | + } | |
1208 | + else | |
1209 | + { | |
1210 | + if (strlen( pkey_identifier ) == 0) | |
1211 | + { | |
1212 | + dbglog( "Substituting certificate identifier for privatekey identifier" ); | |
1213 | + pkey_identifier = cert_identifier; | |
1214 | + } | |
1215 | + } | |
1216 | + | |
1217 | + } | |
1218 | + | |
1219 | + /* load the openssl config file only once */ | |
1220 | + if (!ssl_config) | |
1221 | + { | |
1222 | + if (cert_engine_name || pkey_engine_name) | |
1223 | + ssl_config = eaptls_ssl_load_config(); | |
1224 | + | |
1225 | + if (ssl_config && cert_engine_name) | |
1226 | + cert_engine = eaptls_ssl_load_engine( cert_engine_name ); | |
1227 | + | |
1228 | + if (ssl_config && pkey_engine_name) | |
1229 | + { | |
1230 | + /* don't load the same engine twice */ | |
1231 | + if ( strcmp( cert_engine_name, pkey_engine_name) == 0 ) | |
1232 | + pkey_engine = cert_engine; | |
1233 | + else | |
1234 | + pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); | |
1235 | + } | |
1236 | + } | |
1237 | + | |
1238 | + SSL_CTX_set_default_passwd_cb (ctx, password_callback); | |
1239 | + | |
1240 | + if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) | |
1241 | + { | |
1242 | + error("EAP-TLS: Cannot load or verify CA file %s", cacertfile); | |
1243 | + goto fail; | |
1244 | + } | |
1245 | + | |
1246 | + if (init_server) | |
1247 | + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); | |
1248 | + | |
1249 | + if (cert_engine) | |
1250 | + { | |
1251 | + struct | |
1252 | + { | |
1253 | + const char *s_slot_cert_id; | |
1254 | + X509 *cert; | |
1255 | + } cert_info; | |
1256 | + | |
1257 | + cert_info.s_slot_cert_id = cert_identifier; | |
1258 | + cert_info.cert = NULL; | |
1259 | + | |
1260 | + if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) ) | |
1261 | + { | |
1262 | + error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier ); | |
1263 | + goto fail; | |
1264 | + } | |
1265 | + | |
1266 | + if (cert_info.cert) | |
1267 | + { | |
1268 | + dbglog( "Got the certificate, adding it to SSL context" ); | |
1269 | + dbglog( "subject = %s", X509_NAME_oneline( X509_get_subject_name( cert_info.cert ), NULL, 0 ) ); | |
1270 | + if (SSL_CTX_use_certificate(ctx, cert_info.cert) <= 0) | |
1271 | + { | |
1272 | + error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier); | |
1273 | + goto fail; | |
1274 | + } | |
1275 | + } | |
1276 | + else | |
1277 | + { | |
1278 | + warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier); | |
1279 | + log_ssl_errors(); | |
1280 | + } | |
1281 | + } | |
1282 | + else | |
1283 | + { | |
1284 | + if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) | |
1285 | + { | |
1286 | + error( "EAP-TLS: Cannot use public certificate %s", certfile ); | |
1287 | + goto fail; | |
1288 | + } | |
1289 | + } | |
1290 | + | |
1291 | + if (pkey_engine) | |
1292 | + { | |
1293 | + EVP_PKEY *pkey = NULL; | |
1294 | + PW_CB_DATA cb_data; | |
1295 | + | |
1296 | + cb_data.password = passwd; | |
1297 | + cb_data.prompt_info = pkey_identifier; | |
1298 | + | |
1299 | + dbglog( "Loading private key '%s' from engine", pkey_identifier ); | |
1300 | + pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data); | |
1301 | + if (pkey) | |
1302 | + { | |
1303 | + dbglog( "Got the private key, adding it to SSL context" ); | |
1304 | + if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) | |
1305 | + { | |
1306 | + error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier); | |
1307 | + goto fail; | |
1308 | + } | |
1309 | + } | |
1310 | + else | |
1311 | + { | |
1312 | + warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier); | |
1313 | + log_ssl_errors(); | |
1314 | + } | |
1315 | + } | |
1316 | + else | |
1317 | + { | |
1318 | + if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) | |
1319 | + { | |
1320 | + error("EAP-TLS: Cannot use private key %s", privkeyfile); | |
1321 | + goto fail; | |
1322 | + } | |
1323 | + } | |
1324 | + | |
1325 | + if (SSL_CTX_check_private_key(ctx) != 1) { | |
1326 | + error("EAP-TLS: Private key %s fails security check", privkeyfile); | |
1327 | + goto fail; | |
1328 | + } | |
1329 | + | |
1330 | + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); | |
1331 | + SSL_CTX_set_verify_depth(ctx, 5); | |
1332 | + SSL_CTX_set_verify(ctx, | |
1333 | + SSL_VERIFY_PEER | | |
1334 | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, | |
1335 | + &ssl_verify_callback); | |
1336 | + | |
1337 | + if (crl_dir) { | |
1338 | + if (!(certstore = SSL_CTX_get_cert_store(ctx))) { | |
1339 | + error("EAP-TLS: Failed to get certificate store"); | |
1340 | + goto fail; | |
1341 | + } | |
1342 | + | |
1343 | + if (!(lookup = | |
1344 | + X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) { | |
1345 | + error("EAP-TLS: Store lookup for CRL failed"); | |
1346 | + | |
1347 | + goto fail; | |
1348 | + } | |
1349 | + | |
1350 | + X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); | |
1351 | + X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); | |
1352 | + } | |
1353 | + | |
1354 | + /* | |
1355 | + * If a peer certificate file was specified, it must be valid, else fail | |
1356 | + */ | |
1357 | + if (peer_certfile[0]) { | |
1358 | + if (!(tmp = get_X509_from_file(peer_certfile))) { | |
1359 | + error("EAP-TLS: Error loading client certificate from file %s", | |
1360 | + peer_certfile); | |
1361 | + goto fail; | |
1362 | + } | |
1363 | + X509_free(tmp); | |
1364 | + } | |
1365 | + | |
1366 | + return ctx; | |
1367 | + | |
1368 | +fail: | |
1369 | + log_ssl_errors(); | |
1370 | + SSL_CTX_free(ctx); | |
1371 | + return NULL; | |
1372 | +} | |
1373 | + | |
1374 | +/* | |
1375 | + * Determine the maximum packet size by looking at the LCP handshake | |
1376 | + */ | |
1377 | + | |
1378 | +int eaptls_get_mtu(int unit) | |
1379 | +{ | |
1380 | + int mtu, mru; | |
1381 | + | |
1382 | + lcp_options *wo = &lcp_wantoptions[unit]; | |
1383 | + lcp_options *go = &lcp_gotoptions[unit]; | |
1384 | + lcp_options *ho = &lcp_hisoptions[unit]; | |
1385 | + lcp_options *ao = &lcp_allowoptions[unit]; | |
1386 | + | |
1387 | + mtu = ho->neg_mru? ho->mru: PPP_MRU; | |
1388 | + mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU; | |
1389 | + mtu = MIN(MIN(mtu, mru), ao->mru)- PPP_HDRLEN - 10; | |
1390 | + | |
1391 | + dbglog("MTU = %d", mtu); | |
1392 | + return mtu; | |
1393 | +} | |
1394 | + | |
1395 | + | |
1396 | +/* | |
1397 | + * Init the ssl handshake (server mode) | |
1398 | + */ | |
1399 | +int eaptls_init_ssl_server(eap_state * esp) | |
1400 | +{ | |
1401 | + struct eaptls_session *ets; | |
1402 | + char servcertfile[MAXWORDLEN]; | |
1403 | + char clicertfile[MAXWORDLEN]; | |
1404 | + char cacertfile[MAXWORDLEN]; | |
1405 | + char pkfile[MAXWORDLEN]; | |
1406 | + /* | |
1407 | + * Allocate new eaptls session | |
1408 | + */ | |
1409 | + esp->es_server.ea_session = malloc(sizeof(struct eaptls_session)); | |
1410 | + if (!esp->es_server.ea_session) | |
1411 | + fatal("Allocation error"); | |
1412 | + ets = esp->es_server.ea_session; | |
1413 | + | |
1414 | + if (!esp->es_server.ea_peer) { | |
1415 | + error("EAP-TLS: Error: client name not set (BUG)"); | |
1416 | + return 0; | |
1417 | + } | |
1418 | + | |
1419 | + strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN); | |
1420 | + | |
1421 | + dbglog( "getting eaptls secret" ); | |
1422 | + if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, | |
1423 | + esp->es_server.ea_name, clicertfile, | |
1424 | + servcertfile, cacertfile, pkfile, 1)) { | |
1425 | + error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", | |
1426 | + esp->es_server.ea_peer, esp->es_server.ea_name ); | |
1427 | + return 0; | |
1428 | + } | |
1429 | + | |
1430 | + ets->mtu = eaptls_get_mtu(esp->es_unit); | |
1431 | + | |
1432 | + ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile); | |
1433 | + if (!ets->ctx) | |
1434 | + goto fail; | |
1435 | + | |
1436 | + if (!(ets->ssl = SSL_new(ets->ctx))) | |
1437 | + goto fail; | |
1438 | + | |
1439 | + /* | |
1440 | + * Set auto-retry to avoid timeouts on BIO_read | |
1441 | + */ | |
1442 | + SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY); | |
1443 | + | |
1444 | + /* | |
1445 | + * Initialize the BIOs we use to read/write to ssl engine | |
1446 | + */ | |
1447 | + ets->into_ssl = BIO_new(BIO_s_mem()); | |
1448 | + ets->from_ssl = BIO_new(BIO_s_mem()); | |
1449 | + SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); | |
1450 | + | |
1451 | + SSL_set_msg_callback(ets->ssl, ssl_msg_callback); | |
1452 | + SSL_set_msg_callback_arg(ets->ssl, ets); | |
1453 | + | |
1454 | + /* | |
1455 | + * Attach the session struct to the connection, so we can later | |
1456 | + * retrieve it when doing certificate verification | |
1457 | + */ | |
1458 | + SSL_set_ex_data(ets->ssl, 0, ets); | |
1459 | + | |
1460 | + SSL_set_accept_state(ets->ssl); | |
1461 | + | |
1462 | + ets->data = NULL; | |
1463 | + ets->datalen = 0; | |
1464 | + ets->alert_sent = 0; | |
1465 | + ets->alert_recv = 0; | |
1466 | + | |
1467 | + /* | |
1468 | + * If we specified the client certificate file, store it in ets->peercertfile, | |
1469 | + * so we can check it later in ssl_verify_callback() | |
1470 | + */ | |
1471 | + if (clicertfile[0]) | |
1472 | + strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN); | |
1473 | + else | |
1474 | + ets->peercertfile[0] = 0; | |
1475 | + | |
1476 | + return 1; | |
1477 | + | |
1478 | +fail: | |
1479 | + SSL_CTX_free(ets->ctx); | |
1480 | + return 0; | |
1481 | +} | |
1482 | + | |
1483 | +/* | |
1484 | + * Init the ssl handshake (client mode) | |
1485 | + */ | |
1486 | +int eaptls_init_ssl_client(eap_state * esp) | |
1487 | +{ | |
1488 | + struct eaptls_session *ets; | |
1489 | + char servcertfile[MAXWORDLEN]; | |
1490 | + char clicertfile[MAXWORDLEN]; | |
1491 | + char cacertfile[MAXWORDLEN]; | |
1492 | + char pkfile[MAXWORDLEN]; | |
1493 | + | |
1494 | + /* | |
1495 | + * Allocate new eaptls session | |
1496 | + */ | |
1497 | + esp->es_client.ea_session = malloc(sizeof(struct eaptls_session)); | |
1498 | + if (!esp->es_client.ea_session) | |
1499 | + fatal("Allocation error"); | |
1500 | + ets = esp->es_client.ea_session; | |
1501 | + | |
1502 | + /* | |
1503 | + * If available, copy server name in ets; it will be used in cert | |
1504 | + * verify | |
1505 | + */ | |
1506 | + if (esp->es_client.ea_peer) | |
1507 | + strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN); | |
1508 | + else | |
1509 | + ets->peer[0] = 0; | |
1510 | + | |
1511 | + ets->mtu = eaptls_get_mtu(esp->es_unit); | |
1512 | + | |
1513 | + dbglog( "calling get_eaptls_secret" ); | |
1514 | + if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, | |
1515 | + esp->es_client.ea_peer, clicertfile, | |
1516 | + servcertfile, cacertfile, pkfile, 0)) { | |
1517 | + error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", | |
1518 | + esp->es_client.ea_name, esp->es_client.ea_peer ); | |
1519 | + return 0; | |
1520 | + } | |
1521 | + | |
1522 | + dbglog( "calling eaptls_init_ssl" ); | |
1523 | + ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile); | |
1524 | + if (!ets->ctx) | |
1525 | + goto fail; | |
1526 | + | |
1527 | + ets->ssl = SSL_new(ets->ctx); | |
1528 | + | |
1529 | + if (!ets->ssl) | |
1530 | + goto fail; | |
1531 | + | |
1532 | + /* | |
1533 | + * Initialize the BIOs we use to read/write to ssl engine | |
1534 | + */ | |
1535 | + dbglog( "Initializing SSL BIOs" ); | |
1536 | + ets->into_ssl = BIO_new(BIO_s_mem()); | |
1537 | + ets->from_ssl = BIO_new(BIO_s_mem()); | |
1538 | + SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); | |
1539 | + | |
1540 | + SSL_set_msg_callback(ets->ssl, ssl_msg_callback); | |
1541 | + SSL_set_msg_callback_arg(ets->ssl, ets); | |
1542 | + | |
1543 | + /* | |
1544 | + * Attach the session struct to the connection, so we can later | |
1545 | + * retrieve it when doing certificate verification | |
1546 | + */ | |
1547 | + SSL_set_ex_data(ets->ssl, 0, ets); | |
1548 | + | |
1549 | + SSL_set_connect_state(ets->ssl); | |
1550 | + | |
1551 | + ets->data = NULL; | |
1552 | + ets->datalen = 0; | |
1553 | + ets->alert_sent = 0; | |
1554 | + ets->alert_recv = 0; | |
1555 | + | |
1556 | + /* | |
1557 | + * If we specified the server certificate file, store it in | |
1558 | + * ets->peercertfile, so we can check it later in | |
1559 | + * ssl_verify_callback() | |
1560 | + */ | |
1561 | + if (servcertfile[0]) | |
1562 | + strncpy(ets->peercertfile, servcertfile, MAXWORDLEN); | |
1563 | + else | |
1564 | + ets->peercertfile[0] = 0; | |
1565 | + | |
1566 | + return 1; | |
1567 | + | |
1568 | +fail: | |
1569 | + dbglog( "eaptls_init_ssl_client: fail" ); | |
1570 | + SSL_CTX_free(ets->ctx); | |
1571 | + return 0; | |
1572 | + | |
1573 | +} | |
1574 | + | |
1575 | +void eaptls_free_session(struct eaptls_session *ets) | |
1576 | +{ | |
1577 | + if (ets->ssl) | |
1578 | + SSL_free(ets->ssl); | |
1579 | + | |
1580 | + if (ets->ctx) | |
1581 | + SSL_CTX_free(ets->ctx); | |
1582 | + | |
1583 | + free(ets); | |
1584 | +} | |
1585 | + | |
1586 | +/* | |
1587 | + * Handle a received packet, reassembling fragmented messages and | |
1588 | + * passing them to the ssl engine | |
1589 | + */ | |
1590 | +int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) | |
1591 | +{ | |
1592 | + u_char flags; | |
1593 | + u_int tlslen; | |
1594 | + u_char dummy[65536]; | |
1595 | + | |
1596 | + GETCHAR(flags, inp); | |
1597 | + len--; | |
1598 | + | |
1599 | + if (flags & EAP_TLS_FLAGS_LI && !ets->data) { | |
1600 | + | |
1601 | + /* | |
1602 | + * This is the first packet of a message | |
1603 | + */ | |
1604 | + | |
1605 | + GETLONG(tlslen, inp); | |
1606 | + len -= 4; | |
1607 | + | |
1608 | + if (tlslen > EAP_TLS_MAX_LEN) { | |
1609 | + error("Error: tls message length > %d, truncated", | |
1610 | + EAP_TLS_MAX_LEN); | |
1611 | + tlslen = EAP_TLS_MAX_LEN; | |
1612 | + } | |
1613 | + | |
1614 | + /* | |
1615 | + * Allocate memory for the whole message | |
1616 | + */ | |
1617 | + ets->data = malloc(tlslen); | |
1618 | + if (!ets->data) | |
1619 | + fatal("EAP TLS: allocation error\n"); | |
1620 | + | |
1621 | + ets->datalen = 0; | |
1622 | + ets->tlslen = tlslen; | |
1623 | + | |
1624 | + } | |
1625 | + else if (flags & EAP_TLS_FLAGS_LI && ets->data) { | |
1626 | + /* | |
1627 | + * Non first with LI (strange...) | |
1628 | + */ | |
1629 | + | |
1630 | + GETLONG(tlslen, inp); | |
1631 | + len -= 4; | |
1632 | + | |
1633 | + } | |
1634 | + else if (!ets->data) { | |
1635 | + /* | |
1636 | + * A non fragmented message without LI flag | |
1637 | + */ | |
1638 | + | |
1639 | + ets->data = malloc(len); | |
1640 | + if (!ets->data) | |
1641 | + fatal("EAP TLS: allocation error\n"); | |
1642 | + | |
1643 | + ets->datalen = 0; | |
1644 | + ets->tlslen = len; | |
1645 | + } | |
1646 | + | |
1647 | + if (flags & EAP_TLS_FLAGS_MF) | |
1648 | + ets->frag = 1; | |
1649 | + else | |
1650 | + ets->frag = 0; | |
1651 | + | |
1652 | + if (len + ets->datalen > ets->tlslen) { | |
1653 | + warn("EAP TLS: received data > TLS message length"); | |
1654 | + return 1; | |
1655 | + } | |
1656 | + | |
1657 | + BCOPY(inp, ets->data + ets->datalen, len); | |
1658 | + ets->datalen += len; | |
1659 | + | |
1660 | + if (!ets->frag) { | |
1661 | + | |
1662 | + /* | |
1663 | + * If we have the whole message, pass it to ssl | |
1664 | + */ | |
1665 | + | |
1666 | + if (ets->datalen != ets->tlslen) { | |
1667 | + warn("EAP TLS: received data != TLS message length"); | |
1668 | + return 1; | |
1669 | + } | |
1670 | + | |
1671 | + if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1) | |
1672 | + log_ssl_errors(); | |
1673 | + | |
1674 | + SSL_read(ets->ssl, dummy, 65536); | |
1675 | + | |
1676 | + free(ets->data); | |
1677 | + ets->data = NULL; | |
1678 | + ets->datalen = 0; | |
1679 | + } | |
1680 | + | |
1681 | + return 0; | |
1682 | +} | |
1683 | + | |
1684 | +/* | |
1685 | + * Return an eap-tls packet in outp. | |
1686 | + * A TLS message read from the ssl engine is buffered in ets->data. | |
1687 | + * At each call we control if there is buffered data and send a | |
1688 | + * packet of mtu bytes. | |
1689 | + */ | |
1690 | +int eaptls_send(struct eaptls_session *ets, u_char ** outp) | |
1691 | +{ | |
1692 | + bool first = 0; | |
1693 | + int size; | |
1694 | + u_char fromtls[65536]; | |
1695 | + int res; | |
1696 | + u_char *start; | |
1697 | + | |
1698 | + start = *outp; | |
1699 | + | |
1700 | + if (!ets->data) { | |
1701 | + | |
1702 | + if(!ets->alert_sent) | |
1703 | + SSL_read(ets->ssl, fromtls, 65536); | |
1704 | + | |
1705 | + /* | |
1706 | + * Read from ssl | |
1707 | + */ | |
1708 | + if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1) | |
1709 | + fatal("No data from BIO_read"); | |
1710 | + | |
1711 | + ets->datalen = res; | |
1712 | + | |
1713 | + ets->data = malloc(ets->datalen); | |
1714 | + BCOPY(fromtls, ets->data, ets->datalen); | |
1715 | + | |
1716 | + ets->offset = 0; | |
1717 | + first = 1; | |
1718 | + | |
1719 | + } | |
1720 | + | |
1721 | + size = ets->datalen - ets->offset; | |
1722 | + | |
1723 | + if (size > ets->mtu) { | |
1724 | + size = ets->mtu; | |
1725 | + ets->frag = 1; | |
1726 | + } else | |
1727 | + ets->frag = 0; | |
1728 | + | |
1729 | + PUTCHAR(EAPT_TLS, *outp); | |
1730 | + | |
1731 | + /* | |
1732 | + * Set right flags and length if necessary | |
1733 | + */ | |
1734 | + if (ets->frag && first) { | |
1735 | + PUTCHAR(EAP_TLS_FLAGS_LI | EAP_TLS_FLAGS_MF, *outp); | |
1736 | + PUTLONG(ets->datalen, *outp); | |
1737 | + } else if (ets->frag) { | |
1738 | + PUTCHAR(EAP_TLS_FLAGS_MF, *outp); | |
1739 | + } else | |
1740 | + PUTCHAR(0, *outp); | |
1741 | + | |
1742 | + /* | |
1743 | + * Copy the data in outp | |
1744 | + */ | |
1745 | + BCOPY(ets->data + ets->offset, *outp, size); | |
1746 | + INCPTR(size, *outp); | |
1747 | + | |
1748 | + /* | |
1749 | + * Copy the packet in retransmission buffer | |
1750 | + */ | |
1751 | + BCOPY(start, &ets->rtx[0], *outp - start); | |
1752 | + ets->rtx_len = *outp - start; | |
1753 | + | |
1754 | + ets->offset += size; | |
1755 | + | |
1756 | + if (ets->offset >= ets->datalen) { | |
1757 | + | |
1758 | + /* | |
1759 | + * The whole message has been sent | |
1760 | + */ | |
1761 | + | |
1762 | + free(ets->data); | |
1763 | + ets->data = NULL; | |
1764 | + ets->datalen = 0; | |
1765 | + ets->offset = 0; | |
1766 | + } | |
1767 | + | |
1768 | + return 0; | |
1769 | +} | |
1770 | + | |
1771 | +/* | |
1772 | + * Get the sent packet from the retransmission buffer | |
1773 | + */ | |
1774 | +void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp) | |
1775 | +{ | |
1776 | + BCOPY(ets->rtx, *outp, ets->rtx_len); | |
1777 | + INCPTR(ets->rtx_len, *outp); | |
1778 | +} | |
1779 | + | |
1780 | +/* | |
1781 | + * Verify a certificate. | |
1782 | + * Most of the work (signatures and issuer attributes checking) | |
1783 | + * is done by ssl; we check the CN in the peer certificate | |
1784 | + * against the peer name. | |
1785 | + */ | |
1786 | +int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx) | |
1787 | +{ | |
1788 | + char subject[256]; | |
1789 | + char cn_str[256]; | |
1790 | + X509 *peer_cert; | |
1791 | + int err, depth; | |
1792 | + int ok = preverify_ok; | |
1793 | + SSL *ssl; | |
1794 | + struct eaptls_session *ets; | |
1795 | + | |
1796 | + peer_cert = X509_STORE_CTX_get_current_cert(ctx); | |
1797 | + err = X509_STORE_CTX_get_error(ctx); | |
1798 | + depth = X509_STORE_CTX_get_error_depth(ctx); | |
1799 | + | |
1800 | + dbglog("certificate verify depth: %d", depth); | |
1801 | + | |
1802 | + if (auth_required && !ok) { | |
1803 | + X509_NAME_oneline(X509_get_subject_name(peer_cert), | |
1804 | + subject, 256); | |
1805 | + | |
1806 | + X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), | |
1807 | + NID_commonName, cn_str, 256); | |
1808 | + | |
1809 | + dbglog("Certificate verification error:\n depth: %d CN: %s" | |
1810 | + "\n err: %d (%s)\n", depth, cn_str, err, | |
1811 | + X509_verify_cert_error_string(err)); | |
1812 | + | |
1813 | + return 0; | |
1814 | + } | |
1815 | + | |
1816 | + ssl = X509_STORE_CTX_get_ex_data(ctx, | |
1817 | + SSL_get_ex_data_X509_STORE_CTX_idx()); | |
1818 | + | |
1819 | + ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0); | |
1820 | + | |
1821 | + if (ets == NULL) { | |
1822 | + error("Error: SSL_get_ex_data returned NULL"); | |
1823 | + return 0; | |
1824 | + } | |
1825 | + | |
1826 | + log_ssl_errors(); | |
1827 | + | |
1828 | + if (!depth) { /* This is the peer certificate */ | |
1829 | + | |
1830 | + X509_NAME_oneline(X509_get_subject_name(peer_cert), | |
1831 | + subject, 256); | |
1832 | + | |
1833 | + X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), | |
1834 | + NID_commonName, cn_str, 256); | |
1835 | + | |
1836 | + /* | |
1837 | + * If acting as client and the name of the server wasn't specified | |
1838 | + * explicitely, we can't verify the server authenticity | |
1839 | + */ | |
1840 | + if (!ets->peer[0]) { | |
1841 | + warn("Peer name not specified: no check"); | |
1842 | + return 1; | |
1843 | + } | |
1844 | + | |
1845 | + /* | |
1846 | + * Check the CN | |
1847 | + */ | |
1848 | + if (strcmp(cn_str, ets->peer)) { | |
1849 | + error | |
1850 | + ("Certificate verification error: CN (%s) != peer_name (%s)", | |
1851 | + cn_str, ets->peer); | |
1852 | + return 0; | |
1853 | + } | |
1854 | + | |
1855 | + warn("Certificate CN: %s , peer name %s", cn_str, ets->peer); | |
1856 | + | |
1857 | + /* | |
1858 | + * If a peer certificate file was specified, here we check it | |
1859 | + */ | |
1860 | + if (ets->peercertfile[0]) { | |
1861 | + if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert) | |
1862 | + != 0) { | |
1863 | + error | |
1864 | + ("Peer certificate doesn't match stored certificate"); | |
1865 | + return 0; | |
1866 | + } | |
1867 | + } | |
1868 | + } | |
1869 | + | |
1870 | + return 1; | |
1871 | +} | |
1872 | + | |
1873 | +/* | |
1874 | + * Compare a certificate with the one stored in a file | |
1875 | + */ | |
1876 | +int ssl_cmp_certs(char *filename, X509 * a) | |
1877 | +{ | |
1878 | + X509 *b; | |
1879 | + int ret; | |
1880 | + | |
1881 | + if (!(b = get_X509_from_file(filename))) | |
1882 | + return 1; | |
1883 | + | |
1884 | + ret = X509_cmp(a, b); | |
1885 | + X509_free(b); | |
1886 | + | |
1887 | + return ret; | |
1888 | + | |
1889 | +} | |
1890 | + | |
1891 | +X509 *get_X509_from_file(char *filename) | |
1892 | +{ | |
1893 | + FILE *fp; | |
1894 | + X509 *ret; | |
1895 | + | |
1896 | + if (!(fp = fopen(filename, "r"))) | |
1897 | + return NULL; | |
1898 | + | |
1899 | + ret = PEM_read_X509(fp, NULL, NULL, NULL); | |
1900 | + | |
1901 | + fclose(fp); | |
1902 | + | |
1903 | + return ret; | |
1904 | +} | |
1905 | + | |
1906 | +/* | |
1907 | + * Every sent & received message this callback function is invoked, | |
1908 | + * so we know when alert messages have arrived or are sent and | |
1909 | + * we can print debug information about TLS handshake. | |
1910 | + */ | |
1911 | +void | |
1912 | +ssl_msg_callback(int write_p, int version, int content_type, | |
1913 | + const void *buf, size_t len, SSL * ssl, void *arg) | |
1914 | +{ | |
1915 | + char string[256]; | |
1916 | + struct eaptls_session *ets = (struct eaptls_session *)arg; | |
1917 | + unsigned char code; | |
1918 | + | |
1919 | + if(write_p) | |
1920 | + strcpy(string, " -> "); | |
1921 | + else | |
1922 | + strcpy(string, " <- "); | |
1923 | + | |
1924 | + | |
1925 | + switch(content_type) { | |
1926 | + | |
1927 | + case SSL3_RT_ALERT: | |
1928 | + strcat(string, "Alert: "); | |
1929 | + code = ((const unsigned char *)buf)[1]; | |
1930 | + | |
1931 | + if (write_p) { | |
1932 | + ets->alert_sent = 1; | |
1933 | + ets->alert_sent_desc = code; | |
1934 | + } else { | |
1935 | + ets->alert_recv = 1; | |
1936 | + ets->alert_recv_desc = code; | |
1937 | + } | |
1938 | + | |
1939 | + strcat(string, SSL_alert_desc_string_long(code)); | |
1940 | + break; | |
1941 | + | |
1942 | + case SSL3_RT_CHANGE_CIPHER_SPEC: | |
1943 | + strcat(string, "ChangeCipherSpec"); | |
1944 | + break; | |
1945 | + | |
1946 | + case SSL3_RT_HANDSHAKE: | |
1947 | + | |
1948 | + strcat(string, "Handshake: "); | |
1949 | + code = ((const unsigned char *)buf)[0]; | |
1950 | + | |
1951 | + switch(code) { | |
1952 | + case SSL3_MT_HELLO_REQUEST: | |
1953 | + strcat(string,"Hello Request"); | |
1954 | + break; | |
1955 | + case SSL3_MT_CLIENT_HELLO: | |
1956 | + strcat(string,"Client Hello"); | |
1957 | + break; | |
1958 | + case SSL3_MT_SERVER_HELLO: | |
1959 | + strcat(string,"Server Hello"); | |
1960 | + break; | |
1961 | + case SSL3_MT_CERTIFICATE: | |
1962 | + strcat(string,"Certificate"); | |
1963 | + break; | |
1964 | + case SSL3_MT_SERVER_KEY_EXCHANGE: | |
1965 | + strcat(string,"Server Key Exchange"); | |
1966 | + break; | |
1967 | + case SSL3_MT_CERTIFICATE_REQUEST: | |
1968 | + strcat(string,"Certificate Request"); | |
1969 | + break; | |
1970 | + case SSL3_MT_SERVER_DONE: | |
1971 | + strcat(string,"Server Hello Done"); | |
1972 | + break; | |
1973 | + case SSL3_MT_CERTIFICATE_VERIFY: | |
1974 | + strcat(string,"Certificate Verify"); | |
1975 | + break; | |
1976 | + case SSL3_MT_CLIENT_KEY_EXCHANGE: | |
1977 | + strcat(string,"Client Key Exchange"); | |
1978 | + break; | |
1979 | + case SSL3_MT_FINISHED: | |
1980 | + strcat(string,"Finished"); | |
1981 | + break; | |
1982 | + | |
1983 | + default: | |
1984 | + sprintf( string, "Handshake: Unknown SSL3 code received: %d", code ); | |
1985 | + } | |
1986 | + break; | |
1987 | + | |
1988 | + default: | |
1989 | + sprintf( string, "SSL message contains unknown content type: %d", content_type ); | |
1990 | + | |
1991 | + } | |
1992 | + | |
1993 | + /* Alert messages must always be displayed */ | |
1994 | + if(content_type == SSL3_RT_ALERT) | |
1995 | + error("%s", string); | |
1996 | + else | |
1997 | + dbglog("%s", string); | |
1998 | +} | |
1999 | + | |
2000 | diff -Naur ppp-2.4.5/pppd/eap-tls.h ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.h | |
2001 | --- ppp-2.4.5/pppd/eap-tls.h 1970-01-01 01:00:00.000000000 +0100 | |
2002 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.h 2010-10-01 15:17:54.213271816 +0200 | |
2003 | @@ -0,0 +1,107 @@ | |
2004 | +/* | |
2005 | + * eap-tls.h | |
2006 | + * | |
2007 | + * Copyright (c) Beniamino Galvani 2005 All rights reserved. | |
2008 | + * | |
2009 | + * Redistribution and use in source and binary forms, with or without | |
2010 | + * modification, are permitted provided that the following conditions | |
2011 | + * are met: | |
2012 | + * | |
2013 | + * 1. Redistributions of source code must retain the above copyright | |
2014 | + * notice, this list of conditions and the following disclaimer. | |
2015 | + * | |
2016 | + * 2. Redistributions in binary form must reproduce the above copyright | |
2017 | + * notice, this list of conditions and the following disclaimer in | |
2018 | + * the documentation and/or other materials provided with the | |
2019 | + * distribution. | |
2020 | + * | |
2021 | + * 3. The name(s) of the authors of this software must not be used to | |
2022 | + * endorse or promote products derived from this software without | |
2023 | + * prior written permission. | |
2024 | + * | |
2025 | + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO | |
2026 | + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
2027 | + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |
2028 | + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
2029 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
2030 | + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |
2031 | + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
2032 | + * | |
2033 | + */ | |
2034 | + | |
2035 | +#ifndef __EAP_TLS_H__ | |
2036 | +#define __EAP_TLS_H__ | |
2037 | + | |
2038 | +#include "eap.h" | |
2039 | + | |
2040 | +#include <openssl/ssl.h> | |
2041 | +#include <openssl/bio.h> | |
2042 | +#include <openssl/md5.h> | |
2043 | + | |
2044 | +#define EAP_TLS_FLAGS_LI 128 /* length included flag */ | |
2045 | +#define EAP_TLS_FLAGS_MF 64 /* more fragments flag */ | |
2046 | +#define EAP_TLS_FLAGS_START 32 /* start flag */ | |
2047 | + | |
2048 | +#define EAP_TLS_MAX_LEN 65536 /* max eap tls packet size */ | |
2049 | + | |
2050 | +struct eaptls_session | |
2051 | +{ | |
2052 | + u_char *data; /* buffered data */ | |
2053 | + int datalen; /* buffered data len */ | |
2054 | + int offset; /* from where to send */ | |
2055 | + int tlslen; /* total length of tls data */ | |
2056 | + bool frag; /* packet is fragmented */ | |
2057 | + SSL_CTX *ctx; | |
2058 | + SSL *ssl; /* ssl connection */ | |
2059 | + BIO *from_ssl; | |
2060 | + BIO *into_ssl; | |
2061 | + char peer[MAXWORDLEN]; /* peer name */ | |
2062 | + char peercertfile[MAXWORDLEN]; | |
2063 | + bool alert_sent; | |
2064 | + u_char alert_sent_desc; | |
2065 | + bool alert_recv; | |
2066 | + u_char alert_recv_desc; | |
2067 | + char rtx[65536]; /* retransmission buffer */ | |
2068 | + int rtx_len; | |
2069 | + int mtu; /* unit mtu */ | |
2070 | +}; | |
2071 | + | |
2072 | +typedef struct pw_cb_data | |
2073 | +{ | |
2074 | + const void *password; | |
2075 | + const char *prompt_info; | |
2076 | +} PW_CB_DATA; | |
2077 | + | |
2078 | + | |
2079 | +int ssl_verify_callback(int, X509_STORE_CTX *); | |
2080 | +void ssl_msg_callback(int write_p, int version, int ct, const void *buf, | |
2081 | + size_t len, SSL * ssl, void *arg); | |
2082 | + | |
2083 | +X509 *get_X509_from_file(char *filename); | |
2084 | +int ssl_cmp_certs(char *filename, X509 * a); | |
2085 | + | |
2086 | +SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, | |
2087 | + char *certfile, char *peer_certfile, char *privkeyfile); | |
2088 | +int eaptls_init_ssl_server(eap_state * esp); | |
2089 | +int eaptls_init_ssl_client(eap_state * esp); | |
2090 | +void eaptls_free_session(struct eaptls_session *ets); | |
2091 | + | |
2092 | +int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len); | |
2093 | +int eaptls_send(struct eaptls_session *ets, u_char ** outp); | |
2094 | +void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp); | |
2095 | + | |
2096 | +int get_eaptls_secret(int unit, char *client, char *server, | |
2097 | + char *clicertfile, char *servcertfile, char *cacertfile, | |
2098 | + char *pkfile, int am_server); | |
2099 | + | |
2100 | +#ifdef MPPE | |
2101 | +#include "mppe.h" /* MPPE_MAX_KEY_LEN */ | |
2102 | +extern u_char mppe_send_key[MPPE_MAX_KEY_LEN]; | |
2103 | +extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN]; | |
2104 | +extern int mppe_keys_set; | |
2105 | + | |
2106 | +void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, int client); | |
2107 | + | |
2108 | +#endif | |
2109 | + | |
2110 | +#endif | |
2111 | diff -Naur ppp-2.4.5/pppd/eap.c ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.c | |
2112 | --- ppp-2.4.5/pppd/eap.c 2009-11-16 23:26:07.000000000 +0100 | |
2113 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.c 2010-01-29 16:31:29.000000000 +0100 | |
2114 | @@ -43,6 +43,11 @@ | |
2115 | * Based on draft-ietf-pppext-eap-srp-03.txt. | |
2116 | */ | |
2117 | ||
2118 | +/* | |
2119 | + * Modification by Beniamino Galvani, Mar 2005 | |
2120 | + * Implemented EAP-TLS authentication | |
2121 | + */ | |
2122 | + | |
2123 | #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $" | |
2124 | ||
2125 | /* | |
2126 | @@ -62,8 +67,12 @@ | |
2127 | ||
2128 | #include "pppd.h" | |
2129 | #include "pathnames.h" | |
2130 | -#include "md5.h" | |
2131 | #include "eap.h" | |
2132 | +#ifdef USE_EAPTLS | |
2133 | +#include "eap-tls.h" | |
2134 | +#else | |
2135 | +#include "md5.h" | |
2136 | +#endif /* USE_EAPTLS */ | |
2137 | ||
2138 | #ifdef USE_SRP | |
2139 | #include <t_pwd.h> | |
2140 | @@ -209,6 +218,9 @@ | |
2141 | esp->es_server.ea_id = (u_char)(drand48() * 0x100); | |
2142 | esp->es_client.ea_timeout = EAP_DEFREQTIME; | |
2143 | esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ; | |
2144 | +#ifdef USE_EAPTLS | |
2145 | + esp->es_client.ea_using_eaptls = 0; | |
2146 | +#endif /* USE_EAPTLS */ | |
2147 | } | |
2148 | ||
2149 | /* | |
2150 | @@ -436,8 +448,16 @@ | |
2151 | u_char vals[2]; | |
2152 | struct b64state bs; | |
2153 | #endif /* USE_SRP */ | |
2154 | +#ifdef USE_EAPTLS | |
2155 | + struct eaptls_session *ets; | |
2156 | + int secret_len; | |
2157 | + char secret[MAXWORDLEN]; | |
2158 | +#endif /* USE_EAPTLS */ | |
2159 | ||
2160 | esp->es_server.ea_timeout = esp->es_savedtime; | |
2161 | +#ifdef USE_EAPTLS | |
2162 | + esp->es_server.ea_prev_state = esp->es_server.ea_state; | |
2163 | +#endif /* USE_EAPTLS */ | |
2164 | switch (esp->es_server.ea_state) { | |
2165 | case eapBadAuth: | |
2166 | return; | |
2167 | @@ -562,9 +582,81 @@ | |
2168 | break; | |
2169 | } | |
2170 | #endif /* USE_SRP */ | |
2171 | +#ifdef USE_EAPTLS | |
2172 | + if (!get_secret(esp->es_unit, esp->es_server.ea_peer, | |
2173 | + esp->es_server.ea_name, secret, &secret_len, 1)) { | |
2174 | + | |
2175 | + esp->es_server.ea_state = eapTlsStart; | |
2176 | + break; | |
2177 | + } | |
2178 | +#endif /* USE_EAPTLS */ | |
2179 | + | |
2180 | esp->es_server.ea_state = eapMD5Chall; | |
2181 | break; | |
2182 | ||
2183 | +#ifdef USE_EAPTLS | |
2184 | + case eapTlsStart: | |
2185 | + /* Initialize ssl session */ | |
2186 | + if(!eaptls_init_ssl_server(esp)) { | |
2187 | + esp->es_server.ea_state = eapBadAuth; | |
2188 | + break; | |
2189 | + } | |
2190 | + | |
2191 | + esp->es_server.ea_state = eapTlsRecv; | |
2192 | + break; | |
2193 | + | |
2194 | + case eapTlsRecv: | |
2195 | + ets = (struct eaptls_session *) esp->es_server.ea_session; | |
2196 | + | |
2197 | + if(ets->alert_sent) { | |
2198 | + esp->es_server.ea_state = eapTlsSendAlert; | |
2199 | + break; | |
2200 | + } | |
2201 | + | |
2202 | + if (status) { | |
2203 | + esp->es_server.ea_state = eapBadAuth; | |
2204 | + break; | |
2205 | + } | |
2206 | + ets = (struct eaptls_session *) esp->es_server.ea_session; | |
2207 | + | |
2208 | + if(ets->frag) | |
2209 | + esp->es_server.ea_state = eapTlsSendAck; | |
2210 | + else | |
2211 | + esp->es_server.ea_state = eapTlsSend; | |
2212 | + break; | |
2213 | + | |
2214 | + case eapTlsSend: | |
2215 | + ets = (struct eaptls_session *) esp->es_server.ea_session; | |
2216 | + | |
2217 | + if(SSL_is_init_finished(ets->ssl)) { | |
2218 | + esp->es_server.ea_state = eapTlsRecvClient; | |
2219 | + break; | |
2220 | + } | |
2221 | + | |
2222 | + if(ets->frag) | |
2223 | + esp->es_server.ea_state = eapTlsRecvAck; | |
2224 | + else | |
2225 | + esp->es_server.ea_state = eapTlsRecv; | |
2226 | + break; | |
2227 | + | |
2228 | + case eapTlsSendAck: | |
2229 | + esp->es_server.ea_state = eapTlsRecv; | |
2230 | + break; | |
2231 | + | |
2232 | + case eapTlsRecvAck: | |
2233 | + if (status) { | |
2234 | + esp->es_server.ea_state = eapBadAuth; | |
2235 | + break; | |
2236 | + } | |
2237 | + | |
2238 | + esp->es_server.ea_state = eapTlsSend; | |
2239 | + break; | |
2240 | + | |
2241 | + case eapTlsSendAlert: | |
2242 | + esp->es_server.ea_state = eapTlsRecvAlertAck; | |
2243 | + break; | |
2244 | +#endif /* USE_EAPTLS */ | |
2245 | + | |
2246 | case eapSRP1: | |
2247 | #ifdef USE_SRP | |
2248 | ts = (struct t_server *)esp->es_server.ea_session; | |
2249 | @@ -718,6 +810,30 @@ | |
2250 | INCPTR(esp->es_server.ea_namelen, outp); | |
2251 | break; | |
2252 | ||
2253 | +#ifdef USE_EAPTLS | |
2254 | + case eapTlsStart: | |
2255 | + PUTCHAR(EAPT_TLS, outp); | |
2256 | + PUTCHAR(EAP_TLS_FLAGS_START, outp); | |
2257 | + eap_figure_next_state(esp, 0); | |
2258 | + break; | |
2259 | + | |
2260 | + case eapTlsSend: | |
2261 | + eaptls_send(esp->es_server.ea_session, &outp); | |
2262 | + eap_figure_next_state(esp, 0); | |
2263 | + break; | |
2264 | + | |
2265 | + case eapTlsSendAck: | |
2266 | + PUTCHAR(EAPT_TLS, outp); | |
2267 | + PUTCHAR(0, outp); | |
2268 | + eap_figure_next_state(esp, 0); | |
2269 | + break; | |
2270 | + | |
2271 | + case eapTlsSendAlert: | |
2272 | + eaptls_send(esp->es_server.ea_session, &outp); | |
2273 | + eap_figure_next_state(esp, 0); | |
2274 | + break; | |
2275 | +#endif /* USE_EAPTLS */ | |
2276 | + | |
2277 | #ifdef USE_SRP | |
2278 | case eapSRP1: | |
2279 | PUTCHAR(EAPT_SRP, outp); | |
2280 | @@ -904,11 +1020,57 @@ | |
2281 | eap_server_timeout(arg) | |
2282 | void *arg; | |
2283 | { | |
2284 | +#ifdef USE_EAPTLS | |
2285 | + u_char *outp; | |
2286 | + u_char *lenloc; | |
2287 | + int outlen; | |
2288 | +#endif /* USE_EAPTLS */ | |
2289 | + | |
2290 | eap_state *esp = (eap_state *) arg; | |
2291 | ||
2292 | if (!eap_server_active(esp)) | |
2293 | return; | |
2294 | ||
2295 | +#ifdef USE_EAPTLS | |
2296 | + switch(esp->es_server.ea_prev_state) { | |
2297 | + | |
2298 | + /* | |
2299 | + * In eap-tls the state changes after a request, so we return to | |
2300 | + * previous state ... | |
2301 | + */ | |
2302 | + case(eapTlsStart): | |
2303 | + case(eapTlsSendAck): | |
2304 | + esp->es_server.ea_state = esp->es_server.ea_prev_state; | |
2305 | + break; | |
2306 | + | |
2307 | + /* | |
2308 | + * ... or resend the stored data | |
2309 | + */ | |
2310 | + case(eapTlsSend): | |
2311 | + case(eapTlsSendAlert): | |
2312 | + outp = outpacket_buf; | |
2313 | + MAKEHEADER(outp, PPP_EAP); | |
2314 | + PUTCHAR(EAP_REQUEST, outp); | |
2315 | + PUTCHAR(esp->es_server.ea_id, outp); | |
2316 | + lenloc = outp; | |
2317 | + INCPTR(2, outp); | |
2318 | + | |
2319 | + eaptls_retransmit(esp->es_server.ea_session, &outp); | |
2320 | + | |
2321 | + outlen = (outp - outpacket_buf) - PPP_HDRLEN; | |
2322 | + PUTSHORT(outlen, lenloc); | |
2323 | + output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN); | |
2324 | + esp->es_server.ea_requests++; | |
2325 | + | |
2326 | + if (esp->es_server.ea_timeout > 0) | |
2327 | + TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout); | |
2328 | + | |
2329 | + return; | |
2330 | + default: | |
2331 | + break; | |
2332 | + } | |
2333 | +#endif /* USE_EAPTLS */ | |
2334 | + | |
2335 | /* EAP ID number must not change on timeout. */ | |
2336 | eap_send_request(esp); | |
2337 | } | |
2338 | @@ -1166,6 +1328,81 @@ | |
2339 | } | |
2340 | #endif /* USE_SRP */ | |
2341 | ||
2342 | +#ifdef USE_EAPTLS | |
2343 | +/* | |
2344 | + * Send an EAP-TLS response message with tls data | |
2345 | + */ | |
2346 | +static void | |
2347 | +eap_tls_response(esp, id) | |
2348 | +eap_state *esp; | |
2349 | +u_char id; | |
2350 | +{ | |
2351 | + u_char *outp; | |
2352 | + int outlen; | |
2353 | + u_char *lenloc; | |
2354 | + | |
2355 | + outp = outpacket_buf; | |
2356 | + | |
2357 | + MAKEHEADER(outp, PPP_EAP); | |
2358 | + | |
2359 | + PUTCHAR(EAP_RESPONSE, outp); | |
2360 | + PUTCHAR(id, outp); | |
2361 | + | |
2362 | + lenloc = outp; | |
2363 | + INCPTR(2, outp); | |
2364 | + | |
2365 | + /* | |
2366 | + If the id in the request is unchanged, we must retransmit | |
2367 | + the old data | |
2368 | + */ | |
2369 | + if(id == esp->es_client.ea_id) | |
2370 | + eaptls_retransmit(esp->es_client.ea_session, &outp); | |
2371 | + else | |
2372 | + eaptls_send(esp->es_client.ea_session, &outp); | |
2373 | + | |
2374 | + outlen = (outp - outpacket_buf) - PPP_HDRLEN; | |
2375 | + PUTSHORT(outlen, lenloc); | |
2376 | + | |
2377 | + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen); | |
2378 | + | |
2379 | + esp->es_client.ea_id = id; | |
2380 | + | |
2381 | +} | |
2382 | + | |
2383 | +/* | |
2384 | + * Send an EAP-TLS ack | |
2385 | + */ | |
2386 | +static void | |
2387 | +eap_tls_sendack(esp, id) | |
2388 | +eap_state *esp; | |
2389 | +u_char id; | |
2390 | +{ | |
2391 | + u_char *outp; | |
2392 | + int outlen; | |
2393 | + u_char *lenloc; | |
2394 | + | |
2395 | + outp = outpacket_buf; | |
2396 | + | |
2397 | + MAKEHEADER(outp, PPP_EAP); | |
2398 | + | |
2399 | + PUTCHAR(EAP_RESPONSE, outp); | |
2400 | + PUTCHAR(id, outp); | |
2401 | + esp->es_client.ea_id = id; | |
2402 | + | |
2403 | + lenloc = outp; | |
2404 | + INCPTR(2, outp); | |
2405 | + | |
2406 | + PUTCHAR(EAPT_TLS, outp); | |
2407 | + PUTCHAR(0, outp); | |
2408 | + | |
2409 | + outlen = (outp - outpacket_buf) - PPP_HDRLEN; | |
2410 | + PUTSHORT(outlen, lenloc); | |
2411 | + | |
2412 | + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen); | |
2413 | + | |
2414 | +} | |
2415 | +#endif /* USE_EAPTLS */ | |
2416 | + | |
2417 | static void | |
2418 | eap_send_nak(esp, id, type) | |
2419 | eap_state *esp; | |
2420 | @@ -1320,6 +1557,11 @@ | |
2421 | char rhostname[256]; | |
2422 | MD5_CTX mdContext; | |
2423 | u_char hash[MD5_SIGNATURE_SIZE]; | |
2424 | +#ifdef USE_EAPTLS | |
2425 | + u_char flags; | |
2426 | + struct eaptls_session *ets = esp->es_client.ea_session; | |
2427 | +#endif /* USE_EAPTLS */ | |
2428 | + | |
2429 | #ifdef USE_SRP | |
2430 | struct t_client *tc; | |
2431 | struct t_num sval, gval, Nval, *Ap, Bval; | |
2432 | @@ -1456,6 +1698,90 @@ | |
2433 | esp->es_client.ea_namelen); | |
2434 | break; | |
2435 | ||
2436 | +#ifdef USE_EAPTLS | |
2437 | + case EAPT_TLS: | |
2438 | + | |
2439 | + switch(esp->es_client.ea_state) { | |
2440 | + | |
2441 | + case eapListen: | |
2442 | + | |
2443 | + GETCHAR(flags, inp); | |
2444 | + if(flags & EAP_TLS_FLAGS_START){ | |
2445 | + | |
2446 | + esp->es_client.ea_using_eaptls = 1; | |
2447 | + | |
2448 | + if (explicit_remote){ | |
2449 | + esp->es_client.ea_peer = strdup(remote_name); | |
2450 | + esp->es_client.ea_peerlen = strlen(remote_name); | |
2451 | + } else | |
2452 | + esp->es_client.ea_peer = NULL; | |
2453 | + | |
2454 | + /* Init ssl session */ | |
2455 | + if(!eaptls_init_ssl_client(esp)) { | |
2456 | + dbglog("cannot init ssl"); | |
2457 | + eap_send_nak(esp, id, EAPT_TLS); | |
2458 | + esp->es_client.ea_using_eaptls = 0; | |
2459 | + break; | |
2460 | + } | |
2461 | + | |
2462 | + ets = esp->es_client.ea_session; | |
2463 | + eap_tls_response(esp, id); | |
2464 | + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : | |
2465 | + eapTlsRecv); | |
2466 | + break; | |
2467 | + } | |
2468 | + | |
2469 | + /* The server has sent a bad start packet. */ | |
2470 | + eap_send_nak(esp, id, EAPT_TLS); | |
2471 | + break; | |
2472 | + | |
2473 | + case eapTlsRecvAck: | |
2474 | + eap_tls_response(esp, id); | |
2475 | + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : | |
2476 | + eapTlsRecv); | |
2477 | + break; | |
2478 | + | |
2479 | + case eapTlsRecv: | |
2480 | + eaptls_receive(ets, inp, len); | |
2481 | + | |
2482 | + if(ets->frag) { | |
2483 | + eap_tls_sendack(esp, id); | |
2484 | + esp->es_client.ea_state = eapTlsRecv; | |
2485 | + break; | |
2486 | + } | |
2487 | + | |
2488 | + if(ets->alert_recv) { | |
2489 | + eap_tls_sendack(esp, id); | |
2490 | + esp->es_client.ea_state = eapTlsRecvFailure; | |
2491 | + break; | |
2492 | + } | |
2493 | + | |
2494 | + /* Check if TLS handshake is finished */ | |
2495 | + if(SSL_is_init_finished(ets->ssl)){ | |
2496 | +#ifdef MPPE | |
2497 | + eaptls_gen_mppe_keys( ets, "client EAP encryption", 1 ); | |
2498 | +#endif | |
2499 | + eaptls_free_session(ets); | |
2500 | + eap_tls_sendack(esp, id); | |
2501 | + esp->es_client.ea_state = eapTlsRecvSuccess; | |
2502 | + break; | |
2503 | + } | |
2504 | + | |
2505 | + eap_tls_response(esp,id); | |
2506 | + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : | |
2507 | + eapTlsRecv); | |
2508 | + | |
2509 | + break; | |
2510 | + | |
2511 | + default: | |
2512 | + eap_send_nak(esp, id, EAPT_TLS); | |
2513 | + esp->es_client.ea_using_eaptls = 0; | |
2514 | + break; | |
2515 | + } | |
2516 | + | |
2517 | + break; | |
2518 | +#endif /* USE_EAPTLS */ | |
2519 | + | |
2520 | #ifdef USE_SRP | |
2521 | case EAPT_SRP: | |
2522 | if (len < 1) { | |
2523 | @@ -1737,6 +2063,11 @@ | |
2524 | u_char dig[SHA_DIGESTSIZE]; | |
2525 | #endif /* USE_SRP */ | |
2526 | ||
2527 | +#ifdef USE_EAPTLS | |
2528 | + struct eaptls_session *ets; | |
2529 | + u_char flags; | |
2530 | +#endif /* USE_EAPTLS */ | |
2531 | + | |
2532 | if (esp->es_server.ea_id != id) { | |
2533 | dbglog("EAP: discarding Response %d; expected ID %d", id, | |
2534 | esp->es_server.ea_id); | |
2535 | @@ -1776,6 +2107,60 @@ | |
2536 | eap_figure_next_state(esp, 0); | |
2537 | break; | |
2538 | ||
2539 | +#ifdef USE_EAPTLS | |
2540 | + case EAPT_TLS: | |
2541 | + switch(esp->es_server.ea_state) { | |
2542 | + | |
2543 | + case eapTlsRecv: | |
2544 | + ets = (struct eaptls_session *) esp->es_server.ea_session; | |
2545 | + eap_figure_next_state(esp, | |
2546 | + eaptls_receive(esp->es_server.ea_session, inp, len)); | |
2547 | + | |
2548 | + if(ets->alert_recv) { | |
2549 | + eap_send_failure(esp); | |
2550 | + break; | |
2551 | + } | |
2552 | + break; | |
2553 | + | |
2554 | + case eapTlsRecvAck: | |
2555 | + if(len > 1) { | |
2556 | + dbglog("EAP-TLS ACK with extra data"); | |
2557 | + } | |
2558 | + eap_figure_next_state(esp, 0); | |
2559 | + break; | |
2560 | + | |
2561 | + case eapTlsRecvClient: | |
2562 | + /* Receive authentication response from client */ | |
2563 | + | |
2564 | + GETCHAR(flags, inp); | |
2565 | + | |
2566 | + if(len == 1 && !flags) { /* Ack = ok */ | |
2567 | +#ifdef MPPE | |
2568 | + eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 ); | |
2569 | +#endif | |
2570 | + eap_send_success(esp); | |
2571 | + } | |
2572 | + else { /* failure */ | |
2573 | + eaptls_receive(esp->es_server.ea_session, inp, len); | |
2574 | + warn("Server authentication failed"); | |
2575 | + eap_send_failure(esp); | |
2576 | + } | |
2577 | + | |
2578 | + eaptls_free_session(esp->es_server.ea_session); | |
2579 | + | |
2580 | + break; | |
2581 | + | |
2582 | + case eapTlsRecvAlertAck: | |
2583 | + eap_send_failure(esp); | |
2584 | + break; | |
2585 | + | |
2586 | + default: | |
2587 | + eap_figure_next_state(esp, 1); | |
2588 | + break; | |
2589 | + } | |
2590 | + break; | |
2591 | +#endif /* USE_EAPTLS */ | |
2592 | + | |
2593 | case EAPT_NOTIFICATION: | |
2594 | dbglog("EAP unexpected Notification; response discarded"); | |
2595 | break; | |
2596 | @@ -1807,6 +2192,13 @@ | |
2597 | esp->es_server.ea_state = eapMD5Chall; | |
2598 | break; | |
2599 | ||
2600 | +#ifdef USE_EAPTLS | |
2601 | + /* Send EAP-TLS start packet */ | |
2602 | + case EAPT_TLS: | |
2603 | + esp->es_server.ea_state = eapTlsStart; | |
2604 | + break; | |
2605 | +#endif /* USE_EAPTLS */ | |
2606 | + | |
2607 | default: | |
2608 | dbglog("EAP: peer requesting unknown Type %d", vallen); | |
2609 | switch (esp->es_server.ea_state) { | |
2610 | @@ -2018,13 +2410,27 @@ | |
2611 | int id; | |
2612 | int len; | |
2613 | { | |
2614 | - if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) { | |
2615 | + if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp) | |
2616 | +#ifdef USE_EAPTLS | |
2617 | + && esp->es_client.ea_state != eapTlsRecvSuccess | |
2618 | +#endif /* USE_EAPTLS */ | |
2619 | + ) { | |
2620 | dbglog("EAP unexpected success message in state %s (%d)", | |
2621 | eap_state_name(esp->es_client.ea_state), | |
2622 | esp->es_client.ea_state); | |
2623 | return; | |
2624 | } | |
2625 | ||
2626 | +#ifdef USE_EAPTLS | |
2627 | + if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state != | |
2628 | + eapTlsRecvSuccess) { | |
2629 | + dbglog("EAP-TLS unexpected success message in state %s (%d)", | |
2630 | + eap_state_name(esp->es_client.ea_state), | |
2631 | + esp->es_client.ea_state); | |
2632 | + return; | |
2633 | + } | |
2634 | +#endif /* USE_EAPTLS */ | |
2635 | + | |
2636 | if (esp->es_client.ea_timeout > 0) { | |
2637 | UNTIMEOUT(eap_client_timeout, (void *)esp); | |
2638 | } | |
2639 | @@ -2150,6 +2556,9 @@ | |
2640 | int code, id, len, rtype, vallen; | |
2641 | u_char *pstart; | |
2642 | u_int32_t uval; | |
2643 | +#ifdef USE_EAPTLS | |
2644 | + u_char flags; | |
2645 | +#endif /* USE_EAPTLS */ | |
2646 | ||
2647 | if (inlen < EAP_HEADERLEN) | |
2648 | return (0); | |
2649 | @@ -2214,6 +2623,24 @@ | |
2650 | } | |
2651 | break; | |
2652 | ||
2653 | +#ifdef USE_EAPTLS | |
2654 | + case EAPT_TLS: | |
2655 | + if (len < 1) | |
2656 | + break; | |
2657 | + GETCHAR(flags, inp); | |
2658 | + len--; | |
2659 | + | |
2660 | + if(flags == 0 && len == 0){ | |
2661 | + printer(arg, " Ack"); | |
2662 | + break; | |
2663 | + } | |
2664 | + | |
2665 | + printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -"); | |
2666 | + printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-"); | |
2667 | + printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- "); | |
2668 | + break; | |
2669 | +#endif /* USE_EAPTLS */ | |
2670 | + | |
2671 | case EAPT_SRP: | |
2672 | if (len < 3) | |
2673 | goto truncated; | |
2674 | @@ -2325,6 +2752,25 @@ | |
2675 | } | |
2676 | break; | |
2677 | ||
2678 | +#ifdef USE_EAPTLS | |
2679 | + case EAPT_TLS: | |
2680 | + if (len < 1) | |
2681 | + break; | |
2682 | + GETCHAR(flags, inp); | |
2683 | + len--; | |
2684 | + | |
2685 | + if(flags == 0 && len == 0){ | |
2686 | + printer(arg, " Ack"); | |
2687 | + break; | |
2688 | + } | |
2689 | + | |
2690 | + printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -"); | |
2691 | + printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-"); | |
2692 | + printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- "); | |
2693 | + | |
2694 | + break; | |
2695 | +#endif /* USE_EAPTLS */ | |
2696 | + | |
2697 | case EAPT_NAK: | |
2698 | if (len <= 0) { | |
2699 | printer(arg, " <missing hint>"); | |
2700 | @@ -2426,3 +2872,4 @@ | |
2701 | ||
2702 | return (inp - pstart); | |
2703 | } | |
2704 | + | |
2705 | diff -Naur ppp-2.4.5/pppd/eap.h ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.h | |
2706 | --- ppp-2.4.5/pppd/eap.h 2009-11-16 23:26:07.000000000 +0100 | |
2707 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.h 2010-10-01 15:17:54.214270927 +0200 | |
2708 | @@ -84,6 +84,16 @@ | |
2709 | eapClosed, /* Authentication not in use */ | |
2710 | eapListen, /* Client ready (and timer running) */ | |
2711 | eapIdentify, /* EAP Identify sent */ | |
2712 | + eapTlsStart, /* Send EAP-TLS start packet */ | |
2713 | + eapTlsRecv, /* Receive EAP-TLS tls data */ | |
2714 | + eapTlsSendAck, /* Send EAP-TLS ack */ | |
2715 | + eapTlsSend, /* Send EAP-TLS tls data */ | |
2716 | + eapTlsRecvAck, /* Receive EAP-TLS ack */ | |
2717 | + eapTlsRecvClient, /* Receive EAP-TLS auth response from client*/ | |
2718 | + eapTlsSendAlert, /* Send EAP-TLS tls alert (server)*/ | |
2719 | + eapTlsRecvAlertAck, /* Receive EAP-TLS ack after sending alert */ | |
2720 | + eapTlsRecvSuccess, /* Receive EAP success */ | |
2721 | + eapTlsRecvFailure, /* Receive EAP failure */ | |
2722 | eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ | |
2723 | eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ | |
2724 | eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ | |
2725 | @@ -95,9 +105,18 @@ | |
2726 | ||
2727 | #define EAP_STATES \ | |
2728 | "Initial", "Pending", "Closed", "Listen", "Identify", \ | |
2729 | + "TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\ | |
2730 | + "TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \ | |
2731 | "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" | |
2732 | ||
2733 | -#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen) | |
2734 | +#ifdef USE_EAPTLS | |
2735 | +#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial ||\ | |
2736 | + (esp)->es_client.ea_state != eapPending ||\ | |
2737 | + (esp)->es_client.ea_state != eapClosed) | |
2738 | +#else | |
2739 | +#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen) | |
2740 | +#endif /* USE_EAPTLS */ | |
2741 | + | |
2742 | #define eap_server_active(esp) \ | |
2743 | ((esp)->es_server.ea_state >= eapIdentify && \ | |
2744 | (esp)->es_server.ea_state <= eapMD5Chall) | |
2745 | @@ -112,11 +131,17 @@ | |
2746 | u_short ea_namelen; /* Length of our name */ | |
2747 | u_short ea_peerlen; /* Length of peer's name */ | |
2748 | enum eap_state_code ea_state; | |
2749 | +#ifdef USE_EAPTLS | |
2750 | + enum eap_state_code ea_prev_state; | |
2751 | +#endif | |
2752 | u_char ea_id; /* Current id */ | |
2753 | u_char ea_requests; /* Number of Requests sent/received */ | |
2754 | u_char ea_responses; /* Number of Responses */ | |
2755 | u_char ea_type; /* One of EAPT_* */ | |
2756 | u_int32_t ea_keyflags; /* SRP shared key usage flags */ | |
2757 | +#ifdef USE_EAPTLS | |
2758 | + bool ea_using_eaptls; | |
2759 | +#endif | |
2760 | }; | |
2761 | ||
2762 | /* | |
2763 | @@ -139,7 +164,12 @@ | |
2764 | * Timeouts. | |
2765 | */ | |
2766 | #define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ | |
2767 | +#ifdef USE_EAPTLS | |
2768 | +#define EAP_DEFTRANSMITS 30 /* max # times to transmit */ | |
2769 | + /* certificates can be long ... */ | |
2770 | +#else | |
2771 | #define EAP_DEFTRANSMITS 10 /* max # times to transmit */ | |
2772 | +#endif /* USE_EAPTLS */ | |
2773 | #define EAP_DEFREQTIME 20 /* Time to wait for peer request */ | |
2774 | #define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ | |
2775 | ||
2776 | diff -Naur ppp-2.4.5/pppd/md5.c ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.c | |
2777 | --- ppp-2.4.5/pppd/md5.c 2009-11-16 23:26:07.000000000 +0100 | |
2778 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.c 2010-10-01 15:17:54.214270927 +0200 | |
2779 | @@ -33,6 +33,8 @@ | |
2780 | *********************************************************************** | |
2781 | */ | |
2782 | ||
2783 | +#ifndef USE_EAPTLS | |
2784 | + | |
2785 | #include <string.h> | |
2786 | #include "md5.h" | |
2787 | ||
2788 | @@ -305,3 +307,5 @@ | |
2789 | ** End of md5.c ** | |
2790 | ******************************** (cut) ******************************** | |
2791 | */ | |
2792 | +#endif /* USE_EAPTLS */ | |
2793 | + | |
2794 | diff -Naur ppp-2.4.5/pppd/md5.h ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.h | |
2795 | --- ppp-2.4.5/pppd/md5.h 2009-11-16 23:26:07.000000000 +0100 | |
2796 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.h 2010-10-01 15:17:54.215271014 +0200 | |
2797 | @@ -36,6 +36,7 @@ | |
2798 | ** documentation and/or software. ** | |
2799 | *********************************************************************** | |
2800 | */ | |
2801 | +#ifndef USE_EAPTLS | |
2802 | ||
2803 | #ifndef __MD5_INCLUDE__ | |
2804 | ||
2805 | @@ -63,3 +64,5 @@ | |
2806 | ||
2807 | #define __MD5_INCLUDE__ | |
2808 | #endif /* __MD5_INCLUDE__ */ | |
2809 | + | |
2810 | +#endif /* USE_EAPTLS */ | |
2811 | diff -Naur ppp-2.4.5/pppd/options.c ppp-2.4.5-eaptls-mppe-0.99/pppd/options.c | |
2812 | --- ppp-2.4.5/pppd/options.c 2009-11-16 23:26:07.000000000 +0100 | |
2813 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/options.c 2010-10-01 15:17:54.215271014 +0200 | |
2814 | @@ -119,6 +119,10 @@ | |
2815 | bool dryrun; /* print out option values and exit */ | |
2816 | char *domain; /* domain name set by domain option */ | |
2817 | int child_wait = 5; /* # seconds to wait for children at exit */ | |
2818 | +#ifdef USE_EAPTLS | |
2819 | +bool only_update_crl_server = 0; /* update server crl and exit */ | |
2820 | +bool only_update_crl_client = 0; /* update client crl and exit */ | |
2821 | +#endif /* USE_EAPTLS */ | |
2822 | ||
2823 | #ifdef MAXOCTETS | |
2824 | unsigned int maxoctets = 0; /* default - no limit */ | |
2825 | @@ -320,6 +324,12 @@ | |
2826 | { "mo-timeout", o_int, &maxoctets_timeout, | |
2827 | "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, | |
2828 | #endif | |
2829 | +#ifdef USE_EAPTLS | |
2830 | + { "only-update-crl-server", o_bool, &only_update_crl_server, | |
2831 | + "Update server CA CRLs and exit", 1 }, | |
2832 | + { "only-update-crl-client", o_bool, &only_update_crl_client, | |
2833 | + "Update client CA CRLs and exit", 1 }, | |
2834 | +#endif /* USE_EAPTLS */ | |
2835 | ||
2836 | { NULL } | |
2837 | }; | |
2838 | diff -Naur ppp-2.4.5/pppd/pathnames.h ppp-2.4.5-eaptls-mppe-0.99/pppd/pathnames.h | |
2839 | --- ppp-2.4.5/pppd/pathnames.h 2009-11-16 23:26:07.000000000 +0100 | |
2840 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/pathnames.h 2010-10-01 15:17:54.215271014 +0200 | |
2841 | @@ -21,6 +21,13 @@ | |
2842 | #define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets" | |
2843 | #define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets" | |
2844 | #define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets" | |
2845 | + | |
2846 | +#ifdef USE_EAPTLS | |
2847 | +#define _PATH_EAPTLSCLIFILE _ROOT_PATH "/etc/ppp/eaptls-client" | |
2848 | +#define _PATH_EAPTLSSERVFILE _ROOT_PATH "/etc/ppp/eaptls-server" | |
2849 | +#define _PATH_OPENSSLCONFFILE _ROOT_PATH "/etc/ppp/openssl.cnf" | |
2850 | +#endif /* USE_EAPTLS */ | |
2851 | + | |
2852 | #define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options" | |
2853 | #define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up" | |
2854 | #define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down" | |
2855 | diff -Naur ppp-2.4.5/pppd/plugins/Makefile.linux ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/Makefile.linux | |
2856 | --- ppp-2.4.5/pppd/plugins/Makefile.linux 2009-11-16 23:26:07.000000000 +0100 | |
2857 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/Makefile.linux 2010-10-01 15:17:54.215271014 +0200 | |
2858 | @@ -4,6 +4,9 @@ | |
2859 | LDFLAGS = -shared | |
2860 | INSTALL = install | |
2861 | ||
2862 | +# EAP-TLS | |
2863 | +CFLAGS += -DUSE_EAPTLS=1 | |
2864 | + | |
2865 | DESTDIR = $(INSTROOT)@DESTDIR@ | |
2866 | BINDIR = $(DESTDIR)/sbin | |
2867 | MANDIR = $(DESTDIR)/share/man/man8 | |
2868 | diff -Naur ppp-2.4.5/pppd/plugins/passprompt.c ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passprompt.c | |
2869 | --- ppp-2.4.5/pppd/plugins/passprompt.c 2009-11-16 23:26:07.000000000 +0100 | |
2870 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passprompt.c 2010-10-01 15:17:54.215271014 +0200 | |
2871 | @@ -107,4 +107,7 @@ | |
2872 | { | |
2873 | add_options(options); | |
2874 | pap_passwd_hook = promptpass; | |
2875 | +#ifdef USE_EAPTLS | |
2876 | + eaptls_passwd_hook = promptpass; | |
2877 | +#endif | |
2878 | } | |
2879 | diff -Naur ppp-2.4.5/pppd/plugins/passwordfd.c ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passwordfd.c | |
2880 | --- ppp-2.4.5/pppd/plugins/passwordfd.c 2009-11-16 23:26:07.000000000 +0100 | |
2881 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passwordfd.c 2010-10-01 15:17:54.216270820 +0200 | |
2882 | @@ -79,4 +79,9 @@ | |
2883 | ||
2884 | chap_check_hook = pwfd_check; | |
2885 | chap_passwd_hook = pwfd_passwd; | |
2886 | + | |
2887 | +#ifdef USE_EAPTLS | |
2888 | + eaptls_check_hook = pwfd_check; | |
2889 | + eaptls_passwd_hook = pwfd_passwd; | |
2890 | +#endif | |
2891 | } | |
2892 | diff -Naur ppp-2.4.5/pppd/pppd.h ppp-2.4.5-eaptls-mppe-0.99/pppd/pppd.h | |
2893 | --- ppp-2.4.5/pppd/pppd.h 2009-11-16 23:26:07.000000000 +0100 | |
2894 | +++ ppp-2.4.5-eaptls-mppe-0.99/pppd/pppd.h 2010-10-01 15:17:54.216270820 +0200 | |
2895 | @@ -320,6 +320,10 @@ | |
2896 | extern bool dryrun; /* check everything, print options, exit */ | |
2897 | extern int child_wait; /* # seconds to wait for children at end */ | |
2898 | ||
2899 | +#ifdef USE_EAPTLS | |
2900 | +extern char *crl_dir; | |
2901 | +#endif /* USE_EAPTLS */ | |
2902 | + | |
2903 | #ifdef MAXOCTETS | |
2904 | extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ | |
2905 | extern int maxoctets_dir; /* Direction : | |
2906 | @@ -717,6 +721,11 @@ | |
2907 | extern int (*chap_passwd_hook) __P((char *user, char *passwd)); | |
2908 | extern void (*multilink_join_hook) __P((void)); | |
2909 | ||
2910 | +#ifdef USE_EAPTLS | |
2911 | +extern int (*eaptls_check_hook) __P((void)); | |
2912 | +extern int (*eaptls_passwd_hook) __P((char *user, char *passwd)); | |
2913 | +#endif | |
2914 | + | |
2915 | /* Let a plugin snoop sent and received packets. Useful for L2TP */ | |
2916 | extern void (*snoop_recv_hook) __P((unsigned char *p, int len)); | |
2917 | extern void (*snoop_send_hook) __P((unsigned char *p, int len)); |