EAP-TLS authentication support for PPP

Origin: https://www.nikhef.nl/~janjust/ppp/download.html
Bug-Debian: https://bugs.debian.org/602503
Bug-Ubuntu: https://launchpad.net/bugs/643417
Forwarded: not-needed
Last-Update: 2018-11-04
This patch is based on ppp-2.4.7-eaptls-mppe-1.102.patch, with the following
changes:

 - Patch refreshed to remove fuzz.
 - Trailing spaces removed.


Gbp-Pq: Name eaptls-mppe.patch
This commit is contained in:
Jan Just Keijser 2022-05-14 02:43:52 +08:00 committed by openKylinBot
parent 807808369a
commit fcacaeaf27
21 changed files with 2825 additions and 7 deletions

291
README.eap-tls Normal file
View File

@ -0,0 +1,291 @@
EAP-TLS authentication support for PPP
======================================
1. Intro
The Extensible Authentication Protocol (EAP; RFC 3748) is a
security protocol that can be used with PPP. It provides a means
to plug in multiple optional authentication methods.
Transport Level Security (TLS; RFC 5216) provides for mutual
authentication, integrity-protected ciphersuite negotiation and
key exchange between two endpoints. It also provides for optional
MPPE encryption.
EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets,
allowing TLS mutual authentication to be used as a generic EAP
mechanism. It also provides optional encryption using the MPPE
protocol.
This patch provide EAP-TLS support to pppd.
This authentication method can be used in both client or server
mode.
2. Building
To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org)
is required. Any version from 0.9.7 should work.
Configure, compile, and install as usual.
3. Configuration
On the client side there are two ways to configure EAP-TLS:
1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters
2. edit the /etc/ppp/eaptls-client file.
Insert a line for each system with which you use EAP-TLS.
The line is composed of this fields separated by tab:
- Client name
The name used by the client for authentication, can be *
- Server name
The name of the server, can be *
- Client certificate file
The file containing the certificate chain for the
client in PEM format
- Server certificate file
If you want to specify the certificate that the
server is allowed to use, put the certificate file name.
Else put a dash '-'.
- CA certificate file
The file containing the trusted CA certificates in PEM
format.
- Client private key file
The file containing the client private key in PEM format.
On the server side edit the /etc/ppp/eaptls-server file.
Insert a line for each system with which you use EAP-TLS.
The line is composed of this fields separated by tab:
- Client name
The name used by the client for authentication, can be *
- Server name
The name of the server, can be *
- Client certificate file
If you want to specify the certificate that the
client is allowed to use, put the certificate file name.
Else put a dash '-'.
- Server certificate file
The file containing the certificate chain for the
server in PEM format
- CA certificate file
The file containing the trusted CA certificates in PEM format.
- Client private key file
The file containing the server private key in PEM format.
- addresses
A list of IP addresses the client is allowed to use.
OpenSSL engine support is included starting with v0.95 of this patch.
Currently the only engine tested is the 'pkcs11' engine (hardware token
support). To use the 'pksc11' engine:
- Use a special private key fileiname in the /etc/ppp/eaptls-client file:
<engine>:<identifier>
e.g.
pkcs11:123456
- The certificate can also be loaded from the 'pkcs11' engine using
a special client certificate filename in the /etc/ppp/eaptls-client file:
<engine>:<identifier>
e.g.
pkcs11:123456
- Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior
to starting 'pppd'. A sample openssl.cnf file is
openssl_conf = openssl_def
[ openssl_def ]
engines = engine_section
[ engine_section ]
pkcs11 = pkcs11_section
[ pkcs11_section ]
engine_id = pkcs11
dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
MODULE_PATH = /usr/lib64/libeTPkcs11.so
init = 0
- There are two ways to specify a password/PIN for the PKCS11 engine:
- inside the openssl.cnf file using
PIN = your-secret-pin
Note The keyword 'PIN' is case sensitive!
- Using the 'password' in the ppp options file.
From v0.97 of the eap-tls patch the password can also be supplied
using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c
for an example).
4. Options
These pppd options are available:
ca <ca-file>
Use the CA public certificate found in <ca-file> in PEM format
cert <cert-file>
Use the client public certificate found in <cert-file> in PEM format
or in engine:engine_id format
key <key-file>
Use the client private key found in <key-file> in PEM format
or in engine:engine_id format
crl <crl-file>
Use the Certificate Revocation List (CRL) file <crl-file> in PEM format.
crl-dir <dir>
Use CRL files from directory <dir>. It contains CRL files in PEM
format and each file contains a CRL. The files are looked up
by the issuer name hash value. Use the c_rehash utility
to create necessary links.
need-peer-eap
If the peer doesn't ask us to authenticate or doesn't use eap
to authenticate us, disconnect.
Note:
password-encrypted certificates can be used as of v0.94 of this
patch. The password for the eap-tls.key file is specified using
the regular
password ....
statement in the ppp options file, or by using the appropriate
plugin which supplies a 'eaptls_passwd_hook' routine.
5. Connecting
If you're setting up a pppd server, edit the EAP-TLS configuration file
as written above and then run pppd with the 'auth' option to authenticate
the client. The EAP-TLS method will be used if the other eap methods can't
be used (no secrets).
If you're setting up a client, edit the configuration file and then run
pppd with 'remotename' option to specify the server name. Add the
'need-peer-eap' option if you want to be sure the peer ask you to
authenticate (and to use eap) and to disconnect if it doesn't.
6. Example
The following example can be used to connect a Linux client with the 'pptp'
package to a Linux server running the 'pptpd' (PoPToP) package. The server
was configured with a certificate with name (CN) 'pptp-server', the client
was configured with a certificate with name (CN) 'pptp-client', both
signed by the same Certificate Authority (CA).
Server side:
- /etc/pptpd.conf file:
option /etc/ppp/options-pptpd-eaptls
localip 172.16.1.1
remoteip 172.16.1.10-20
- /etc/ppp/options-pptpd-eaptls file:
name pptp-server
lock
mtu 1500
mru 1450
auth
lcp-echo-failure 3
lcp-echo-interval 5
nodeflate
nobsdcomp
nopredictor1
nopcomp
noaccomp
require-eap
require-mppe-128
crl /home/janjust/ppp/keys/crl.pem
debug
logfile /tmp/pppd.log
- /etc/ppp/eaptls-server file:
* pptp-server - /etc/ppp/pptp-server.crt /etc/ppp/ca.crt /etc/ppp/pptp-server.key *
- On the server, run
pptdp --conf /etc/pptpd.conf
Client side:
- Run
pppd noauth require-eap require-mppe-128 \
ipcp-accept-local ipcp-accept-remote noipdefault \
cert /etc/ppp/keys/pptp-client.crt \
key /etc/ppp/keys/pptp-client.key \
ca /etc/ppp/keys/ca.crt \
name pptp-client remotename pptp-server \
debug logfile /tmp/pppd.log
pty "pptp pptp-server.example.com --nolaunchpppd"
Check /var/log/messages and the files /tmp/pppd.log on both sides for debugging info.
7. Notes
This is experimental code.
Send suggestions and comments to Jan Just Keijser <janjust@nikhef.nl>
8. Changelog of ppp-<>-eaptls-mppe-* patches
v0.7 (22-Nov-2005)
- First version of the patch to include MPPE support
- ppp-2.4.3 only
v0.9 (25-Jul-2006)
- Bug fixes
- First version for ppp-2.4.4
v0.91 (03-Sep-2006)
- Added missing #include for md5.h
- Last version for ppp-2.4.3
v0.92 (22-Apr-2008)
- Fix for openssl 0.9.8 issue with md5 function overload.
v0.93 (14-Aug-2008)
- Make sure 'noauth' option can be used to bypass server certificate verification.
v0.94 (15-Oct-2008)
- Added support for password-protected private keys by (ab)using the 'password' field.
v0.95 (23-Dec-2009)
- First version with OpenSSL engine support.
v0.96 (27-Jan-2010)
- Added fully functional support for OpenSSL engines (PKCS#11)
- First version for ppp-2.4.5
v0.97 (20-Apr-2010)
- Some bug fixes for v0.96
- Added support for entering the password via a plugin. The sample plugin
.../pppd/plugins/passprompt.c has been extended with EAP-TLS support.
The "old" methods using the password option or the /etc/ppp/openssl.cnf file still work.
- Added support for specifying the client CA, certificate and private key on the command-line
or via the ppp config file.
v0.98 (20-Apr-2010)
- Fix initialisation bug when using ca/cert/key command-line options.
- Last version for ppp-2.4.4
v0.99 (05-Oct-2010)
- Fix coredump when using multilink option.
v0.991 (08-Aug-2011)
- Fix compilation issue with openssl 1.0.
v0.992 (01-Dec-2011)
- Fix compilation issue with eaptls_check_hook and passwordfd plugin.
v0.993 (24-Apr-2012)
- Fix compilation issue when EAP_TLS=n in pppd/Makefile.
v0.994 (11-Jun-2012)
- Fix compilation issue on Ubuntu 11.10.
v0.995 (27-May-2014)
- Add support for a CRL file using the command-line option 'crl'
(prior only 'crl-dir' was supported).
- Fix segfault when pkcs11 enginename was not specified correctly.
- Fix segfault when client was misconfigured.
- Disable SSL Session Ticket support as Windows 8 does not support this.
v0.996 (28-May-2014)
- Fix minor bug where SessionTicket message was printed as 'Unknown SSL3 code 4'
- Add EAP-TLS-specific options to pppd.8 manual page.
- Updated README.eap-tls file with new options and provide an example.
v0.997 (19-Jun-2014)
- Change SSL_OP_NO_TICKETS to SSL_OP_NO_TICKET
- Fix bug in initialisation code with fragmented packets.
v0.998 (13-Mar-2015)
- Add fix for https://bugzilla.redhat.com/show_bug.cgi?id=1023620
v0.999 (11-May-2017)
- Add support for OpenSSL 1.1: the code will now compile against OpenSSL 1.0.x or 1.1.x.
v1.101 (1-Jun-2018)
- Fix vulnerabilities CVE-2018-11574.
v1.102 (2-Nov-2018)
- Add TLS 1.2 support. Windows 7/8 will connect using TLS 1.0, Windows 10 clients using TLS 1.2.
This works both when compiling against OpenSSL 1.0.1+ and 1.1+.
- Print warning when certificate is either not yet valid or has expired.
- Perform better peer certificate checks.
- Allow certificate chain files to be used.

10
etc.ppp/eaptls-client Normal file
View File

@ -0,0 +1,10 @@
# Parameters for authentication using EAP-TLS (client)
# client name (can be *)
# server name (can be *)
# client certificate file (required)
# server certificate file (optional, if unused put '-')
# CA certificate file (required)
# client private key file (required)
#client server /root/cert/client.crt - /root/cert/ca.crt /root/cert/client.key

11
etc.ppp/eaptls-server Normal file
View File

@ -0,0 +1,11 @@
# Parameters for authentication using EAP-TLS (server)
# client name (can be *)
# server name (can be *)
# client certificate file (optional, if unused put '-')
# server certificate file (required)
# CA certificate file (required)
# server private key file (required)
# allowed addresses (required, can be *)
#client server - /root/cert/server.crt /root/cert/ca.crt /root/cert/server.key 192.168.1.0/24

14
etc.ppp/openssl.cnf Normal file
View File

@ -0,0 +1,14 @@
openssl_conf = openssl_def
[ openssl_def ]
engines = engine_section
[ engine_section ]
pkcs11 = pkcs11_section
[ pkcs11_section ]
engine_id = pkcs11
dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
MODULE_PATH = /usr/lib64/libeTPkcs11.so
init = 0

View File

@ -26,7 +26,7 @@ install-progs:
cd pppdump; $(MAKE) $(MFLAGS) install
install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
$(ETCDIR)/chap-secrets
$(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client
install-devel:
cd pppd; $(MAKE) $(MFLAGS) install-devel
@ -37,6 +37,10 @@ $(ETCDIR)/pap-secrets:
$(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
$(ETCDIR)/chap-secrets:
$(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
$(ETCDIR)/eaptls-server:
$(INSTALL) -c -m 600 etc.ppp/eaptls-server $@
$(ETCDIR)/eaptls-client:
$(INSTALL) -c -m 600 etc.ppp/eaptls-client $@
$(BINDIR):
$(INSTALL) -d -m 755 $@

View File

@ -76,6 +76,9 @@ CBCP=y
# Use libutil
USE_LIBUTIL=y
# Enable EAP-TLS authentication (requires libssl and libcrypto)
USE_EAPTLS=y
MAXOCTETS=y
INCLUDE_DIRS= -I../include
@ -116,6 +119,15 @@ HEADERS += sha1.h
PPPDOBJS += sha1.o
endif
# EAP-TLS
ifdef USE_EAPTLS
CFLAGS += -DUSE_EAPTLS=1 -I/usr/kerberos/include
LIBS += -lssl -lcrypto
PPPDSRC += eap-tls.c
HEADERS += eap-tls.h
PPPDOBJS += eap-tls.o
endif
ifdef HAS_SHADOW
CFLAGS += -DHAS_SHADOW
#LIBS += -lshadow $(LIBS)

View File

@ -109,6 +109,9 @@
#include "upap.h"
#include "chap-new.h"
#include "eap.h"
#ifdef USE_EAPTLS
#include "eap-tls.h"
#endif
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
@ -183,6 +186,11 @@ int (*chap_check_hook) __P((void)) = NULL;
/* Hook for a plugin to get the CHAP password for authenticating us */
int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL;
#ifdef USE_EAPTLS
/* Hook for a plugin to get the EAP-TLS password for authenticating us */
int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL;
#endif
/* Hook for a plugin to say whether it is OK if the peer
refuses to authenticate. */
int (*null_auth_hook) __P((struct wordlist **paddrs,
@ -238,6 +246,14 @@ bool explicit_remote = 0; /* User specified explicit remote name */
bool explicit_user = 0; /* Set if "user" option supplied */
bool explicit_passwd = 0; /* Set if "password" option supplied */
char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
#ifdef USE_EAPTLS
char *cacert_file = NULL; /* CA certificate file (pem format) */
char *cert_file = NULL; /* client certificate file (pem format) */
char *privkey_file = NULL; /* client private key file (pem format) */
char *crl_dir = NULL; /* directory containing CRL files */
char *crl_file = NULL; /* Certificate Revocation List (CRL) file (pem format) */
bool need_peer_eap = 0; /* Require peer to authenticate us */
#endif
static char *uafname; /* name of most recent +ua file */
@ -254,6 +270,19 @@ static int have_pap_secret __P((int *));
static int have_chap_secret __P((char *, char *, int, int *));
static int have_srp_secret __P((char *client, char *server, int need_ip,
int *lacks_ipp));
#ifdef USE_EAPTLS
static int have_eaptls_secret_server
__P((char *client, char *server, int need_ip, int *lacks_ipp));
static int have_eaptls_secret_client __P((char *client, char *server));
static int scan_authfile_eaptls __P((FILE * f, char *client, char *server,
char *cli_cert, char *serv_cert,
char *ca_cert, char *pk,
struct wordlist ** addrs,
struct wordlist ** opts,
char *filename, int flags));
#endif
static int ip_addr_check __P((u_int32_t, struct permitted_ip *));
static int scan_authfile __P((FILE *, char *, char *, char *,
struct wordlist **, struct wordlist **,
@ -401,6 +430,15 @@ option_t auth_options[] = {
"Set telephone number(s) which are allowed to connect",
OPT_PRIV | OPT_A2LIST },
#ifdef USE_EAPTLS
{ "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" },
{ "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" },
{ "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" },
{ "crl-dir", o_string, &crl_dir, "Use CRLs in directory" },
{ "crl", o_string, &crl_file, "Use specific CRL file" },
{ "need-peer-eap", o_bool, &need_peer_eap,
"Require the peer to authenticate us", 1 },
#endif /* USE_EAPTLS */
{ NULL }
};
@ -730,6 +768,9 @@ link_established(unit)
lcp_options *wo = &lcp_wantoptions[unit];
lcp_options *go = &lcp_gotoptions[unit];
lcp_options *ho = &lcp_hisoptions[unit];
#ifdef USE_EAPTLS
lcp_options *ao = &lcp_allowoptions[unit];
#endif
int i;
struct protent *protp;
@ -764,6 +805,22 @@ link_established(unit)
}
}
#ifdef USE_EAPTLS
if (need_peer_eap && !ao->neg_eap) {
warn("eap required to authenticate us but no suitable secrets");
lcp_close(unit, "couldn't negotiate eap");
status = EXIT_AUTH_TOPEER_FAILED;
return;
}
if (need_peer_eap && !ho->neg_eap) {
warn("peer doesn't want to authenticate us with eap");
lcp_close(unit, "couldn't negotiate eap");
status = EXIT_PEER_AUTH_FAILED;
return;
}
#endif
new_phase(PHASE_AUTHENTICATE);
auth = 0;
if (go->neg_eap) {
@ -1277,6 +1334,15 @@ auth_check_options()
our_name, 1, &lacks_ip);
}
#ifdef USE_EAPTLS
if (!can_auth && wo->neg_eap) {
can_auth =
have_eaptls_secret_server((explicit_remote ? remote_name :
NULL), our_name, 1, &lacks_ip);
}
#endif
if (auth_required && !can_auth && noauth_addrs == NULL) {
if (default_auth) {
option_error(
@ -1331,7 +1397,11 @@ auth_reset(unit)
passwd[0] != 0 ||
(hadchap == 1 || (hadchap == -1 && have_chap_secret(user,
(explicit_remote? remote_name: NULL), 0, NULL))) ||
have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL));
have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)
#ifdef USE_EAPTLS
|| have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL))
#endif
);
hadchap = -1;
if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
@ -1346,8 +1416,14 @@ auth_reset(unit)
!have_chap_secret((explicit_remote? remote_name: NULL), our_name,
1, NULL))) &&
!have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
NULL))
NULL)
#ifdef USE_EAPTLS
&& !have_eaptls_secret_server((explicit_remote? remote_name: NULL),
our_name, 1, NULL)
#endif
)
go->neg_eap = 0;
}
@ -1709,6 +1785,7 @@ have_srp_secret(client, server, need_ip, lacks_ipp)
}
/*
* get_secret - open the CHAP secret file and return the secret
* for authenticating the given client on the given server.
@ -2361,3 +2438,335 @@ auth_script(script)
auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
}
#ifdef USE_EAPTLS
static int
have_eaptls_secret_server(client, server, need_ip, lacks_ipp)
char *client;
char *server;
int need_ip;
int *lacks_ipp;
{
FILE *f;
int ret;
char *filename;
struct wordlist *addrs;
char servcertfile[MAXWORDLEN];
char clicertfile[MAXWORDLEN];
char cacertfile[MAXWORDLEN];
char pkfile[MAXWORDLEN];
filename = _PATH_EAPTLSSERVFILE;
f = fopen(filename, "r");
if (f == NULL)
return 0;
if (client != NULL && client[0] == 0)
client = NULL;
else if (server != NULL && server[0] == 0)
server = NULL;
ret =
scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
cacertfile, pkfile, &addrs, NULL, filename,
0);
fclose(f);
/*
if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
clicertfile, pkfile))
ret = -1;
*/
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
if (lacks_ipp != 0)
*lacks_ipp = 1;
ret = -1;
}
if (addrs != 0)
free_wordlist(addrs);
return ret >= 0;
}
static int
have_eaptls_secret_client(client, server)
char *client;
char *server;
{
FILE *f;
int ret;
char *filename;
struct wordlist *addrs = NULL;
char servcertfile[MAXWORDLEN];
char clicertfile[MAXWORDLEN];
char cacertfile[MAXWORDLEN];
char pkfile[MAXWORDLEN];
if (client != NULL && client[0] == 0)
client = NULL;
else if (server != NULL && server[0] == 0)
server = NULL;
if (cacert_file && cert_file && privkey_file)
return 1;
filename = _PATH_EAPTLSCLIFILE;
f = fopen(filename, "r");
if (f == NULL)
return 0;
ret =
scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
cacertfile, pkfile, &addrs, NULL, filename,
0);
fclose(f);
/*
if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile,
servcertfile, pkfile))
ret = -1;
*/
if (addrs != 0)
free_wordlist(addrs);
return ret >= 0;
}
static int
scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk,
addrs, opts, filename, flags)
FILE *f;
char *client;
char *server;
char *cli_cert;
char *serv_cert;
char *ca_cert;
char *pk;
struct wordlist **addrs;
struct wordlist **opts;
char *filename;
int flags;
{
int newline;
int got_flag, best_flag;
struct wordlist *ap, *addr_list, *alist, **app;
char word[MAXWORDLEN];
if (addrs != NULL)
*addrs = NULL;
if (opts != NULL)
*opts = NULL;
addr_list = NULL;
if (!getword(f, word, &newline, filename))
return -1; /* file is empty??? */
newline = 1;
best_flag = -1;
for (;;) {
/*
* Skip until we find a word at the start of a line.
*/
while (!newline && getword(f, word, &newline, filename));
if (!newline)
break; /* got to end of file */
/*
* Got a client - check if it's a match or a wildcard.
*/
got_flag = 0;
if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
newline = 0;
continue;
}
if (!ISWILD(word))
got_flag = NONWILD_CLIENT;
/*
* Now get a server and check if it matches.
*/
if (!getword(f, word, &newline, filename))
break;
if (newline)
continue;
if (!ISWILD(word)) {
if (server != NULL && strcmp(word, server) != 0)
continue;
got_flag |= NONWILD_SERVER;
}
/*
* Got some sort of a match - see if it's better than what
* we have already.
*/
if (got_flag <= best_flag)
continue;
/*
* Get the cli_cert
*/
if (!getword(f, word, &newline, filename))
break;
if (newline)
continue;
if (strcmp(word, "-") != 0) {
strlcpy(cli_cert, word, MAXWORDLEN);
} else
cli_cert[0] = 0;
/*
* Get serv_cert
*/
if (!getword(f, word, &newline, filename))
break;
if (newline)
continue;
if (strcmp(word, "-") != 0) {
strlcpy(serv_cert, word, MAXWORDLEN);
} else
serv_cert[0] = 0;
/*
* Get ca_cert
*/
if (!getword(f, word, &newline, filename))
break;
if (newline)
continue;
strlcpy(ca_cert, word, MAXWORDLEN);
/*
* Get pk
*/
if (!getword(f, word, &newline, filename))
break;
if (newline)
continue;
strlcpy(pk, word, MAXWORDLEN);
/*
* Now read address authorization info and make a wordlist.
*/
app = &alist;
for (;;) {
if (!getword(f, word, &newline, filename) || newline)
break;
ap = (struct wordlist *)
malloc(sizeof(struct wordlist) + strlen(word) + 1);
if (ap == NULL)
novm("authorized addresses");
ap->word = (char *) (ap + 1);
strcpy(ap->word, word);
*app = ap;
app = &ap->next;
}
*app = NULL;
/*
* This is the best so far; remember it.
*/
best_flag = got_flag;
if (addr_list)
free_wordlist(addr_list);
addr_list = alist;
if (!newline)
break;
}
/* scan for a -- word indicating the start of options */
for (app = &addr_list; (ap = *app) != NULL; app = &ap->next)
if (strcmp(ap->word, "--") == 0)
break;
/* ap = start of options */
if (ap != NULL) {
ap = ap->next; /* first option */
free(*app); /* free the "--" word */
*app = NULL; /* terminate addr list */
}
if (opts != NULL)
*opts = ap;
else if (ap != NULL)
free_wordlist(ap);
if (addrs != NULL)
*addrs = addr_list;
else if (addr_list != NULL)
free_wordlist(addr_list);
return best_flag;
}
int
get_eaptls_secret(unit, client, server, clicertfile, servcertfile,
cacertfile, pkfile, am_server)
int unit;
char *client;
char *server;
char *clicertfile;
char *servcertfile;
char *cacertfile;
char *pkfile;
int am_server;
{
FILE *fp;
int ret;
char *filename = NULL;
struct wordlist *addrs = NULL;
struct wordlist *opts = NULL;
/* in client mode the ca+cert+privkey can also be specified as options */
if (!am_server && cacert_file && cert_file && privkey_file )
{
strlcpy( clicertfile, cert_file, MAXWORDLEN );
strlcpy( cacertfile, cacert_file, MAXWORDLEN );
strlcpy( pkfile, privkey_file, MAXWORDLEN );
servcertfile[0] = '\0';
}
else
{
filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE);
addrs = NULL;
fp = fopen(filename, "r");
if (fp == NULL)
{
error("Can't open eap-tls secret file %s: %m", filename);
return 0;
}
check_access(fp, filename);
ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile,
cacertfile, pkfile, &addrs, &opts, filename, 0);
fclose(fp);
if (ret < 0) return 0;
}
if (eaptls_passwd_hook)
{
dbglog( "Calling eaptls password hook" );
if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0)
{
error("Unable to obtain EAP-TLS password for %s (%s) from plugin",
client, pkfile);
return 0;
}
}
if (am_server)
set_allowed_addrs(unit, addrs, opts);
else if (opts != NULL)
free_wordlist(opts);
if (addrs != NULL)
free_wordlist(addrs);
return 1;
}
#endif

