1
Author: Jan Just Keijser <janjust@nikhef.nl>
2
Description: EAP-TLS patch for pppd (0.994)
3
Bug-Ubuntu: https://launchpad.net/bugs/643417
4
Bug-Debian: http://bugs.debian.org/602503
5
But-Fedora: https://bugzilla.redhat.com/556407
6
Origin: http://www.nikhef.nl/~janjust/ppp/download.html
8
Index: ppp-2.4.5/README.eap-tls
9
===================================================================
10
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
11
+++ ppp-2.4.5/README.eap-tls 2013-01-22 15:19:29.000000000 -0600
13
+EAP-TLS authentication support for PPP
14
+======================================
18
+ The Extensible Authentication Protocol (EAP; RFC 3748) is a
19
+ security protocol that can be used with PPP. It provides a means
20
+ to plug in multiple optional authentication methods.
22
+ Transport Level Security (TLS; RFC 2246) provides for mutual
23
+ authentication, integrity-protected ciphersuite negotiation and
24
+ key exchange between two endpoints. It also provides for optional
27
+ EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets,
28
+ allowing TLS mutual authentication to be used as a generic EAP
29
+ mechanism. It also provides optional encryption using the MPPE
32
+ This patch provide EAP-TLS support to pppd.
33
+ This authentication method can be used in both client or server
38
+ To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org)
39
+ is required. Any version from 0.9.7 should work.
41
+ Configure, compile, and install as usual.
45
+ On the client side there are two ways to configure EAP-TLS:
47
+ 1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters
49
+ 2. edit the /etc/ppp/eaptls-client file.
50
+ Insert a line for each system with which you use EAP-TLS.
51
+ The line is composed of this fields separated by tab:
54
+ The name used by the client for authentication, can be *
56
+ The name of the server, can be *
57
+ - Client certificate file
58
+ The file containing the certificate chain for the
59
+ client in PEM format
60
+ - Server certificate file
61
+ If you want to specify the certificate that the
62
+ server is allowed to use, put the certificate file name.
63
+ Else put a dash '-'.
64
+ - CA certificate file
65
+ The file containing the trusted CA certificates in PEM
67
+ - Client private key file
68
+ The file containing the client private key in PEM format.
71
+ On the server side edit the /etc/ppp/eaptls-server file.
72
+ Insert a line for each system with which you use EAP-TLS.
73
+ The line is composed of this fields separated by tab:
76
+ The name used by the client for authentication, can be *
78
+ The name of the server, can be *
79
+ - Client certificate file
80
+ If you want to specify the certificate that the
81
+ client is allowed to use, put the certificate file name.
82
+ Else put a dash '-'.
83
+ - Server certificate file
84
+ The file containing the certificate chain for the
85
+ server in PEM format
86
+ - CA certificate file
87
+ The file containing the trusted CA certificates in PEM
89
+ - Client private key file
90
+ The file containing the server private key in PEM format.
92
+ A list of IP addresses the client is allowed to use.
95
+ OpenSSL engine support is included starting with v0.95 of this patch.
96
+ Currently the only engine tested is the 'pkcs11' engine (hardware token
97
+ support). To use the 'pksc11' engine:
98
+ - Use a special private key fileiname in the /etc/ppp/eaptls-client file:
99
+ <engine>:<identifier>
103
+ - The certificate can also be loaded from the 'pkcs11' engine using
104
+ a special client certificate filename in the /etc/ppp/eaptls-client file:
105
+ <engine>:<identifier>
109
+ - Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior
110
+ to starting 'pppd'. A sample openssl.cnf file is
112
+ openssl_conf = openssl_def
115
+ engines = engine_section
118
+ pkcs11 = pkcs11_section
122
+ dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
123
+ MODULE_PATH = /usr/lib64/libeTPkcs11.so
126
+ - There are two ways to specify a password/PIN for the PKCS11 engine:
127
+ - inside the openssl.cnf file using
128
+ PIN = your-secret-pin
129
+ Note The keyword 'PIN' is case sensitive!
130
+ - Using the 'password' in the ppp options file.
131
+ From v0.97 of the eap-tls patch the password can also be supplied
132
+ using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c
138
+ These pppd options are available:
141
+ Use the CA public certificate found in <ca-file> in PEM format
143
+ Use the client public certificate found in <cert-file> in PEM format
144
+ or in engine:engine_id format
146
+ Use the client private key found in <key-file> in PEM format
147
+ or in engine:engine_id format
149
+ Use CRL files from dir. It contains CRL files in PEM
150
+ format and each file contains a CRL. The files are looked up
151
+ by the issuer name hash value. Use the c_rehash utility
152
+ to create necessary links.
154
+ If the peer doesn't ask us to authenticate or doesn't use eap
155
+ to authenticate us, disconnect.
158
+ password-encrypted certificates can be used as of v0.94 of this
159
+ patch. The password for the eap-tls.key file is specified using
162
+ statement in the ppp options file, or by using the appropriate
163
+ plugin which supplies a 'eaptls_passwd_hook' routine.
167
+ If you're setting up a pppd server, edit the EAP-TLS configuration file
168
+ as written above and then run pppd with the 'auth' option to authenticate
169
+ the client. The EAP-TLS method will be used if the other eap methods can't
170
+ be used (no secrets).
172
+ If you're setting up a client, edit the configuration file and then run
173
+ pppd with 'remotename' option to specify the server name. Add the
174
+ 'need-peer-eap' option if you want to be sure the peer ask you to
175
+ authenticate (and to use eap) and to disconnect if it doesn't.
179
+ This is experimental code.
180
+ Send suggestions and comments to Jan Just Keijser <janjust@nikhef.nl>
182
Index: ppp-2.4.5/etc.ppp/eaptls-client
183
===================================================================
184
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
185
+++ ppp-2.4.5/etc.ppp/eaptls-client 2013-01-22 15:19:29.000000000 -0600
187
+# Parameters for authentication using EAP-TLS (client)
189
+# client name (can be *)
190
+# server name (can be *)
191
+# client certificate file (required)
192
+# server certificate file (optional, if unused put '-')
193
+# CA certificate file (required)
194
+# client private key file (required)
196
+#client server /root/cert/client.crt - /root/cert/ca.crt /root/cert/client.key
197
Index: ppp-2.4.5/etc.ppp/eaptls-server
198
===================================================================
199
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
200
+++ ppp-2.4.5/etc.ppp/eaptls-server 2013-01-22 15:19:29.000000000 -0600
202
+# Parameters for authentication using EAP-TLS (server)
204
+# client name (can be *)
205
+# server name (can be *)
206
+# client certificate file (optional, if unused put '-')
207
+# server certificate file (required)
208
+# CA certificate file (required)
209
+# server private key file (required)
210
+# allowed addresses (required, can be *)
212
+#client server - /root/cert/server.crt /root/cert/ca.crt /root/cert/server.key 192.168.1.0/24
213
Index: ppp-2.4.5/etc.ppp/openssl.cnf
214
===================================================================
215
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
216
+++ ppp-2.4.5/etc.ppp/openssl.cnf 2013-01-22 15:19:29.000000000 -0600
218
+openssl_conf = openssl_def
221
+engines = engine_section
224
+pkcs11 = pkcs11_section
228
+dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
229
+MODULE_PATH = /usr/lib64/libeTPkcs11.so
232
Index: ppp-2.4.5/linux/Makefile.top
233
===================================================================
234
--- ppp-2.4.5.orig/linux/Makefile.top 2013-01-22 15:19:11.000000000 -0600
235
+++ ppp-2.4.5/linux/Makefile.top 2013-01-22 15:19:29.000000000 -0600
237
cd pppdump; $(MAKE) $(MFLAGS) install
239
install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
240
- $(ETCDIR)/chap-secrets
241
+ $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client
244
cd pppd; $(MAKE) $(MFLAGS) install-devel
246
$(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
247
$(ETCDIR)/chap-secrets:
248
$(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
249
+$(ETCDIR)/eaptls-server:
250
+ $(INSTALL) -c -m 600 etc.ppp/eaptls-server $@
251
+$(ETCDIR)/eaptls-client:
252
+ $(INSTALL) -c -m 600 etc.ppp/eaptls-client $@
255
$(INSTALL) -d -m 755 $@
256
Index: ppp-2.4.5/pppd/Makefile.linux
257
===================================================================
258
--- ppp-2.4.5.orig/pppd/Makefile.linux 2013-01-22 15:19:29.000000000 -0600
259
+++ ppp-2.4.5/pppd/Makefile.linux 2013-01-22 15:19:29.000000000 -0600
261
# Enable EAP SRP-SHA1 authentication (requires libsrp)
264
+# Enable EAP-TLS authentication (requires libssl and libcrypto)
269
INCLUDE_DIRS= -I../include
276
+COMPILE_FLAGS += -DUSE_EAPTLS=1 -I/usr/kerberos/include
277
+LIBS += -lssl -lcrypto
278
+PPPDSRC += eap-tls.c
279
+HEADERS += eap-tls.h
280
+PPPDOBJS += eap-tls.o
284
COMPILE_FLAGS += -DHAS_SHADOW
285
#LIBS += -lshadow $(LIBS)
286
Index: ppp-2.4.5/pppd/auth.c
287
===================================================================
288
--- ppp-2.4.5.orig/pppd/auth.c 2013-01-22 15:19:29.000000000 -0600
289
+++ ppp-2.4.5/pppd/auth.c 2013-01-22 15:19:29.000000000 -0600
292
#include "chap-new.h"
295
+#include "eap-tls.h"
301
/* Hook for a plugin to get the CHAP password for authenticating us */
302
int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL;
305
+/* Hook for a plugin to get the EAP-TLS password for authenticating us */
306
+int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL;
309
/* Hook for a plugin to say whether it is OK if the peer
310
refuses to authenticate. */
311
int (*null_auth_hook) __P((struct wordlist **paddrs,
313
bool explicit_user = 0; /* Set if "user" option supplied */
314
bool explicit_passwd = 0; /* Set if "password" option supplied */
315
char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
317
+char *cacert_file = NULL; /* CA certificate file (pem format) */
318
+char *cert_file = NULL; /* client certificate file (pem format) */
319
+char *privkey_file = NULL; /* client private key file (pem format) */
320
+char *crl_dir = NULL; /* directory containing CRL files */
321
+bool need_peer_eap = 0; /* Require peer to authenticate us */
324
static char *uafname; /* name of most recent +ua file */
327
static int have_chap_secret __P((char *, char *, int, int *));
328
static int have_srp_secret __P((char *client, char *server, int need_ip,
332
+static int have_eaptls_secret_server
333
+__P((char *client, char *server, int need_ip, int *lacks_ipp));
334
+static int have_eaptls_secret_client __P((char *client, char *server));
335
+static int scan_authfile_eaptls __P((FILE * f, char *client, char *server,
336
+ char *cli_cert, char *serv_cert,
337
+ char *ca_cert, char *pk,
338
+ struct wordlist ** addrs,
339
+ struct wordlist ** opts,
340
+ char *filename, int flags));
343
static int ip_addr_check __P((u_int32_t, struct permitted_ip *));
344
static int scan_authfile __P((FILE *, char *, char *, char *,
345
struct wordlist **, struct wordlist **,
347
"Set telephone number(s) which are allowed to connect",
348
OPT_PRIV | OPT_A2LIST },
351
+ { "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" },
352
+ { "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" },
353
+ { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" },
354
+ { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" },
355
+ { "need-peer-eap", o_bool, &need_peer_eap,
356
+ "Require the peer to authenticate us", 1 },
357
+#endif /* USE_EAPTLS */
362
lcp_options *wo = &lcp_wantoptions[unit];
363
lcp_options *go = &lcp_gotoptions[unit];
364
lcp_options *ho = &lcp_hisoptions[unit];
366
+ lcp_options *ao = &lcp_allowoptions[unit];
369
struct protent *protp;
376
+ if (need_peer_eap && !ao->neg_eap) {
377
+ warn("eap required to authenticate us but no suitable secrets");
378
+ lcp_close(unit, "couldn't negotiate eap");
379
+ status = EXIT_AUTH_TOPEER_FAILED;
383
+ if (need_peer_eap && !ho->neg_eap) {
384
+ warn("peer doesn't want to authenticate us with eap");
385
+ lcp_close(unit, "couldn't negotiate eap");
386
+ status = EXIT_PEER_AUTH_FAILED;
391
new_phase(PHASE_AUTHENTICATE);
394
@@ -1278,6 +1333,15 @@
395
our_name, 1, &lacks_ip);
399
+ if (!can_auth && wo->neg_eap) {
401
+ have_eaptls_secret_server((explicit_remote ? remote_name :
402
+ NULL), our_name, 1, &lacks_ip);
407
if (auth_required && !can_auth && noauth_addrs == NULL) {
410
@@ -1332,7 +1396,11 @@
412
(hadchap == 1 || (hadchap == -1 && have_chap_secret(user,
413
(explicit_remote? remote_name: NULL), 0, NULL))) ||
414
- have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL));
415
+ have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)
417
+ || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL))
422
if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
423
@@ -1347,8 +1415,14 @@
424
!have_chap_secret((explicit_remote? remote_name: NULL), our_name,
426
!have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
430
+ && !have_eaptls_secret_server((explicit_remote? remote_name: NULL),
439
@@ -1708,6 +1782,7 @@
445
* get_secret - open the CHAP secret file and return the secret
446
* for authenticating the given client on the given server.
447
@@ -2360,3 +2435,335 @@
449
auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
455
+have_eaptls_secret_server(client, server, need_ip, lacks_ipp)
464
+ struct wordlist *addrs;
465
+ char servcertfile[MAXWORDLEN];
466
+ char clicertfile[MAXWORDLEN];
467
+ char cacertfile[MAXWORDLEN];
468
+ char pkfile[MAXWORDLEN];
470
+ filename = _PATH_EAPTLSSERVFILE;
471
+ f = fopen(filename, "r");
475
+ if (client != NULL && client[0] == 0)
477
+ else if (server != NULL && server[0] == 0)
481
+ scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
482
+ cacertfile, pkfile, &addrs, NULL, filename,
488
+ if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
489
+ clicertfile, pkfile))
493
+ if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
494
+ if (lacks_ipp != 0)
499
+ free_wordlist(addrs);
506
+have_eaptls_secret_client(client, server)
513
+ struct wordlist *addrs = NULL;
514
+ char servcertfile[MAXWORDLEN];
515
+ char clicertfile[MAXWORDLEN];
516
+ char cacertfile[MAXWORDLEN];
517
+ char pkfile[MAXWORDLEN];
519
+ if (client != NULL && client[0] == 0)
521
+ else if (server != NULL && server[0] == 0)
524
+ if (cacert_file && cert_file && privkey_file)
527
+ filename = _PATH_EAPTLSCLIFILE;
528
+ f = fopen(filename, "r");
533
+ scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
534
+ cacertfile, pkfile, &addrs, NULL, filename,
539
+ if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile,
540
+ servcertfile, pkfile))
545
+ free_wordlist(addrs);
552
+scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk,
553
+ addrs, opts, filename, flags)
561
+ struct wordlist **addrs;
562
+ struct wordlist **opts;
567
+ int got_flag, best_flag;
568
+ struct wordlist *ap, *addr_list, *alist, **app;
569
+ char word[MAXWORDLEN];
576
+ if (!getword(f, word, &newline, filename))
577
+ return -1; /* file is empty??? */
582
+ * Skip until we find a word at the start of a line.
584
+ while (!newline && getword(f, word, &newline, filename));
586
+ break; /* got to end of file */
589
+ * Got a client - check if it's a match or a wildcard.
592
+ if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
597
+ got_flag = NONWILD_CLIENT;
600
+ * Now get a server and check if it matches.
602
+ if (!getword(f, word, &newline, filename))
606
+ if (!ISWILD(word)) {
607
+ if (server != NULL && strcmp(word, server) != 0)
609
+ got_flag |= NONWILD_SERVER;
613
+ * Got some sort of a match - see if it's better than what
616
+ if (got_flag <= best_flag)
622
+ if (!getword(f, word, &newline, filename))
626
+ if (strcmp(word, "-") != 0) {
627
+ strlcpy(cli_cert, word, MAXWORDLEN);
634
+ if (!getword(f, word, &newline, filename))
638
+ if (strcmp(word, "-") != 0) {
639
+ strlcpy(serv_cert, word, MAXWORDLEN);
646
+ if (!getword(f, word, &newline, filename))
650
+ strlcpy(ca_cert, word, MAXWORDLEN);
655
+ if (!getword(f, word, &newline, filename))
659
+ strlcpy(pk, word, MAXWORDLEN);
663
+ * Now read address authorization info and make a wordlist.
667
+ if (!getword(f, word, &newline, filename) || newline)
669
+ ap = (struct wordlist *)
670
+ malloc(sizeof(struct wordlist) + strlen(word) + 1);
672
+ novm("authorized addresses");
673
+ ap->word = (char *) (ap + 1);
674
+ strcpy(ap->word, word);
680
+ * This is the best so far; remember it.
682
+ best_flag = got_flag;
684
+ free_wordlist(addr_list);
691
+ /* scan for a -- word indicating the start of options */
692
+ for (app = &addr_list; (ap = *app) != NULL; app = &ap->next)
693
+ if (strcmp(ap->word, "--") == 0)
695
+ /* ap = start of options */
697
+ ap = ap->next; /* first option */
698
+ free(*app); /* free the "--" word */
699
+ *app = NULL; /* terminate addr list */
703
+ else if (ap != NULL)
706
+ *addrs = addr_list;
707
+ else if (addr_list != NULL)
708
+ free_wordlist(addr_list);
715
+get_eaptls_secret(unit, client, server, clicertfile, servcertfile,
716
+ cacertfile, pkfile, am_server)
721
+ char *servcertfile;
728
+ char *filename = NULL;
729
+ struct wordlist *addrs = NULL;
730
+ struct wordlist *opts = NULL;
732
+ /* in client mode the ca+cert+privkey can also be specified as options */
733
+ if (!am_server && cacert_file && cert_file && privkey_file )
735
+ strlcpy( clicertfile, cert_file, MAXWORDLEN );
736
+ strlcpy( cacertfile, cacert_file, MAXWORDLEN );
737
+ strlcpy( pkfile, privkey_file, MAXWORDLEN );
738
+ servcertfile[0] = '\0';
742
+ filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE);
745
+ fp = fopen(filename, "r");
748
+ error("Can't open eap-tls secret file %s: %m", filename);
752
+ check_access(fp, filename);
754
+ ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile,
755
+ cacertfile, pkfile, &addrs, &opts, filename, 0);
759
+ if (ret < 0) return 0;
762
+ if (eaptls_passwd_hook)
764
+ dbglog( "Calling eaptls password hook" );
765
+ if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0)
767
+ error("Unable to obtain EAP-TLS password for %s (%s) from plugin",
773
+ set_allowed_addrs(unit, addrs, opts);
774
+ else if (opts != NULL)
775
+ free_wordlist(opts);
777
+ free_wordlist(addrs);
783
Index: ppp-2.4.5/pppd/ccp.c
784
===================================================================
785
--- ppp-2.4.5.orig/pppd/ccp.c 2013-01-22 15:19:11.000000000 -0600
786
+++ ppp-2.4.5/pppd/ccp.c 2013-01-22 15:19:29.000000000 -0600
789
ccp_options *ao = &ccp_allowoptions[f->unit];
790
int auth_mschap_bits = auth_done[f->unit];
792
+ int auth_eap_bits = auth_done[f->unit];
798
lcp_close(f->unit, "MPPE required but not available");
804
+ * MPPE is also possible in combination with EAP-TLS.
805
+ * It is not possible to detect if we're doing EAP or EAP-TLS
806
+ * at this stage, hence we accept all forms of EAP. If TLS is
807
+ * not used then the MPPE keys will not be derived anyway.
809
+ /* Leave only the eap auth bits set */
810
+ auth_eap_bits &= (EAP_WITHPEER | EAP_PEER );
812
+ if ((numbits == 0) && (auth_eap_bits == 0)) {
813
+ error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed.");
816
- error("MPPE required, but MS-CHAP[v2] auth not performed.");
817
+ error("MPPE required, but MS-CHAP[v2] auth not performed.");
819
lcp_close(f->unit, "MPPE required but not available");
822
Index: ppp-2.4.5/pppd/chap-md5.c
823
===================================================================
824
--- ppp-2.4.5.orig/pppd/chap-md5.c 2013-01-22 15:19:11.000000000 -0600
825
+++ ppp-2.4.5/pppd/chap-md5.c 2013-01-22 15:19:29.000000000 -0600
827
#include "chap-new.h"
828
#include "chap-md5.h"
831
+#include "eap-tls.h"
834
+#endif /* USE_EAPTLS */
836
#define MD5_HASH_SIZE 16
837
#define MD5_MIN_CHALLENGE 16
838
Index: ppp-2.4.5/pppd/eap-tls.c
839
===================================================================
840
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
841
+++ ppp-2.4.5/pppd/eap-tls.c 2013-01-22 15:19:29.000000000 -0600
844
+ * eap-tls.c - EAP-TLS implementation for PPP
846
+ * Copyright (c) Beniamino Galvani 2005 All rights reserved.
848
+ * Redistribution and use in source and binary forms, with or without
849
+ * modification, are permitted provided that the following conditions
852
+ * 1. Redistributions of source code must retain the above copyright
853
+ * notice, this list of conditions and the following disclaimer.
855
+ * 2. Redistributions in binary form must reproduce the above copyright
856
+ * notice, this list of conditions and the following disclaimer in
857
+ * the documentation and/or other materials provided with the
860
+ * 3. The name(s) of the authors of this software must not be used to
861
+ * endorse or promote products derived from this software without
862
+ * prior written permission.
864
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
865
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
866
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
867
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
868
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
869
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
870
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
876
+#include <sys/types.h>
877
+#include <sys/stat.h>
880
+#include <openssl/conf.h>
881
+#include <openssl/engine.h>
882
+#include <openssl/hmac.h>
883
+#include <openssl/err.h>
884
+#include <openssl/x509v3.h>
888
+#include "eap-tls.h"
891
+#include "pathnames.h"
893
+/* The openssl configuration file and engines can be loaded only once */
894
+static CONF *ssl_config = NULL;
895
+static ENGINE *cert_engine = NULL;
896
+static ENGINE *pkey_engine = NULL;
901
+ * TLS PRF from RFC 2246
903
+static void P_hash(const EVP_MD *evp_md,
904
+ const unsigned char *secret, unsigned int secret_len,
905
+ const unsigned char *seed, unsigned int seed_len,
906
+ unsigned char *out, unsigned int out_len)
908
+ HMAC_CTX ctx_a, ctx_out;
909
+ unsigned char a[HMAC_MAX_MD_CBLOCK];
912
+ HMAC_CTX_init(&ctx_a);
913
+ HMAC_CTX_init(&ctx_out);
914
+ HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL);
915
+ HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL);
917
+ size = HMAC_size(&ctx_out);
919
+ /* Calculate A(1) */
920
+ HMAC_Update(&ctx_a, seed, seed_len);
921
+ HMAC_Final(&ctx_a, a, NULL);
924
+ /* Calculate next part of output */
925
+ HMAC_Update(&ctx_out, a, size);
926
+ HMAC_Update(&ctx_out, seed, seed_len);
928
+ /* Check if last part */
929
+ if (out_len < size) {
930
+ HMAC_Final(&ctx_out, a, NULL);
931
+ memcpy(out, a, out_len);
935
+ /* Place digest in output buffer */
936
+ HMAC_Final(&ctx_out, out, NULL);
937
+ HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL);
941
+ /* Calculate next A(i) */
942
+ HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL);
943
+ HMAC_Update(&ctx_a, a, size);
944
+ HMAC_Final(&ctx_a, a, NULL);
947
+ HMAC_CTX_cleanup(&ctx_a);
948
+ HMAC_CTX_cleanup(&ctx_out);
949
+ memset(a, 0, sizeof(a));
952
+static void PRF(const unsigned char *secret, unsigned int secret_len,
953
+ const unsigned char *seed, unsigned int seed_len,
954
+ unsigned char *out, unsigned char *buf, unsigned int out_len)
957
+ unsigned int len = (secret_len + 1) / 2;
958
+ const unsigned char *s1 = secret;
959
+ const unsigned char *s2 = secret + (secret_len - len);
961
+ P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len);
962
+ P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
964
+ for (i=0; i < out_len; i++) {
969
+#define EAPTLS_MPPE_KEY_LEN 32
972
+ * Generate keys according to RFC 2716 and add to reply
974
+void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label,
977
+ unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN];
978
+ unsigned char seed[64 + 2*SSL3_RANDOM_SIZE];
979
+ unsigned char *p = seed;
983
+ prf_size = strlen(prf_label);
985
+ memcpy(p, prf_label, prf_size);
988
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
989
+ p += SSL3_RANDOM_SIZE;
990
+ prf_size += SSL3_RANDOM_SIZE;
992
+ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
993
+ prf_size += SSL3_RANDOM_SIZE;
995
+ PRF(s->session->master_key, s->session->master_key_length,
996
+ seed, prf_size, out, buf, sizeof(out));
999
+ * We now have the master send and receive keys.
1000
+ * From these, generate the session send and receive keys.
1001
+ * (see RFC3079 / draft-ietf-pppext-mppe-keys-03.txt for details)
1006
+ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) );
1007
+ p += EAPTLS_MPPE_KEY_LEN;
1008
+ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) );
1013
+ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) );
1014
+ p += EAPTLS_MPPE_KEY_LEN;
1015
+ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) );
1018
+ mppe_keys_set = 1;
1023
+void log_ssl_errors( void )
1025
+ unsigned long ssl_err = ERR_get_error();
1028
+ dbglog("EAP-TLS SSL error stack:");
1029
+ while (ssl_err != 0) {
1030
+ dbglog( ERR_error_string( ssl_err, NULL ) );
1031
+ ssl_err = ERR_get_error();
1036
+int password_callback (char *buf, int size, int rwflag, void *u)
1040
+ strncpy (buf, passwd, size);
1041
+ return strlen (buf);
1047
+CONF *eaptls_ssl_load_config( void )
1051
+ long error_line = 33;
1053
+ config = NCONF_new( NULL );
1054
+ dbglog( "Loading OpenSSL config file" );
1055
+ ret_code = NCONF_load( config, _PATH_OPENSSLCONFFILE, &error_line );
1056
+ if (ret_code == 0)
1058
+ warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line );
1059
+ NCONF_free( config );
1061
+ ERR_clear_error();
1064
+ dbglog( "Loading OpenSSL built-ins" );
1065
+ ENGINE_load_builtin_engines();
1066
+ OPENSSL_load_builtin_modules();
1068
+ dbglog( "Loading OpenSSL configured modules" );
1069
+ if (CONF_modules_load( config, NULL, 0 ) <= 0 )
1071
+ warn( "EAP-TLS: Error loading OpenSSL modules" );
1079
+ENGINE *eaptls_ssl_load_engine( char *engine_name )
1083
+ dbglog( "Enabling OpenSSL auto engines" );
1084
+ ENGINE_register_all_complete();
1086
+ dbglog( "Loading OpenSSL '%s' engine support", engine_name );
1087
+ e = ENGINE_by_id( engine_name );
1090
+ dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name );
1091
+ e = ENGINE_by_id( "dynamic" );
1094
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0)
1095
+ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
1097
+ warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name );
1105
+ warn( "EAP-TLS: Cannot load dynamic engine support" );
1111
+ dbglog( "Initialising engine" );
1112
+ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
1114
+ warn( "EAP-TLS: Cannot use that engine" );
1125
+ * Initialize the SSL stacks and tests if certificates, key and crl
1126
+ * for client or server use can be loaded.
1128
+SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile,
1129
+ char *certfile, char *peer_certfile, char *privkeyfile)
1131
+ char *cert_engine_name = NULL;
1132
+ char *cert_identifier = NULL;
1133
+ char *pkey_engine_name = NULL;
1134
+ char *pkey_identifier = NULL;
1136
+ X509_STORE *certstore;
1137
+ X509_LOOKUP *lookup;
1141
+ * Without these can't continue
1143
+ if (!cacertfile[0])
1145
+ error("EAP-TLS: CA certificate missing");
1151
+ error("EAP-TLS: User certificate missing");
1155
+ if (!privkeyfile[0])
1157
+ error("EAP-TLS: User private key missing");
1161
+ SSL_library_init();
1162
+ SSL_load_error_strings();
1164
+ ctx = SSL_CTX_new(TLSv1_method());
1167
+ error("EAP-TLS: Cannot initialize SSL CTX context");
1171
+ /* if the certificate filename is of the form engine:id. e.g.
1173
+ then we try to load and use this engine.
1174
+ If the certificate filename starts with a / or . then we
1175
+ ALWAYS assume it is a file and not an engine/pkcs11 identifier
1177
+ if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL )
1179
+ cert_identifier = index( certfile, ':' );
1181
+ if (cert_identifier)
1183
+ cert_engine_name = certfile;
1184
+ *cert_identifier = '\0';
1185
+ cert_identifier++;
1187
+ dbglog( "Found certificate engine '%s'", cert_engine_name );
1188
+ dbglog( "Found certificate identifier '%s'", cert_identifier );
1192
+ /* if the privatekey filename is of the form engine:id. e.g.
1194
+ then we try to load and use this engine.
1195
+ If the privatekey filename starts with a / or . then we
1196
+ ALWAYS assume it is a file and not an engine/pkcs11 identifier
1198
+ if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL )
1200
+ pkey_identifier = index( privkeyfile, ':' );
1202
+ if (pkey_identifier)
1204
+ pkey_engine_name = privkeyfile;
1205
+ *pkey_identifier = '\0';
1206
+ pkey_identifier++;
1208
+ dbglog( "Found privatekey engine '%s'", pkey_engine_name );
1209
+ dbglog( "Found privatekey identifier '%s'", pkey_identifier );
1213
+ if (cert_identifier && pkey_identifier)
1215
+ if (strlen( cert_identifier ) == 0)
1217
+ if (strlen( pkey_identifier ) == 0)
1218
+ error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" );
1221
+ dbglog( "Substituting privatekey identifier for certificate identifier" );
1222
+ cert_identifier = pkey_identifier;
1227
+ if (strlen( pkey_identifier ) == 0)
1229
+ dbglog( "Substituting certificate identifier for privatekey identifier" );
1230
+ pkey_identifier = cert_identifier;
1236
+ /* load the openssl config file only once */
1239
+ if (cert_engine_name || pkey_engine_name)
1240
+ ssl_config = eaptls_ssl_load_config();
1242
+ if (ssl_config && cert_engine_name)
1243
+ cert_engine = eaptls_ssl_load_engine( cert_engine_name );
1245
+ if (ssl_config && pkey_engine_name)
1247
+ /* don't load the same engine twice */
1248
+ if ( strcmp( cert_engine_name, pkey_engine_name) == 0 )
1249
+ pkey_engine = cert_engine;
1251
+ pkey_engine = eaptls_ssl_load_engine( pkey_engine_name );
1255
+ SSL_CTX_set_default_passwd_cb (ctx, password_callback);
1257
+ if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL))
1259
+ error("EAP-TLS: Cannot load or verify CA file %s", cacertfile);
1264
+ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile));
1270
+ const char *s_slot_cert_id;
1274
+ cert_info.s_slot_cert_id = cert_identifier;
1275
+ cert_info.cert = NULL;
1277
+ if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) )
1279
+ error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier );
1283
+ if (cert_info.cert)
1285
+ dbglog( "Got the certificate, adding it to SSL context" );
1286
+ dbglog( "subject = %s", X509_NAME_oneline( X509_get_subject_name( cert_info.cert ), NULL, 0 ) );
1287
+ if (SSL_CTX_use_certificate(ctx, cert_info.cert) <= 0)
1289
+ error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier);
1295
+ warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier);
1301
+ if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM))
1303
+ error( "EAP-TLS: Cannot use public certificate %s", certfile );
1310
+ EVP_PKEY *pkey = NULL;
1311
+ PW_CB_DATA cb_data;
1313
+ cb_data.password = passwd;
1314
+ cb_data.prompt_info = pkey_identifier;
1316
+ dbglog( "Loading private key '%s' from engine", pkey_identifier );
1317
+ pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data);
1320
+ dbglog( "Got the private key, adding it to SSL context" );
1321
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
1323
+ error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier);
1329
+ warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier);
1335
+ if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM))
1337
+ error("EAP-TLS: Cannot use private key %s", privkeyfile);
1342
+ if (SSL_CTX_check_private_key(ctx) != 1) {
1343
+ error("EAP-TLS: Private key %s fails security check", privkeyfile);
1347
+ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
1348
+ SSL_CTX_set_verify_depth(ctx, 5);
1349
+ SSL_CTX_set_verify(ctx,
1351
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1352
+ &ssl_verify_callback);
1355
+ if (!(certstore = SSL_CTX_get_cert_store(ctx))) {
1356
+ error("EAP-TLS: Failed to get certificate store");
1361
+ X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) {
1362
+ error("EAP-TLS: Store lookup for CRL failed");
1367
+ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM);
1368
+ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK);
1372
+ * If a peer certificate file was specified, it must be valid, else fail
1374
+ if (peer_certfile[0]) {
1375
+ if (!(tmp = get_X509_from_file(peer_certfile))) {
1376
+ error("EAP-TLS: Error loading client certificate from file %s",
1387
+ SSL_CTX_free(ctx);
1392
+ * Determine the maximum packet size by looking at the LCP handshake
1395
+int eaptls_get_mtu(int unit)
1399
+ lcp_options *wo = &lcp_wantoptions[unit];
1400
+ lcp_options *go = &lcp_gotoptions[unit];
1401
+ lcp_options *ho = &lcp_hisoptions[unit];
1402
+ lcp_options *ao = &lcp_allowoptions[unit];
1404
+ mtu = ho->neg_mru? ho->mru: PPP_MRU;
1405
+ mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU;
1406
+ mtu = MIN(MIN(mtu, mru), ao->mru)- PPP_HDRLEN - 10;
1408
+ dbglog("MTU = %d", mtu);
1414
+ * Init the ssl handshake (server mode)
1416
+int eaptls_init_ssl_server(eap_state * esp)
1418
+ struct eaptls_session *ets;
1419
+ char servcertfile[MAXWORDLEN];
1420
+ char clicertfile[MAXWORDLEN];
1421
+ char cacertfile[MAXWORDLEN];
1422
+ char pkfile[MAXWORDLEN];
1424
+ * Allocate new eaptls session
1426
+ esp->es_server.ea_session = malloc(sizeof(struct eaptls_session));
1427
+ if (!esp->es_server.ea_session)
1428
+ fatal("Allocation error");
1429
+ ets = esp->es_server.ea_session;
1431
+ if (!esp->es_server.ea_peer) {
1432
+ error("EAP-TLS: Error: client name not set (BUG)");
1436
+ strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN);
1438
+ dbglog( "getting eaptls secret" );
1439
+ if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer,
1440
+ esp->es_server.ea_name, clicertfile,
1441
+ servcertfile, cacertfile, pkfile, 1)) {
1442
+ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"",
1443
+ esp->es_server.ea_peer, esp->es_server.ea_name );
1447
+ ets->mtu = eaptls_get_mtu(esp->es_unit);
1449
+ ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile);
1453
+ if (!(ets->ssl = SSL_new(ets->ctx)))
1457
+ * Set auto-retry to avoid timeouts on BIO_read
1459
+ SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY);
1462
+ * Initialize the BIOs we use to read/write to ssl engine
1464
+ ets->into_ssl = BIO_new(BIO_s_mem());
1465
+ ets->from_ssl = BIO_new(BIO_s_mem());
1466
+ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl);
1468
+ SSL_set_msg_callback(ets->ssl, ssl_msg_callback);
1469
+ SSL_set_msg_callback_arg(ets->ssl, ets);
1472
+ * Attach the session struct to the connection, so we can later
1473
+ * retrieve it when doing certificate verification
1475
+ SSL_set_ex_data(ets->ssl, 0, ets);
1477
+ SSL_set_accept_state(ets->ssl);
1481
+ ets->alert_sent = 0;
1482
+ ets->alert_recv = 0;
1485
+ * If we specified the client certificate file, store it in ets->peercertfile,
1486
+ * so we can check it later in ssl_verify_callback()
1488
+ if (clicertfile[0])
1489
+ strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN);
1491
+ ets->peercertfile[0] = 0;
1496
+ SSL_CTX_free(ets->ctx);
1501
+ * Init the ssl handshake (client mode)
1503
+int eaptls_init_ssl_client(eap_state * esp)
1505
+ struct eaptls_session *ets;
1506
+ char servcertfile[MAXWORDLEN];
1507
+ char clicertfile[MAXWORDLEN];
1508
+ char cacertfile[MAXWORDLEN];
1509
+ char pkfile[MAXWORDLEN];
1512
+ * Allocate new eaptls session
1514
+ esp->es_client.ea_session = malloc(sizeof(struct eaptls_session));
1515
+ if (!esp->es_client.ea_session)
1516
+ fatal("Allocation error");
1517
+ ets = esp->es_client.ea_session;
1520
+ * If available, copy server name in ets; it will be used in cert
1523
+ if (esp->es_client.ea_peer)
1524
+ strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN);
1528
+ ets->mtu = eaptls_get_mtu(esp->es_unit);
1530
+ dbglog( "calling get_eaptls_secret" );
1531
+ if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name,
1532
+ esp->es_client.ea_peer, clicertfile,
1533
+ servcertfile, cacertfile, pkfile, 0)) {
1534
+ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"",
1535
+ esp->es_client.ea_name, esp->es_client.ea_peer );
1539
+ dbglog( "calling eaptls_init_ssl" );
1540
+ ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile);
1544
+ ets->ssl = SSL_new(ets->ctx);
1550
+ * Initialize the BIOs we use to read/write to ssl engine
1552
+ dbglog( "Initializing SSL BIOs" );
1553
+ ets->into_ssl = BIO_new(BIO_s_mem());
1554
+ ets->from_ssl = BIO_new(BIO_s_mem());
1555
+ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl);
1557
+ SSL_set_msg_callback(ets->ssl, ssl_msg_callback);
1558
+ SSL_set_msg_callback_arg(ets->ssl, ets);
1561
+ * Attach the session struct to the connection, so we can later
1562
+ * retrieve it when doing certificate verification
1564
+ SSL_set_ex_data(ets->ssl, 0, ets);
1566
+ SSL_set_connect_state(ets->ssl);
1570
+ ets->alert_sent = 0;
1571
+ ets->alert_recv = 0;
1574
+ * If we specified the server certificate file, store it in
1575
+ * ets->peercertfile, so we can check it later in
1576
+ * ssl_verify_callback()
1578
+ if (servcertfile[0])
1579
+ strncpy(ets->peercertfile, servcertfile, MAXWORDLEN);
1581
+ ets->peercertfile[0] = 0;
1586
+ dbglog( "eaptls_init_ssl_client: fail" );
1587
+ SSL_CTX_free(ets->ctx);
1592
+void eaptls_free_session(struct eaptls_session *ets)
1595
+ SSL_free(ets->ssl);
1598
+ SSL_CTX_free(ets->ctx);
1604
+ * Handle a received packet, reassembling fragmented messages and
1605
+ * passing them to the ssl engine
1607
+int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len)
1611
+ u_char dummy[65536];
1613
+ GETCHAR(flags, inp);
1616
+ if (flags & EAP_TLS_FLAGS_LI && !ets->data) {
1619
+ * This is the first packet of a message
1622
+ GETLONG(tlslen, inp);
1625
+ if (tlslen > EAP_TLS_MAX_LEN) {
1626
+ error("Error: tls message length > %d, truncated",
1628
+ tlslen = EAP_TLS_MAX_LEN;
1632
+ * Allocate memory for the whole message
1634
+ ets->data = malloc(tlslen);
1636
+ fatal("EAP TLS: allocation error\n");
1639
+ ets->tlslen = tlslen;
1642
+ else if (flags & EAP_TLS_FLAGS_LI && ets->data) {
1644
+ * Non first with LI (strange...)
1647
+ GETLONG(tlslen, inp);
1651
+ else if (!ets->data) {
1653
+ * A non fragmented message without LI flag
1656
+ ets->data = malloc(len);
1658
+ fatal("EAP TLS: allocation error\n");
1661
+ ets->tlslen = len;
1664
+ if (flags & EAP_TLS_FLAGS_MF)
1669
+ if (len + ets->datalen > ets->tlslen) {
1670
+ warn("EAP TLS: received data > TLS message length");
1674
+ BCOPY(inp, ets->data + ets->datalen, len);
1675
+ ets->datalen += len;
1680
+ * If we have the whole message, pass it to ssl
1683
+ if (ets->datalen != ets->tlslen) {
1684
+ warn("EAP TLS: received data != TLS message length");
1688
+ if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1)
1691
+ SSL_read(ets->ssl, dummy, 65536);
1702
+ * Return an eap-tls packet in outp.
1703
+ * A TLS message read from the ssl engine is buffered in ets->data.
1704
+ * At each call we control if there is buffered data and send a
1705
+ * packet of mtu bytes.
1707
+int eaptls_send(struct eaptls_session *ets, u_char ** outp)
1711
+ u_char fromtls[65536];
1719
+ if(!ets->alert_sent)
1720
+ SSL_read(ets->ssl, fromtls, 65536);
1725
+ if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1)
1726
+ fatal("No data from BIO_read");
1728
+ ets->datalen = res;
1730
+ ets->data = malloc(ets->datalen);
1731
+ BCOPY(fromtls, ets->data, ets->datalen);
1738
+ size = ets->datalen - ets->offset;
1740
+ if (size > ets->mtu) {
1746
+ PUTCHAR(EAPT_TLS, *outp);
1749
+ * Set right flags and length if necessary
1751
+ if (ets->frag && first) {
1752
+ PUTCHAR(EAP_TLS_FLAGS_LI | EAP_TLS_FLAGS_MF, *outp);
1753
+ PUTLONG(ets->datalen, *outp);
1754
+ } else if (ets->frag) {
1755
+ PUTCHAR(EAP_TLS_FLAGS_MF, *outp);
1757
+ PUTCHAR(0, *outp);
1760
+ * Copy the data in outp
1762
+ BCOPY(ets->data + ets->offset, *outp, size);
1763
+ INCPTR(size, *outp);
1766
+ * Copy the packet in retransmission buffer
1768
+ BCOPY(start, &ets->rtx[0], *outp - start);
1769
+ ets->rtx_len = *outp - start;
1771
+ ets->offset += size;
1773
+ if (ets->offset >= ets->datalen) {
1776
+ * The whole message has been sent
1789
+ * Get the sent packet from the retransmission buffer
1791
+void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp)
1793
+ BCOPY(ets->rtx, *outp, ets->rtx_len);
1794
+ INCPTR(ets->rtx_len, *outp);
1798
+ * Verify a certificate.
1799
+ * Most of the work (signatures and issuer attributes checking)
1800
+ * is done by ssl; we check the CN in the peer certificate
1801
+ * against the peer name.
1803
+int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx)
1805
+ char subject[256];
1809
+ int ok = preverify_ok;
1811
+ struct eaptls_session *ets;
1813
+ peer_cert = X509_STORE_CTX_get_current_cert(ctx);
1814
+ err = X509_STORE_CTX_get_error(ctx);
1815
+ depth = X509_STORE_CTX_get_error_depth(ctx);
1817
+ dbglog("certificate verify depth: %d", depth);
1819
+ if (auth_required && !ok) {
1820
+ X509_NAME_oneline(X509_get_subject_name(peer_cert),
1823
+ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
1824
+ NID_commonName, cn_str, 256);
1826
+ dbglog("Certificate verification error:\n depth: %d CN: %s"
1827
+ "\n err: %d (%s)\n", depth, cn_str, err,
1828
+ X509_verify_cert_error_string(err));
1833
+ ssl = X509_STORE_CTX_get_ex_data(ctx,
1834
+ SSL_get_ex_data_X509_STORE_CTX_idx());
1836
+ ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0);
1838
+ if (ets == NULL) {
1839
+ error("Error: SSL_get_ex_data returned NULL");
1845
+ if (!depth) { /* This is the peer certificate */
1847
+ X509_NAME_oneline(X509_get_subject_name(peer_cert),
1850
+ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
1851
+ NID_commonName, cn_str, 256);
1854
+ * If acting as client and the name of the server wasn't specified
1855
+ * explicitely, we can't verify the server authenticity
1857
+ if (!ets->peer[0]) {
1858
+ warn("Peer name not specified: no check");
1865
+ if (strcmp(cn_str, ets->peer)) {
1867
+ ("Certificate verification error: CN (%s) != peer_name (%s)",
1868
+ cn_str, ets->peer);
1872
+ warn("Certificate CN: %s , peer name %s", cn_str, ets->peer);
1875
+ * If a peer certificate file was specified, here we check it
1877
+ if (ets->peercertfile[0]) {
1878
+ if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert)
1881
+ ("Peer certificate doesn't match stored certificate");
1891
+ * Compare a certificate with the one stored in a file
1893
+int ssl_cmp_certs(char *filename, X509 * a)
1898
+ if (!(b = get_X509_from_file(filename)))
1901
+ ret = X509_cmp(a, b);
1908
+X509 *get_X509_from_file(char *filename)
1913
+ if (!(fp = fopen(filename, "r")))
1916
+ ret = PEM_read_X509(fp, NULL, NULL, NULL);
1924
+ * Every sent & received message this callback function is invoked,
1925
+ * so we know when alert messages have arrived or are sent and
1926
+ * we can print debug information about TLS handshake.
1929
+ssl_msg_callback(int write_p, int version, int content_type,
1930
+ const void *buf, size_t len, SSL * ssl, void *arg)
1933
+ struct eaptls_session *ets = (struct eaptls_session *)arg;
1934
+ unsigned char code;
1937
+ strcpy(string, " -> ");
1939
+ strcpy(string, " <- ");
1942
+ switch(content_type) {
1944
+ case SSL3_RT_ALERT:
1945
+ strcat(string, "Alert: ");
1946
+ code = ((const unsigned char *)buf)[1];
1949
+ ets->alert_sent = 1;
1950
+ ets->alert_sent_desc = code;
1952
+ ets->alert_recv = 1;
1953
+ ets->alert_recv_desc = code;
1956
+ strcat(string, SSL_alert_desc_string_long(code));
1959
+ case SSL3_RT_CHANGE_CIPHER_SPEC:
1960
+ strcat(string, "ChangeCipherSpec");
1963
+ case SSL3_RT_HANDSHAKE:
1965
+ strcat(string, "Handshake: ");
1966
+ code = ((const unsigned char *)buf)[0];
1969
+ case SSL3_MT_HELLO_REQUEST:
1970
+ strcat(string,"Hello Request");
1972
+ case SSL3_MT_CLIENT_HELLO:
1973
+ strcat(string,"Client Hello");
1975
+ case SSL3_MT_SERVER_HELLO:
1976
+ strcat(string,"Server Hello");
1978
+ case SSL3_MT_CERTIFICATE:
1979
+ strcat(string,"Certificate");
1981
+ case SSL3_MT_SERVER_KEY_EXCHANGE:
1982
+ strcat(string,"Server Key Exchange");
1984
+ case SSL3_MT_CERTIFICATE_REQUEST:
1985
+ strcat(string,"Certificate Request");
1987
+ case SSL3_MT_SERVER_DONE:
1988
+ strcat(string,"Server Hello Done");
1990
+ case SSL3_MT_CERTIFICATE_VERIFY:
1991
+ strcat(string,"Certificate Verify");
1993
+ case SSL3_MT_CLIENT_KEY_EXCHANGE:
1994
+ strcat(string,"Client Key Exchange");
1996
+ case SSL3_MT_FINISHED:
1997
+ strcat(string,"Finished");
2001
+ sprintf( string, "Handshake: Unknown SSL3 code received: %d", code );
2006
+ sprintf( string, "SSL message contains unknown content type: %d", content_type );
2010
+ /* Alert messages must always be displayed */
2011
+ if(content_type == SSL3_RT_ALERT)
2012
+ error("%s", string);
2014
+ dbglog("%s", string);
2017
Index: ppp-2.4.5/pppd/eap-tls.h
2018
===================================================================
2019
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2020
+++ ppp-2.4.5/pppd/eap-tls.h 2013-01-22 15:19:29.000000000 -0600
2025
+ * Copyright (c) Beniamino Galvani 2005 All rights reserved.
2027
+ * Redistribution and use in source and binary forms, with or without
2028
+ * modification, are permitted provided that the following conditions
2031
+ * 1. Redistributions of source code must retain the above copyright
2032
+ * notice, this list of conditions and the following disclaimer.
2034
+ * 2. Redistributions in binary form must reproduce the above copyright
2035
+ * notice, this list of conditions and the following disclaimer in
2036
+ * the documentation and/or other materials provided with the
2039
+ * 3. The name(s) of the authors of this software must not be used to
2040
+ * endorse or promote products derived from this software without
2041
+ * prior written permission.
2043
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
2044
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2045
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
2046
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2047
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
2048
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
2049
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2053
+#ifndef __EAP_TLS_H__
2054
+#define __EAP_TLS_H__
2058
+#include <openssl/ssl.h>
2059
+#include <openssl/bio.h>
2060
+#include <openssl/md5.h>
2062
+#define EAP_TLS_FLAGS_LI 128 /* length included flag */
2063
+#define EAP_TLS_FLAGS_MF 64 /* more fragments flag */
2064
+#define EAP_TLS_FLAGS_START 32 /* start flag */
2066
+#define EAP_TLS_MAX_LEN 65536 /* max eap tls packet size */
2068
+struct eaptls_session
2070
+ u_char *data; /* buffered data */
2071
+ int datalen; /* buffered data len */
2072
+ int offset; /* from where to send */
2073
+ int tlslen; /* total length of tls data */
2074
+ bool frag; /* packet is fragmented */
2076
+ SSL *ssl; /* ssl connection */
2079
+ char peer[MAXWORDLEN]; /* peer name */
2080
+ char peercertfile[MAXWORDLEN];
2082
+ u_char alert_sent_desc;
2084
+ u_char alert_recv_desc;
2085
+ char rtx[65536]; /* retransmission buffer */
2087
+ int mtu; /* unit mtu */
2090
+typedef struct pw_cb_data
2092
+ const void *password;
2093
+ const char *prompt_info;
2097
+int ssl_verify_callback(int, X509_STORE_CTX *);
2098
+void ssl_msg_callback(int write_p, int version, int ct, const void *buf,
2099
+ size_t len, SSL * ssl, void *arg);
2101
+X509 *get_X509_from_file(char *filename);
2102
+int ssl_cmp_certs(char *filename, X509 * a);
2104
+SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile,
2105
+ char *certfile, char *peer_certfile, char *privkeyfile);
2106
+int eaptls_init_ssl_server(eap_state * esp);
2107
+int eaptls_init_ssl_client(eap_state * esp);
2108
+void eaptls_free_session(struct eaptls_session *ets);
2110
+int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len);
2111
+int eaptls_send(struct eaptls_session *ets, u_char ** outp);
2112
+void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp);
2114
+int get_eaptls_secret(int unit, char *client, char *server,
2115
+ char *clicertfile, char *servcertfile, char *cacertfile,
2116
+ char *pkfile, int am_server);
2119
+#include "mppe.h" /* MPPE_MAX_KEY_LEN */
2120
+extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
2121
+extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
2122
+extern int mppe_keys_set;
2124
+void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, int client);
2129
Index: ppp-2.4.5/pppd/eap.c
2130
===================================================================
2131
--- ppp-2.4.5.orig/pppd/eap.c 2013-01-22 15:19:11.000000000 -0600
2132
+++ ppp-2.4.5/pppd/eap.c 2013-01-22 15:19:29.000000000 -0600
2134
* Based on draft-ietf-pppext-eap-srp-03.txt.
2138
+ * Modification by Beniamino Galvani, Mar 2005
2139
+ * Implemented EAP-TLS authentication
2142
#define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
2148
#include "pathnames.h"
2152
+#include "eap-tls.h"
2155
+#endif /* USE_EAPTLS */
2160
esp->es_server.ea_id = (u_char)(drand48() * 0x100);
2161
esp->es_client.ea_timeout = EAP_DEFREQTIME;
2162
esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
2164
+ esp->es_client.ea_using_eaptls = 0;
2165
+#endif /* USE_EAPTLS */
2169
@@ -436,8 +448,16 @@
2172
#endif /* USE_SRP */
2174
+ struct eaptls_session *ets;
2176
+ char secret[MAXWORDLEN];
2177
+#endif /* USE_EAPTLS */
2179
esp->es_server.ea_timeout = esp->es_savedtime;
2181
+ esp->es_server.ea_prev_state = esp->es_server.ea_state;
2182
+#endif /* USE_EAPTLS */
2183
switch (esp->es_server.ea_state) {
2186
@@ -562,9 +582,81 @@
2189
#endif /* USE_SRP */
2191
+ if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
2192
+ esp->es_server.ea_name, secret, &secret_len, 1)) {
2194
+ esp->es_server.ea_state = eapTlsStart;
2197
+#endif /* USE_EAPTLS */
2199
esp->es_server.ea_state = eapMD5Chall;
2204
+ /* Initialize ssl session */
2205
+ if(!eaptls_init_ssl_server(esp)) {
2206
+ esp->es_server.ea_state = eapBadAuth;
2210
+ esp->es_server.ea_state = eapTlsRecv;
2214
+ ets = (struct eaptls_session *) esp->es_server.ea_session;
2216
+ if(ets->alert_sent) {
2217
+ esp->es_server.ea_state = eapTlsSendAlert;
2222
+ esp->es_server.ea_state = eapBadAuth;
2225
+ ets = (struct eaptls_session *) esp->es_server.ea_session;
2228
+ esp->es_server.ea_state = eapTlsSendAck;
2230
+ esp->es_server.ea_state = eapTlsSend;
2234
+ ets = (struct eaptls_session *) esp->es_server.ea_session;
2236
+ if(SSL_is_init_finished(ets->ssl)) {
2237
+ esp->es_server.ea_state = eapTlsRecvClient;
2242
+ esp->es_server.ea_state = eapTlsRecvAck;
2244
+ esp->es_server.ea_state = eapTlsRecv;
2247
+ case eapTlsSendAck:
2248
+ esp->es_server.ea_state = eapTlsRecv;
2251
+ case eapTlsRecvAck:
2253
+ esp->es_server.ea_state = eapBadAuth;
2257
+ esp->es_server.ea_state = eapTlsSend;
2260
+ case eapTlsSendAlert:
2261
+ esp->es_server.ea_state = eapTlsRecvAlertAck;
2263
+#endif /* USE_EAPTLS */
2267
ts = (struct t_server *)esp->es_server.ea_session;
2268
@@ -718,6 +810,30 @@
2269
INCPTR(esp->es_server.ea_namelen, outp);
2274
+ PUTCHAR(EAPT_TLS, outp);
2275
+ PUTCHAR(EAP_TLS_FLAGS_START, outp);
2276
+ eap_figure_next_state(esp, 0);
2280
+ eaptls_send(esp->es_server.ea_session, &outp);
2281
+ eap_figure_next_state(esp, 0);
2284
+ case eapTlsSendAck:
2285
+ PUTCHAR(EAPT_TLS, outp);
2287
+ eap_figure_next_state(esp, 0);
2290
+ case eapTlsSendAlert:
2291
+ eaptls_send(esp->es_server.ea_session, &outp);
2292
+ eap_figure_next_state(esp, 0);
2294
+#endif /* USE_EAPTLS */
2298
PUTCHAR(EAPT_SRP, outp);
2299
@@ -904,11 +1020,57 @@
2300
eap_server_timeout(arg)
2307
+#endif /* USE_EAPTLS */
2309
eap_state *esp = (eap_state *) arg;
2311
if (!eap_server_active(esp))
2315
+ switch(esp->es_server.ea_prev_state) {
2318
+ * In eap-tls the state changes after a request, so we return to
2319
+ * previous state ...
2321
+ case(eapTlsStart):
2322
+ case(eapTlsSendAck):
2323
+ esp->es_server.ea_state = esp->es_server.ea_prev_state;
2327
+ * ... or resend the stored data
2330
+ case(eapTlsSendAlert):
2331
+ outp = outpacket_buf;
2332
+ MAKEHEADER(outp, PPP_EAP);
2333
+ PUTCHAR(EAP_REQUEST, outp);
2334
+ PUTCHAR(esp->es_server.ea_id, outp);
2338
+ eaptls_retransmit(esp->es_server.ea_session, &outp);
2340
+ outlen = (outp - outpacket_buf) - PPP_HDRLEN;
2341
+ PUTSHORT(outlen, lenloc);
2342
+ output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
2343
+ esp->es_server.ea_requests++;
2345
+ if (esp->es_server.ea_timeout > 0)
2346
+ TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
2352
+#endif /* USE_EAPTLS */
2354
/* EAP ID number must not change on timeout. */
2355
eap_send_request(esp);
2357
@@ -1166,6 +1328,81 @@
2359
#endif /* USE_SRP */
2363
+ * Send an EAP-TLS response message with tls data
2366
+eap_tls_response(esp, id)
2374
+ outp = outpacket_buf;
2376
+ MAKEHEADER(outp, PPP_EAP);
2378
+ PUTCHAR(EAP_RESPONSE, outp);
2379
+ PUTCHAR(id, outp);
2385
+ If the id in the request is unchanged, we must retransmit
2388
+ if(id == esp->es_client.ea_id)
2389
+ eaptls_retransmit(esp->es_client.ea_session, &outp);
2391
+ eaptls_send(esp->es_client.ea_session, &outp);
2393
+ outlen = (outp - outpacket_buf) - PPP_HDRLEN;
2394
+ PUTSHORT(outlen, lenloc);
2396
+ output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
2398
+ esp->es_client.ea_id = id;
2403
+ * Send an EAP-TLS ack
2406
+eap_tls_sendack(esp, id)
2414
+ outp = outpacket_buf;
2416
+ MAKEHEADER(outp, PPP_EAP);
2418
+ PUTCHAR(EAP_RESPONSE, outp);
2419
+ PUTCHAR(id, outp);
2420
+ esp->es_client.ea_id = id;
2425
+ PUTCHAR(EAPT_TLS, outp);
2428
+ outlen = (outp - outpacket_buf) - PPP_HDRLEN;
2429
+ PUTSHORT(outlen, lenloc);
2431
+ output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
2434
+#endif /* USE_EAPTLS */
2437
eap_send_nak(esp, id, type)
2439
@@ -1320,6 +1557,11 @@
2440
char rhostname[256];
2442
u_char hash[MD5_SIGNATURE_SIZE];
2445
+ struct eaptls_session *ets = esp->es_client.ea_session;
2446
+#endif /* USE_EAPTLS */
2449
struct t_client *tc;
2450
struct t_num sval, gval, Nval, *Ap, Bval;
2451
@@ -1456,6 +1698,90 @@
2452
esp->es_client.ea_namelen);
2458
+ switch(esp->es_client.ea_state) {
2462
+ GETCHAR(flags, inp);
2463
+ if(flags & EAP_TLS_FLAGS_START){
2465
+ esp->es_client.ea_using_eaptls = 1;
2467
+ if (explicit_remote){
2468
+ esp->es_client.ea_peer = strdup(remote_name);
2469
+ esp->es_client.ea_peerlen = strlen(remote_name);
2471
+ esp->es_client.ea_peer = NULL;
2473
+ /* Init ssl session */
2474
+ if(!eaptls_init_ssl_client(esp)) {
2475
+ dbglog("cannot init ssl");
2476
+ eap_send_nak(esp, id, EAPT_TLS);
2477
+ esp->es_client.ea_using_eaptls = 0;
2481
+ ets = esp->es_client.ea_session;
2482
+ eap_tls_response(esp, id);
2483
+ esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2488
+ /* The server has sent a bad start packet. */
2489
+ eap_send_nak(esp, id, EAPT_TLS);
2492
+ case eapTlsRecvAck:
2493
+ eap_tls_response(esp, id);
2494
+ esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2499
+ eaptls_receive(ets, inp, len);
2502
+ eap_tls_sendack(esp, id);
2503
+ esp->es_client.ea_state = eapTlsRecv;
2507
+ if(ets->alert_recv) {
2508
+ eap_tls_sendack(esp, id);
2509
+ esp->es_client.ea_state = eapTlsRecvFailure;
2513
+ /* Check if TLS handshake is finished */
2514
+ if(SSL_is_init_finished(ets->ssl)){
2516
+ eaptls_gen_mppe_keys( ets, "client EAP encryption", 1 );
2518
+ eaptls_free_session(ets);
2519
+ eap_tls_sendack(esp, id);
2520
+ esp->es_client.ea_state = eapTlsRecvSuccess;
2524
+ eap_tls_response(esp,id);
2525
+ esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
2531
+ eap_send_nak(esp, id, EAPT_TLS);
2532
+ esp->es_client.ea_using_eaptls = 0;
2537
+#endif /* USE_EAPTLS */
2542
@@ -1737,6 +2063,11 @@
2543
u_char dig[SHA_DIGESTSIZE];
2544
#endif /* USE_SRP */
2547
+ struct eaptls_session *ets;
2549
+#endif /* USE_EAPTLS */
2551
if (esp->es_server.ea_id != id) {
2552
dbglog("EAP: discarding Response %d; expected ID %d", id,
2553
esp->es_server.ea_id);
2554
@@ -1776,6 +2107,60 @@
2555
eap_figure_next_state(esp, 0);
2560
+ switch(esp->es_server.ea_state) {
2563
+ ets = (struct eaptls_session *) esp->es_server.ea_session;
2564
+ eap_figure_next_state(esp,
2565
+ eaptls_receive(esp->es_server.ea_session, inp, len));
2567
+ if(ets->alert_recv) {
2568
+ eap_send_failure(esp);
2573
+ case eapTlsRecvAck:
2575
+ dbglog("EAP-TLS ACK with extra data");
2577
+ eap_figure_next_state(esp, 0);
2580
+ case eapTlsRecvClient:
2581
+ /* Receive authentication response from client */
2583
+ GETCHAR(flags, inp);
2585
+ if(len == 1 && !flags) { /* Ack = ok */
2587
+ eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 );
2589
+ eap_send_success(esp);
2591
+ else { /* failure */
2592
+ eaptls_receive(esp->es_server.ea_session, inp, len);
2593
+ warn("Server authentication failed");
2594
+ eap_send_failure(esp);
2597
+ eaptls_free_session(esp->es_server.ea_session);
2601
+ case eapTlsRecvAlertAck:
2602
+ eap_send_failure(esp);
2606
+ eap_figure_next_state(esp, 1);
2610
+#endif /* USE_EAPTLS */
2612
case EAPT_NOTIFICATION:
2613
dbglog("EAP unexpected Notification; response discarded");
2615
@@ -1807,6 +2192,13 @@
2616
esp->es_server.ea_state = eapMD5Chall;
2620
+ /* Send EAP-TLS start packet */
2622
+ esp->es_server.ea_state = eapTlsStart;
2624
+#endif /* USE_EAPTLS */
2627
dbglog("EAP: peer requesting unknown Type %d", vallen);
2628
switch (esp->es_server.ea_state) {
2629
@@ -2018,13 +2410,27 @@
2633
- if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
2634
+ if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
2636
+ && esp->es_client.ea_state != eapTlsRecvSuccess
2637
+#endif /* USE_EAPTLS */
2639
dbglog("EAP unexpected success message in state %s (%d)",
2640
eap_state_name(esp->es_client.ea_state),
2641
esp->es_client.ea_state);
2646
+ if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
2647
+ eapTlsRecvSuccess) {
2648
+ dbglog("EAP-TLS unexpected success message in state %s (%d)",
2649
+ eap_state_name(esp->es_client.ea_state),
2650
+ esp->es_client.ea_state);
2653
+#endif /* USE_EAPTLS */
2655
if (esp->es_client.ea_timeout > 0) {
2656
UNTIMEOUT(eap_client_timeout, (void *)esp);
2658
@@ -2150,6 +2556,9 @@
2659
int code, id, len, rtype, vallen;
2664
+#endif /* USE_EAPTLS */
2666
if (inlen < EAP_HEADERLEN)
2668
@@ -2214,6 +2623,24 @@
2676
+ GETCHAR(flags, inp);
2679
+ if(flags == 0 && len == 0){
2680
+ printer(arg, " Ack");
2684
+ printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2685
+ printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2686
+ printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2688
+#endif /* USE_EAPTLS */
2693
@@ -2325,6 +2752,25 @@
2701
+ GETCHAR(flags, inp);
2704
+ if(flags == 0 && len == 0){
2705
+ printer(arg, " Ack");
2709
+ printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
2710
+ printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
2711
+ printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
2714
+#endif /* USE_EAPTLS */
2718
printer(arg, " <missing hint>");
2719
@@ -2426,3 +2872,4 @@
2721
return (inp - pstart);
2724
Index: ppp-2.4.5/pppd/eap.h
2725
===================================================================
2726
--- ppp-2.4.5.orig/pppd/eap.h 2013-01-22 15:19:11.000000000 -0600
2727
+++ ppp-2.4.5/pppd/eap.h 2013-01-22 15:19:29.000000000 -0600
2729
eapClosed, /* Authentication not in use */
2730
eapListen, /* Client ready (and timer running) */
2731
eapIdentify, /* EAP Identify sent */
2732
+ eapTlsStart, /* Send EAP-TLS start packet */
2733
+ eapTlsRecv, /* Receive EAP-TLS tls data */
2734
+ eapTlsSendAck, /* Send EAP-TLS ack */
2735
+ eapTlsSend, /* Send EAP-TLS tls data */
2736
+ eapTlsRecvAck, /* Receive EAP-TLS ack */
2737
+ eapTlsRecvClient, /* Receive EAP-TLS auth response from client*/
2738
+ eapTlsSendAlert, /* Send EAP-TLS tls alert (server)*/
2739
+ eapTlsRecvAlertAck, /* Receive EAP-TLS ack after sending alert */
2740
+ eapTlsRecvSuccess, /* Receive EAP success */
2741
+ eapTlsRecvFailure, /* Receive EAP failure */
2742
eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */
2743
eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */
2744
eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */
2747
#define EAP_STATES \
2748
"Initial", "Pending", "Closed", "Listen", "Identify", \
2749
+ "TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\
2750
+ "TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \
2751
"SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
2753
-#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
2755
+#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial ||\
2756
+ (esp)->es_client.ea_state != eapPending ||\
2757
+ (esp)->es_client.ea_state != eapClosed)
2759
+#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
2760
+#endif /* USE_EAPTLS */
2762
#define eap_server_active(esp) \
2763
((esp)->es_server.ea_state >= eapIdentify && \
2764
(esp)->es_server.ea_state <= eapMD5Chall)
2765
@@ -112,11 +131,17 @@
2766
u_short ea_namelen; /* Length of our name */
2767
u_short ea_peerlen; /* Length of peer's name */
2768
enum eap_state_code ea_state;
2770
+ enum eap_state_code ea_prev_state;
2772
u_char ea_id; /* Current id */
2773
u_char ea_requests; /* Number of Requests sent/received */
2774
u_char ea_responses; /* Number of Responses */
2775
u_char ea_type; /* One of EAPT_* */
2776
u_int32_t ea_keyflags; /* SRP shared key usage flags */
2778
+ bool ea_using_eaptls;
2783
@@ -139,7 +164,12 @@
2786
#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */
2788
+#define EAP_DEFTRANSMITS 30 /* max # times to transmit */
2789
+ /* certificates can be long ... */
2791
#define EAP_DEFTRANSMITS 10 /* max # times to transmit */
2792
+#endif /* USE_EAPTLS */
2793
#define EAP_DEFREQTIME 20 /* Time to wait for peer request */
2794
#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */
2796
Index: ppp-2.4.5/pppd/md5.c
2797
===================================================================
2798
--- ppp-2.4.5.orig/pppd/md5.c 2013-01-22 15:19:11.000000000 -0600
2799
+++ ppp-2.4.5/pppd/md5.c 2013-01-22 15:19:29.000000000 -0600
2801
***********************************************************************
2811
******************************** (cut) ********************************
2813
+#endif /* USE_EAPTLS */
2815
Index: ppp-2.4.5/pppd/md5.h
2816
===================================================================
2817
--- ppp-2.4.5.orig/pppd/md5.h 2013-01-22 15:19:11.000000000 -0600
2818
+++ ppp-2.4.5/pppd/md5.h 2013-01-22 15:19:29.000000000 -0600
2820
** documentation and/or software. **
2821
***********************************************************************
2825
#ifndef __MD5_INCLUDE__
2829
#define __MD5_INCLUDE__
2830
#endif /* __MD5_INCLUDE__ */
2832
+#endif /* USE_EAPTLS */
2833
Index: ppp-2.4.5/pppd/options.c
2834
===================================================================
2835
--- ppp-2.4.5.orig/pppd/options.c 2013-01-22 15:19:29.000000000 -0600
2836
+++ ppp-2.4.5/pppd/options.c 2013-01-22 15:19:29.000000000 -0600
2837
@@ -121,6 +121,10 @@
2838
bool dryrun; /* print out option values and exit */
2839
char *domain; /* domain name set by domain option */
2840
int child_wait = 5; /* # seconds to wait for children at exit */
2842
+bool only_update_crl_server = 0; /* update server crl and exit */
2843
+bool only_update_crl_client = 0; /* update client crl and exit */
2844
+#endif /* USE_EAPTLS */
2847
unsigned int maxoctets = 0; /* default - no limit */
2848
@@ -329,6 +333,12 @@
2849
{ "mo-timeout", o_int, &maxoctets_timeout,
2850
"Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },
2853
+ { "only-update-crl-server", o_bool, &only_update_crl_server,
2854
+ "Update server CA CRLs and exit", 1 },
2855
+ { "only-update-crl-client", o_bool, &only_update_crl_client,
2856
+ "Update client CA CRLs and exit", 1 },
2857
+#endif /* USE_EAPTLS */
2861
Index: ppp-2.4.5/pppd/pathnames.h
2862
===================================================================
2863
--- ppp-2.4.5.orig/pppd/pathnames.h 2013-01-22 15:19:29.000000000 -0600
2864
+++ ppp-2.4.5/pppd/pathnames.h 2013-01-22 15:19:29.000000000 -0600
2866
#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
2867
#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
2868
#define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets"
2871
+#define _PATH_EAPTLSCLIFILE _ROOT_PATH "/etc/ppp/eaptls-client"
2872
+#define _PATH_EAPTLSSERVFILE _ROOT_PATH "/etc/ppp/eaptls-server"
2873
+#define _PATH_OPENSSLCONFFILE _ROOT_PATH "/etc/ppp/openssl.cnf"
2874
+#endif /* USE_EAPTLS */
2876
#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
2877
#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
2878
#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"
2879
Index: ppp-2.4.5/pppd/plugins/Makefile.linux
2880
===================================================================
2881
--- ppp-2.4.5.orig/pppd/plugins/Makefile.linux 2013-01-22 15:19:29.000000000 -0600
2882
+++ ppp-2.4.5/pppd/plugins/Makefile.linux 2013-01-22 15:19:29.000000000 -0600
2888
+CFLAGS += -DUSE_EAPTLS=1
2890
DESTDIR = $(INSTROOT)@DESTDIR@
2891
BINDIR = $(DESTDIR)/sbin
2892
MANDIR = $(DESTDIR)/share/man/man8
2893
Index: ppp-2.4.5/pppd/plugins/passprompt.c
2894
===================================================================
2895
--- ppp-2.4.5.orig/pppd/plugins/passprompt.c 2013-01-22 15:19:11.000000000 -0600
2896
+++ ppp-2.4.5/pppd/plugins/passprompt.c 2013-01-22 15:19:29.000000000 -0600
2899
add_options(options);
2900
pap_passwd_hook = promptpass;
2902
+ eaptls_passwd_hook = promptpass;
2905
Index: ppp-2.4.5/pppd/plugins/passwordfd.c
2906
===================================================================
2907
--- ppp-2.4.5.orig/pppd/plugins/passwordfd.c 2013-01-22 15:19:11.000000000 -0600
2908
+++ ppp-2.4.5/pppd/plugins/passwordfd.c 2013-01-22 15:19:29.000000000 -0600
2911
chap_check_hook = pwfd_check;
2912
chap_passwd_hook = pwfd_passwd;
2915
+ eaptls_passwd_hook = pwfd_passwd;
2918
Index: ppp-2.4.5/pppd/pppd.h
2919
===================================================================
2920
--- ppp-2.4.5.orig/pppd/pppd.h 2013-01-22 15:19:29.000000000 -0600
2921
+++ ppp-2.4.5/pppd/pppd.h 2013-01-22 15:19:29.000000000 -0600
2922
@@ -322,6 +322,10 @@
2923
extern bool dryrun; /* check everything, print options, exit */
2924
extern int child_wait; /* # seconds to wait for children at end */
2927
+extern char *crl_dir;
2928
+#endif /* USE_EAPTLS */
2931
extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */
2932
extern int maxoctets_dir; /* Direction :
2933
@@ -721,6 +725,10 @@
2934
extern int (*chap_passwd_hook) __P((char *user, char *passwd));
2935
extern void (*multilink_join_hook) __P((void));
2938
+extern int (*eaptls_passwd_hook) __P((char *user, char *passwd));
2941
/* Let a plugin snoop sent and received packets. Useful for L2TP */
2942
extern void (*snoop_recv_hook) __P((unsigned char *p, int len));
2943
extern void (*snoop_send_hook) __P((unsigned char *p, int len));