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