View File

@ -540,6 +540,9 @@ ccp_resetci(f)
if (go->mppe) {
ccp_options *ao = &ccp_allowoptions[f->unit];
int auth_mschap_bits = auth_done[f->unit];
#ifdef USE_EAPTLS
int auth_eap_bits = auth_done[f->unit];
#endif
int numbits;
/*
@ -567,8 +570,23 @@ ccp_resetci(f)
lcp_close(f->unit, "MPPE required but not available");
return;
}
#ifdef USE_EAPTLS
/*
* MPPE is also possible in combination with EAP-TLS.
* It is not possible to detect if we're doing EAP or EAP-TLS
* at this stage, hence we accept all forms of EAP. If TLS is
* not used then the MPPE keys will not be derived anyway.
*/
/* Leave only the eap auth bits set */
auth_eap_bits &= (EAP_WITHPEER | EAP_PEER );
if ((numbits == 0) && (auth_eap_bits == 0)) {
error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed.");
#else
if (!numbits) {
error("MPPE required, but MS-CHAP[v2] auth not performed.");
error("MPPE required, but MS-CHAP[v2] auth not performed.");
#endif
lcp_close(f->unit, "MPPE required but not available");
return;
}

View File

@ -36,7 +36,11 @@
#include "chap-new.h"
#include "chap-md5.h"
#include "magic.h"
#ifdef USE_EAPTLS
#include "eap-tls.h"
#else
#include "md5.h"
#endif /* USE_EAPTLS */
#define MD5_HASH_SIZE 16
#define MD5_MIN_CHALLENGE 16

1383
pppd/eap-tls.c Normal file

File diff suppressed because it is too large Load Diff

107
pppd/eap-tls.h Normal file
View File

@ -0,0 +1,107 @@
/*
* eap-tls.h
*
* Copyright (c) Beniamino Galvani 2005 All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#ifndef __EAP_TLS_H__
#define __EAP_TLS_H__
#include "eap.h"
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/md5.h>
#define EAP_TLS_FLAGS_LI 128 /* length included flag */
#define EAP_TLS_FLAGS_MF 64 /* more fragments flag */
#define EAP_TLS_FLAGS_START 32 /* start flag */
#define EAP_TLS_MAX_LEN 65536 /* max eap tls packet size */
struct eaptls_session
{
u_char *data; /* buffered data */
int datalen; /* buffered data len */
int offset; /* from where to send */
int tlslen; /* total length of tls data */
bool frag; /* packet is fragmented */
SSL_CTX *ctx;
SSL *ssl; /* ssl connection */
BIO *from_ssl;
BIO *into_ssl;
char peer[MAXWORDLEN]; /* peer name */
char peercertfile[MAXWORDLEN];
bool alert_sent;
u_char alert_sent_desc;
bool alert_recv;
u_char alert_recv_desc;
char rtx[65536]; /* retransmission buffer */
int rtx_len;
int mtu; /* unit mtu */
};
typedef struct pw_cb_data
{
const void *password;
const char *prompt_info;
} PW_CB_DATA;
int ssl_verify_callback(int, X509_STORE_CTX *);
void ssl_msg_callback(int write_p, int version, int ct, const void *buf,
size_t len, SSL * ssl, void *arg);
X509 *get_X509_from_file(char *filename);
int ssl_cmp_certs(char *filename, X509 * a);
SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile,
char *certfile, char *peer_certfile, char *privkeyfile);
int eaptls_init_ssl_server(eap_state * esp);
int eaptls_init_ssl_client(eap_state * esp);
void eaptls_free_session(struct eaptls_session *ets);
int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len);
int eaptls_send(struct eaptls_session *ets, u_char ** outp);
void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp);
int get_eaptls_secret(int unit, char *client, char *server,
char *clicertfile, char *servcertfile, char *cacertfile,
char *pkfile, int am_server);
#ifdef MPPE
#include "mppe.h" /* MPPE_MAX_KEY_LEN */
extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
extern int mppe_keys_set;
void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, int client);
#endif
#endif

