Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 71081 Details for
Bug 109935
Support for authenticating with Extensible Authentication Protocol and Transport Level Security for PPPd (EAP-TLS)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch that enables ppp 2.4.3-r8 to be built with EAP-TLS
eap-tls-mppe-support.patch (text/plain), 85.59 KB, created by
Boky
on 2005-10-20 10:08:33 UTC
(
hide
)
Description:
Patch that enables ppp 2.4.3-r8 to be built with EAP-TLS
Filename:
MIME Type:
Creator:
Boky
Created:
2005-10-20 10:08:33 UTC
Size:
85.59 KB
patch
obsolete
>diff -Naur /usr/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-0.7.patch /usr/local/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-0.7.patch >--- /usr/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-0.7.patch 1970-01-01 01:00:00.000000000 +0100 >+++ /usr/local/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-0.7.patch 2005-03-30 13:18:02.000000000 +0200 >@@ -0,0 +1,2808 @@ >+diff -Naur ppp-2.4.3/etc.ppp/eaptls-client ppp-2.4.3-eaptls-0.7/etc.ppp/eaptls-client >+--- ppp-2.4.3/etc.ppp/eaptls-client 1970-01-01 01:00:00.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/etc.ppp/eaptls-client 2005-03-18 10:45:22.000000000 +0100 >+@@ -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 >+diff -Naur ppp-2.4.3/etc.ppp/eaptls-server ppp-2.4.3-eaptls-0.7/etc.ppp/eaptls-server >+--- ppp-2.4.3/etc.ppp/eaptls-server 1970-01-01 01:00:00.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/etc.ppp/eaptls-server 2005-03-18 10:44:49.000000000 +0100 >+@@ -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 >+diff -Naur ppp-2.4.3/linux/Makefile.top ppp-2.4.3-eaptls-0.7/linux/Makefile.top >+--- ppp-2.4.3/linux/Makefile.top 2004-10-31 23:25:16.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/linux/Makefile.top 2005-03-07 11:40:46.000000000 +0100 >+@@ -26,7 +26,7 @@ >+ 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 @@ >+ $(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 $@ >+diff -Naur ppp-2.4.3/pppd/auth.c ppp-2.4.3-eaptls-0.7/pppd/auth.c >+--- ppp-2.4.3/pppd/auth.c 2004-11-12 11:30:51.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/auth.c 2005-03-21 14:15:18.000000000 +0100 >+@@ -112,6 +112,7 @@ >+ #include "upap.h" >+ #include "chap-new.h" >+ #include "eap.h" >++#include "eap-tls.h" >+ #ifdef CBCP_SUPPORT >+ #include "cbcp.h" >+ #endif >+@@ -237,6 +238,7 @@ >+ bool allow_any_ip = 0; /* Allow peer to use any IP address */ >+ bool explicit_remote = 0; /* User specified explicit remote name */ >+ char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ >++bool need_peer_eap = 0; /* Require peer to authenticate us */ >+ >+ static char *uafname; /* name of most recent +ua file */ >+ >+@@ -255,10 +257,23 @@ >+ 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)); >++ >++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 ip_addr_check __P((u_int32_t, struct permitted_ip *)); >+ static int scan_authfile __P((FILE *, char *, char *, char *, >+ struct wordlist **, struct wordlist **, >+ char *, int)); >++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)); >++ >+ static void free_wordlist __P((struct wordlist *)); >+ static void auth_script __P((char *)); >+ static void auth_script_done __P((void *)); >+@@ -397,6 +412,9 @@ >+ "Set telephone number(s) which are allowed to connect", >+ OPT_PRIV | OPT_A2LIST }, >+ >++ { "need-peer-eap", o_bool, &need_peer_eap, >++ "Require the peer to authenticate us", 1 }, >++ >+ { NULL } >+ }; >+ >+@@ -706,6 +724,7 @@ >+ lcp_options *wo = &lcp_wantoptions[unit]; >+ lcp_options *go = &lcp_gotoptions[unit]; >+ lcp_options *ho = &lcp_hisoptions[unit]; >++ lcp_options *ao = &lcp_allowoptions[unit]; >+ int i; >+ struct protent *protp; >+ >+@@ -740,6 +759,20 @@ >+ } >+ } >+ >++ 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; >++ } >++ >+ new_phase(PHASE_AUTHENTICATE); >+ used_login = 0; >+ auth = 0; >+@@ -1244,6 +1277,13 @@ >+ our_name, 1, &lacks_ip); >+ } >+ >++ if (!can_auth && wo->neg_eap) { >++ can_auth = >++ have_eaptls_secret_server((explicit_remote ? remote_name : >++ NULL), our_name, 1, &lacks_ip); >++ >++ } >++ >+ if (auth_required && !can_auth && noauth_addrs == NULL) { >+ if (default_auth) { >+ option_error( >+@@ -1298,7 +1338,8 @@ >+ 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) || >++ have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL))); >+ >+ hadchap = -1; >+ if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) >+@@ -1313,8 +1354,11 @@ >+ !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) && >++ !have_eaptls_secret_server((explicit_remote? remote_name: NULL), >++ our_name, 1, NULL)) >+ go->neg_eap = 0; >++ >+ } >+ >+ >+@@ -1893,6 +1937,100 @@ >+ } >+ >+ >++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_test_certs_server(servcertfile, cacertfile, >++ pkfile, clicertfile) == 0) >++ 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; >++ char servcertfile[MAXWORDLEN]; >++ char clicertfile[MAXWORDLEN]; >++ char cacertfile[MAXWORDLEN]; >++ char pkfile[MAXWORDLEN]; >++ >++ filename = _PATH_EAPTLSCLIFILE; >++ 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 (addrs != 0) >++ free_wordlist(addrs); >++ >++ if (ret < 0) >++ return 0; >++ >++ if (eaptls_test_certs_client >++ (clicertfile, cacertfile, pkfile, servcertfile) == 0) >++ return 0; >++ >++ >++ return 1; >++} >++ >+ /* >+ * get_secret - open the CHAP secret file and return the secret >+ * for authenticating the given client on the given server. >+@@ -2545,3 +2683,215 @@ >+ >+ auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); >+ } >++ >++ >++ >++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; >++ struct wordlist *addrs, *opts; >++ >++ 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 (am_server) >++ set_allowed_addrs(unit, addrs, opts); >++ else if (opts != NULL) >++ free_wordlist(opts); >++ if (addrs != NULL) >++ free_wordlist(addrs); >++ >++ return 1; >++} >+diff -Naur ppp-2.4.3/pppd/eap.c ppp-2.4.3-eaptls-0.7/pppd/eap.c >+--- ppp-2.4.3/pppd/eap.c 2004-11-09 23:39:25.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/eap.c 2005-03-21 11:19:55.000000000 +0100 >+@@ -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,9 @@ >+ >+ #include "pppd.h" >+ #include "pathnames.h" >+-#include "md5.h" >++// #include "md5.h" >+ #include "eap.h" >++#include "eap-tls.h" >+ >+ #ifdef USE_SRP >+ #include <t_pwd.h> >+@@ -83,6 +89,10 @@ >+ static char *pn_secret = NULL; /* Pseudonym generating secret */ >+ #endif >+ >++char *crl_dir = NULL; >++bool auto_update_crl = 0; >++int crl_update_time = CRL_UPDATE_TIME; >++ >+ /* >+ * Command-line options. >+ */ >+@@ -105,6 +115,13 @@ >+ { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, >+ "Use pseudonym if offered one by server", 1 }, >+ #endif >++ { "crl-dir", o_string, &crl_dir, >++ "Use CRLs in directory" }, >++ { "auto-update-crl", o_bool, &auto_update_crl, >++ "Automatically download CA CRL if old or non existent", 1 }, >++ { "crl-update-time", o_int, &crl_update_time, >++ "Time (in hours) after which reload CA CRL" }, >++ >+ { NULL } >+ }; >+ >+@@ -209,6 +226,7 @@ >+ esp->es_server.ea_id = (u_char)(drand48() * 0x100); >+ esp->es_client.ea_timeout = EAP_DEFREQTIME; >+ esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ; >++ esp->es_client.ea_using_eaptls = 0; >+ } >+ >+ /* >+@@ -426,6 +444,10 @@ >+ eap_state *esp; >+ int status; >+ { >++ >++ struct eaptls_session *ets; >++ int secret_len; >++ char secret[MAXWORDLEN]; >+ #ifdef USE_SRP >+ unsigned char secbuf[MAXWORDLEN], clear[8], *sp, *dp; >+ struct t_pw tpw; >+@@ -438,6 +460,9 @@ >+ #endif /* USE_SRP */ >+ >+ esp->es_server.ea_timeout = esp->es_savedtime; >++ >++ esp->es_server.ea_prev_state = esp->es_server.ea_state; >++ >+ switch (esp->es_server.ea_state) { >+ case eapBadAuth: >+ return; >+@@ -562,9 +587,78 @@ >+ break; >+ } >+ #endif /* USE_SRP */ >++ >++ 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; >++ } >++ >+ esp->es_server.ea_state = eapMD5Chall; >+ break; >+ >++ 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(SSL_is_init_finished(ets->ssl)) { >++ esp->es_server.ea_state = eapTlsRecvClient; >++ break; >++ } >++ >++ if(ets->frag) >++ esp->es_server.ea_state = eapTlsRecvAck; >++ 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; >++ >+ case eapSRP1: >+ #ifdef USE_SRP >+ ts = (struct t_server *)esp->es_server.ea_session; >+@@ -718,6 +812,28 @@ >+ INCPTR(esp->es_server.ea_namelen, outp); >+ break; >+ >++ 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; >++ >+ #ifdef USE_SRP >+ case eapSRP1: >+ PUTCHAR(EAPT_SRP, outp); >+@@ -904,11 +1020,53 @@ >+ eap_server_timeout(arg) >+ void *arg; >+ { >++ u_char *outp; >++ u_char *lenloc; >++ int outlen; >++ >+ eap_state *esp = (eap_state *) arg; >+ >+ if (!eap_server_active(esp)) >+ return; >+ >++ 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; >++ } >++ >+ /* EAP ID number must not change on timeout. */ >+ eap_send_request(esp); >+ } >+@@ -1166,6 +1324,79 @@ >+ } >+ #endif /* USE_SRP */ >+ >++/* >++ * 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); >++ >++} >++ >+ static void >+ eap_send_nak(esp, id, type) >+ eap_state *esp; >+@@ -1320,6 +1551,8 @@ >+ char rhostname[256]; >+ MD5_CTX mdContext; >+ u_char hash[MD5_SIGNATURE_SIZE]; >++ u_char flags; >++ struct eaptls_session *ets = esp->es_client.ea_session; >+ #ifdef USE_SRP >+ struct t_client *tc; >+ struct t_num sval, gval, Nval, *Ap, Bval; >+@@ -1442,7 +1675,7 @@ >+ if (!get_secret(esp->es_unit, esp->es_client.ea_name, >+ rhostname, secret, &secret_len, 0)) { >+ dbglog("EAP: no MD5 secret for auth to %q", rhostname); >+- eap_send_nak(esp, id, EAPT_SRP); >++ eap_send_nak(esp, id, EAPT_TLS); >+ break; >+ } >+ MD5_Init(&mdContext); >+@@ -1456,6 +1689,85 @@ >+ esp->es_client.ea_namelen); >+ break; >+ >++ case EAPT_TLS: >++ >++ switch(esp->es_client.ea_state) { >++ >++ case eapListen: >++ >++ 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_SRP); >++ 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_SRP); >++ break; >++ >++ case eapTlsRecvAck: >++ eap_tls_response(esp, id); >++ esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : >++ eapTlsRecv); >++ break; >++ >++ case eapTlsRecv: >++ 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)){ >++ 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_SRP); >++ esp->es_client.ea_using_eaptls = 0; >++ break; >++ } >++ >++ break; >++ >+ #ifdef USE_SRP >+ case EAPT_SRP: >+ if (len < 1) { >+@@ -1690,7 +2002,7 @@ >+ >+ default: >+ info("EAP: unknown authentication type %d; Naking", typenum); >+- eap_send_nak(esp, id, EAPT_SRP); >++ eap_send_nak(esp, id, EAPT_TLS); >+ break; >+ } >+ >+@@ -1730,6 +2042,8 @@ >+ char rhostname[256]; >+ MD5_CTX mdContext; >+ u_char hash[MD5_SIGNATURE_SIZE]; >++ struct eaptls_session *ets; >++ u_char flags; >+ #ifdef USE_SRP >+ struct t_server *ts; >+ struct t_num A; >+@@ -1776,6 +2090,54 @@ >+ eap_figure_next_state(esp, 0); >+ break; >+ >++ 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 */ >++ >++ GETCHAR(flags, inp); >++ >++ if(len == 1 && !flags) /* Ack = ok */ >++ eap_send_success(esp); >++ else { /* failure */ >++ eaptls_receive(esp->es_server.ea_session, inp, len); >++ warn("Server authentication failed"); >++ eap_send_failure(esp); >++ } >++ >++ 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; >++ >+ case EAPT_NOTIFICATION: >+ dbglog("EAP unexpected Notification; response discarded"); >+ break; >+@@ -1807,6 +2169,11 @@ >+ esp->es_server.ea_state = eapMD5Chall; >+ break; >+ >++ /* Send EAP-TLS start packet */ >++ case EAPT_TLS: >++ esp->es_server.ea_state = eapTlsStart; >++ break; >++ >+ default: >+ dbglog("EAP: peer requesting unknown Type %d", vallen); >+ switch (esp->es_server.ea_state) { >+@@ -2018,13 +2385,22 @@ >+ 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) && >++ esp->es_client.ea_state != eapTlsRecvSuccess) { >+ dbglog("EAP unexpected success message in state %s (%d)", >+ eap_state_name(esp->es_client.ea_state), >+ esp->es_client.ea_state); >+ return; >+ } >+ >++ 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; >++ } >++ >+ if (esp->es_client.ea_timeout > 0) { >+ UNTIMEOUT(eap_client_timeout, (void *)esp); >+ } >+@@ -2150,6 +2526,7 @@ >+ int code, id, len, rtype, vallen; >+ u_char *pstart; >+ u_int32_t uval; >++ u_char flags; >+ >+ if (inlen < EAP_HEADERLEN) >+ return (0); >+@@ -2214,6 +2591,22 @@ >+ } >+ break; >+ >++ 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; >+ case EAPT_SRP: >+ if (len < 3) >+ goto truncated; >+@@ -2325,6 +2718,23 @@ >+ } >+ break; >+ >++ >++ 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; >+ case EAPT_NAK: >+ if (len <= 0) { >+ printer(arg, " <missing hint>"); >+@@ -2426,3 +2836,5 @@ >+ >+ return (inp - pstart); >+ } >++ >++ >+diff -Naur ppp-2.4.3/pppd/eap.h ppp-2.4.3-eaptls-0.7/pppd/eap.h >+--- ppp-2.4.3/pppd/eap.h 2003-06-12 01:56:26.000000000 +0200 >++++ ppp-2.4.3-eaptls-0.7/pppd/eap.h 2005-03-07 09:25:12.000000000 +0100 >+@@ -84,6 +84,18 @@ >+ 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 +107,13 @@ >+ >+ #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) >++#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial ||\ >++ (esp)->es_client.ea_state != eapPending ||\ >++ (esp)->es_client.ea_state != eapClosed) >+ #define eap_server_active(esp) \ >+ ((esp)->es_server.ea_state >= eapIdentify && \ >+ (esp)->es_server.ea_state <= eapMD5Chall) >+@@ -112,11 +128,13 @@ >+ u_short ea_namelen; /* Length of our name */ >+ u_short ea_peerlen; /* Length of peer's name */ >+ enum eap_state_code ea_state; >++ enum eap_state_code ea_prev_state; >+ 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 */ >++ bool ea_using_eaptls; >+ }; >+ >+ /* >+@@ -139,7 +157,8 @@ >+ * Timeouts. >+ */ >+ #define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ >+-#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ >++#define EAP_DEFTRANSMITS 30 /* max # times to transmit */ >++ /* certificates can be long ... */ >+ #define EAP_DEFREQTIME 20 /* Time to wait for peer request */ >+ #define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ >+ >+diff -Naur ppp-2.4.3/pppd/eap-tls.c ppp-2.4.3-eaptls-0.7/pppd/eap-tls.c >+--- ppp-2.4.3/pppd/eap-tls.c 1970-01-01 01:00:00.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/eap-tls.c 2005-03-21 14:39:48.000000000 +0100 >+@@ -0,0 +1,1270 @@ >++/* >++ * eap-tls.c - EAP-TLS implementation for PPP >++ * >++ * 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. >++ * >++ */ >++ >++#include <string.h> >++#include <unistd.h> >++#include <sys/types.h> >++#include <sys/stat.h> >++#include <fcntl.h> >++ >++#include <openssl/ssl.h> >++#include <openssl/err.h> >++#include <openssl/x509v3.h> >++#include <curl/curl.h> >++ >++#include "pppd.h" >++#include "eap.h" >++#include "eap-tls.h" >++#include "pathnames.h" >++ >++extern char *crl_dir; >++extern bool auto_update_crl; >++extern int crl_update_time; >++ >++static int search_wordlist(struct wordlist *wl, char *word); >++static void add_wordlist(struct wordlist *wl, char *word); >++static void destroy_wordlist(struct wordlist *wl); >++ >++/* >++ * Tests if certificates, key and crl for server use can be loaded. >++ */ >++int eaptls_test_certs_server(char *servcertfile, char *cacertfile, >++ char *pkfile, char *clicertfile) >++{ >++ SSL_CTX *ctx; >++ X509_STORE *certstore; >++ X509_LOOKUP *lookup; >++ X509 *tmp; >++ >++ /* >++ * Without these can't continue >++ */ >++ if (!cacertfile[0] || !servcertfile[0] || !pkfile[0]) >++ return 0; >++ >++ SSL_library_init(); >++ SSL_load_error_strings(); >++ >++ ctx = SSL_CTX_new(TLSv1_method()); >++ >++ if (!ctx) { >++ ERR_print_errors_fp(stderr); >++ error("Can't initialize CTX"); >++ return 0; >++ } >++ >++ if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) >++ goto fail; >++ >++ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); >++ >++ if (!SSL_CTX_use_certificate_file(ctx, servcertfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (!SSL_CTX_use_PrivateKey_file(ctx, pkfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (SSL_CTX_check_private_key(ctx) != 1) >++ goto fail; >++ >++ if (crl_dir) { >++ if (!(certstore = SSL_CTX_get_cert_store(ctx))) >++ goto fail; >++ >++ if (!(lookup = >++ X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) >++ goto fail; >++ >++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); >++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); >++ } >++ >++ /* >++ * If a client certificate file was specified, it must be valid, else >++ * fail >++ */ >++ if (clicertfile[0]) { >++ if (!(tmp = get_X509_from_file(clicertfile))) { >++ warn("Error loading client certificate from file %s", >++ clicertfile); >++ goto fail; >++ } >++ X509_free(tmp); >++ } >++ >++ SSL_CTX_free(ctx); >++ >++ return 1; >++ >++ fail: >++ ERR_print_errors_fp(stderr); >++ SSL_CTX_free(ctx); >++ return 0; >++} >++ >++/* >++ * Tests if certificates, key and crl for client use can be loaded. >++ */ >++int eaptls_test_certs_client(char *clicertfile, char *cacertfile, char *pkfile, >++ char *servcertfile) >++{ >++ >++ SSL_CTX *ctx; >++ X509_STORE *certstore; >++ X509_LOOKUP *lookup; >++ X509 *tmp; >++ >++ /* >++ * Without these we can't continue >++ */ >++ if (!cacertfile[0] || !clicertfile[0] || !pkfile[0]) >++ return 0; >++ >++ SSL_library_init(); >++ SSL_load_error_strings(); >++ >++ ctx = SSL_CTX_new(TLSv1_method()); >++ >++ if (!ctx) { >++ ERR_print_errors_fp(stderr); >++ error("Can't initialize CTX"); >++ return 0; >++ } >++ >++ if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) >++ goto fail; >++ >++ if (!SSL_CTX_use_certificate_file(ctx, clicertfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (!SSL_CTX_use_PrivateKey_file(ctx, pkfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (SSL_CTX_check_private_key(ctx) != 1) >++ goto fail; >++ >++ if (crl_dir) { >++ >++ if (!(certstore = SSL_CTX_get_cert_store(ctx))) >++ goto fail; >++ >++ if (!(lookup = >++ X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) >++ goto fail; >++ >++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); >++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); >++ } >++ >++ /* >++ * If a server certificate file was specified, it must be valid, else >++ * fail >++ */ >++ if (servcertfile[0]) { >++ if (!(tmp = get_X509_from_file(servcertfile))) { >++ warn("Error loading client certificate from file %s", >++ clicertfile); >++ goto fail; >++ } >++ X509_free(tmp); >++ } >++ >++ SSL_CTX_free(ctx); >++ >++ return 1; >++ >++ fail: >++ ERR_print_errors_fp(stderr); >++ SSL_CTX_free(ctx); >++ return 0; >++} >++ >++/* >++ * Init the ssl handshake (server mode) >++ */ >++int eaptls_init_ssl_server(eap_state * esp) >++{ >++ struct eaptls_session *ets; >++ X509_STORE *certstore; >++ X509_LOOKUP *lookup; >++ char servcertfile[MAXWORDLEN]; >++ char clicertfile[MAXWORDLEN]; >++ char cacertfile[MAXWORDLEN]; >++ char pkfile[MAXWORDLEN]; >++ struct wordlist updatedfiles; >++ >++ updatedfiles.next = NULL; >++ updatedfiles.word = NULL; >++ >++ /* >++ * Allocate new eaptls session >++ */ >++ esp->es_server.ea_session = malloc(sizeof(struct eaptls_session)); >++ if (!esp->es_server.ea_session) >++ fatal("Allocation error"); >++ ets = esp->es_server.ea_session; >++ >++ if (!esp->es_server.ea_peer) { >++ error("Error: client name not set (BUG)"); >++ return 0; >++ } >++ >++ strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN); >++ >++ if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, >++ esp->es_server.ea_name, clicertfile, >++ servcertfile, cacertfile, pkfile, 1)) { >++ dbglog("get_eaptls_secret error"); >++ return 0; >++ } >++ >++ ets->mtu = netif_get_mtu(esp->es_unit) - PPP_HDRLEN - 10; >++ >++ SSL_library_init(); >++ SSL_load_error_strings(); >++ >++ ets->ctx = SSL_CTX_new(TLSv1_method()); >++ >++ if (!ets->ctx) { >++ ERR_print_errors_fp(stderr); >++ error("Can't initialize CTX"); >++ return 0; >++ } >++ >++ if (!SSL_CTX_load_verify_locations(ets->ctx, cacertfile, NULL)) >++ goto fail; >++ >++ SSL_CTX_set_client_CA_list(ets->ctx, >++ SSL_load_client_CA_file(cacertfile)); >++ >++ if (!SSL_CTX_use_certificate_file >++ (ets->ctx, servcertfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (!SSL_CTX_use_PrivateKey_file(ets->ctx, pkfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (SSL_CTX_check_private_key(ets->ctx) != 1) >++ goto fail; >++ >++ SSL_CTX_set_options(ets->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); >++ SSL_CTX_set_verify_depth(ets->ctx, 5); >++ SSL_CTX_set_verify(ets->ctx, >++ SSL_VERIFY_PEER | >++ SSL_VERIFY_FAIL_IF_NO_PEER_CERT, >++ &ssl_verify_callback); >++ >++ if (crl_dir) { >++ if (!(certstore = SSL_CTX_get_cert_store(ets->ctx))) >++ goto fail; >++ >++ if (!(lookup = X509_STORE_add_lookup(certstore, >++ X509_LOOKUP_hash_dir()))) >++ goto fail; >++ >++ if (auto_update_crl) >++ eaptls_update_crls(crl_dir, cacertfile, &updatedfiles); >++ >++ destroy_wordlist(&updatedfiles); >++ >++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); >++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); >++ } >++ >++ if (!(ets->ssl = SSL_new(ets->ctx))) >++ goto fail; >++ >++ /* >++ * Initialize the BIOs we use to read/write to ssl engine >++ */ >++ ets->into_ssl = BIO_new(BIO_s_mem()); >++ ets->from_ssl = BIO_new(BIO_s_mem()); >++ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); >++ >++ SSL_set_msg_callback(ets->ssl, ssl_msg_callback); >++ SSL_set_msg_callback_arg(ets->ssl, ets); >++ >++ /* >++ * Attach the session struct to the connection, so we can later >++ * retrieve it when doing certificate verification >++ */ >++ SSL_set_ex_data(ets->ssl, 0, ets); >++ >++ SSL_set_accept_state(ets->ssl); >++ >++ ets->data = NULL; >++ ets->datalen = 0; >++ ets->alert_sent = 0; >++ ets->alert_recv = 0; >++ >++ /* >++ * If we specified the client certificate file, store it in ets->peercertfile, >++ * so we can check it later in ssl_verify_callback() >++ */ >++ if (clicertfile[0]) >++ strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN); >++ else >++ ets->peercertfile[0] = 0; >++ >++ return 1; >++ >++ fail: >++ ERR_print_errors_fp(stderr); >++ SSL_CTX_free(ets->ctx); >++ return 0; >++} >++ >++/* >++ * Init the ssl handshake (client mode) >++ */ >++int eaptls_init_ssl_client(eap_state * esp) >++{ >++ struct eaptls_session *ets; >++ X509_STORE *certstore; >++ X509_LOOKUP *lookup; >++ char servcertfile[MAXWORDLEN]; >++ char clicertfile[MAXWORDLEN]; >++ char cacertfile[MAXWORDLEN]; >++ char pkfile[MAXWORDLEN]; >++ struct wordlist updatedfiles; >++ >++ updatedfiles.next = NULL; >++ updatedfiles.word = NULL; >++ >++ /* >++ * Allocate new eaptls session >++ */ >++ esp->es_client.ea_session = malloc(sizeof(struct eaptls_session)); >++ if (!esp->es_client.ea_session) >++ fatal("Allocation error"); >++ ets = esp->es_client.ea_session; >++ >++ /* >++ * If available, copy server name in ets; it will be used in cert >++ * verify >++ */ >++ if (esp->es_client.ea_peer) >++ strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN); >++ else >++ ets->peer[0] = 0; >++ >++ ets->mtu = netif_get_mtu(esp->es_unit) - PPP_HDRLEN - 10; >++ >++ if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, >++ esp->es_client.ea_peer, clicertfile, >++ servcertfile, cacertfile, pkfile, 0)) { >++ dbglog("get_eaptls_secret error"); >++ return 0; >++ } >++ >++ SSL_library_init(); >++ SSL_load_error_strings(); >++ >++ ets->ctx = SSL_CTX_new(TLSv1_method()); >++ >++ if (!ets->ctx) { >++ ERR_print_errors_fp(stderr); >++ error("Can't initialize CTX"); >++ return 0; >++ } >++ >++ if (!SSL_CTX_load_verify_locations(ets->ctx, cacertfile, NULL)) >++ goto fail; >++ >++ if (!SSL_CTX_use_certificate_file >++ (ets->ctx, clicertfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (!SSL_CTX_use_PrivateKey_file(ets->ctx, pkfile, SSL_FILETYPE_PEM)) >++ goto fail; >++ >++ if (SSL_CTX_check_private_key(ets->ctx) != 1) >++ goto fail; >++ >++ SSL_CTX_set_options(ets->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); >++ SSL_CTX_set_verify_depth(ets->ctx, 5); >++ SSL_CTX_set_verify(ets->ctx, SSL_VERIFY_PEER, &ssl_verify_callback); >++ >++ if (crl_dir) { >++ if (!(certstore = SSL_CTX_get_cert_store(ets->ctx))) >++ goto fail; >++ >++ if (!(lookup = X509_STORE_add_lookup(certstore, >++ X509_LOOKUP_hash_dir()))) >++ goto fail; >++ >++ if (auto_update_crl) >++ eaptls_update_crls(crl_dir, cacertfile, &updatedfiles); >++ >++ destroy_wordlist(&updatedfiles); >++ >++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); >++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); >++ } >++ >++ ets->ssl = SSL_new(ets->ctx); >++ >++ if (!ets->ssl) >++ goto fail; >++ >++ /* >++ * Initialize the BIOs we use to read/write to ssl engine >++ */ >++ ets->into_ssl = BIO_new(BIO_s_mem()); >++ ets->from_ssl = BIO_new(BIO_s_mem()); >++ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); >++ >++ SSL_set_msg_callback(ets->ssl, ssl_msg_callback); >++ SSL_set_msg_callback_arg(ets->ssl, ets); >++ >++ /* >++ * Attach the session struct to the connection, so we can later >++ * retrieve it when doing certificate verification >++ */ >++ SSL_set_ex_data(ets->ssl, 0, ets); >++ >++ SSL_set_connect_state(ets->ssl); >++ >++ ets->data = NULL; >++ ets->datalen = 0; >++ ets->alert_sent = 0; >++ ets->alert_recv = 0; >++ >++ /* >++ * If we specified the server certificate file, store it in >++ * ets->peercertfile, so we can check it later in >++ * ssl_verify_callback() >++ */ >++ if (servcertfile[0]) >++ strncpy(ets->peercertfile, servcertfile, MAXWORDLEN); >++ else >++ ets->peercertfile[0] = 0; >++ >++ return 1; >++ fail: >++ ERR_print_errors_fp(stderr); >++ SSL_CTX_free(ets->ctx); >++ return 0; >++ >++} >++ >++/* >++ * Updates the CA CRL >++ */ >++void eaptls_update_crls(char *crldir, char *cacertfile, struct wordlist *uf) >++{ >++ FILE *file; >++ X509 *cert; >++ char *filename; >++ >++ if (!(file = fopen(cacertfile, "r"))) >++ return; >++ >++ filename = malloc(strlen(crldir) + 15); >++ >++ /* >++ * for each CA certificate, control if the CRL must be updated >++ */ >++ while ((cert = PEM_read_X509(file, NULL, NULL, NULL))) { >++ >++ if (eaptls_must_update(cert, crldir, filename, uf) == 1) { >++ >++ eaptls_get_crl(cert, filename); >++ add_wordlist(uf, filename); >++ } >++ >++ } >++ >++ free(filename); >++ fclose(file); >++ >++} >++ >++/* >++ * Control if the CA CRL must be updated >++ * Return in filename the file to be updated >++ */ >++int eaptls_must_update(X509 * cert, char *crldir, char *filename, >++ struct wordlist *uf) >++{ >++ X509_NAME *xn; >++ unsigned long hash; >++ int found = 0, i, hours; >++ FILE *file; >++ X509_CRL *crl; >++ time_t curr_time, mod_time; >++ struct stat file_stat; >++ char tmpname[15]; >++ char subject[256]; >++ char cn_str[256]; >++ >++ /* >++ * Get CA subject name and calculate its hash >++ */ >++ xn = X509_get_subject_name(cert); >++ hash = X509_NAME_hash(xn); >++ >++ X509_NAME_oneline(xn, subject, 256); >++ X509_NAME_get_text_by_NID(xn, NID_commonName, cn_str, 256); >++ dbglog(" -> processing CA: %s", cn_str); >++ >++ /* >++ * Search a CRL for this CA in crldir >++ */ >++ for (i = 0; i < 10; i++) { >++ sprintf(tmpname, "%08lx.r%1d", hash, i); >++ strcpy(filename, crldir); >++ strcat(filename, "/"); >++ strcat(filename, tmpname); >++ >++ if (!(file = fopen(filename, "r"))) >++ break; /* CRL not found */ >++ >++ if (!(crl = PEM_read_X509_CRL(file, NULL, NULL, NULL))) { >++ fclose(file); >++ continue; >++ } >++ fclose(file); >++ >++ /* >++ * test if it's the right CRL >++ */ >++ if (X509_NAME_cmp(xn, X509_CRL_get_issuer(crl)) == 0) { >++ found = 1; >++ X509_CRL_free(crl); >++ break; >++ } >++ X509_CRL_free(crl); >++ } >++ >++ /* >++ * If file already in list, we've already updated it >++ */ >++ if (search_wordlist(uf, filename) == 1) >++ return 0; >++ >++ /* >++ * If CRL file for this CA not found, need update >++ */ >++ if (!found) >++ return 1; >++ >++ curr_time = time(NULL); >++ stat(filename, &file_stat); >++ mod_time = file_stat.st_mtime; >++ hours = (curr_time - mod_time) / 3600; >++ >++ /* >++ * If file too old, need update >++ */ >++ if (hours >= crl_update_time) { >++ dbglog(" file %s is %d hours old, need update", >++ filename, hours); >++ return 1; >++ } >++ >++ return 0; >++} >++ >++/* >++ * Extract CDPs from certificate >++ */ >++void eaptls_get_crl(X509 * cert, char *filename) >++{ >++ STACK_OF(DIST_POINT) * distpoints = NULL; >++ DIST_POINT *dp; >++ DIST_POINT_NAME *dpn; >++ STACK_OF(GENERAL_NAME) * names; >++ GENERAL_NAME *name; >++ ASN1_IA5STRING *uri_asn; >++ char *uri; >++ int num_dp, i; >++ int num_name, j; >++ >++ distpoints = X509_get_ext_d2i(cert, >++ NID_crl_distribution_points, NULL, NULL); >++ num_dp = sk_DIST_POINT_num(distpoints); >++ >++ dbglog(" CA certificate contains %d CDP", num_dp); >++ >++ for (i = 0; i < num_dp; i++) { >++ >++ dp = sk_DIST_POINT_value(distpoints, i); >++ dpn = dp->distpoint; >++ names = dpn->name.fullname; >++ num_name = sk_GENERAL_NAME_num(names); >++ >++ for (j = 0; j < num_name; j++) { >++ >++ name = sk_GENERAL_NAME_value(names, j); >++ >++ if (name->type == GEN_URI) { >++ uri_asn = name->d.uniformResourceIdentifier; >++ uri = ASN1_STRING_data(uri_asn); >++ >++ if (eaptls_download_crl(uri, filename)) { >++ dbglog >++ (" * %s successfully loaded", >++ uri); >++ return; >++ } >++ >++ } >++ >++ } >++ } >++} >++ >++/* >++ * Download a CRL from uri into file >++ */ >++int eaptls_download_crl(char *uri, char *filename) >++{ >++ FILE *tmpfile; >++ FILE *destfile; >++ int tmpfd; >++ char tmpname[30]; >++ CURL *curl; >++ int res; >++ X509_CRL *crl; >++ >++ strcpy(tmpname, "/tmp/ppp-tmp-XXXXXX"); >++ >++ if ((tmpfd = mkstemp(tmpname)) == -1) { >++ error("error creating temp file /tmp/ppp-tmp-*"); >++ return 0; >++ } >++ >++ tmpfile = fdopen(tmpfd, "w"); >++ if (!tmpfile) { >++ error("error fdopen"); >++ close(tmpfd); >++ return 0; >++ } >++ >++ /* >++ * download in temp file using libcurl >++ */ >++ curl_global_init(CURL_GLOBAL_NOTHING); >++ curl = curl_easy_init(); >++ curl_easy_setopt(curl, CURLOPT_URL, uri); >++ curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmpfile); >++ >++ res = curl_easy_perform(curl); >++ >++ curl_easy_cleanup(curl); >++ curl_global_cleanup(); >++ >++ if (res != CURLE_OK) { >++ dbglog(" * %s download failed", uri); >++ fclose(tmpfile); >++ unlink(tmpname); >++ return 0; >++ } >++ >++ fclose(tmpfile); >++ tmpfile = fopen(tmpname, "r"); >++ if(!tmpfile) >++ return 0; >++ >++ /* >++ * load CRL from temp file >++ */ >++ crl = d2i_X509_CRL_fp(tmpfile, NULL); >++ >++ fclose(tmpfile); >++ unlink(tmpname); >++ >++ if (!crl) { >++ warn("cannot load DER CRL"); >++ return 0; >++ } >++ >++ destfile = fopen(filename, "w"); >++ if (!destfile) { >++ X509_CRL_free(crl); >++ return 0; >++ } >++ >++ /* >++ * write CRL in PEM format to destination file >++ */ >++ PEM_write_X509_CRL(destfile, crl); >++ >++ X509_CRL_free(crl); >++ fclose(destfile); >++ >++ return 1; >++} >++ >++void eaptls_free_session(struct eaptls_session *ets) >++{ >++ if (ets->ssl) >++ SSL_free(ets->ssl); >++ >++ if (ets->ctx) >++ SSL_CTX_free(ets->ctx); >++ >++ free(ets); >++} >++ >++/* >++ * Handle a received packet, reassembling fragmented messages and >++ * passing them to the ssl engine >++ */ >++int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) >++{ >++ u_char flags; >++ u_int tlslen; >++ u_char dummy[65536]; >++ >++ GETCHAR(flags, inp); >++ len--; >++ >++ if (flags & EAP_TLS_FLAGS_LI) { >++ >++ /* >++ * This is the first packet of a message >++ */ >++ >++ if (ets->data) { >++ warn("EAP TLS: unexpected first fragment"); >++ return 1; >++ } >++ >++ GETLONG(tlslen, inp); >++ len -= 4; >++ >++ if (tlslen > EAP_TLS_MAX_LEN) { >++ error("Error: tls message length > %d, truncated", >++ EAP_TLS_MAX_LEN); >++ tlslen = EAP_TLS_MAX_LEN; >++ } >++ >++ /* >++ * Allocate memory for the whole message >++ */ >++ ets->data = malloc(tlslen); >++ if (!ets->data) >++ fatal("EAP TLS: allocation error\n"); >++ >++ ets->datalen = 0; >++ ets->tlslen = tlslen; >++ >++ } else if (!ets->data) { >++ >++ /* >++ * A non fragmented message without LI flag >++ */ >++ >++ ets->data = malloc(len); >++ if (!ets->data) >++ fatal("EAP TLS: allocation error\n"); >++ >++ ets->datalen = 0; >++ ets->tlslen = len; >++ } >++ >++ if (flags & EAP_TLS_FLAGS_MF) >++ ets->frag = 1; >++ else >++ ets->frag = 0; >++ >++ if (len + ets->datalen > ets->tlslen) { >++ warn("EAP TLS: received data > TLS message length"); >++ return 1; >++ } >++ >++ BCOPY(inp, ets->data + ets->datalen, len); >++ ets->datalen += len; >++ >++ if (!ets->frag) { >++ >++ /* >++ * If we have the whole message, pass it to ssl >++ */ >++ >++ if (ets->datalen != ets->tlslen) { >++ warn("EAP TLS: received data != TLS message length"); >++ return 1; >++ } >++ >++ if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1) >++ ERR_print_errors_fp(stderr); >++ >++ SSL_read(ets->ssl, dummy, 65536); >++ >++ free(ets->data); >++ ets->data = NULL; >++ ets->datalen = 0; >++ } >++ >++ return 0; >++} >++ >++/* >++ * Return an eap-tls packet in outp. >++ * A TLS message read from the ssl engine is buffered in ets->data. >++ * At each call we control if there is buffered data and send a >++ * packet of mtu bytes. >++ */ >++int eaptls_send(struct eaptls_session *ets, u_char ** outp) >++{ >++ bool first = 0; >++ int size; >++ u_char fromtls[65536]; >++ int res; >++ u_char *start; >++ >++ start = *outp; >++ >++ if (!ets->data) { >++ >++ if(!ets->alert_sent) >++ SSL_read(ets->ssl, fromtls, 65536); >++ >++ /* >++ * Read from ssl >++ */ >++ if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1) >++ fatal("No data from BIO_read"); >++ >++ ets->datalen = res; >++ >++ ets->data = malloc(ets->datalen); >++ BCOPY(fromtls, ets->data, ets->datalen); >++ >++ ets->offset = 0; >++ first = 1; >++ >++ } >++ >++ size = ets->datalen - ets->offset; >++ >++ if (size > ets->mtu) { >++ size = ets->mtu; >++ ets->frag = 1; >++ } else >++ ets->frag = 0; >++ >++ PUTCHAR(EAPT_TLS, *outp); >++ >++ /* >++ * Set right flags and length if necessary >++ */ >++ if (ets->frag && first) { >++ PUTCHAR(EAP_TLS_FLAGS_LI | EAP_TLS_FLAGS_MF, *outp); >++ PUTLONG(ets->datalen, *outp); >++ } else if (ets->frag) { >++ PUTCHAR(EAP_TLS_FLAGS_MF, *outp); >++ } else >++ PUTCHAR(0, *outp); >++ >++ /* >++ * Copy the data in outp >++ */ >++ BCOPY(ets->data + ets->offset, *outp, size); >++ INCPTR(size, *outp); >++ >++ /* >++ * Copy the packet in retransmission buffer >++ */ >++ BCOPY(start, &ets->rtx[0], *outp - start); >++ ets->rtx_len = *outp - start; >++ >++ ets->offset += size; >++ >++ if (ets->offset >= ets->datalen) { >++ >++ /* >++ * The whole message has been sent >++ */ >++ >++ free(ets->data); >++ ets->data = NULL; >++ ets->datalen = 0; >++ ets->offset = 0; >++ } >++ >++ return 0; >++} >++ >++/* >++ * Get the sent packet from the retransmission buffer >++ */ >++void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp) >++{ >++ BCOPY(ets->rtx, *outp, ets->rtx_len); >++ INCPTR(ets->rtx_len, *outp); >++} >++ >++/* >++ * Verify a certificate. >++ * Most of the work (signatures and issuer attributes checking) >++ * is done by ssl; we check the CN in the peer certificate >++ * against the peer name. >++ */ >++int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx) >++{ >++ char subject[256]; >++ char cn_str[256]; >++ X509 *peer_cert; >++ int err, depth; >++ int ok = preverify_ok; >++ SSL *ssl; >++ struct eaptls_session *ets; >++ >++ peer_cert = X509_STORE_CTX_get_current_cert(ctx); >++ err = X509_STORE_CTX_get_error(ctx); >++ depth = X509_STORE_CTX_get_error_depth(ctx); >++ >++ dbglog("certificate verify depth: %d", depth); >++ >++ if (!ok) { >++ X509_NAME_oneline(X509_get_subject_name(peer_cert), >++ subject, 256); >++ >++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), >++ NID_commonName, cn_str, 256); >++ >++ dbglog("Certificate verification error:\n depth: %d CN: %s" >++ "\n err: %d (%s)\n", depth, cn_str, err, >++ X509_verify_cert_error_string(err)); >++ >++ return 0; >++ } >++ >++ ssl = X509_STORE_CTX_get_ex_data(ctx, >++ SSL_get_ex_data_X509_STORE_CTX_idx()); >++ >++ ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0); >++ >++ if (ets == NULL) { >++ error("Error: SSL_get_ex_data returned NULL"); >++ return 0; >++ } >++ >++ ERR_print_errors_fp(stderr); >++ >++ if (!depth) { /* This is the peer certificate */ >++ >++ X509_NAME_oneline(X509_get_subject_name(peer_cert), >++ subject, 256); >++ >++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), >++ NID_commonName, cn_str, 256); >++ >++ /* >++ * If acting as client and the name of the server wasn't specified >++ * explicitely, we can't verify the server authenticity >++ */ >++ if (!ets->peer[0]) { >++ warn("Peer name not specified: no check"); >++ return 1; >++ } >++ >++ /* >++ * Check the CN >++ */ >++ if (strcmp(cn_str, ets->peer)) { >++ error >++ ("Certificate verification error: CN (%s) != peer_name (%s)", >++ cn_str, ets->peer); >++ return 0; >++ } >++ >++ warn("Certificate CN: %s , peer name %s", cn_str, ets->peer); >++ >++ /* >++ * If a peer certificate file was specified, here we check it >++ */ >++ if (ets->peercertfile[0]) { >++ if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert) >++ != 0) { >++ error >++ ("Peer certificate doesn't match stored certificate"); >++ return 0; >++ } >++ } >++ } >++ >++ return 1; >++} >++ >++/* >++ * Compare a certificate with the one stored in a file >++ */ >++int ssl_cmp_certs(char *filename, X509 * a) >++{ >++ X509 *b; >++ int ret; >++ >++ if (!(b = get_X509_from_file(filename))) >++ return 1; >++ >++ ret = X509_cmp(a, b); >++ X509_free(b); >++ >++ return ret; >++ >++} >++ >++X509 *get_X509_from_file(char *filename) >++{ >++ FILE *fp; >++ X509 *ret; >++ >++ if (!(fp = fopen(filename, "r"))) >++ return NULL; >++ >++ ret = PEM_read_X509(fp, NULL, NULL, NULL); >++ >++ fclose(fp); >++ >++ return ret; >++} >++ >++/* >++ * Every sent & received message this callback function is invoked, >++ * so we know when alert messages have arrived or are sent and >++ * we can print debug information about TLS handshake. >++ */ >++void >++ssl_msg_callback(int write_p, int version, int content_type, >++ const void *buf, size_t len, SSL * ssl, void *arg) >++{ >++ char string[256]; >++ struct eaptls_session *ets = (struct eaptls_session *)arg; >++ unsigned char code; >++ >++ if(write_p) >++ strcpy(string, " -> "); >++ else >++ strcpy(string, " <- "); >++ >++ >++ switch(content_type) { >++ >++ case SSL3_RT_ALERT: >++ strcat(string, "Alert: "); >++ code = ((const unsigned char *)buf)[1]; >++ >++ if (write_p) { >++ ets->alert_sent = 1; >++ ets->alert_sent_desc = code; >++ } else { >++ ets->alert_recv = 1; >++ ets->alert_recv_desc = code; >++ } >++ >++ strcat(string, SSL_alert_desc_string_long(code)); >++ break; >++ >++ case SSL3_RT_CHANGE_CIPHER_SPEC: >++ strcat(string, "ChangeCipherSpec"); >++ break; >++ >++ case SSL3_RT_HANDSHAKE: >++ >++ strcat(string, "Handshake: "); >++ code = ((const unsigned char *)buf)[0]; >++ >++ switch(code) { >++ case SSL3_MT_HELLO_REQUEST: >++ strcat(string,"Hello Request"); >++ break; >++ case SSL3_MT_CLIENT_HELLO: >++ strcat(string,"Client Hello"); >++ break; >++ case SSL3_MT_SERVER_HELLO: >++ strcat(string,"Server Hello"); >++ break; >++ case SSL3_MT_CERTIFICATE: >++ strcat(string,"Certificate"); >++ break; >++ case SSL3_MT_SERVER_KEY_EXCHANGE: >++ strcat(string,"Server Key Exchange"); >++ break; >++ case SSL3_MT_CERTIFICATE_REQUEST: >++ strcat(string,"Certificate Request"); >++ break; >++ case SSL3_MT_SERVER_DONE: >++ strcat(string,"Server Hello Done"); >++ break; >++ case SSL3_MT_CERTIFICATE_VERIFY: >++ strcat(string,"Certificate Verify"); >++ break; >++ case SSL3_MT_CLIENT_KEY_EXCHANGE: >++ strcat(string,"Client Key Exchange"); >++ break; >++ case SSL3_MT_FINISHED: >++ strcat(string,"Finished"); >++ break; >++ } >++ break; >++ } >++ >++ /* Alert messages must always be displayed */ >++ if(content_type == SSL3_RT_ALERT) >++ error("%s", string); >++ else >++ dbglog("%s", string); >++} >++ >++/* >++ * Extract all CA files from conf file 'filename' and update crl >++ */ >++void eaptls_do_update(char *filename, struct wordlist *updatedfiles) >++{ >++ int newline; >++ FILE *f; >++ char word[MAXWORDLEN]; >++ >++ if (!(f = fopen(filename, "r"))) { >++ fprintf(stderr, "can't open %s", filename); >++ die(1); >++ } >++ >++ if (!getword(f, word, &newline, filename)) >++ return; /* file is empty??? */ >++ >++ newline = 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 */ >++ >++ /* >++ * server >++ */ >++ if (!getword(f, word, &newline, filename)) >++ break; >++ if (newline) >++ continue; >++ >++ /* >++ * client cert >++ */ >++ if (!getword(f, word, &newline, filename)) >++ break; >++ if (newline) >++ continue; >++ >++ /* >++ * server cert >++ */ >++ if (!getword(f, word, &newline, filename)) >++ break; >++ if (newline) >++ continue; >++ >++ /* >++ * ca cert >++ */ >++ if (!getword(f, word, &newline, filename)) >++ break; >++ if (newline) >++ continue; >++ >++ printf("Updating CRLs for CA file %s\n", word); >++ >++ eaptls_update_crls(crl_dir, word, updatedfiles); >++ } >++ >++ fclose(f); >++} >++ >++void eaptls_only_update_crl(int server, int client) >++{ >++ /* >++ * mantain a list of updated crl files, so if a CA appears more >++ * times, it is updated once >++ */ >++ struct wordlist updatedfiles; >++ >++ updatedfiles.next = NULL; >++ updatedfiles.word = NULL; >++ >++ if (server) >++ eaptls_do_update(_PATH_EAPTLSSERVFILE, &updatedfiles); >++ >++ if (client) >++ eaptls_do_update(_PATH_EAPTLSCLIFILE, &updatedfiles); >++ >++ destroy_wordlist(&updatedfiles); >++} >++ >++static int search_wordlist(struct wordlist *wl, char *word) >++{ >++ struct wordlist *tmp = wl->next; >++ >++ while (tmp) { >++ if (strcmp(tmp->word, word) == 0) >++ return 1; >++ tmp = tmp->next; >++ } >++ return 0; >++} >++ >++static void add_wordlist(struct wordlist *wl, char *word) >++{ >++ struct wordlist *tmp = wl; >++ >++ while (tmp->next) >++ tmp = tmp->next; >++ >++ tmp->next = malloc(sizeof(struct wordlist)); >++ tmp->next->word = strdup(word); >++ tmp->next->next = NULL; >++ >++} >++ >++static void destroy_wordlist(struct wordlist *wl) >++{ >++ struct wordlist *tmp = wl->next; >++ struct wordlist *next; >++ >++ while (tmp) { >++ next = tmp->next; >++ >++ if (tmp->word) >++ free(tmp->word); >++ >++ free(tmp); >++ tmp = next; >++ } >++ >++} >+diff -Naur ppp-2.4.3/pppd/eap-tls.h ppp-2.4.3-eaptls-0.7/pppd/eap-tls.h >+--- ppp-2.4.3/pppd/eap-tls.h 1970-01-01 01:00:00.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/eap-tls.h 2005-03-21 14:58:51.268855248 +0100 >+@@ -0,0 +1,99 @@ >++/* >++ * 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> >++ >++#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 */ >++ >++#define CRL_UPDATE_TIME 72 /* update time for crl: 72 hours */ >++ >++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 */ >++}; >++ >++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); >++ >++int eaptls_test_certs_server(char *servcertfile, char *cacertfile, char *pkfile, >++ char *clicertfile); >++int eaptls_test_certs_client(char *clicertfile, char *cacertfile, char *pkfile, >++ char *servcertfile); >++ >++X509 *get_X509_from_file(char *filename); >++int ssl_cmp_certs(char *filename, X509 * a); >++ >++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); >++ >++void eaptls_update_crls(char *crldir, char *cacertfile, struct wordlist *wl); >++int eaptls_must_update(X509 * cert, char *crldir, char *filename, >++ struct wordlist *wl); >++void eaptls_get_crl(X509 * cert, char *filename); >++int eaptls_download_crl(char *uri, char *filename); >++ >++#endif >+diff -Naur ppp-2.4.3/pppd/main.c ppp-2.4.3-eaptls-0.7/pppd/main.c >+--- ppp-2.4.3/pppd/main.c 2004-11-13 13:05:48.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/main.c 2005-03-09 11:48:26.000000000 +0100 >+@@ -258,6 +258,7 @@ >+ extern char *ttyname __P((int)); >+ extern char *getlogin __P((void)); >+ int main __P((int, char *[])); >++void eaptls_only_update_crl(int serv, int cli); >+ >+ #ifdef ultrix >+ #undef O_NONBLOCK >+@@ -417,6 +418,17 @@ >+ if (dryrun) >+ die(0); >+ >++ if(only_update_crl_server || only_update_crl_client) { >++ if(!crl_dir){ >++ fprintf(stderr, "You must specify a crl dir\n"); >++ die(1); >++ } >++ >++ eaptls_only_update_crl(only_update_crl_server, only_update_crl_client); >++ >++ die(0); >++ } >++ >+ /* Make sure fds 0, 1, 2 are open to somewhere. */ >+ fd_devnull = open(_PATH_DEVNULL, O_RDWR); >+ if (fd_devnull < 0) >+diff -Naur ppp-2.4.3/pppd/Makefile.linux ppp-2.4.3-eaptls-0.7/pppd/Makefile.linux >+--- ppp-2.4.3/pppd/Makefile.linux 2004-11-13 13:02:22.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/Makefile.linux 2005-03-18 10:47:31.000000000 +0100 >+@@ -13,16 +13,16 @@ >+ >+ PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap-new.c md5.c ccp.c \ >+ ecp.c ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \ >+- demand.c utils.c tty.c eap.c chap-md5.c >++ demand.c utils.c tty.c eap.c chap-md5.c eap-tls.c >+ >+ HEADERS = ccp.h chap-new.h ecp.h fsm.h ipcp.h \ >+ ipxcp.h lcp.h magic.h md5.h patchlevel.h pathnames.h pppd.h \ >+- upap.h eap.h >++ upap.h eap.h eap-tls.h >+ >+ MANPAGES = pppd.8 >+ PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o md5.o ccp.o \ >+ ecp.o auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o \ >+- eap.o chap-md5.o >++ eap.o chap-md5.o eap-tls.o >+ >+ # >+ # include dependencies if present >+@@ -32,8 +32,8 @@ >+ >+ # CC = gcc >+ # >+-COPTS = -O2 -pipe -Wall -g >+-LIBS = >++COPTS = -O2 -pipe -Wall -g -I/usr/kerberos/include >++LIBS = -lssl -lcurl >+ >+ # Uncomment the next 2 lines to include support for Microsoft's >+ # MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. >+diff -Naur ppp-2.4.3/pppd/options.c ppp-2.4.3-eaptls-0.7/pppd/options.c >+--- ppp-2.4.3/pppd/options.c 2004-11-09 23:33:35.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/options.c 2005-03-09 10:25:12.000000000 +0100 >+@@ -114,6 +114,8 @@ >+ bool dryrun; /* print out option values and exit */ >+ char *domain; /* domain name set by domain option */ >+ int child_wait = 5; /* # seconds to wait for children at exit */ >++bool only_update_crl_server = 0; /* update server crl and exit */ >++bool only_update_crl_client = 0; /* update client crl and exit */ >+ >+ #ifdef MAXOCTETS >+ unsigned int maxoctets = 0; /* default - no limit */ >+@@ -315,6 +317,10 @@ >+ { "mo-timeout", o_int, &maxoctets_timeout, >+ "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, >+ #endif >++ { "only-update-crl-server", o_bool, &only_update_crl_server, >++ "Update server CA CRLs and exit", 1 }, >++ { "only-update-crl-client", o_bool, &only_update_crl_client, >++ "Update client CA CRLs and exit", 1 }, >+ >+ { NULL } >+ }; >+diff -Naur ppp-2.4.3/pppd/pathnames.h ppp-2.4.3-eaptls-0.7/pppd/pathnames.h >+--- ppp-2.4.3/pppd/pathnames.h 2004-11-13 13:02:22.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/pathnames.h 2005-02-28 17:38:17.000000000 +0100 >+@@ -21,6 +21,8 @@ >+ #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" >++#define _PATH_EAPTLSCLIFILE _ROOT_PATH "/etc/ppp/eaptls-client" >++#define _PATH_EAPTLSSERVFILE _ROOT_PATH "/etc/ppp/eaptls-server" >+ #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" >+diff -Naur ppp-2.4.3/pppd/pppd.h ppp-2.4.3-eaptls-0.7/pppd/pppd.h >+--- ppp-2.4.3/pppd/pppd.h 2004-11-13 13:02:22.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/pppd/pppd.h 2005-03-09 10:26:18.000000000 +0100 >+@@ -318,6 +318,9 @@ >+ 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 */ >++extern bool only_update_crl_server; /* update server crls and exit */ >++extern bool only_update_crl_client; /* update client crls and exit */ >++extern char *crl_dir; >+ >+ #ifdef MAXOCTETS >+ extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ >+diff -Naur ppp-2.4.3/README.eap-tls ppp-2.4.3-eaptls-0.7/README.eap-tls >+--- ppp-2.4.3/README.eap-tls 1970-01-01 01:00:00.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/README.eap-tls 2005-03-21 15:14:01.872422464 +0100 >+@@ -0,0 +1,147 @@ >++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 2246) provides for mutual >++ authentication, integrity-protected ciphersuite negotiation and >++ key exchange between two endpoints. >++ >++ EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets, >++ allowing TLS mutual authentication to be used as a generic EAP >++ mechanism. >++ >++ 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. >++ >++ You must also have libcurl installed (used to fetch CRLs). >++ The version required is 7.9.8 or newer (because that's the one I used, >++ but an earlier version may work). >++ >++ Configure, compile, and install as usual. >++ >++3. Configuration >++ >++ On the client side 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. >++ >++ >++4. Options >++ >++ These pppd options are available: >++ >++ crl-dir <dir> >++ Use CRL files from 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. >++ >++ auto-update-crl >++ On a new TLS handshake, try to fetch updated CRLs for the >++ trusted CAs. This is done only if the crl-dir option was used. >++ For each trusted CA, the appropriate CRL is checked and if >++ it doesn't exist or is too old, the update take place. >++ >++ crl-update-time >++ Time (in hours) after which a CRL must be updated if the option >++ auto-update-crl or only-update-crl-* were specified. Use 0 as >++ value if you want to force update. The default value is 72 >++ >++ need-peer-eap >++ If the peer doesn't ask us to authenticate or doesn't use eap >++ to authenticate us, disconnect. >++ >++ only-update-crl-server >++ Parse EAP-TLS server configuration file (/etc/ppp/eaptls-server) >++ and find all files containing trusted CAs; then update their CRL >++ and exit. >++ The 'crl-dir' option must be used to specify crl directory. >++ >++ only-update-crl-client >++ Similar to only-update-crl-server, but uses client configuration >++ file. >++ >++ >++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. Updating CRLs with cron >++ >++ With the 'auto-update-crl' option you can do crl updating at connect time. >++ In some situations this approach can't be used, because the download can >++ take long time and the peer will have to wait too much, possibly going in >++ timeout. >++ In such cases, you can update crls periodically (with cron) using pppd with >++ the 'only-update-crl-client' or 'only-update-crl-server' options, as >++ explained above. >++ Example: >++ >++ pppd crl-dir /root/crldir only-update-crl-server crl-update-time 0 >++ >++ To show debug information add '/dev/null debug' to the command line. >++ >++7. Notes >++ >++ This is experimental code. >++ Send suggestions and comments to Beniamino Galvani <bengal@interfree.it> >+diff -Naur ppp-2.4.3/solaris/Makefile.top ppp-2.4.3-eaptls-0.7/solaris/Makefile.top >+--- ppp-2.4.3/solaris/Makefile.top 2004-11-01 10:31:07.000000000 +0100 >++++ ppp-2.4.3-eaptls-0.7/solaris/Makefile.top 2005-03-07 11:42:57.000000000 +0100 >+@@ -22,7 +22,7 @@ >+ cd pppdump; $(MAKE) install >+ >+ install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ >+- $(ETCDIR)/chap-secrets >++ $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client >+ >+ install-modules: >+ cd solaris; $(MAKE) install >+@@ -34,6 +34,11 @@ >+ $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/pap-secrets >+ $(ETCDIR)/chap-secrets: >+ $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/chap-secrets >++$(ETCDIR)/eaptls-server: >++ $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/eaptls-server >++$(ETCDIR)/eaptls-client: >++ $(INSTALL) -f $(ETCDIR) -m 600 etc.ppp/eaptls-client >++ >+ >+ $(BINDIR): >+ mkdir -m 755 -p $@ >diff -Naur /usr/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-mppe-0.7.patch /usr/local/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-mppe-0.7.patch >--- /usr/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-mppe-0.7.patch 1970-01-01 01:00:00.000000000 +0100 >+++ /usr/local/portage/net-dialup/ppp/files/ppp-2.4.3-eaptls-mppe-0.7.patch 2005-10-18 15:59:46.000000000 +0200 >@@ -0,0 +1,217 @@ >+--- ppp-2.4.3/pppd/ccp.c 2004-11-13 03:28:15.000000000 +0100 >++++ ppp-2.4.3-eap-tls-mppe/pppd/ccp.c 2005-10-17 14:45:28.000000000 +0200 >+@@ -540,6 +540,7 @@ >+ if (go->mppe) { >+ ccp_options *ao = &ccp_allowoptions[f->unit]; >+ int auth_mschap_bits = auth_done[f->unit]; >++ int auth_eap_bits = auth_done[f->unit]; >+ int numbits; >+ >+ /* >+@@ -567,8 +568,18 @@ >+ lcp_close(f->unit, "MPPE required but not available"); >+ return; >+ } >+- if (!numbits) { >+- error("MPPE required, but MS-CHAP[v2] auth not performed."); >++ >++ /* >++ * 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."); >+ lcp_close(f->unit, "MPPE required but not available"); >+ return; >+ } >+--- ppp-2.4.3/pppd/eap-tls.c 2005-10-17 14:57:22.000000000 +0200 >++++ ppp-2.4.3-eap-tls-mppe/pppd/eap-tls.c 2005-10-17 14:41:40.000000000 +0200 >+@@ -35,7 +35,7 @@ >+ #include <sys/stat.h> >+ #include <fcntl.h> >+ >+-#include <openssl/ssl.h> >++#include <openssl/hmac.h> >+ #include <openssl/err.h> >+ #include <openssl/x509v3.h> >+ #include <curl/curl.h> >+@@ -53,6 +53,120 @@ >+ static void add_wordlist(struct wordlist *wl, char *word); >+ static void destroy_wordlist(struct wordlist *wl); >+ >++#ifdef MPPE >++ >++/* >++ * TLS PRF from RFC 2246 >++ */ >++static void P_hash(const EVP_MD *evp_md, >++ const unsigned char *secret, unsigned int secret_len, >++ const unsigned char *seed, unsigned int seed_len, >++ unsigned char *out, unsigned int out_len) >++{ >++ HMAC_CTX ctx_a, ctx_out; >++ unsigned char a[HMAC_MAX_MD_CBLOCK]; >++ unsigned int size; >++ >++ HMAC_CTX_init(&ctx_a); >++ HMAC_CTX_init(&ctx_out); >++ HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL); >++ HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL); >++ >++ size = HMAC_size(&ctx_out); >++ >++ /* Calculate A(1) */ >++ HMAC_Update(&ctx_a, seed, seed_len); >++ HMAC_Final(&ctx_a, a, NULL); >++ >++ while (1) { >++ /* Calculate next part of output */ >++ HMAC_Update(&ctx_out, a, size); >++ HMAC_Update(&ctx_out, seed, seed_len); >++ >++ /* Check if last part */ >++ if (out_len < size) { >++ HMAC_Final(&ctx_out, a, NULL); >++ memcpy(out, a, out_len); >++ break; >++ } >++ >++ /* Place digest in output buffer */ >++ HMAC_Final(&ctx_out, out, NULL); >++ HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL); >++ out += size; >++ out_len -= size; >++ >++ /* Calculate next A(i) */ >++ HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL); >++ HMAC_Update(&ctx_a, a, size); >++ HMAC_Final(&ctx_a, a, NULL); >++ } >++ >++ HMAC_CTX_cleanup(&ctx_a); >++ HMAC_CTX_cleanup(&ctx_out); >++ memset(a, 0, sizeof(a)); >++} >++ >++static void PRF(const unsigned char *secret, unsigned int secret_len, >++ const unsigned char *seed, unsigned int seed_len, >++ unsigned char *out, unsigned char *buf, unsigned int out_len) >++{ >++ unsigned int i; >++ unsigned int len = (secret_len + 1) / 2; >++ const unsigned char *s1 = secret; >++ const unsigned char *s2 = secret + (secret_len - len); >++ >++ P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len); >++ P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len); >++ >++ for (i=0; i < out_len; i++) { >++ out[i] ^= buf[i]; >++ } >++} >++ >++#define EAPTLS_MPPE_KEY_LEN 32 >++ >++/* >++ * Generate keys according to RFC 2716 and add to reply >++ */ >++void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label) >++{ >++ unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN]; >++ unsigned char seed[64 + 2*SSL3_RANDOM_SIZE]; >++ unsigned char *p = seed; >++ SSL *s = ets->ssl; >++ size_t prf_size; >++ >++ prf_size = strlen(prf_label); >++ >++ memcpy(p, prf_label, prf_size); >++ p += prf_size; >++ >++ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); >++ p += SSL3_RANDOM_SIZE; >++ prf_size += SSL3_RANDOM_SIZE; >++ >++ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); >++ prf_size += SSL3_RANDOM_SIZE; >++ >++ PRF(s->session->master_key, s->session->master_key_length, >++ seed, prf_size, out, buf, sizeof(out)); >++ >++ /* >++ * We now have the master send and receive keys. >++ * From these, generate the session send and receive keys. >++ * (see RFC3079 / draft-ietf-pppext-mppe-keys-03.txt for details) >++ */ >++ p = out; >++ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); >++ p += EAPTLS_MPPE_KEY_LEN; >++ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); >++ >++ mppe_keys_set = 1; >++} >++ >++#endif >++ >+ /* >+ * Tests if certificates, key and crl for server use can be loaded. >+ */ >+@@ -190,8 +304,8 @@ >+ */ >+ if (servcertfile[0]) { >+ if (!(tmp = get_X509_from_file(servcertfile))) { >+- warn("Error loading client certificate from file %s", >+- clicertfile); >++ warn("Error loading server certificate from file %s", >++ servcertfile); >+ goto fail; >+ } >+ X509_free(tmp); >+--- ppp-2.4.3/pppd/eap-tls.h 2005-10-17 14:57:22.000000000 +0200 >++++ ppp-2.4.3-eap-tls-mppe/pppd/eap-tls.h 2005-10-18 09:24:28.342960526 +0200 >+@@ -96,4 +96,14 @@ >+ void eaptls_get_crl(X509 * cert, char *filename); >+ int eaptls_download_crl(char *uri, char *filename); >+ >++#ifdef MPPE >++#include <net/ppp-comp.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); >++ >++#endif >++ >+ #endif >+--- ppp-2.4.3/pppd/eap.c 2005-10-17 14:57:22.000000000 +0200 >++++ ppp-2.4.3-eap-tls-mppe/pppd/eap.c 2005-10-18 09:25:17.175205819 +0200 >+@@ -2116,15 +2116,22 @@ >+ >+ GETCHAR(flags, inp); >+ >+- if(len == 1 && !flags) /* Ack = ok */ >++ if(len == 1 && !flags) { /* Ack = ok */ >++#ifdef MPPE >++ eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption" ); >++#endif >+ eap_send_success(esp); >++ } >+ else { /* failure */ >+ eaptls_receive(esp->es_server.ea_session, inp, len); >+ warn("Server authentication failed"); >+ eap_send_failure(esp); >+ } >+ >++#ifndef MPPE >++ /* how can we determine if MPPE is required? */ >+ eaptls_free_session(esp->es_server.ea_session); >++#endif >+ >+ break; >+ >diff -Naur /usr/portage/net-dialup/ppp/Manifest /usr/local/portage/net-dialup/ppp/Manifest >--- /usr/portage/net-dialup/ppp/Manifest 2005-09-24 11:05:49.000000000 +0200 >+++ /usr/local/portage/net-dialup/ppp/Manifest 2005-10-20 21:17:13.000000000 +0200 >@@ -1,24 +1,26 @@ >+MD5 06756b9843bf54824792153605bcac28 ppp-2.4.2-r12.ebuild 6935 >+MD5 6205d840f3f2fda06c502408de02a298 ppp-2.4.3-r8.ebuild 9523 > MD5 1679bdc947d662d842ffba712c44bc94 ChangeLog 22834 >+MD5 ff2e9f24c17c1fa83d260539af3149cb ppp-2.4.2-r15.ebuild 7411 > MD5 e6fdfdc4317d7fe324c50bd0477ca3f8 metadata.xml 295 > MD5 fc56767c28bef6332decb0a5c48cad83 ppp-2.4.2-r10.ebuild 6209 >-MD5 06756b9843bf54824792153605bcac28 ppp-2.4.2-r12.ebuild 6935 >-MD5 ff2e9f24c17c1fa83d260539af3149cb ppp-2.4.2-r15.ebuild 7411 >-MD5 2b7d702806660278ad8fc0f38b3cb842 ppp-2.4.3-r8.ebuild 8082 >-MD5 1fd88dda7f4996799c69a9501d42cc23 files/README.mpls 530 >+MD5 4e62cdeb360ca0a22becbd2deb6f2dac files/pon 957 >+MD5 86cdaf133f7a79fb464f02d83afc7734 files/plog 146 >+MD5 05b7394b35a2342033b52134568bf6b8 files/poff 2723 >+MD5 2890b47660f967a07ac5b211850e46c5 files/options-pptp 238 > MD5 140bc2a08334d3546f43259934da603e files/chat-default 347 >+MD5 341c2661a11f00fdd1043a4d4e82977e files/ip-up 1083 >+MD5 44cc662ba9aa61dd9add3ddd4c5ded57 files/pon.1 3607 > MD5 c9117abf5fed623d5290779446e9855e files/confd.ppp0 2775 > MD5 d90deeaef8dbdfcd18d1567681d03559 files/digest-ppp-2.4.2-r10 271 > MD5 d90deeaef8dbdfcd18d1567681d03559 files/digest-ppp-2.4.2-r12 271 >-MD5 5a554e2a04b9e11bb5bea839213bf97c files/ip-down 931 >-MD5 341c2661a11f00fdd1043a4d4e82977e files/ip-up 1083 >-MD5 5d83af7b897082a0b1ecd70a2cc2a0c7 files/modules.ppp 268 >-MD5 2f3f8eb46b9d97a435a8694683f84651 files/net.ppp0 4408 >-MD5 fa2a5b8df496922fa2fb592115953b6b files/options-pppoe 53 >-MD5 2890b47660f967a07ac5b211850e46c5 files/options-pptp 238 >-MD5 86cdaf133f7a79fb464f02d83afc7734 files/plog 146 >-MD5 05b7394b35a2342033b52134568bf6b8 files/poff 2723 >-MD5 4e62cdeb360ca0a22becbd2deb6f2dac files/pon 957 >-MD5 44cc662ba9aa61dd9add3ddd4c5ded57 files/pon.1 3607 >-MD5 f0ad3e0c62aec1771536caf00e28b9c6 files/pppoe.html 7605 > MD5 23a7e77ad13ddd12f281fe134508e52f files/digest-ppp-2.4.2-r15 271 >+MD5 fa2a5b8df496922fa2fb592115953b6b files/options-pppoe 53 >+MD5 2f3f8eb46b9d97a435a8694683f84651 files/net.ppp0 4408 >+MD5 af39f6df6bcd564f9ff725f3ab457ae4 files/ppp-2.4.3-eaptls-mppe-0.7.patch 6308 > MD5 b7ba474b501edf4a1179142b306bdcd0 files/digest-ppp-2.4.3-r8 195 >+MD5 1fd88dda7f4996799c69a9501d42cc23 files/README.mpls 530 >+MD5 5d83af7b897082a0b1ecd70a2cc2a0c7 files/modules.ppp 268 >+MD5 0dcb7dd0a688a256ca520727b5fc36d4 files/ppp-2.4.3-eaptls-0.7.patch 72420 >+MD5 5a554e2a04b9e11bb5bea839213bf97c files/ip-down 931 >+MD5 f0ad3e0c62aec1771536caf00e28b9c6 files/pppoe.html 7605 >diff -Naur /usr/portage/net-dialup/ppp/ppp-2.4.3-r8.ebuild /usr/local/portage/net-dialup/ppp/ppp-2.4.3-r8.ebuild >--- /usr/portage/net-dialup/ppp/ppp-2.4.3-r8.ebuild 2005-09-23 01:05:52.000000000 +0200 >+++ /usr/local/portage/net-dialup/ppp/ppp-2.4.3-r8.ebuild 2005-10-20 21:05:11.000000000 +0200 >@@ -13,13 +13,15 @@ > LICENSE="BSD GPL-2" > SLOT="0" > KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sparc ~x86" >-IUSE="activefilter atm dhcp gtk ipv6 mppe-mppc pam radius" >+IUSE="activefilter atm dhcp eap-tls gtk ipv6 mppe-mppc pam radius" > > RDEPEND="virtual/libc > activefilter? ( >=virtual/libpcap-0.9.3 ) > atm? ( net-dialup/linux-atm ) > pam? ( sys-libs/pam ) >- gtk? ( =x11-libs/gtk+-1* )" >+ gtk? ( =x11-libs/gtk+-1* ) >+ eap-tls? ( net-misc/curl ) >+ eap-tls? ( dev-libs/openssl )" > DEPEND="${RDEPEND} > >=sys-apps/sed-4" > >@@ -68,6 +70,28 @@ > sed -i "s/#HAVE_INET6/HAVE_INET6/" pppd/Makefile.linux > } > >+ use eap-tls && { >+ einfo "Adding support of authenticating with certificates..." >+ cp ${FILESDIR}/ppp-2.4.3-eaptls-0.7.patch ${WORKDIR}/patch/ >+ sed -i "s/ eap\.c chap-md5\.c$/ eap.c chap-md5.c mplscp.c/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/ eap\.c chap-md5\.c eap-tls\.c$/ eap.c chap-md5.c mplscp.c eap-tls.c/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/ eap\.o chap-md5\.o$/ eap.o chap-md5.o mplscp.o/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/ eap\.o chap-md5\.o eap-tls\.o$/ eap.o chap-md5.o mplscp.o eap-tls.o/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/^-.*upap\.h eap\.h/- upap.h eap.h mplscp.h/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/^\+.*upap\.h eap\.h eap-tls\.h$/+ upap.h eap.h mplscp.h eap-tls.h/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s/^-COPTS = -O2 -pipe -Wall -g$/-COPTS+= -Wall/" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ sed -i "s|^\+COPTS = -O2 -pipe -Wall -g -I/usr/kerberos/include|+COPTS+= -Wall -I/usr/kerberos/include|" ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ epatch ${WORKDIR}/patch/ppp-2.4.3-eaptls-0.7.patch >+ } >+ >+ use eap-tls && use mppe-mppc && { >+ einfo "Allowing MPPE to work with autentification with certificates..." >+ opt="$EPATCH_OPTS" >+ EPATCH_OPTS="-l" >+ epatch ${FILESDIR}/ppp-2.4.3-eaptls-mppe-0.7.patch >+ EPATCH_OPTS="$opt" >+ } >+ > einfo "Enabling CBCP" > sed -i "s/^#CBCP=y/CBCP=y/" ${S}/pppd/Makefile.linux >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 109935
: 71081