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
5 +EAP-TLS authentication support for PPP
6 +======================================
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.
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
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
24 + This patch provide EAP-TLS support to pppd.
25 + This authentication method can be used in both client or server
30 + To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org)
31 + is required. Any version from 0.9.7 should work.
33 + Configure, compile, and install as usual.
37 + On the client side there are two ways to configure EAP-TLS:
39 + 1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters
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:
46 + The name used by the client for authentication, can be *
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
59 + - Client private key file
60 + The file containing the client private key in PEM format.
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:
68 + The name used by the client for authentication, can be *
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
81 + - Client private key file
82 + The file containing the server private key in PEM format.
84 + A list of IP addresses the client is allowed to use.
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>
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>
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
104 + openssl_conf = openssl_def
107 + engines = engine_section
110 + pkcs11 = pkcs11_section
114 + dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
115 + MODULE_PATH = /usr/lib64/libeTPkcs11.so
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
130 + These pppd options are available:
133 + Use the CA public certificate found in <ca-file> in PEM format
135 + Use the client public certificate found in <cert-file> in PEM format
136 + or in engine:engine_id format
138 + Use the client private key found in <key-file> in PEM format
139 + or in engine:engine_id format
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.
146 + If the peer doesn't ask us to authenticate or doesn't use eap
147 + to authenticate us, disconnect.
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
154 + statement in the ppp options file, or by using the appropriate
155 + plugin which supplies a 'eaptls_passwd_hook' routine.
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).
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.
171 + This is experimental code.
172 + Send suggestions and comments to Jan Just Keijser <janjust@nikhef.nl>
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
178 +# Parameters for authentication using EAP-TLS (client)
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)
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
192 +# Parameters for authentication using EAP-TLS (server)
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 *)
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
207 +openssl_conf = openssl_def
210 +engines = engine_section
213 +pkcs11 = pkcs11_section
217 +dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
218 +MODULE_PATH = /usr/lib64/libeTPkcs11.so
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
225 cd pppdump; $(MAKE) $(MFLAGS) install
227 install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
228 - $(ETCDIR)/chap-secrets
229 + $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client
232 cd pppd; $(MAKE) $(MFLAGS) install-devel
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 $@
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
248 # Enable EAP SRP-SHA1 authentication (requires libsrp)
251 +# Enable EAP-TLS authentication (requires libssl and libcurl)
256 INCLUDE_DIRS= -I../include
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
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
278 #include "chap-new.h"
281 +#include "eap-tls.h"
287 /* Hook for a plugin to get the CHAP password for authenticating us */
288 int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL;
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;
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,
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 */
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 */
310 static char *uafname; /* name of most recent +ua file */
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,
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));
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 **,
333 "Set telephone number(s) which are allowed to connect",
334 OPT_PRIV | OPT_A2LIST },
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 */
348 lcp_options *wo = &lcp_wantoptions[unit];
349 lcp_options *go = &lcp_gotoptions[unit];
350 lcp_options *ho = &lcp_hisoptions[unit];
352 + lcp_options *ao = &lcp_allowoptions[unit];
355 struct protent *protp;
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;
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;
377 new_phase(PHASE_AUTHENTICATE);
380 @@ -1278,6 +1333,15 @@
381 our_name, 1, &lacks_ip);
385 + if (!can_auth && wo->neg_eap) {
387 + have_eaptls_secret_server((explicit_remote ? remote_name :
388 + NULL), our_name, 1, &lacks_ip);
393 if (auth_required && !can_auth && noauth_addrs == NULL) {
396 @@ -1332,7 +1396,11 @@
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)
403 + || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL)))
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,
412 !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
416 + && !have_eaptls_secret_server((explicit_remote? remote_name: NULL),
425 @@ -1706,6 +1780,7 @@
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 @@
435 auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
441 +have_eaptls_secret_server(client, server, need_ip, lacks_ipp)
450 + struct wordlist *addrs;
451 + char servcertfile[MAXWORDLEN];
452 + char clicertfile[MAXWORDLEN];
453 + char cacertfile[MAXWORDLEN];
454 + char pkfile[MAXWORDLEN];
456 + filename = _PATH_EAPTLSSERVFILE;
457 + f = fopen(filename, "r");
461 + if (client != NULL && client[0] == 0)
463 + else if (server != NULL && server[0] == 0)
467 + scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
468 + cacertfile, pkfile, &addrs, NULL, filename,
474 + if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
475 + clicertfile, pkfile))
479 + if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
480 + if (lacks_ipp != 0)
485 + free_wordlist(addrs);
492 +have_eaptls_secret_client(client, server)
499 + struct wordlist *addrs = NULL;
500 + char servcertfile[MAXWORDLEN];
501 + char clicertfile[MAXWORDLEN];
502 + char cacertfile[MAXWORDLEN];
503 + char pkfile[MAXWORDLEN];
505 + if (client != NULL && client[0] == 0)
507 + else if (server != NULL && server[0] == 0)
510 + if (cacert_file && cert_file && privkey_file)
513 + filename = _PATH_EAPTLSCLIFILE;
514 + f = fopen(filename, "r");
519 + scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
520 + cacertfile, pkfile, &addrs, NULL, filename,
525 + if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile,
526 + servcertfile, pkfile))
531 + free_wordlist(addrs);
538 +scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk,
539 + addrs, opts, filename, flags)
547 + struct wordlist **addrs;
548 + struct wordlist **opts;
553 + int got_flag, best_flag;
554 + struct wordlist *ap, *addr_list, *alist, **app;
555 + char word[MAXWORDLEN];
562 + if (!getword(f, word, &newline, filename))
563 + return -1; /* file is empty??? */
568 + * Skip until we find a word at the start of a line.
570 + while (!newline && getword(f, word, &newline, filename));
572 + break; /* got to end of file */
575 + * Got a client - check if it's a match or a wildcard.
578 + if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
583 + got_flag = NONWILD_CLIENT;
586 + * Now get a server and check if it matches.
588 + if (!getword(f, word, &newline, filename))
592 + if (!ISWILD(word)) {
593 + if (server != NULL && strcmp(word, server) != 0)
595 + got_flag |= NONWILD_SERVER;
599 + * Got some sort of a match - see if it's better than what
602 + if (got_flag <= best_flag)
608 + if (!getword(f, word, &newline, filename))
612 + if (strcmp(word, "-") != 0) {
613 + strlcpy(cli_cert, word, MAXWORDLEN);
620 + if (!getword(f, word, &newline, filename))
624 + if (strcmp(word, "-") != 0) {
625 + strlcpy(serv_cert, word, MAXWORDLEN);
632 + if (!getword(f, word, &newline, filename))
636 + strlcpy(ca_cert, word, MAXWORDLEN);
641 + if (!getword(f, word, &newline, filename))
645 + strlcpy(pk, word, MAXWORDLEN);
649 + * Now read address authorization info and make a wordlist.
653 + if (!getword(f, word, &newline, filename) || newline)
655 + ap = (struct wordlist *)
656 + malloc(sizeof(struct wordlist) + strlen(word) + 1);
658 + novm("authorized addresses");
659 + ap->word = (char *) (ap + 1);
660 + strcpy(ap->word, word);
666 + * This is the best so far; remember it.
668 + best_flag = got_flag;
670 + free_wordlist(addr_list);
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)
681 + /* ap = start of options */
683 + ap = ap->next; /* first option */
684 + free(*app); /* free the "--" word */
685 + *app = NULL; /* terminate addr list */
689 + else if (ap != NULL)
692 + *addrs = addr_list;
693 + else if (addr_list != NULL)
694 + free_wordlist(addr_list);
701 +get_eaptls_secret(unit, client, server, clicertfile, servcertfile,
702 + cacertfile, pkfile, am_server)
707 + char *servcertfile;
714 + char *filename = NULL;
715 + struct wordlist *addrs = NULL;
716 + struct wordlist *opts = NULL;
718 + /* in client mode the ca+cert+privkey can also be specified as options */
719 + if (!am_server && cacert_file && cert_file && privkey_file )
721 + strlcpy( clicertfile, cert_file, MAXWORDLEN );
722 + strlcpy( cacertfile, cacert_file, MAXWORDLEN );
723 + strlcpy( pkfile, privkey_file, MAXWORDLEN );
724 + servcertfile[0] = '\0';
728 + filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE);
731 + fp = fopen(filename, "r");
734 + error("Can't open eap-tls secret file %s: %m", filename);
738 + check_access(fp, filename);
740 + ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile,
741 + cacertfile, pkfile, &addrs, &opts, filename, 0);
745 + if (ret < 0) return 0;
748 + if (eaptls_passwd_hook)
750 + dbglog( "Calling eaptls password hook" );
751 + if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0)
753 + error("Unable to obtain EAP-TLS password for %s (%s) from plugin",
759 + set_allowed_addrs(unit, addrs, opts);
760 + else if (opts != NULL)
761 + free_wordlist(opts);
763 + free_wordlist(addrs);
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
774 ccp_options *ao = &ccp_allowoptions[f->unit];
775 int auth_mschap_bits = auth_done[f->unit];
777 + int auth_eap_bits = auth_done[f->unit];
783 lcp_close(f->unit, "MPPE required but not available");
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.
794 + /* Leave only the eap auth bits set */
795 + auth_eap_bits &= (EAP_WITHPEER | EAP_PEER );
797 + if ((numbits == 0) && (auth_eap_bits == 0)) {
798 + error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed.");
801 - error("MPPE required, but MS-CHAP[v2] auth not performed.");
802 + error("MPPE required, but MS-CHAP[v2] auth not performed.");
804 lcp_close(f->unit, "MPPE required but not available");
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
811 #include "chap-new.h"
812 #include "chap-md5.h"
815 +#include "eap-tls.h"
818 +#endif /* USE_EAPTLS */
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
827 + * eap-tls.c - EAP-TLS implementation for PPP
829 + * Copyright (c) Beniamino Galvani 2005 All rights reserved.
831 + * Redistribution and use in source and binary forms, with or without
832 + * modification, are permitted provided that the following conditions
835 + * 1. Redistributions of source code must retain the above copyright
836 + * notice, this list of conditions and the following disclaimer.
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
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.
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.
859 +#include <sys/types.h>
860 +#include <sys/stat.h>
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>
871 +#include "eap-tls.h"
874 +#include "pathnames.h"
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;
884 + * TLS PRF from RFC 2246
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)
891 + HMAC_CTX ctx_a, ctx_out;
892 + unsigned char a[HMAC_MAX_MD_CBLOCK];
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);
900 + size = HMAC_size(&ctx_out);
902 + /* Calculate A(1) */
903 + HMAC_Update(&ctx_a, seed, seed_len);
904 + HMAC_Final(&ctx_a, a, NULL);
907 + /* Calculate next part of output */
908 + HMAC_Update(&ctx_out, a, size);
909 + HMAC_Update(&ctx_out, seed, seed_len);
911 + /* Check if last part */
912 + if (out_len < size) {
913 + HMAC_Final(&ctx_out, a, NULL);
914 + memcpy(out, a, out_len);
918 + /* Place digest in output buffer */
919 + HMAC_Final(&ctx_out, out, NULL);
920 + HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL);
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);
930 + HMAC_CTX_cleanup(&ctx_a);
931 + HMAC_CTX_cleanup(&ctx_out);
932 + memset(a, 0, sizeof(a));
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)
940 + unsigned int len = (secret_len + 1) / 2;
941 + const unsigned char *s1 = secret;
942 + const unsigned char *s2 = secret + (secret_len - len);
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);
947 + for (i=0; i < out_len; i++) {
952 +#define EAPTLS_MPPE_KEY_LEN 32
955 + * Generate keys according to RFC 2716 and add to reply
957 +void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label,
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;
966 + prf_size = strlen(prf_label);
968 + memcpy(p, prf_label, prf_size);
971 + memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
972 + p += SSL3_RANDOM_SIZE;
973 + prf_size += SSL3_RANDOM_SIZE;
975 + memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
976 + prf_size += SSL3_RANDOM_SIZE;
978 + PRF(s->session->master_key, s->session->master_key_length,
979 + seed, prf_size, out, buf, sizeof(out));
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)
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) );
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) );
1001 + mppe_keys_set = 1;
1006 +void log_ssl_errors( void )
1008 + unsigned long ssl_err = ERR_get_error();
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();
1019 +int password_callback (char *buf, int size, int rwflag, void *u)
1023 + strncpy (buf, passwd, size);
1024 + return strlen (buf);
1030 +CONF *eaptls_ssl_load_config( void )
1034 + long error_line = 33;
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)
1041 + warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line );
1042 + NCONF_free( config );
1044 + ERR_clear_error();
1047 + dbglog( "Loading OpenSSL built-ins" );
1048 + ENGINE_load_builtin_engines();
1049 + OPENSSL_load_builtin_modules();
1051 + dbglog( "Loading OpenSSL configured modules" );
1052 + if (CONF_modules_load( config, NULL, 0 ) <= 0 )
1054 + warn( "EAP-TLS: Error loading OpenSSL modules" );
1062 +ENGINE *eaptls_ssl_load_engine( char *engine_name )
1066 + dbglog( "Enabling OpenSSL auto engines" );
1067 + ENGINE_register_all_complete();
1069 + dbglog( "Loading OpenSSL '%s' engine support", engine_name );
1070 + e = ENGINE_by_id( engine_name );
1073 + dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name );
1074 + e = ENGINE_by_id( "dynamic" );
1077 + if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0)
1078 + || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
1080 + warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name );
1088 + warn( "EAP-TLS: Cannot load dynamic engine support" );
1094 + dbglog( "Initialising engine" );
1095 + if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
1097 + warn( "EAP-TLS: Cannot use that engine" );
1108 + * Initialize the SSL stacks and tests if certificates, key and crl
1109 + * for client or server use can be loaded.
1111 +SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile,
1112 + char *certfile, char *peer_certfile, char *privkeyfile)
1114 + char *cert_engine_name = NULL;
1115 + char *cert_identifier = NULL;
1116 + char *pkey_engine_name = NULL;
1117 + char *pkey_identifier = NULL;
1119 + X509_STORE *certstore;
1120 + X509_LOOKUP *lookup;
1124 + * Without these can't continue
1126 + if (!cacertfile[0])
1128 + error("EAP-TLS: CA certificate missing");
1134 + error("EAP-TLS: User certificate missing");
1138 + if (!privkeyfile[0])
1140 + error("EAP-TLS: User private key missing");
1144 + SSL_library_init();
1145 + SSL_load_error_strings();
1147 + ctx = SSL_CTX_new(TLSv1_method());
1150 + error("EAP-TLS: Cannot initialize SSL CTX context");
1154 + /* if the certificate filename is of the form engine:id. e.g.
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
1160 + if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL )
1162 + cert_identifier = index( certfile, ':' );
1164 + if (cert_identifier)
1166 + cert_engine_name = certfile;
1167 + *cert_identifier = '\0';
1168 + cert_identifier++;
1170 + dbglog( "Found certificate engine '%s'", cert_engine_name );
1171 + dbglog( "Found certificate identifier '%s'", cert_identifier );
1175 + /* if the privatekey filename is of the form engine:id. e.g.
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
1181 + if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL )
1183 + pkey_identifier = index( privkeyfile, ':' );
1185 + if (pkey_identifier)
1187 + pkey_engine_name = privkeyfile;
1188 + *pkey_identifier = '\0';
1189 + pkey_identifier++;
1191 + dbglog( "Found privatekey engine '%s'", pkey_engine_name );
1192 + dbglog( "Found privatekey identifier '%s'", pkey_identifier );
1196 + if (cert_identifier && pkey_identifier)
1198 + if (strlen( cert_identifier ) == 0)
1200 + if (strlen( pkey_identifier ) == 0)
1201 + error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" );
1204 + dbglog( "Substituting privatekey identifier for certificate identifier" );
1205 + cert_identifier = pkey_identifier;
1210 + if (strlen( pkey_identifier ) == 0)
1212 + dbglog( "Substituting certificate identifier for privatekey identifier" );
1213 + pkey_identifier = cert_identifier;
1219 + /* load the openssl config file only once */
1222 + if (cert_engine_name || pkey_engine_name)
1223 + ssl_config = eaptls_ssl_load_config();
1225 + if (ssl_config && cert_engine_name)
1226 + cert_engine = eaptls_ssl_load_engine( cert_engine_name );
1228 + if (ssl_config && pkey_engine_name)
1230 + /* don't load the same engine twice */
1231 + if ( strcmp( cert_engine_name, pkey_engine_name) == 0 )
1232 + pkey_engine = cert_engine;
1234 + pkey_engine = eaptls_ssl_load_engine( pkey_engine_name );
1238 + SSL_CTX_set_default_passwd_cb (ctx, password_callback);
1240 + if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL))
1242 + error("EAP-TLS: Cannot load or verify CA file %s", cacertfile);
1247 + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile));
1253 + const char *s_slot_cert_id;
1257 + cert_info.s_slot_cert_id = cert_identifier;
1258 + cert_info.cert = NULL;
1260 + if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) )
1262 + error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier );
1266 + if (cert_info.cert)
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)
1272 + error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier);
1278 + warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier);
1284 + if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
1286 + error( "EAP-TLS: Cannot use public certificate %s", certfile );
1293 + EVP_PKEY *pkey = NULL;
1294 + PW_CB_DATA cb_data;
1296 + cb_data.password = passwd;
1297 + cb_data.prompt_info = pkey_identifier;
1299 + dbglog( "Loading private key '%s' from engine", pkey_identifier );
1300 + pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data);
1303 + dbglog( "Got the private key, adding it to SSL context" );
1304 + if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
1306 + error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier);
1312 + warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier);
1318 + if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM))
1320 + error("EAP-TLS: Cannot use private key %s", privkeyfile);
1325 + if (SSL_CTX_check_private_key(ctx) != 1) {
1326 + error("EAP-TLS: Private key %s fails security check", privkeyfile);
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,
1334 + SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1335 + &ssl_verify_callback);
1338 + if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
1339 + error("EAP-TLS: Failed to get certificate store");
1344 + X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) {
1345 + error("EAP-TLS: Store lookup for CRL failed");
1350 + X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM);
1351 + X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
1355 + * If a peer certificate file was specified, it must be valid, else fail
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",
1370 + SSL_CTX_free(ctx);
1375 + * Determine the maximum packet size by looking at the LCP handshake
1378 +int eaptls_get_mtu(int unit)
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];
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;
1391 + dbglog("MTU = %d", mtu);
1397 + * Init the ssl handshake (server mode)
1399 +int eaptls_init_ssl_server(eap_state * esp)
1401 + struct eaptls_session *ets;
1402 + char servcertfile[MAXWORDLEN];
1403 + char clicertfile[MAXWORDLEN];
1404 + char cacertfile[MAXWORDLEN];
1405 + char pkfile[MAXWORDLEN];
1407 + * Allocate new eaptls session
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;
1414 + if (!esp->es_server.ea_peer) {
1415 + error("EAP-TLS: Error: client name not set (BUG)");
1419 + strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN);
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 );
1430 + ets->mtu = eaptls_get_mtu(esp->es_unit);
1432 + ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile);
1436 + if (!(ets->ssl = SSL_new(ets->ctx)))
1440 + * Set auto-retry to avoid timeouts on BIO_read
1442 + SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY);
1445 + * Initialize the BIOs we use to read/write to ssl engine
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);
1451 + SSL_set_msg_callback(ets->ssl, ssl_msg_callback);
1452 + SSL_set_msg_callback_arg(ets->ssl, ets);
1455 + * Attach the session struct to the connection, so we can later
1456 + * retrieve it when doing certificate verification
1458 + SSL_set_ex_data(ets->ssl, 0, ets);
1460 + SSL_set_accept_state(ets->ssl);
1464 + ets->alert_sent = 0;
1465 + ets->alert_recv = 0;
1468 + * If we specified the client certificate file, store it in ets->peercertfile,
1469 + * so we can check it later in ssl_verify_callback()
1471 + if (clicertfile[0])
1472 + strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN);
1474 + ets->peercertfile[0] = 0;
1479 + SSL_CTX_free(ets->ctx);
1484 + * Init the ssl handshake (client mode)
1486 +int eaptls_init_ssl_client(eap_state * esp)
1488 + struct eaptls_session *ets;
1489 + char servcertfile[MAXWORDLEN];
1490 + char clicertfile[MAXWORDLEN];
1491 + char cacertfile[MAXWORDLEN];
1492 + char pkfile[MAXWORDLEN];
1495 + * Allocate new eaptls session
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;
1503 + * If available, copy server name in ets; it will be used in cert
1506 + if (esp->es_client.ea_peer)
1507 + strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN);
1511 + ets->mtu = eaptls_get_mtu(esp->es_unit);
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 );
1522 + dbglog( "calling eaptls_init_ssl" );
1523 + ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile);
1527 + ets->ssl = SSL_new(ets->ctx);
1533 + * Initialize the BIOs we use to read/write to ssl engine
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);
1540 + SSL_set_msg_callback(ets->ssl, ssl_msg_callback);
1541 + SSL_set_msg_callback_arg(ets->ssl, ets);
1544 + * Attach the session struct to the connection, so we can later
1545 + * retrieve it when doing certificate verification
1547 + SSL_set_ex_data(ets->ssl, 0, ets);
1549 + SSL_set_connect_state(ets->ssl);
1553 + ets->alert_sent = 0;
1554 + ets->alert_recv = 0;
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()
1561 + if (servcertfile[0])
1562 + strncpy(ets->peercertfile, servcertfile, MAXWORDLEN);
1564 + ets->peercertfile[0] = 0;
1569 + dbglog( "eaptls_init_ssl_client: fail" );
1570 + SSL_CTX_free(ets->ctx);
1575 +void eaptls_free_session(struct eaptls_session *ets)
1578 + SSL_free(ets->ssl);
1581 + SSL_CTX_free(ets->ctx);
1587 + * Handle a received packet, reassembling fragmented messages and
1588 + * passing them to the ssl engine
1590 +int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len)
1594 + u_char dummy[65536];
1596 + GETCHAR(flags, inp);
1599 + if (flags & EAP_TLS_FLAGS_LI && !ets->data) {
1602 + * This is the first packet of a message
1605 + GETLONG(tlslen, inp);
1608 + if (tlslen > EAP_TLS_MAX_LEN) {
1609 + error("Error: tls message length > %d, truncated",
1611 + tlslen = EAP_TLS_MAX_LEN;
1615 + * Allocate memory for the whole message
1617 + ets->data = malloc(tlslen);
1619 + fatal("EAP TLS: allocation error\n");
1622 + ets->tlslen = tlslen;
1625 + else if (flags & EAP_TLS_FLAGS_LI && ets->data) {
1627 + * Non first with LI (strange...)
1630 + GETLONG(tlslen, inp);
1634 + else if (!ets->data) {
1636 + * A non fragmented message without LI flag
1639 + ets->data = malloc(len);
1641 + fatal("EAP TLS: allocation error\n");
1644 + ets->tlslen = len;
1647 + if (flags & EAP_TLS_FLAGS_MF)
1652 + if (len + ets->datalen > ets->tlslen) {
1653 + warn("EAP TLS: received data > TLS message length");
1657 + BCOPY(inp, ets->data + ets->datalen, len);
1658 + ets->datalen += len;
1663 + * If we have the whole message, pass it to ssl
1666 + if (ets->datalen != ets->tlslen) {
1667 + warn("EAP TLS: received data != TLS message length");
1671 + if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1)
1674 + SSL_read(ets->ssl, dummy, 65536);
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.
1690 +int eaptls_send(struct eaptls_session *ets, u_char ** outp)
1694 + u_char fromtls[65536];
1702 + if(!ets->alert_sent)
1703 + SSL_read(ets->ssl, fromtls, 65536);
1708 + if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1)
1709 + fatal("No data from BIO_read");
1711 + ets->datalen = res;
1713 + ets->data = malloc(ets->datalen);
1714 + BCOPY(fromtls, ets->data, ets->datalen);
1721 + size = ets->datalen - ets->offset;
1723 + if (size > ets->mtu) {
1729 + PUTCHAR(EAPT_TLS, *outp);
1732 + * Set right flags and length if necessary
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);
1740 + PUTCHAR(0, *outp);
1743 + * Copy the data in outp
1745 + BCOPY(ets->data + ets->offset, *outp, size);
1746 + INCPTR(size, *outp);
1749 + * Copy the packet in retransmission buffer
1751 + BCOPY(start, &ets->rtx[0], *outp - start);
1752 + ets->rtx_len = *outp - start;
1754 + ets->offset += size;
1756 + if (ets->offset >= ets->datalen) {
1759 + * The whole message has been sent
1772 + * Get the sent packet from the retransmission buffer
1774 +void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp)
1776 + BCOPY(ets->rtx, *outp, ets->rtx_len);
1777 + INCPTR(ets->rtx_len, *outp);
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.
1786 +int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx)
1788 + char subject[256];
1792 + int ok = preverify_ok;
1794 + struct eaptls_session *ets;
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);
1800 + dbglog("certificate verify depth: %d", depth);
1802 + if (auth_required && !ok) {
1803 + X509_NAME_oneline(X509_get_subject_name(peer_cert),
1806 + X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
1807 + NID_commonName, cn_str, 256);
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));
1816 + ssl = X509_STORE_CTX_get_ex_data(ctx,
1817 + SSL_get_ex_data_X509_STORE_CTX_idx());
1819 + ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0);
1821 + if (ets == NULL) {
1822 + error("Error: SSL_get_ex_data returned NULL");
1828 + if (!depth) { /* This is the peer certificate */
1830 + X509_NAME_oneline(X509_get_subject_name(peer_cert),
1833 + X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
1834 + NID_commonName, cn_str, 256);
1837 + * If acting as client and the name of the server wasn't specified
1838 + * explicitely, we can't verify the server authenticity
1840 + if (!ets->peer[0]) {
1841 + warn("Peer name not specified: no check");
1848 + if (strcmp(cn_str, ets->peer)) {
1850 + ("Certificate verification error: CN (%s) != peer_name (%s)",
1851 + cn_str, ets->peer);
1855 + warn("Certificate CN: %s , peer name %s", cn_str, ets->peer);
1858 + * If a peer certificate file was specified, here we check it
1860 + if (ets->peercertfile[0]) {
1861 + if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert)
1864 + ("Peer certificate doesn't match stored certificate");
1874 + * Compare a certificate with the one stored in a file
1876 +int ssl_cmp_certs(char *filename, X509 * a)
1881 + if (!(b = get_X509_from_file(filename)))
1884 + ret = X509_cmp(a, b);
1891 +X509 *get_X509_from_file(char *filename)
1896 + if (!(fp = fopen(filename, "r")))
1899 + ret = PEM_read_X509(fp, NULL, NULL, NULL);
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.
1912 +ssl_msg_callback(int write_p, int version, int content_type,
1913 + const void *buf, size_t len, SSL * ssl, void *arg)
1916 + struct eaptls_session *ets = (struct eaptls_session *)arg;
1917 + unsigned char code;
1920 + strcpy(string, " -> ");
1922 + strcpy(string, " <- ");
1925 + switch(content_type) {
1927 + case SSL3_RT_ALERT:
1928 + strcat(string, "Alert: ");
1929 + code = ((const unsigned char *)buf)[1];
1932 + ets->alert_sent = 1;
1933 + ets->alert_sent_desc = code;
1935 + ets->alert_recv = 1;
1936 + ets->alert_recv_desc = code;
1939 + strcat(string, SSL_alert_desc_string_long(code));
1942 + case SSL3_RT_CHANGE_CIPHER_SPEC:
1943 + strcat(string, "ChangeCipherSpec");
1946 + case SSL3_RT_HANDSHAKE:
1948 + strcat(string, "Handshake: ");
1949 + code = ((const unsigned char *)buf)[0];
1952 + case SSL3_MT_HELLO_REQUEST:
1953 + strcat(string,"Hello Request");
1955 + case SSL3_MT_CLIENT_HELLO:
1956 + strcat(string,"Client Hello");
1958 + case SSL3_MT_SERVER_HELLO:
1959 + strcat(string,"Server Hello");
1961 + case SSL3_MT_CERTIFICATE:
1962 + strcat(string,"Certificate");
1964 + case SSL3_MT_SERVER_KEY_EXCHANGE:
1965 + strcat(string,"Server Key Exchange");
1967 + case SSL3_MT_CERTIFICATE_REQUEST:
1968 + strcat(string,"Certificate Request");
1970 + case SSL3_MT_SERVER_DONE:
1971 + strcat(string,"Server Hello Done");
1973 + case SSL3_MT_CERTIFICATE_VERIFY:
1974 + strcat(string,"Certificate Verify");
1976 + case SSL3_MT_CLIENT_KEY_EXCHANGE:
1977 + strcat(string,"Client Key Exchange");
1979 + case SSL3_MT_FINISHED:
1980 + strcat(string,"Finished");
1984 + sprintf( string, "Handshake: Unknown SSL3 code received: %d", code );
1989 + sprintf( string, "SSL message contains unknown content type: %d", content_type );
1993 + /* Alert messages must always be displayed */
1994 + if(content_type == SSL3_RT_ALERT)
1995 + error("%s", string);
1997 + dbglog("%s", string);
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
2007 + * Copyright (c) Beniamino Galvani 2005 All rights reserved.
2009 + * Redistribution and use in source and binary forms, with or without
2010 + * modification, are permitted provided that the following conditions
2013 + * 1. Redistributions of source code must retain the above copyright
2014 + * notice, this list of conditions and the following disclaimer.
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
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.
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.
2035 +#ifndef __EAP_TLS_H__
2036 +#define __EAP_TLS_H__
2040 +#include <openssl/ssl.h>
2041 +#include <openssl/bio.h>
2042 +#include <openssl/md5.h>
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 */
2048 +#define EAP_TLS_MAX_LEN 65536 /* max eap tls packet size */
2050 +struct eaptls_session
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 */
2058 + SSL *ssl; /* ssl connection */
2061 + char peer[MAXWORDLEN]; /* peer name */
2062 + char peercertfile[MAXWORDLEN];
2064 + u_char alert_sent_desc;
2066 + u_char alert_recv_desc;
2067 + char rtx[65536]; /* retransmission buffer */
2069 + int mtu; /* unit mtu */
2072 +typedef struct pw_cb_data
2074 + const void *password;
2075 + const char *prompt_info;
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);
2083 +X509 *get_X509_from_file(char *filename);
2084 +int ssl_cmp_certs(char *filename, X509 * a);
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);
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);
2096 +int get_eaptls_secret(int unit, char *client, char *server,
2097 + char *clicertfile, char *servcertfile, char *cacertfile,
2098 + char *pkfile, int am_server);
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;
2106 +void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, int client);
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
2115 * Based on draft-ietf-pppext-eap-srp-03.txt.
2119 + * Modification by Beniamino Galvani, Mar 2005
2120 + * Implemented EAP-TLS authentication
2123 #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
2129 #include "pathnames.h"
2133 +#include "eap-tls.h"
2136 +#endif /* USE_EAPTLS */
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;
2145 + esp->es_client.ea_using_eaptls = 0;
2146 +#endif /* USE_EAPTLS */
2150 @@ -436,8 +448,16 @@
2153 #endif /* USE_SRP */
2155 + struct eaptls_session *ets;
2157 + char secret[MAXWORDLEN];
2158 +#endif /* USE_EAPTLS */
2160 esp->es_server.ea_timeout = esp->es_savedtime;
2162 + esp->es_server.ea_prev_state = esp->es_server.ea_state;
2163 +#endif /* USE_EAPTLS */
2164 switch (esp->es_server.ea_state) {
2167 @@ -562,9 +582,81 @@
2170 #endif /* USE_SRP */
2172 + if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
2173 + esp->es_server.ea_name, secret, &secret_len, 1)) {
2175 + esp->es_server.ea_state = eapTlsStart;
2178 +#endif /* USE_EAPTLS */
2180 esp->es_server.ea_state = eapMD5Chall;
2185 + /* Initialize ssl session */
2186 + if(!eaptls_init_ssl_server(esp)) {
2187 + esp->es_server.ea_state = eapBadAuth;
2191 + esp->es_server.ea_state = eapTlsRecv;
2195 + ets = (struct eaptls_session *) esp->es_server.ea_session;
2197 + if(ets->alert_sent) {
2198 + esp->es_server.ea_state = eapTlsSendAlert;
2203 + esp->es_server.ea_state = eapBadAuth;
2206 + ets = (struct eaptls_session *) esp->es_server.ea_session;
2209 + esp->es_server.ea_state = eapTlsSendAck;
2211 + esp->es_server.ea_state = eapTlsSend;
2215 + ets = (struct eaptls_session *) esp->es_server.ea_session;
2217 + if(SSL_is_init_finished(ets->ssl)) {
2218 + esp->es_server.ea_state = eapTlsRecvClient;
2223 + esp->es_server.ea_state = eapTlsRecvAck;
2225 + esp->es_server.ea_state = eapTlsRecv;
2228 + case eapTlsSendAck:
2229 + esp->es_server.ea_state = eapTlsRecv;
2232 + case eapTlsRecvAck:
2234 + esp->es_server.ea_state = eapBadAuth;
2238 + esp->es_server.ea_state = eapTlsSend;
2241 + case eapTlsSendAlert:
2242 + esp->es_server.ea_state = eapTlsRecvAlertAck;
2244 +#endif /* USE_EAPTLS */
2248 ts = (struct t_server *)esp->es_server.ea_session;
2249 @@ -718,6 +810,30 @@
2250 INCPTR(esp->es_server.ea_namelen, outp);
2255 + PUTCHAR(EAPT_TLS, outp);
2256 + PUTCHAR(EAP_TLS_FLAGS_START, outp);
2257 + eap_figure_next_state(esp, 0);
2261 + eaptls_send(esp->es_server.ea_session, &outp);
2262 + eap_figure_next_state(esp, 0);
2265 + case eapTlsSendAck:
2266 + PUTCHAR(EAPT_TLS, outp);
2268 + eap_figure_next_state(esp, 0);
2271 + case eapTlsSendAlert:
2272 + eaptls_send(esp->es_server.ea_session, &outp);
2273 + eap_figure_next_state(esp, 0);
2275 +#endif /* USE_EAPTLS */
2279 PUTCHAR(EAPT_SRP, outp);
2280 @@ -904,11 +1020,57 @@
2281 eap_server_timeout(arg)
2288 +#endif /* USE_EAPTLS */
2290 eap_state *esp = (eap_state *) arg;
2292 if (!eap_server_active(esp))
2296 + switch(esp->es_server.ea_prev_state) {
2299 + * In eap-tls the state changes after a request, so we return to
2300 + * previous state ...
2302 + case(eapTlsStart):
2303 + case(eapTlsSendAck):
2304 + esp->es_server.ea_state = esp->es_server.ea_prev_state;
2308 + * ... or resend the stored data
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);
2319 + eaptls_retransmit(esp->es_server.ea_session, &outp);
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++;
2326 + if (esp->es_server.ea_timeout > 0)
2327 + TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
2333 +#endif /* USE_EAPTLS */
2335 /* EAP ID number must not change on timeout. */
2336 eap_send_request(esp);
2338 @@ -1166,6 +1328,81 @@
2340 #endif /* USE_SRP */
2344 + * Send an EAP-TLS response message with tls data
2347 +eap_tls_response(esp, id)
2355 + outp = outpacket_buf;
2357 + MAKEHEADER(outp, PPP_EAP);
2359 + PUTCHAR(EAP_RESPONSE, outp);
2360 + PUTCHAR(id, outp);
2366 + If the id in the request is unchanged, we must retransmit
2369 + if(id == esp->es_client.ea_id)
2370 + eaptls_retransmit(esp->es_client.ea_session, &outp);
2372 + eaptls_send(esp->es_client.ea_session, &outp);
2374 + outlen = (outp - outpacket_buf) - PPP_HDRLEN;
2375 + PUTSHORT(outlen, lenloc);
2377 + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
2379 + esp->es_client.ea_id = id;
2384 + * Send an EAP-TLS ack
2387 +eap_tls_sendack(esp, id)
2395 + outp = outpacket_buf;
2397 + MAKEHEADER(outp, PPP_EAP);
2399 + PUTCHAR(EAP_RESPONSE, outp);
2400 + PUTCHAR(id, outp);
2401 + esp->es_client.ea_id = id;
2406 + PUTCHAR(EAPT_TLS, outp);
2409 + outlen = (outp - outpacket_buf) - PPP_HDRLEN;
2410 + PUTSHORT(outlen, lenloc);
2412 + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
2415 +#endif /* USE_EAPTLS */
2418 eap_send_nak(esp, id, type)
2420 @@ -1320,6 +1557,11 @@
2421 char rhostname[256];
2423 u_char hash[MD5_SIGNATURE_SIZE];
2426 + struct eaptls_session *ets = esp->es_client.ea_session;
2427 +#endif /* USE_EAPTLS */
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);
2439 + switch(esp->es_client.ea_state) {
2443 + GETCHAR(flags, inp);
2444 + if(flags & EAP_TLS_FLAGS_START){
2446 + esp->es_client.ea_using_eaptls = 1;
2448 + if (explicit_remote){
2449 + esp->es_client.ea_peer = strdup(remote_name);
2450 + esp->es_client.ea_peerlen = strlen(remote_name);
2452 + esp->es_client.ea_peer = NULL;
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;
2462 + ets = esp->es_client.ea_session;
2463 + eap_tls_response(esp, id);
2464 + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2469 + /* The server has sent a bad start packet. */
2470 + eap_send_nak(esp, id, EAPT_TLS);
2473 + case eapTlsRecvAck:
2474 + eap_tls_response(esp, id);
2475 + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2480 + eaptls_receive(ets, inp, len);
2483 + eap_tls_sendack(esp, id);
2484 + esp->es_client.ea_state = eapTlsRecv;
2488 + if(ets->alert_recv) {
2489 + eap_tls_sendack(esp, id);
2490 + esp->es_client.ea_state = eapTlsRecvFailure;
2494 + /* Check if TLS handshake is finished */
2495 + if(SSL_is_init_finished(ets->ssl)){
2497 + eaptls_gen_mppe_keys( ets, "client EAP encryption", 1 );
2499 + eaptls_free_session(ets);
2500 + eap_tls_sendack(esp, id);
2501 + esp->es_client.ea_state = eapTlsRecvSuccess;
2505 + eap_tls_response(esp,id);
2506 + esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2512 + eap_send_nak(esp, id, EAPT_TLS);
2513 + esp->es_client.ea_using_eaptls = 0;
2518 +#endif /* USE_EAPTLS */
2523 @@ -1737,6 +2063,11 @@
2524 u_char dig[SHA_DIGESTSIZE];
2525 #endif /* USE_SRP */
2528 + struct eaptls_session *ets;
2530 +#endif /* USE_EAPTLS */
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);
2541 + switch(esp->es_server.ea_state) {
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));
2548 + if(ets->alert_recv) {
2549 + eap_send_failure(esp);
2554 + case eapTlsRecvAck:
2556 + dbglog("EAP-TLS ACK with extra data");
2558 + eap_figure_next_state(esp, 0);
2561 + case eapTlsRecvClient:
2562 + /* Receive authentication response from client */
2564 + GETCHAR(flags, inp);
2566 + if(len == 1 && !flags) { /* Ack = ok */
2568 + eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 );
2570 + eap_send_success(esp);
2572 + else { /* failure */
2573 + eaptls_receive(esp->es_server.ea_session, inp, len);
2574 + warn("Server authentication failed");
2575 + eap_send_failure(esp);
2578 + eaptls_free_session(esp->es_server.ea_session);
2582 + case eapTlsRecvAlertAck:
2583 + eap_send_failure(esp);
2587 + eap_figure_next_state(esp, 1);
2591 +#endif /* USE_EAPTLS */
2593 case EAPT_NOTIFICATION:
2594 dbglog("EAP unexpected Notification; response discarded");
2596 @@ -1807,6 +2192,13 @@
2597 esp->es_server.ea_state = eapMD5Chall;
2601 + /* Send EAP-TLS start packet */
2603 + esp->es_server.ea_state = eapTlsStart;
2605 +#endif /* USE_EAPTLS */
2608 dbglog("EAP: peer requesting unknown Type %d", vallen);
2609 switch (esp->es_server.ea_state) {
2610 @@ -2018,13 +2410,27 @@
2614 - if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2615 + if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2617 + && esp->es_client.ea_state != eapTlsRecvSuccess
2618 +#endif /* USE_EAPTLS */
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);
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);
2634 +#endif /* USE_EAPTLS */
2636 if (esp->es_client.ea_timeout > 0) {
2637 UNTIMEOUT(eap_client_timeout, (void *)esp);
2639 @@ -2150,6 +2556,9 @@
2640 int code, id, len, rtype, vallen;
2645 +#endif /* USE_EAPTLS */
2647 if (inlen < EAP_HEADERLEN)
2649 @@ -2214,6 +2623,24 @@
2657 + GETCHAR(flags, inp);
2660 + if(flags == 0 && len == 0){
2661 + printer(arg, " Ack");
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":"- ");
2669 +#endif /* USE_EAPTLS */
2674 @@ -2325,6 +2752,25 @@
2682 + GETCHAR(flags, inp);
2685 + if(flags == 0 && len == 0){
2686 + printer(arg, " Ack");
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":"- ");
2695 +#endif /* USE_EAPTLS */
2699 printer(arg, " <missing hint>");
2700 @@ -2426,3 +2872,4 @@
2702 return (inp - pstart);
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
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 */
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"
2733 -#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
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)
2739 +#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
2740 +#endif /* USE_EAPTLS */
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;
2750 + enum eap_state_code ea_prev_state;
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 */
2758 + bool ea_using_eaptls;
2763 @@ -139,7 +164,12 @@
2766 #define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */
2768 +#define EAP_DEFTRANSMITS 30 /* max # times to transmit */
2769 + /* certificates can be long ... */
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 */
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
2780 ***********************************************************************
2790 ******************************** (cut) ********************************
2792 +#endif /* USE_EAPTLS */
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
2798 ** documentation and/or software. **
2799 ***********************************************************************
2803 #ifndef __MD5_INCLUDE__
2807 #define __MD5_INCLUDE__
2808 #endif /* __MD5_INCLUDE__ */
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 */
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 */
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 },
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 */
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
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"
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 */
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
2863 +CFLAGS += -DUSE_EAPTLS=1
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
2873 add_options(options);
2874 pap_passwd_hook = promptpass;
2876 + eaptls_passwd_hook = promptpass;
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
2884 chap_check_hook = pwfd_check;
2885 chap_passwd_hook = pwfd_passwd;
2888 + eaptls_check_hook = pwfd_check;
2889 + eaptls_passwd_hook = pwfd_passwd;
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 */
2900 +extern char *crl_dir;
2901 +#endif /* USE_EAPTLS */
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));
2911 +extern int (*eaptls_check_hook) __P((void));
2912 +extern int (*eaptls_passwd_hook) __P((char *user, char *passwd));
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));