View File

@ -43,6 +43,11 @@
* Based on draft-ietf-pppext-eap-srp-03.txt.
*/
/*
* Modification by Beniamino Galvani, Mar 2005
* Implemented EAP-TLS authentication
*/
#define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
/*
@ -62,8 +67,12 @@
#include "pppd.h"
#include "pathnames.h"
#include "md5.h"
#include "eap.h"
#ifdef USE_EAPTLS
#include "eap-tls.h"
#else
#include "md5.h"
#endif /* USE_EAPTLS */
#ifdef USE_SRP
#include <t_pwd.h>
@ -209,6 +218,9 @@ int unit;
esp->es_server.ea_id = (u_char)(drand48() * 0x100);
esp->es_client.ea_timeout = EAP_DEFREQTIME;
esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
#ifdef USE_EAPTLS
esp->es_client.ea_using_eaptls = 0;
#endif /* USE_EAPTLS */
}
/*
@ -436,8 +448,16 @@ int status;
u_char vals[2];
struct b64state bs;
#endif /* USE_SRP */
#ifdef USE_EAPTLS
struct eaptls_session *ets;
int secret_len;
char secret[MAXWORDLEN];
#endif /* USE_EAPTLS */
esp->es_server.ea_timeout = esp->es_savedtime;
#ifdef USE_EAPTLS
esp->es_server.ea_prev_state = esp->es_server.ea_state;
#endif /* USE_EAPTLS */
switch (esp->es_server.ea_state) {
case eapBadAuth:
return;
@ -562,9 +582,79 @@ int status;
break;
}
#endif /* USE_SRP */
#ifdef USE_EAPTLS
if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
esp->es_server.ea_name, secret, &secret_len, 1)) {
esp->es_server.ea_state = eapTlsStart;
break;
}
#endif /* USE_EAPTLS */
esp->es_server.ea_state = eapMD5Chall;
break;
#ifdef USE_EAPTLS
case eapTlsStart:
/* Initialize ssl session */
if(!eaptls_init_ssl_server(esp)) {
esp->es_server.ea_state = eapBadAuth;
break;
}
esp->es_server.ea_state = eapTlsRecv;
break;
case eapTlsRecv:
ets = (struct eaptls_session *) esp->es_server.ea_session;
if(ets->alert_sent) {
esp->es_server.ea_state = eapTlsSendAlert;
break;
}
if (status) {
esp->es_server.ea_state = eapBadAuth;
break;
}
ets = (struct eaptls_session *) esp->es_server.ea_session;
if(ets->frag)
esp->es_server.ea_state = eapTlsSendAck;
else
esp->es_server.ea_state = eapTlsSend;
break;
case eapTlsSend:
ets = (struct eaptls_session *) esp->es_server.ea_session;
if(ets->frag)
esp->es_server.ea_state = eapTlsRecvAck;
else
if(SSL_is_init_finished(ets->ssl))
esp->es_server.ea_state = eapTlsRecvClient;
else
esp->es_server.ea_state = eapTlsRecv;
break;
case eapTlsSendAck:
esp->es_server.ea_state = eapTlsRecv;
break;
case eapTlsRecvAck:
if (status) {
esp->es_server.ea_state = eapBadAuth;
break;
}
esp->es_server.ea_state = eapTlsSend;
break;
case eapTlsSendAlert:
esp->es_server.ea_state = eapTlsRecvAlertAck;
break;
#endif /* USE_EAPTLS */
case eapSRP1:
#ifdef USE_SRP
ts = (struct t_server *)esp->es_server.ea_session;
@ -718,6 +808,30 @@ eap_state *esp;
INCPTR(esp->es_server.ea_namelen, outp);
break;
#ifdef USE_EAPTLS
case eapTlsStart:
PUTCHAR(EAPT_TLS, outp);
PUTCHAR(EAP_TLS_FLAGS_START, outp);
eap_figure_next_state(esp, 0);
break;
case eapTlsSend:
eaptls_send(esp->es_server.ea_session, &outp);
eap_figure_next_state(esp, 0);
break;
case eapTlsSendAck:
PUTCHAR(EAPT_TLS, outp);
PUTCHAR(0, outp);
eap_figure_next_state(esp, 0);
break;
case eapTlsSendAlert:
eaptls_send(esp->es_server.ea_session, &outp);
eap_figure_next_state(esp, 0);
break;
#endif /* USE_EAPTLS */
#ifdef USE_SRP
case eapSRP1:
PUTCHAR(EAPT_SRP, outp);
@ -904,11 +1018,57 @@ static void
eap_server_timeout(arg)
void *arg;
{
#ifdef USE_EAPTLS
u_char *outp;
u_char *lenloc;
int outlen;
#endif /* USE_EAPTLS */
eap_state *esp = (eap_state *) arg;
if (!eap_server_active(esp))
return;
#ifdef USE_EAPTLS
switch(esp->es_server.ea_prev_state) {
/*
* In eap-tls the state changes after a request, so we return to
* previous state ...
*/
case(eapTlsStart):
case(eapTlsSendAck):
esp->es_server.ea_state = esp->es_server.ea_prev_state;
break;
/*
* ... or resend the stored data
*/
case(eapTlsSend):
case(eapTlsSendAlert):
outp = outpacket_buf;
MAKEHEADER(outp, PPP_EAP);
PUTCHAR(EAP_REQUEST, outp);
PUTCHAR(esp->es_server.ea_id, outp);
lenloc = outp;
INCPTR(2, outp);
eaptls_retransmit(esp->es_server.ea_session, &outp);
outlen = (outp - outpacket_buf) - PPP_HDRLEN;
PUTSHORT(outlen, lenloc);
output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
esp->es_server.ea_requests++;
if (esp->es_server.ea_timeout > 0)
TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
return;
default:
break;
}
#endif /* USE_EAPTLS */
/* EAP ID number must not change on timeout. */
eap_send_request(esp);
}
@ -1166,6 +1326,81 @@ u_char *str;
}
#endif /* USE_SRP */
#ifdef USE_EAPTLS
/*
* Send an EAP-TLS response message with tls data
*/
static void
eap_tls_response(esp, id)
eap_state *esp;
u_char id;
{
u_char *outp;
int outlen;
u_char *lenloc;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_EAP);
PUTCHAR(EAP_RESPONSE, outp);
PUTCHAR(id, outp);
lenloc = outp;
INCPTR(2, outp);
/*
If the id in the request is unchanged, we must retransmit
the old data
*/
if(id == esp->es_client.ea_id)
eaptls_retransmit(esp->es_client.ea_session, &outp);
else
eaptls_send(esp->es_client.ea_session, &outp);
outlen = (outp - outpacket_buf) - PPP_HDRLEN;
PUTSHORT(outlen, lenloc);
output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
esp->es_client.ea_id = id;
}
/*
* Send an EAP-TLS ack
*/
static void
eap_tls_sendack(esp, id)
eap_state *esp;
u_char id;
{
u_char *outp;
int outlen;
u_char *lenloc;
outp = outpacket_buf;
MAKEHEADER(outp, PPP_EAP);
PUTCHAR(EAP_RESPONSE, outp);
PUTCHAR(id, outp);
esp->es_client.ea_id = id;
lenloc = outp;
INCPTR(2, outp);
PUTCHAR(EAPT_TLS, outp);
PUTCHAR(0, outp);
outlen = (outp - outpacket_buf) - PPP_HDRLEN;
PUTSHORT(outlen, lenloc);
output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
}
#endif /* USE_EAPTLS */
static void
eap_send_nak(esp, id, type)
eap_state *esp;
@ -1320,6 +1555,11 @@ int len;
char rhostname[256];
MD5_CTX mdContext;
u_char hash[MD5_SIGNATURE_SIZE];
#ifdef USE_EAPTLS
u_char flags;
struct eaptls_session *ets = esp->es_client.ea_session;
#endif /* USE_EAPTLS */
#ifdef USE_SRP
struct t_client *tc;
struct t_num sval, gval, Nval, *Ap, Bval;
@ -1456,6 +1696,100 @@ int len;
esp->es_client.ea_namelen);
break;
#ifdef USE_EAPTLS
case EAPT_TLS:
switch(esp->es_client.ea_state) {
case eapListen:
if (len < 1) {
error("EAP: received EAP-TLS Listen packet with no data");
/* Bogus request; wait for something real. */
return;
}
GETCHAR(flags, inp);
if(flags & EAP_TLS_FLAGS_START){
esp->es_client.ea_using_eaptls = 1;
if (explicit_remote){
esp->es_client.ea_peer = strdup(remote_name);
esp->es_client.ea_peerlen = strlen(remote_name);
} else
esp->es_client.ea_peer = NULL;
/* Init ssl session */
if(!eaptls_init_ssl_client(esp)) {
dbglog("cannot init ssl");
eap_send_nak(esp, id, EAPT_TLS);
esp->es_client.ea_using_eaptls = 0;
break;
}
ets = esp->es_client.ea_session;
eap_tls_response(esp, id);
esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
eapTlsRecv);
break;
}
/* The server has sent a bad start packet. */
eap_send_nak(esp, id, EAPT_TLS);
break;
case eapTlsRecvAck:
eap_tls_response(esp, id);
esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
eapTlsRecv);
break;
case eapTlsRecv:
if (len < 1) {
error("EAP: discarding EAP-TLS Receive packet with no data");
/* Bogus request; wait for something real. */
return;
}
eaptls_receive(ets, inp, len);
if(ets->frag) {
eap_tls_sendack(esp, id);
esp->es_client.ea_state = eapTlsRecv;
break;
}
if(ets->alert_recv) {
eap_tls_sendack(esp, id);
esp->es_client.ea_state = eapTlsRecvFailure;
break;
}
/* Check if TLS handshake is finished */
if(SSL_is_init_finished(ets->ssl)){
#ifdef MPPE
eaptls_gen_mppe_keys( ets, "client EAP encryption", 1 );
#endif
eaptls_free_session(ets);
eap_tls_sendack(esp, id);
esp->es_client.ea_state = eapTlsRecvSuccess;
break;
}
eap_tls_response(esp,id);
esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
eapTlsRecv);
break;
default:
eap_send_nak(esp, id, EAPT_TLS);
esp->es_client.ea_using_eaptls = 0;
break;
}
break;
#endif /* USE_EAPTLS */
#ifdef USE_SRP
case EAPT_SRP:
if (len < 1) {
@ -1737,6 +2071,11 @@ int len;
u_char dig[SHA_DIGESTSIZE];
#endif /* USE_SRP */
#ifdef USE_EAPTLS
struct eaptls_session *ets;
u_char flags;
#endif /* USE_EAPTLS */
if (esp->es_server.ea_id != id) {
dbglog("EAP: discarding Response %d; expected ID %d", id,
esp->es_server.ea_id);
@ -1776,6 +2115,64 @@ int len;
eap_figure_next_state(esp, 0);
break;
#ifdef USE_EAPTLS
case EAPT_TLS:
switch(esp->es_server.ea_state) {
case eapTlsRecv:
ets = (struct eaptls_session *) esp->es_server.ea_session;
eap_figure_next_state(esp,
eaptls_receive(esp->es_server.ea_session, inp, len));
if(ets->alert_recv) {
eap_send_failure(esp);
break;
}
break;
case eapTlsRecvAck:
if(len > 1) {
dbglog("EAP-TLS ACK with extra data");
}
eap_figure_next_state(esp, 0);
break;
case eapTlsRecvClient:
/* Receive authentication response from client */
if (len > 0) {
GETCHAR(flags, inp);
if(len == 1 && !flags) { /* Ack = ok */
#ifdef MPPE
eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 );
#endif
eap_send_success(esp);
}
else { /* failure */
warn("Server authentication failed");
eap_send_failure(esp);
}
}
else
warn("Bogus EAP-TLS packet received from client");
eaptls_free_session(esp->es_server.ea_session);
break;
case eapTlsRecvAlertAck:
eap_send_failure(esp);
break;
default:
eap_figure_next_state(esp, 1);
break;
}
break;
#endif /* USE_EAPTLS */
case EAPT_NOTIFICATION:
dbglog("EAP unexpected Notification; response discarded");
break;
@ -1807,6 +2204,13 @@ int len;
esp->es_server.ea_state = eapMD5Chall;
break;
#ifdef USE_EAPTLS
/* Send EAP-TLS start packet */
case EAPT_TLS:
esp->es_server.ea_state = eapTlsStart;
break;
#endif /* USE_EAPTLS */
default:
dbglog("EAP: peer requesting unknown Type %d", vallen);
switch (esp->es_server.ea_state) {
@ -2018,13 +2422,27 @@ u_char *inp;
int id;
int len;
{
if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
#ifdef USE_EAPTLS
&& esp->es_client.ea_state != eapTlsRecvSuccess
#endif /* USE_EAPTLS */
) {
dbglog("EAP unexpected success message in state %s (%d)",
eap_state_name(esp->es_client.ea_state),
esp->es_client.ea_state);
return;
}
#ifdef USE_EAPTLS
if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state !=
eapTlsRecvSuccess) {
dbglog("EAP-TLS unexpected success message in state %s (%d)",
eap_state_name(esp->es_client.ea_state),
esp->es_client.ea_state);
return;
}
#endif /* USE_EAPTLS */
if (esp->es_client.ea_timeout > 0) {
UNTIMEOUT(eap_client_timeout, (void *)esp);
}
@ -2150,6 +2568,9 @@ void *arg;
int code, id, len, rtype, vallen;
u_char *pstart;
u_int32_t uval;
#ifdef USE_EAPTLS
u_char flags;
#endif /* USE_EAPTLS */
if (inlen < EAP_HEADERLEN)
return (0);
@ -2214,6 +2635,24 @@ void *arg;
}
break;
#ifdef USE_EAPTLS
case EAPT_TLS:
if (len < 1)
break;
GETCHAR(flags, inp);
len--;
if(flags == 0 && len == 0){
printer(arg, " Ack");
break;
}
printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
break;
#endif /* USE_EAPTLS */
case EAPT_SRP:
if (len < 3)
goto truncated;
@ -2325,6 +2764,25 @@ void *arg;
}
break;
#ifdef USE_EAPTLS
case EAPT_TLS:
if (len < 1)
break;
GETCHAR(flags, inp);
len--;
if(flags == 0 && len == 0){
printer(arg, " Ack");
break;
}
printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
break;
#endif /* USE_EAPTLS */
case EAPT_NAK:
if (len <= 0) {
printer(arg, " <missing hint>");
@ -2426,3 +2884,4 @@ void *arg;
return (inp - pstart);
}

View File

@ -84,6 +84,16 @@ enum eap_state_code {
eapClosed, /* Authentication not in use */
eapListen, /* Client ready (and timer running) */
eapIdentify, /* EAP Identify sent */
eapTlsStart, /* Send EAP-TLS start packet */
eapTlsRecv, /* Receive EAP-TLS tls data */
eapTlsSendAck, /* Send EAP-TLS ack */
eapTlsSend, /* Send EAP-TLS tls data */
eapTlsRecvAck, /* Receive EAP-TLS ack */
eapTlsRecvClient, /* Receive EAP-TLS auth response from client*/
eapTlsSendAlert, /* Send EAP-TLS tls alert (server)*/
eapTlsRecvAlertAck, /* Receive EAP-TLS ack after sending alert */
eapTlsRecvSuccess, /* Receive EAP success */
eapTlsRecvFailure, /* Receive EAP failure */
eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */
eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */
eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */
@ -95,9 +105,18 @@ enum eap_state_code {
#define EAP_STATES \
"Initial", "Pending", "Closed", "Listen", "Identify", \
"TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\
"TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \
"SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
#ifdef USE_EAPTLS
#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial &&\
(esp)->es_client.ea_state != eapPending &&\
(esp)->es_client.ea_state != eapClosed)
#else
#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen)
#endif /* USE_EAPTLS */
#define eap_server_active(esp) \
((esp)->es_server.ea_state >= eapIdentify && \
(esp)->es_server.ea_state <= eapMD5Chall)
@ -112,11 +131,17 @@ struct eap_auth {
u_short ea_namelen; /* Length of our name */
u_short ea_peerlen; /* Length of peer's name */
enum eap_state_code ea_state;
#ifdef USE_EAPTLS
enum eap_state_code ea_prev_state;
#endif
u_char ea_id; /* Current id */
u_char ea_requests; /* Number of Requests sent/received */
u_char ea_responses; /* Number of Responses */
u_char ea_type; /* One of EAPT_* */
u_int32_t ea_keyflags; /* SRP shared key usage flags */
#ifdef USE_EAPTLS
bool ea_using_eaptls;
#endif
};
/*
@ -139,7 +164,12 @@ typedef struct eap_state {
* Timeouts.
*/
#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */
#ifdef USE_EAPTLS
#define EAP_DEFTRANSMITS 30 /* max # times to transmit */
/* certificates can be long ... */
#else
#define EAP_DEFTRANSMITS 10 /* max # times to transmit */
#endif /* USE_EAPTLS */
#define EAP_DEFREQTIME 20 /* Time to wait for peer request */
#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */

View File

@ -33,6 +33,8 @@
***********************************************************************
*/
#ifndef USE_EAPTLS
#include <string.h>
#include "md5.h"
@ -305,3 +307,5 @@ UINT4 *in;
** End of md5.c **
******************************** (cut) ********************************
*/
#endif /* USE_EAPTLS */

View File

@ -36,6 +36,7 @@
** documentation and/or software. **
***********************************************************************
*/
#ifndef USE_EAPTLS
#ifndef __MD5_INCLUDE__
@ -63,3 +64,5 @@ void MD5_Final (unsigned char hash[], MD5_CTX *mdContext);
#define __MD5_INCLUDE__
#endif /* __MD5_INCLUDE__ */
#endif /* USE_EAPTLS */

View File

@ -21,6 +21,13 @@
#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
#define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets"
#ifdef USE_EAPTLS
#define _PATH_EAPTLSCLIFILE _ROOT_PATH "/etc/ppp/eaptls-client"
#define _PATH_EAPTLSSERVFILE _ROOT_PATH "/etc/ppp/eaptls-server"
#define _PATH_OPENSSLCONFFILE _ROOT_PATH "/etc/ppp/openssl.cnf"
#endif /* USE_EAPTLS */
#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"

View File

@ -4,6 +4,9 @@ CFLAGS = $(COPTS) -I.. -I../../include -fPIC
LDFLAGS = $(LDOPTS)
INSTALL = install
# EAP-TLS
CFLAGS += -DUSE_EAPTLS=1
DESTDIR = $(INSTROOT)@DESTDIR@
BINDIR = $(DESTDIR)/sbin
MANDIR = $(DESTDIR)/share/man/man8

View File

@ -107,4 +107,7 @@ void plugin_init(void)
{
add_options(options);
pap_passwd_hook = promptpass;
#ifdef USE_EAPTLS
eaptls_passwd_hook = promptpass;
#endif
}

View File

@ -79,4 +79,8 @@ void plugin_init (void)
chap_check_hook = pwfd_check;
chap_passwd_hook = pwfd_passwd;
#ifdef USE_EAPTLS
eaptls_passwd_hook = pwfd_passwd;
#endif
}

View File

@ -253,6 +253,12 @@ Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
compression in the corresponding direction. Use \fInobsdcomp\fR or
\fIbsdcomp 0\fR to disable BSD-Compress compression entirely.
.TP
.B ca \fIca-file
(EAP-TLS) Use the file \fIca-file\fR as the X.509 Certificate Authority
(CA) file (in PEM format), needed for setting up an EAP-TLS connection.
This option is used on the client-side in conjunction with the \fBcert\fR
and \fBkey\fR options.
.TP
.B cdtrcts
Use a non-standard hardware flow control (i.e. DTR/CTS) to control
the flow of data on the serial port. If neither the \fIcrtscts\fR,
@ -264,6 +270,12 @@ RTS output. Such serial ports use this mode to implement true
bi-directional flow control. The sacrifice is that this flow
control mode does not permit using DTR as a modem control line.
.TP
.B cert \fIcertfile
(EAP-TLS) Use the file \fIcertfile\fR as the X.509 certificate (in PEM
format), needed for setting up an EAP-TLS connection. This option is
used on the client-side in conjunction with the \fBca\fR and
\fBkey\fR options.
.TP
.B chap\-interval \fIn
If this option is given, pppd will rechallenge the peer every \fIn\fR
seconds.
@ -292,6 +304,18 @@ negotiation by sending its first LCP packet. The default value is
1000 (1 second). This wait period only applies if the \fBconnect\fR
or \fBpty\fR option is used.
.TP
.B crl \fIfilename
(EAP-TLS) Use the file \fIfilename\fR as the Certificate Revocation List
to check for the validity of the peer's certificate. This option is not
mandatory for setting up an EAP-TLS connection. Also see the \fBcrl-dir\fR
option.
.TP
.B crl-dir \fIdirectory
(EAP-TLS) Use the directory \fIdirectory\fR to scan for CRL files in
has format ($hash.r0) to check for the validity of the peer's certificate.
This option is not mandatory for setting up an EAP-TLS connection.
Also see the \fBcrl\fR option.
.TP
.B debug
Enables connection debugging facilities.
If this option is given, pppd will log the contents of all
@ -561,6 +585,12 @@ transmitted packets be printed. On most systems, messages printed by
the kernel are logged by syslog(1) to a file as directed in the
/etc/syslog.conf configuration file.
.TP
.B key \fIkeyfile
(EAP-TLS) Use the file \fIkeyfile\fR as the private key file (in PEM
format), needed for setting up an EAP-TLS connection. This option is
used on the client-side in conjunction with the \fBca\fR and
\fBcert\fR options.
.TP
.B ktune
Enables pppd to alter kernel settings as appropriate. Under Linux,
pppd will enable IP forwarding (i.e. set /proc/sys/net/ipv4/ip_forward
@ -724,6 +754,9 @@ name to \fIname\fR.)
Disable Address/Control compression in both directions (send and
receive).
.TP
.B need-peer-eap
(EAP-TLS) Require the peer to verify our authentication credentials.
.TP
.B noauth
Do not require the peer to authenticate itself. This option is
privileged.

View File

@ -338,6 +338,11 @@ extern bool dump_options; /* print out option values */
extern bool dryrun; /* check everything, print options, exit */
extern int child_wait; /* # seconds to wait for children at end */
#ifdef USE_EAPTLS
extern char *crl_dir;
extern char *crl_file;
#endif /* USE_EAPTLS */
#ifdef MAXOCTETS
extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */
extern int maxoctets_dir; /* Direction :
@ -758,6 +763,10 @@ extern int (*chap_check_hook) __P((void));
extern int (*chap_passwd_hook) __P((char *user, char *passwd));
extern void (*multilink_join_hook) __P((void));
#ifdef USE_EAPTLS
extern int (*eaptls_passwd_hook) __P((char *user, char *passwd));
#endif
/* Let a plugin snoop sent and received packets. Useful for L2TP */
extern void (*snoop_recv_hook) __P((unsigned char *p, int len));
extern void (*snoop_send_hook) __P((unsigned char *p, int len));