diffstat of debian/ for ppp_2.4.5-5.1 ppp_2.4.5-5.1ubuntu2.3 debian/patches/CVE-2014-3158.patch | 55 debian/patches/CVE-2015-3310.patch | 23 debian/patches/CVE-2018-11574.patch | 174 + debian/patches/load_ppp_generic_if_needed | 66 debian/patches/ppp-2.4.5-eaptls-mppe-0.994.patch | 2943 +++++++++++++++++++++++ ppp-2.4.5/debian/changelog | 373 ++ ppp-2.4.5/debian/control | 5 ppp-2.4.5/debian/patches/series | 6 ppp-2.4.5/debian/patches/update_if_pppol2tp | 38 ppp-2.4.5/debian/ppp.postinst | 5 ppp-2.4.5/debian/ppp.pppd-dns | 4 ppp-2.4.5/debian/rules | 4 12 files changed, 3684 insertions(+), 12 deletions(-) diff -u ppp-2.4.5/debian/control ppp-2.4.5/debian/control --- ppp-2.4.5/debian/control +++ ppp-2.4.5/debian/control @@ -1,8 +1,9 @@ Source: ppp Section: admin Priority: optional -Maintainer: Marco d'Itri -Build-Depends: debhelper (>= 5), quilt (>= 0.40), libpcap0.8-dev, libpam0g-dev, zlib1g-dev +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Marco d'Itri +Build-Depends: debhelper (>= 5), quilt (>= 0.40), libpcap0.8-dev, libpam0g-dev, libssl-dev, zlib1g-dev Standards-Version: 3.9.1 Package: ppp diff -u ppp-2.4.5/debian/ppp.postinst ppp-2.4.5/debian/ppp.postinst --- ppp-2.4.5/debian/ppp.postinst +++ ppp-2.4.5/debian/ppp.postinst @@ -38,6 +38,11 @@ } +# Migrate init script +if dpkg --compare-versions "$2" lt "2.4.5~git20081126t100229-0ubuntu2"; then + update-rc.d -f pppd-dns remove >/dev/null +fi + case "$1" in configure) everything diff -u ppp-2.4.5/debian/ppp.pppd-dns ppp-2.4.5/debian/ppp.pppd-dns --- ppp-2.4.5/debian/ppp.pppd-dns +++ ppp-2.4.5/debian/ppp.pppd-dns @@ -1,9 +1,9 @@ #!/bin/sh -e ### BEGIN INIT INFO # Provides: pppd-dns -# Required-Start: $local_fs +# Required-Start: $local_fs gdm # Required-Stop: -# Default-Start: S +# Default-Start: 1 2 3 4 5 # Default-Stop: # Short-Description: Restore resolv.conf if the system crashed. ### END INIT INFO diff -u ppp-2.4.5/debian/rules ppp-2.4.5/debian/rules --- ppp-2.4.5/debian/rules +++ ppp-2.4.5/debian/rules @@ -81,6 +81,8 @@ rm -rf $D/etc/ppp/*-secrets mv $D/usr/include/ $D-dev/usr/ + install -m 750 -o root -g dip extra/pppoe_on_boot $D/etc/ppp/ + install -m755 extra/pon extra/plog extra/poff $D/usr/bin/ cp extra/pon.completion $D/etc/bash_completion.d/pon @@ -109,7 +111,7 @@ dh_link dh_installlogrotate dh_installinit --init-script=pppd-dns --no-start \ - --update-rcd-params='start 38 S .' + --update-rcd-params='start 70 1 2 3 4 5 .' dh_installpam ifdef BUILD_UDEB diff -u ppp-2.4.5/debian/changelog ppp-2.4.5/debian/changelog --- ppp-2.4.5/debian/changelog +++ ppp-2.4.5/debian/changelog @@ -1,3 +1,55 @@ +ppp (2.4.5-5.1ubuntu2.3) trusty-security; urgency=medium + + * SECURITY UPDATE: buffer overflow in pppd EAP-TLS implementation + - debian/patches/CVE-2018-11574.patch: check lengths in pppd/eap.c, + pppd/eap-tls.c. + - CVE-2018-11574 + + -- Marc Deslauriers Tue, 12 Jun 2018 13:34:15 -0400 + +ppp (2.4.5-5.1ubuntu2.2) trusty-security; urgency=medium + + * SECURITY UPDATE: denial of service via big process id + - debian/patches/CVE-2015-3310.patch: limit size of process id in + pppd/plugins/radius/util.c. + - CVE-2015-3310 + + -- Marc Deslauriers Tue, 21 Apr 2015 13:02:32 -0400 + +ppp (2.4.5-5.1ubuntu2.1) trusty-security; urgency=medium + + * SECURITY UPDATE: possible privilege escalation via option parsing + - debian/patches/CVE-2014-3158.patch: fix integer overflow in + pppd/options.c. + - CVE-2014-3158 + + -- Marc Deslauriers Tue, 25 Nov 2014 16:16:56 -0500 + +ppp (2.4.5-5.1ubuntu2) raring-proposed; urgency=low + + * add EAPTLS-MPPE 0.994 patch from http://www.nikhef.nl/~janjust/ppp/ + (Closes: #602503, LP: #643417) (quilt refreshed) + * debian/control: Build-Depends on libssl-dev + + -- Pavel Plesov Sun, 23 Dec 2012 23:44:40 +0400 + +ppp (2.4.5-5.1ubuntu1) raring; urgency=low + + [ Ubuntu Merge-o-Matic ] + * Merge from Debian unstable. Remaining changes: + - /etc/ppp/options: default is noauth instead of auth. + - extra/pon: Perform ppp_on_boot migration from pppoe package. + - debian/ppp.postinst: init script migration for version before + 2.4.5~git20081126t100229-0ubuntu2. + - debian/ppp.pppd-dns: Update LSB header. + - Provide pppoe_on_boot file. + - Move pppd-dns script to S45. + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + - Fix FTBFS with linux 3.5 headers. + + -- Adam Conrad Sun, 02 Dec 2012 03:57:07 -0700 + ppp (2.4.5-5.1) unstable; urgency=low * Non-maintainer upload. @@ -5,12 +57,49 @@ -- Robert Millan Sun, 22 Apr 2012 16:25:45 +0200 +ppp (2.4.5-5ubuntu2) quantal-proposed; urgency=low + + * FTBS fix against linux 3.5 headers: Update debian/patches/update_if_pppol2tp + to reflect changes in Linux 3.5 includes. + + -- Tim Gardner Tue, 25 Sep 2012 16:20:00 +0000 + +ppp (2.4.5-5ubuntu1) natty; urgency=low + + * Merge from debian unstable. (LP: #712419) Remaining changes: + - /etc/ppp/options: default is noauth instead of auth. + - extra/pon: Perform ppp_on_boot migration from pppoe package. + - debian/ppp.postinst: init script migration for version before + 2.4.5~git20081126t100229-0ubuntu2. + - debian/ppp.pppd-dns: Update LSB header. + - Provide pppoe_on_boot file. + - Move pppd-dns script to S45. + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + + -- Angel Abad Thu, 03 Feb 2011 13:16:46 +0100 + ppp (2.4.5-5) unstable; urgency=medium * Updated debconf translation: da. (Closes: #601791) -- Marco d'Itri Wed, 19 Jan 2011 23:24:16 +0100 +ppp (2.4.5-4ubuntu1) natty; urgency=low + + * Merge with Debian; remaining changes: + - /etc/ppp/options: default is noauth instead of auth. + - extra/pon: Perform ppp_on_boot migration from pppoe package. + - debian/ppp.postinst: init script migration for version before + 2.4.5~git20081126t100229-0ubuntu2. + - debian/ppp.pppd-dns: Update LSB header. + - Provide pppoe_on_boot file. + - Move pppd-dns script to S45. + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + + -- Matthias Klose Wed, 24 Nov 2010 18:12:47 +0100 + ppp (2.4.5-4) unstable; urgency=low * Make sure to actually rebuild pppd for the udeb instead of using the @@ -87,6 +176,102 @@ -- Christian Perrier Fri, 28 Nov 2008 18:36:26 +0100 +ppp (2.4.5~git20081126t100229-0ubuntu4) maverick; urgency=low + + * debian/patches/update_if_pppol2tp: Update include/linux/if_pppol2tp.h to + match current kernel definitions (LP: #600947). + + -- Colin Watson Fri, 09 Jul 2010 17:27:36 +0100 + +ppp (2.4.5~git20081126t100229-0ubuntu3) lucid; urgency=low + + * rebuild rest of main for armel armv7/thumb2 optimization; + UbuntuSpec:mobile-lucid-arm-gcc-v7-thumb2 + + -- Alexander Sack Sun, 07 Mar 2010 01:01:51 +0100 + +ppp (2.4.5~git20081126t100229-0ubuntu2) jaunty; urgency=low + + * debian/rules: Start the init script in runlevels 1-5, it does not need to + start before gdm. + * debian/ppp.postinst: Remove old init script symlinks. + * debian/ppp.pppd-dns: Update LSB header. + + -- Scott James Remnant Fri, 20 Feb 2009 15:15:49 +0000 + +ppp (2.4.5~git20081126t100229-0ubuntu1) jaunty; urgency=low + + * new upstream snapshot 2.4.5pre gitXXXX + * debian/rules,debian/scripts/vars bump upstream version and + and tarball dir + * rebase debian patches that still apply + - debian/patches/008_pathnames.h.diff, + debian/patches/010_scripts_README.diff, + debian/patches/011_scripts_redialer.diff, + debian/patches/018_ip-up_option.diff, + debian/patches/atm_resolver_light, + debian/patches/chat_man, + debian/patches/cifdefroute.dif, + debian/patches/close_dev_ppp, + debian/patches/fix_linkpidfile, + debian/patches/fix_null_pppdb, + debian/patches/load_ppp_generic_if_needed, + debian/patches/no_crypt_hack, + debian/patches/no_crypt_hack_2.4.5, + debian/patches/ppp-2.3.11-oedod.dif, + debian/patches/ppp-2.4.2-stripMSdomain, + debian/patches/pppdump_use_zlib, + debian/patches/pppdump_z_no_deflate, + debian/patches/pppoatm_cleanup, + debian/patches/pppoe_readme, + debian/patches/readable_connerrs, + debian/patches/resolv.conf_no_log, + debian/patches/setevn_call_file, + debian/patches/syslog_local2, + debian/patches/zzz_config, + debian/patches/zzz_man_typos + * drop patches superseeded upstream + - debian/patches/fix_close_fd0 + - debian/patches/fix_mschapv2_ppp + - debian/patches/pppoatm_fix_mtu + - debian/patches/pppoe_cleanup + - debian/patches/zzzz_lp258801_fix_ppp_dns_1.patch + - debian/patches/zzzz_lp258801_fix_ppp_dns_2.patch + - debian/patches/zzzz_lp258801_fix_ppp_dns.patch + * add patches required for new codebase: + - no_crypt_hack_2.4.5: crypt is now also getting used in session.c + apply NO_CRYPT_HACK for -udeb support here too + + -- Alexander Sack Mon, 16 Feb 2009 11:57:28 +0100 + +ppp (2.4.4rel-10ubuntu2.8.10.1) intrepid-proposed; urgency=low + + * fix LP: #258801; Gets bogus DNS servers during PPP negotiation; we + apply two more patches from git (details in patch) + - add debian/patches/zzzz_lp258801_fix_ppp_dns_1.patch + - add debian/patches/zzzz_lp258801_fix_ppp_dns_2.patch + + -- Alexander Sack Wed, 19 Nov 2008 14:05:43 +0100 + +ppp (2.4.4rel-10ubuntu2) intrepid; urgency=low + + * fix LP: #258801; Gets bogus DNS servers during PPP negotiation; we apply + the patch from http://marc.info/?l=linux-ppp&m=119559914711075&w=2 + - add debian/patches/zzzz_lp258801_fix_ppp_dns.patch + + -- Alexander Sack Thu, 16 Oct 2008 03:17:37 +0200 + +ppp (2.4.4rel-10ubuntu1) intrepid; urgency=low + + * Merge from debian unstable, remaining changes: + - "Perform ppp_on_boot migration from pppoe package." + - provide pppoe_on_boot file + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed + - /etc/ppp/options: default is noauth instead of auth. + + -- Michael Vogt Mon, 23 Jun 2008 14:04:47 +0200 + ppp (2.4.4rel-10) unstable; urgency=low * ppp-udeb: allow for preseeding of the netcfg/get_hostname template. @@ -123,6 +308,24 @@ -- Frans Pop Tue, 08 Apr 2008 16:53:04 +0200 +ppp (2.4.4rel-9ubuntu2) gutsy; urgency=low + + * Trigger rebuild for hppa + + -- LaMont Jones Thu, 04 Oct 2007 12:21:29 -0600 + +ppp (2.4.4rel-9ubuntu1) gutsy; urgency=low + + * Merge from debian unstable, remaining changes: + - "Perform ppp_on_boot migration from pppoe package." + - provide pppoe_on_boot file + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed + - /etc/ppp/options: default is noauth instead of auth. + - maintainer field set to ubuntu + + -- Michael Vogt Tue, 15 May 2007 11:09:49 +0200 + ppp (2.4.4rel-9) unstable; urgency=low * ppp-udeb: quote username and password in pap/chap secrets since they @@ -196,6 +399,22 @@ -- Eddy Petrișor Mon, 29 Jan 2007 16:58:03 +0200 +ppp (2.4.4rel-4.1ubuntu2) feisty; urgency=low + + * /etc/ppp/options: default is noauth instead of auth. + + -- Ian Jackson Wed, 4 Apr 2007 16:46:49 +0100 + +ppp (2.4.4rel-4.1ubuntu1) feisty; urgency=low + + * Merge from debian unstable, remaining changes: + - "Perform ppp_on_boot migration from pppoe package." + - provide pppoe_on_boot file + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed + + -- Michael Vogt Wed, 20 Dec 2006 12:23:42 +0100 + ppp (2.4.4rel-4.1) unstable; urgency=low * Non-maintainer upload with maintainer's consent. @@ -208,6 +427,16 @@ -- Arnaud Fontaine Thu, 14 Dec 2006 21:31:55 +0100 +ppp (2.4.4rel-4ubuntu1) feisty; urgency=low + + * Merge from debian unstable. Remaining changes: + - "Perform ppp_on_boot migration from pppoe package." + - provide pppoe_on_boot file + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed + + -- Michael Vogt Fri, 24 Nov 2006 08:39:13 +0100 + ppp (2.4.4rel-4) unstable; urgency=low [ Eddy Petrișor ] @@ -261,6 +490,12 @@ -- Marco d'Itri Wed, 12 Jul 2006 18:26:01 +0200 +ppp (2.4.4rel-1ubuntu1) edgy; urgency=low + + * Merge to Debian unstable. + + -- Martin Pitt Mon, 10 Jul 2006 18:34:10 +0200 + ppp (2.4.4rel-1) unstable; urgency=high * New upstream release. Fixes: @@ -276,6 +511,36 @@ -- Marco d'Itri Sun, 9 Jul 2006 18:38:54 +0200 +ppp (2.4.4b1-1ubuntu4) edgy; urgency=low + + * SECURITY UPDATE: Potential privilege escalation. + * debian/patches/winbind-setuid-failure-check: + - Check for a failing setuid() call (which can happen if the user hits PAM + limits). Before, a failing setuid() call would execute the NTLM + authentication helper as root. + - CVE-2006-2194 + + -- Martin Pitt Wed, 5 Jul 2006 11:48:13 +0200 + +ppp (2.4.4b1-1ubuntu3) dapper; urgency=low + + * Move script to S55. + + -- Scott James Remnant Thu, 23 Feb 2006 15:30:22 +0000 + +ppp (2.4.4b1-1ubuntu2) dapper; urgency=low + + * Move pppd-dns script to S45. + + -- Scott James Remnant Mon, 30 Jan 2006 14:23:23 +0000 + +ppp (2.4.4b1-1ubuntu1) dapper; urgency=low + + * Synchronise with Debian unstable. + * Still keep the pppoe_on_boot stuff. + + -- Matthias Klose Thu, 15 Dec 2005 14:46:57 +0000 + ppp (2.4.4b1-1) unstable; urgency=low * New upstream release. Fixes: @@ -305,6 +570,12 @@ -- Marco d'Itri Sun, 4 Dec 2005 15:22:23 +0100 +ppp (2.4.3-20050321+2ubuntu1) breezy; urgency=low + + * Resynchronise with Debian. + + -- Adam Conrad Fri, 27 May 2005 15:47:55 +0000 + ppp (2.4.3-20050321+2) unstable; urgency=high * Added patch close_dev_ppp to fix pppd spinning on select() and using @@ -320,6 +591,20 @@ -- Marco d'Itri Wed, 4 May 2005 02:00:04 +0200 +ppp (2.4.3-20050321+1ubuntu2) breezy; urgency=low + + * Drop debian/patches/libpcap0.8, which has since been applied to + the upstream sources, and debian/patches/pcap, which is the + Debian patch to revert to libpcap0.7 (Closes Ubuntu bug #10033) + + -- Adam Conrad Fri, 22 Apr 2005 00:16:08 +0000 + +ppp (2.4.3-20050321+1ubuntu1) breezy; urgency=low + + * Resynchronise with Debian, resolving merge conflicts. + + -- Adam Conrad Thu, 21 Apr 2005 08:53:53 +0000 + ppp (2.4.3-20050321+1) unstable; urgency=high * New upstream snapshot, with a fix for the persist configuration option. @@ -379,6 +664,12 @@ -- Marco d'Itri Thu, 24 Feb 2005 23:51:54 +0100 +ppp (2.4.2+20040428-6ubuntu1) hoary; urgency=low + + * Resynchronise with Debian. + + -- Michael Vogt Wed, 12 Jan 2005 10:00:49 +0100 + ppp (2.4.2+20040428-6) unstable; urgency=medium * Removed references to nscd from the 0000usepeerdns scripts. @@ -397,6 +688,27 @@ -- Marco d'Itri Thu, 30 Dec 2004 17:21:22 +0100 +ppp (2.4.2+20040428-5ubuntu3) hoary; urgency=low + + * Migrate to libpcap0.8 + - debian/patches/libpcap0.8 + - Build-Depend on libpcap0.8-dev rather than libpcap0.7-dev + + -- Matt Zimmerman Tue, 28 Dec 2004 13:44:43 -0800 + +ppp (2.4.2+20040428-5ubuntu2) hoary; urgency=low + + * Merge debian/ppp.init file. + * Remove patch applied in unstable (cbcp-check-packetlengths.diff). + + -- Matthias Klose Mon, 15 Nov 2004 15:22:11 +0000 + +ppp (2.4.2+20040428-5ubuntu1) hoary; urgency=low + + * Resynchronise with Debian. + + -- Scott James Remnant Tue, 09 Nov 2004 23:37:30 +0000 + ppp (2.4.2+20040428-5) unstable; urgency=medium * Removed patch pty_command_timeout. (Closes: #279929) @@ -439,6 +751,66 @@ -- Marco d'Itri Sun, 31 Oct 2004 16:02:19 +0100 +ppp (2.4.2+20040428-2ubuntu7) hoary; urgency=low + + * Security upload for hoary (see previous changelog for details). + + -- Martin Pitt Fri, 29 Oct 2004 09:02:37 +0200 + +ppp (2.4.2+20040428-2ubuntu6.1) warty-security; urgency=low + + * SECURITY UPDATE: fix potential buffer overflow and DOS (Warty bug #2808) + * added debian/patches/cbcp-check-packetlengths.diff to add proper packet + length and bounds checking to pppd/cbcp.c (taken from upstream CVS) + * References: + http://www.securityfocus.com/archive/1/379450 + + -- Martin Pitt Thu, 28 Oct 2004 14:48:17 +0200 + +ppp (2.4.2+20040428-2ubuntu6) warty; urgency=low + + * Small fix for ppp_on_boot migration; also fixes pointless warning in pon + (closes: Ubuntu#1977). + * Make really, really sure we get a /dev/ppp device by only loading + ppp_generic if /dev/ppp doesn't exist, and sleep for five seconds to work + around the udev race; move this to pppd, instead of pon, which also + guarantees that it's run as root (closes: Ubuntu#1980, #1981). + + -- Daniel Stone Sat, 2 Oct 2004 17:27:53 +1000 + +ppp (2.4.2+20040428-2ubuntu5) warty; urgency=low + + * If /etc/ppp_on_boot exists and is a symlink to /etc/ppp/ppp_on_boot.dsl, + which doesn't exist, then transition the symlink to pppoe_on_boot (closes: + Ubuntu#1153). + + -- Daniel Stone Sun, 26 Sep 2004 14:13:45 +1000 + +ppp (2.4.2+20040428-2ubuntu4) warty; urgency=low + + * Made pon load ppp_deflate (quietly), so /dev/ppp gets created (closes: + Ubuntu#1644). + + -- Daniel Stone Fri, 24 Sep 2004 14:12:06 +1000 + +ppp (2.4.2+20040428-2ubuntu3) warty; urgency=low + + * Add pppoe_on_boot, from pppoe's ppp_on_boot.dsl. + + -- Daniel Stone Thu, 23 Sep 2004 13:02:42 +1000 + +ppp (2.4.2+20040428-2ubuntu2) warty; urgency=low + + * Added versioned depend on lsb-base + + -- Nathaniel McCallum Fri, 3 Sep 2004 15:14:36 -0400 + +ppp (2.4.2+20040428-2ubuntu1) warty; urgency=low + + * debian/ppp.init: pretty initscript + + -- Nathaniel McCallum Fri, 3 Sep 2004 11:52:53 -0400 + ppp (2.4.2+20040428-2) unstable; urgency=medium * Temporarily removed patch ppp-2.4.2-libpcap.diff: switch back to @@ -817,0 +1190 @@ + diff -u ppp-2.4.5/debian/patches/update_if_pppol2tp ppp-2.4.5/debian/patches/update_if_pppol2tp --- ppp-2.4.5/debian/patches/update_if_pppol2tp +++ ppp-2.4.5/debian/patches/update_if_pppol2tp @@ -1,7 +1,5 @@ -diff --git a/include/linux/if_pppol2tp.h b/include/linux/if_pppol2tp.h -index 4113d6a..7ee86b2 100644 ---- a/include/linux/if_pppol2tp.h -+++ b/include/linux/if_pppol2tp.h +--- ./include/linux/if_pppol2tp.h 2012-09-25 16:14:23.449883865 +0000 ++++ /usr/include/linux/if_pppol2tp.h 2012-09-19 20:46:59.000000000 +0000 @@ -2,7 +2,7 @@ * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661) * @@ -20,7 +18,8 @@ + /* Structure used to connect() the socket to a particular tunnel UDP - * socket. +- * socket. ++ * socket over IPv4. */ -struct pppol2tp_addr -{ @@ -30,15 +29,29 @@ * 0 => current */ int fd; /* FD of UDP socket to use */ -@@ -32,6 +32,20 @@ struct pppol2tp_addr +@@ -32,6 +32,45 @@ __u16 d_tunnel, d_session; /* For sending outgoing packets */ }; ++/* Structure used to connect() the socket to a particular tunnel UDP ++ * socket over IPv6. ++ */ ++struct pppol2tpin6_addr { ++ __kernel_pid_t pid; /* pid that owns the fd. ++ * 0 => current */ ++ int fd; /* FD of UDP socket to use */ ++ ++ __u16 s_tunnel, s_session; /* For matching incoming packets */ ++ __u16 d_tunnel, d_session; /* For sending outgoing packets */ ++ ++ struct sockaddr_in6 addr; /* IP address and port to send to */ ++}; ++ +/* The L2TPv3 protocol changes tunnel and session ids from 16 to 32 + * bits. So we need a different sockaddr structure. + */ +struct pppol2tpv3_addr { -+ pid_t pid; /* pid that owns the fd. ++ __kernel_pid_t pid; /* pid that owns the fd. + * 0 => current */ + int fd; /* FD of UDP or IP socket to use */ + @@ -48,6 +61,17 @@ + __u32 d_tunnel, d_session; /* For sending outgoing packets */ +}; + ++struct pppol2tpv3in6_addr { ++ __kernel_pid_t pid; /* pid that owns the fd. ++ * 0 => current */ ++ int fd; /* FD of UDP or IP socket to use */ ++ ++ __u32 s_tunnel, s_session; /* For matching incoming packets */ ++ __u32 d_tunnel, d_session; /* For sending outgoing packets */ ++ ++ struct sockaddr_in6 addr; /* IP address and port to send to */ ++}; ++ /* Socket options: * DEBUG - bitmask of debug message categories * SENDSEQ - 0 => don't send packets with sequence numbers diff -u ppp-2.4.5/debian/patches/series ppp-2.4.5/debian/patches/series --- ppp-2.4.5/debian/patches/series +++ ppp-2.4.5/debian/patches/series @@ -42,0 +43,6 @@ +# ubuntu +load_ppp_generic_if_needed +ppp-2.4.5-eaptls-mppe-0.994.patch +CVE-2014-3158.patch +CVE-2015-3310.patch +CVE-2018-11574.patch --- ppp-2.4.5.orig/debian/patches/CVE-2014-3158.patch +++ ppp-2.4.5/debian/patches/CVE-2014-3158.patch @@ -0,0 +1,55 @@ +From 7658e8257183f062dc01f87969c140707c7e52cb Mon Sep 17 00:00:00 2001 +From: Paul Mackerras +Date: Fri, 1 Aug 2014 16:05:42 +1000 +Subject: [PATCH] pppd: Eliminate potential integer overflow in option parsing + +When we are reading in a word from an options file, we maintain a count +of the length we have seen so far in 'len', which is an int. When len +exceeds MAXWORDLEN - 1 (i.e. 1023) we cease storing characters in the +buffer but we continue to increment len. Since len is an int, it will +wrap around to -2147483648 after it reaches 2147483647. At that point +our test of (len < MAXWORDLEN-1) will succeed and we will start writing +characters to memory again. + +This may enable an attacker to overwrite the heap and thereby corrupt +security-relevant variables. For this reason it has been assigned a +CVE identifier, CVE-2014-3158. + +This fixes the bug by ceasing to increment len once it reaches MAXWORDLEN. + +Reported-by: Lee Campbell +Signed-off-by: Paul Mackerras +--- + pppd/options.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +Index: ppp-2.4.5/pppd/options.c +=================================================================== +--- ppp-2.4.5.orig/pppd/options.c 2014-11-25 16:14:05.839756746 -0500 ++++ ppp-2.4.5/pppd/options.c 2014-11-25 16:14:05.839756746 -0500 +@@ -1300,9 +1300,10 @@ + /* + * Store the resulting character for the escape sequence. + */ +- if (len < MAXWORDLEN-1) ++ if (len < MAXWORDLEN) { + word[len] = value; +- ++len; ++ ++len; ++ } + + if (!got) + c = getc(f); +@@ -1335,9 +1336,10 @@ + /* + * An ordinary character: store it in the word and get another. + */ +- if (len < MAXWORDLEN-1) ++ if (len < MAXWORDLEN) { + word[len] = c; +- ++len; ++ ++len; ++ } + + c = getc(f); + } --- ppp-2.4.5.orig/debian/patches/CVE-2015-3310.patch +++ ppp-2.4.5/debian/patches/CVE-2015-3310.patch @@ -0,0 +1,23 @@ +Description: Fix buffer overflow in rc_mksid() + rc_mksid converts the PID of pppd to hex to generate a pseudo-unique string. + . + If the process id is bigger than 65535 (FFFF), its hex representation will be + longer than 4 characters, resulting in a buffer overflow. + . + The bug can be exploited to cause a remote DoS. + . +Author: Emanuele Rocca +Bug-Debian: https://bugs.debian.org/782450 +Last-Update: <2015-04-14> + +--- ppp-2.4.6.orig/pppd/plugins/radius/util.c ++++ ppp-2.4.6/pppd/plugins/radius/util.c +@@ -77,7 +77,7 @@ rc_mksid (void) + static unsigned short int cnt = 0; + sprintf (buf, "%08lX%04X%02hX", + (unsigned long int) time (NULL), +- (unsigned int) getpid (), ++ (unsigned int) getpid () % 65535, + cnt & 0xFF); + cnt++; + return buf; --- ppp-2.4.5.orig/debian/patches/CVE-2018-11574.patch +++ ppp-2.4.5/debian/patches/CVE-2018-11574.patch @@ -0,0 +1,174 @@ +Description: fix buffer overflow in pppd EAP-TLS implementation +Origin: backport, https://www.nikhef.nl/~janjust/ppp/ppp-2.4.7-eaptls-mppe-1.101.patch + +Index: ppp-2.4.5/pppd/eap.c +=================================================================== +--- ppp-2.4.5.orig/pppd/eap.c 2018-06-12 13:30:50.691785434 -0400 ++++ ppp-2.4.5/pppd/eap.c 2018-06-12 13:33:49.604166443 -0400 +@@ -1705,6 +1705,11 @@ int len; + + 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){ + +@@ -1742,6 +1747,11 @@ int len; + 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) { +@@ -2112,6 +2122,7 @@ int len; + 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)); +@@ -2132,19 +2143,22 @@ int len; + case eapTlsRecvClient: + /* Receive authentication response from client */ + +- GETCHAR(flags, inp); ++ if (len > 0) { ++ 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", 0 ); ++ eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 ); + #endif +- eap_send_success(esp); +- } +- else { /* failure */ +- eaptls_receive(esp->es_server.ea_session, inp, len); +- warn("Server authentication failed"); +- eap_send_failure(esp); ++ 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); + +Index: ppp-2.4.5/pppd/eap-tls.c +=================================================================== +--- ppp-2.4.5.orig/pppd/eap-tls.c 2018-06-12 13:30:50.691785434 -0400 ++++ ppp-2.4.5/pppd/eap-tls.c 2018-06-12 13:30:50.691785434 -0400 +@@ -765,46 +765,47 @@ void eaptls_free_session(struct eaptls_s + int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) + { + u_char flags; +- u_int tlslen; ++ u_int tlslen = 0; + u_char dummy[65536]; + ++ if (len < 1) { ++ warn("EAP-TLS: received no or invalid data"); ++ return 1; ++ } ++ + GETCHAR(flags, inp); + len--; + +- if (flags & EAP_TLS_FLAGS_LI && !ets->data) { +- ++ if (flags & EAP_TLS_FLAGS_LI && len >= 4) { + /* +- * This is the first packet of a message ++ * LenghtIncluded flag set -> this is the first packet of a message + */ + ++ /* ++ * the first 4 octets are the length of the EAP-TLS message ++ */ + 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"); ++ if (!ets->data) { + +- ets->datalen = 0; +- ets->tlslen = tlslen; +- +- } +- else if (flags & EAP_TLS_FLAGS_LI && ets->data) { +- /* +- * Non first with LI (strange...) +- */ +- +- GETLONG(tlslen, inp); +- len -= 4; ++ if (tlslen > EAP_TLS_MAX_LEN) { ++ error("EAP-TLS: 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 ++ warn("EAP-TLS: non-first LI packet? that's odd..."); + } + else if (!ets->data) { + /* +@@ -824,8 +825,13 @@ int eaptls_receive(struct eaptls_session + else + ets->frag = 0; + ++ if (len < 0) { ++ warn("EAP-TLS: received malformed data"); ++ return 1; ++ } ++ + if (len + ets->datalen > ets->tlslen) { +- warn("EAP TLS: received data > TLS message length"); ++ warn("EAP-TLS: received data > TLS message length"); + return 1; + } + +@@ -839,7 +845,7 @@ int eaptls_receive(struct eaptls_session + */ + + if (ets->datalen != ets->tlslen) { +- warn("EAP TLS: received data != TLS message length"); ++ warn("EAP-TLS: received data != TLS message length"); + return 1; + } + --- ppp-2.4.5.orig/debian/patches/load_ppp_generic_if_needed +++ ppp-2.4.5/debian/patches/load_ppp_generic_if_needed @@ -0,0 +1,66 @@ +From 053fa32a9ccd0ac1fbbda50db7aff7fdae18652a Mon Sep 17 00:00:00 2001 +From: Alexander Sack +Date: Thu, 18 Dec 2008 05:33:13 +0100 +Subject: [PATCH] port: ppp-2.4.4rel/debian/patches/load_ppp_generic_if_needed + +--- + pppd/sys-linux.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 41 insertions(+), 0 deletions(-) + +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -92,6 +92,7 @@ + #include + #include + #include ++#include + + /* This is in netdevice.h. However, this compile will fail miserably if + you attempt to include netdevice.h because it has so many references +@@ -2104,6 +2105,46 @@ + + if (kernel_version >= KVERSION(2,3,13)) { + error("Couldn't open the /dev/ppp device: %m"); ++ char modprobePath[PATH_MAX] = ""; ++ int status, p, count; ++ pid_t pid; ++ ++ fd = open("/proc/sys/kernel/modprobe", O_RDONLY); ++ if (fd >= 0) { ++ int count = read(fd, modprobePath, PATH_MAX - 1); ++ if (count < 1) ++ modprobePath[0] = 0; ++ else if (modprobePath[count - 1] == '\n') ++ modprobePath[count - 1] = 0; ++ close(fd); ++ } ++ ++ if (modprobePath[0] == 0) ++ strcpy(modprobePath, "/sbin/modprobe"); ++ ++ switch (pid = fork()) { ++ case 0: /* child */ ++ setenv("PATH", "/sbin", 1); ++ status = execl(modprobePath, "modprobe", "ppp_generic", NULL); ++ case -1: /* couldn't fork */ ++ errno = ENOENT; ++ default: /* parent */ ++ do ++ p = waitpid(pid, &status, 0); ++ while (p == -1 && count++ < 4); ++ ++ sleep (5); ++ ++ } ++ ++ if ((fd = open("/dev/ppp", O_RDWR)) >= 0) { ++ new_style_driver = 1; ++ driver_version = 2; ++ driver_modification = 4; ++ driver_patch = 0; ++ close(fd); ++ return 1; ++ } + if (errno == ENOENT) + no_ppp_msg = + "You need to create the /dev/ppp device node by\n" --- ppp-2.4.5.orig/debian/patches/ppp-2.4.5-eaptls-mppe-0.994.patch +++ ppp-2.4.5/debian/patches/ppp-2.4.5-eaptls-mppe-0.994.patch @@ -0,0 +1,2943 @@ +Author: Jan Just Keijser +Description: EAP-TLS patch for pppd (0.994) +Bug-Ubuntu: https://launchpad.net/bugs/643417 +Bug-Debian: http://bugs.debian.org/602503 +But-Fedora: https://bugzilla.redhat.com/556407 +Origin: http://www.nikhef.nl/~janjust/ppp/download.html + +Index: ppp-2.4.5/README.eap-tls +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/README.eap-tls 2013-01-22 15:19:29.000000000 -0600 +@@ -0,0 +1,169 @@ ++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. 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: ++ : ++ 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: ++ : ++ 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 ++ Use the CA public certificate found in in PEM format ++ cert ++ Use the client public certificate found in in PEM format ++ or in engine:engine_id format ++ key ++ Use the client private key found in in PEM format ++ or in engine:engine_id format ++ crl-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. ++ 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. Notes ++ ++ This is experimental code. ++ Send suggestions and comments to Jan Just Keijser ++ +Index: ppp-2.4.5/etc.ppp/eaptls-client +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/etc.ppp/eaptls-client 2013-01-22 15:19:29.000000000 -0600 +@@ -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 +Index: ppp-2.4.5/etc.ppp/eaptls-server +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/etc.ppp/eaptls-server 2013-01-22 15:19:29.000000000 -0600 +@@ -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 +Index: ppp-2.4.5/etc.ppp/openssl.cnf +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/etc.ppp/openssl.cnf 2013-01-22 15:19:29.000000000 -0600 +@@ -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 ++ +Index: ppp-2.4.5/linux/Makefile.top +=================================================================== +--- ppp-2.4.5.orig/linux/Makefile.top 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/linux/Makefile.top 2013-01-22 15:19:29.000000000 -0600 +@@ -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 $@ +Index: ppp-2.4.5/pppd/Makefile.linux +=================================================================== +--- ppp-2.4.5.orig/pppd/Makefile.linux 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/Makefile.linux 2013-01-22 15:19:29.000000000 -0600 +@@ -73,6 +73,9 @@ + # Enable EAP SRP-SHA1 authentication (requires libsrp) + #USE_SRP=y + ++# Enable EAP-TLS authentication (requires libssl and libcrypto) ++USE_EAPTLS=y ++ + MAXOCTETS=y + + INCLUDE_DIRS= -I../include +@@ -111,6 +114,15 @@ + PPPDOBJS += sha1.o + endif + ++# EAP-TLS ++ifdef USE_EAPTLS ++COMPILE_FLAGS += -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 + COMPILE_FLAGS += -DHAS_SHADOW + #LIBS += -lshadow $(LIBS) +Index: ppp-2.4.5/pppd/auth.c +=================================================================== +--- ppp-2.4.5.orig/pppd/auth.c 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/auth.c 2013-01-22 15:19:29.000000000 -0600 +@@ -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 @@ + /* 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,13 @@ + 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 */ ++bool need_peer_eap = 0; /* Require peer to authenticate us */ ++#endif + + static char *uafname; /* name of most recent +ua file */ + +@@ -254,6 +269,19 @@ + 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 +429,14 @@ + "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" }, ++ { "need-peer-eap", o_bool, &need_peer_eap, ++ "Require the peer to authenticate us", 1 }, ++#endif /* USE_EAPTLS */ + { NULL } + }; + +@@ -731,6 +767,9 @@ + 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; + +@@ -765,6 +804,22 @@ + } + } + ++#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) { +@@ -1278,6 +1333,15 @@ + 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( +@@ -1332,7 +1396,11 @@ + 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)) +@@ -1347,8 +1415,14 @@ + !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; ++ + } + + +@@ -1708,6 +1782,7 @@ + } + + ++ + /* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. +@@ -2360,3 +2435,335 @@ + + 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 ++ +Index: ppp-2.4.5/pppd/ccp.c +=================================================================== +--- ppp-2.4.5.orig/pppd/ccp.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/ccp.c 2013-01-22 15:19:29.000000000 -0600 +@@ -540,6 +540,9 @@ + 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 @@ + 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; + } +Index: ppp-2.4.5/pppd/chap-md5.c +=================================================================== +--- ppp-2.4.5.orig/pppd/chap-md5.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/chap-md5.c 2013-01-22 15:19:29.000000000 -0600 +@@ -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 +Index: ppp-2.4.5/pppd/eap-tls.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/pppd/eap-tls.c 2013-01-22 15:19:29.000000000 -0600 +@@ -0,0 +1,1174 @@ ++/* ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pppd.h" ++#include "eap.h" ++#include "eap-tls.h" ++#include "fsm.h" ++#include "lcp.h" ++#include "pathnames.h" ++ ++/* The openssl configuration file and engines can be loaded only once */ ++static CONF *ssl_config = NULL; ++static ENGINE *cert_engine = NULL; ++static ENGINE *pkey_engine = NULL; ++ ++#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, ++ int client) ++{ ++ 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) ++ */ ++ if (client) ++ { ++ p = out; ++ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); ++ p += EAPTLS_MPPE_KEY_LEN; ++ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); ++ } ++ else ++ { ++ 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 ++ ++void log_ssl_errors( void ) ++{ ++ unsigned long ssl_err = ERR_get_error(); ++ ++ if (ssl_err != 0) ++ dbglog("EAP-TLS SSL error stack:"); ++ while (ssl_err != 0) { ++ dbglog( ERR_error_string( ssl_err, NULL ) ); ++ ssl_err = ERR_get_error(); ++ } ++} ++ ++ ++int password_callback (char *buf, int size, int rwflag, void *u) ++{ ++ if (buf) ++ { ++ strncpy (buf, passwd, size); ++ return strlen (buf); ++ } ++ return 0; ++} ++ ++ ++CONF *eaptls_ssl_load_config( void ) ++{ ++ CONF *config; ++ int ret_code; ++ long error_line = 33; ++ ++ config = NCONF_new( NULL ); ++ dbglog( "Loading OpenSSL config file" ); ++ ret_code = NCONF_load( config, _PATH_OPENSSLCONFFILE, &error_line ); ++ if (ret_code == 0) ++ { ++ warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line ); ++ NCONF_free( config ); ++ config = NULL; ++ ERR_clear_error(); ++ } ++ ++ dbglog( "Loading OpenSSL built-ins" ); ++ ENGINE_load_builtin_engines(); ++ OPENSSL_load_builtin_modules(); ++ ++ dbglog( "Loading OpenSSL configured modules" ); ++ if (CONF_modules_load( config, NULL, 0 ) <= 0 ) ++ { ++ warn( "EAP-TLS: Error loading OpenSSL modules" ); ++ log_ssl_errors(); ++ config = NULL; ++ } ++ ++ return config; ++} ++ ++ENGINE *eaptls_ssl_load_engine( char *engine_name ) ++{ ++ ENGINE *e = NULL; ++ ++ dbglog( "Enabling OpenSSL auto engines" ); ++ ENGINE_register_all_complete(); ++ ++ dbglog( "Loading OpenSSL '%s' engine support", engine_name ); ++ e = ENGINE_by_id( engine_name ); ++ if (!e) ++ { ++ dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name ); ++ e = ENGINE_by_id( "dynamic" ); ++ if (e) ++ { ++ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0) ++ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) ++ { ++ warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name ); ++ log_ssl_errors(); ++ ENGINE_free(e); ++ e = NULL; ++ } ++ } ++ else ++ { ++ warn( "EAP-TLS: Cannot load dynamic engine support" ); ++ } ++ } ++ ++ if (e) ++ { ++ dbglog( "Initialising engine" ); ++ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) ++ { ++ warn( "EAP-TLS: Cannot use that engine" ); ++ log_ssl_errors(); ++ ENGINE_free(e); ++ e = NULL; ++ } ++ } ++ ++ return e; ++} ++ ++/* ++ * Initialize the SSL stacks and tests if certificates, key and crl ++ * for client or server use can be loaded. ++ */ ++SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, ++ char *certfile, char *peer_certfile, char *privkeyfile) ++{ ++ char *cert_engine_name = NULL; ++ char *cert_identifier = NULL; ++ char *pkey_engine_name = NULL; ++ char *pkey_identifier = NULL; ++ SSL_CTX *ctx; ++ X509_STORE *certstore; ++ X509_LOOKUP *lookup; ++ X509 *tmp; ++ ++ /* ++ * Without these can't continue ++ */ ++ if (!cacertfile[0]) ++ { ++ error("EAP-TLS: CA certificate missing"); ++ return NULL; ++ } ++ ++ if (!certfile[0]) ++ { ++ error("EAP-TLS: User certificate missing"); ++ return NULL; ++ } ++ ++ if (!privkeyfile[0]) ++ { ++ error("EAP-TLS: User private key missing"); ++ return NULL; ++ } ++ ++ SSL_library_init(); ++ SSL_load_error_strings(); ++ ++ ctx = SSL_CTX_new(TLSv1_method()); ++ ++ if (!ctx) { ++ error("EAP-TLS: Cannot initialize SSL CTX context"); ++ goto fail; ++ } ++ ++ /* if the certificate filename is of the form engine:id. e.g. ++ pkcs11:12345 ++ then we try to load and use this engine. ++ If the certificate filename starts with a / or . then we ++ ALWAYS assume it is a file and not an engine/pkcs11 identifier ++ */ ++ if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL ) ++ { ++ cert_identifier = index( certfile, ':' ); ++ ++ if (cert_identifier) ++ { ++ cert_engine_name = certfile; ++ *cert_identifier = '\0'; ++ cert_identifier++; ++ ++ dbglog( "Found certificate engine '%s'", cert_engine_name ); ++ dbglog( "Found certificate identifier '%s'", cert_identifier ); ++ } ++ } ++ ++ /* if the privatekey filename is of the form engine:id. e.g. ++ pkcs11:12345 ++ then we try to load and use this engine. ++ If the privatekey filename starts with a / or . then we ++ ALWAYS assume it is a file and not an engine/pkcs11 identifier ++ */ ++ if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL ) ++ { ++ pkey_identifier = index( privkeyfile, ':' ); ++ ++ if (pkey_identifier) ++ { ++ pkey_engine_name = privkeyfile; ++ *pkey_identifier = '\0'; ++ pkey_identifier++; ++ ++ dbglog( "Found privatekey engine '%s'", pkey_engine_name ); ++ dbglog( "Found privatekey identifier '%s'", pkey_identifier ); ++ } ++ } ++ ++ if (cert_identifier && pkey_identifier) ++ { ++ if (strlen( cert_identifier ) == 0) ++ { ++ if (strlen( pkey_identifier ) == 0) ++ error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" ); ++ else ++ { ++ dbglog( "Substituting privatekey identifier for certificate identifier" ); ++ cert_identifier = pkey_identifier; ++ } ++ } ++ else ++ { ++ if (strlen( pkey_identifier ) == 0) ++ { ++ dbglog( "Substituting certificate identifier for privatekey identifier" ); ++ pkey_identifier = cert_identifier; ++ } ++ } ++ ++ } ++ ++ /* load the openssl config file only once */ ++ if (!ssl_config) ++ { ++ if (cert_engine_name || pkey_engine_name) ++ ssl_config = eaptls_ssl_load_config(); ++ ++ if (ssl_config && cert_engine_name) ++ cert_engine = eaptls_ssl_load_engine( cert_engine_name ); ++ ++ if (ssl_config && pkey_engine_name) ++ { ++ /* don't load the same engine twice */ ++ if ( strcmp( cert_engine_name, pkey_engine_name) == 0 ) ++ pkey_engine = cert_engine; ++ else ++ pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); ++ } ++ } ++ ++ SSL_CTX_set_default_passwd_cb (ctx, password_callback); ++ ++ if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) ++ { ++ error("EAP-TLS: Cannot load or verify CA file %s", cacertfile); ++ goto fail; ++ } ++ ++ if (init_server) ++ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); ++ ++ if (cert_engine) ++ { ++ struct ++ { ++ const char *s_slot_cert_id; ++ X509 *cert; ++ } cert_info; ++ ++ cert_info.s_slot_cert_id = cert_identifier; ++ cert_info.cert = NULL; ++ ++ if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) ) ++ { ++ error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier ); ++ goto fail; ++ } ++ ++ if (cert_info.cert) ++ { ++ dbglog( "Got the certificate, adding it to SSL context" ); ++ dbglog( "subject = %s", X509_NAME_oneline( X509_get_subject_name( cert_info.cert ), NULL, 0 ) ); ++ if (SSL_CTX_use_certificate(ctx, cert_info.cert) <= 0) ++ { ++ error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier); ++ goto fail; ++ } ++ } ++ else ++ { ++ warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier); ++ log_ssl_errors(); ++ } ++ } ++ else ++ { ++ if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) ++ { ++ error( "EAP-TLS: Cannot use public certificate %s", certfile ); ++ goto fail; ++ } ++ } ++ ++ if (pkey_engine) ++ { ++ EVP_PKEY *pkey = NULL; ++ PW_CB_DATA cb_data; ++ ++ cb_data.password = passwd; ++ cb_data.prompt_info = pkey_identifier; ++ ++ dbglog( "Loading private key '%s' from engine", pkey_identifier ); ++ pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data); ++ if (pkey) ++ { ++ dbglog( "Got the private key, adding it to SSL context" ); ++ if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) ++ { ++ error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier); ++ goto fail; ++ } ++ } ++ else ++ { ++ warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier); ++ log_ssl_errors(); ++ } ++ } ++ else ++ { ++ if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) ++ { ++ error("EAP-TLS: Cannot use private key %s", privkeyfile); ++ goto fail; ++ } ++ } ++ ++ if (SSL_CTX_check_private_key(ctx) != 1) { ++ error("EAP-TLS: Private key %s fails security check", privkeyfile); ++ goto fail; ++ } ++ ++ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); ++ SSL_CTX_set_verify_depth(ctx, 5); ++ SSL_CTX_set_verify(ctx, ++ SSL_VERIFY_PEER | ++ SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ++ &ssl_verify_callback); ++ ++ if (crl_dir) { ++ if (!(certstore = SSL_CTX_get_cert_store(ctx))) { ++ error("EAP-TLS: Failed to get certificate store"); ++ goto fail; ++ } ++ ++ if (!(lookup = ++ X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) { ++ error("EAP-TLS: Store lookup for CRL failed"); ++ ++ goto fail; ++ } ++ ++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); ++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); ++ } ++ ++ /* ++ * If a peer certificate file was specified, it must be valid, else fail ++ */ ++ if (peer_certfile[0]) { ++ if (!(tmp = get_X509_from_file(peer_certfile))) { ++ error("EAP-TLS: Error loading client certificate from file %s", ++ peer_certfile); ++ goto fail; ++ } ++ X509_free(tmp); ++ } ++ ++ return ctx; ++ ++fail: ++ log_ssl_errors(); ++ SSL_CTX_free(ctx); ++ return NULL; ++} ++ ++/* ++ * Determine the maximum packet size by looking at the LCP handshake ++ */ ++ ++int eaptls_get_mtu(int unit) ++{ ++ int mtu, mru; ++ ++ lcp_options *wo = &lcp_wantoptions[unit]; ++ lcp_options *go = &lcp_gotoptions[unit]; ++ lcp_options *ho = &lcp_hisoptions[unit]; ++ lcp_options *ao = &lcp_allowoptions[unit]; ++ ++ mtu = ho->neg_mru? ho->mru: PPP_MRU; ++ mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU; ++ mtu = MIN(MIN(mtu, mru), ao->mru)- PPP_HDRLEN - 10; ++ ++ dbglog("MTU = %d", mtu); ++ return mtu; ++} ++ ++ ++/* ++ * Init the ssl handshake (server mode) ++ */ ++int eaptls_init_ssl_server(eap_state * esp) ++{ ++ struct eaptls_session *ets; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ /* ++ * 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("EAP-TLS: Error: client name not set (BUG)"); ++ return 0; ++ } ++ ++ strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN); ++ ++ dbglog( "getting eaptls secret" ); ++ if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, ++ esp->es_server.ea_name, clicertfile, ++ servcertfile, cacertfile, pkfile, 1)) { ++ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", ++ esp->es_server.ea_peer, esp->es_server.ea_name ); ++ return 0; ++ } ++ ++ ets->mtu = eaptls_get_mtu(esp->es_unit); ++ ++ ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile); ++ if (!ets->ctx) ++ goto fail; ++ ++ if (!(ets->ssl = SSL_new(ets->ctx))) ++ goto fail; ++ ++ /* ++ * Set auto-retry to avoid timeouts on BIO_read ++ */ ++ SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY); ++ ++ /* ++ * 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: ++ 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; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ ++ /* ++ * 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 = eaptls_get_mtu(esp->es_unit); ++ ++ dbglog( "calling get_eaptls_secret" ); ++ if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, ++ esp->es_client.ea_peer, clicertfile, ++ servcertfile, cacertfile, pkfile, 0)) { ++ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", ++ esp->es_client.ea_name, esp->es_client.ea_peer ); ++ return 0; ++ } ++ ++ dbglog( "calling eaptls_init_ssl" ); ++ ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile); ++ if (!ets->ctx) ++ goto fail; ++ ++ ets->ssl = SSL_new(ets->ctx); ++ ++ if (!ets->ssl) ++ goto fail; ++ ++ /* ++ * Initialize the BIOs we use to read/write to ssl engine ++ */ ++ dbglog( "Initializing SSL BIOs" ); ++ 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: ++ dbglog( "eaptls_init_ssl_client: fail" ); ++ SSL_CTX_free(ets->ctx); ++ return 0; ++ ++} ++ ++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 && !ets->data) { ++ ++ /* ++ * This is the first packet of a message ++ */ ++ ++ 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 (flags & EAP_TLS_FLAGS_LI && ets->data) { ++ /* ++ * Non first with LI (strange...) ++ */ ++ ++ GETLONG(tlslen, inp); ++ len -= 4; ++ ++ } ++ 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) ++ log_ssl_errors(); ++ ++ 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 (auth_required && !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; ++ } ++ ++ log_ssl_errors(); ++ ++ 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; ++ ++ default: ++ sprintf( string, "Handshake: Unknown SSL3 code received: %d", code ); ++ } ++ break; ++ ++ default: ++ sprintf( string, "SSL message contains unknown content type: %d", content_type ); ++ ++ } ++ ++ /* Alert messages must always be displayed */ ++ if(content_type == SSL3_RT_ALERT) ++ error("%s", string); ++ else ++ dbglog("%s", string); ++} ++ +Index: ppp-2.4.5/pppd/eap-tls.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ ppp-2.4.5/pppd/eap-tls.h 2013-01-22 15:19:29.000000000 -0600 +@@ -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 ++#include ++#include ++ ++#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 +Index: ppp-2.4.5/pppd/eap.c +=================================================================== +--- ppp-2.4.5.orig/pppd/eap.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/eap.c 2013-01-22 15:19:29.000000000 -0600 +@@ -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 +@@ -209,6 +218,9 @@ + 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 @@ + 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,81 @@ + 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(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; ++#endif /* USE_EAPTLS */ ++ + case eapSRP1: + #ifdef USE_SRP + ts = (struct t_server *)esp->es_server.ea_session; +@@ -718,6 +810,30 @@ + 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 +1020,57 @@ + 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 +1328,81 @@ + } + #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 +1557,11 @@ + 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 +1698,90 @@ + esp->es_client.ea_namelen); + break; + ++#ifdef USE_EAPTLS ++ 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_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: ++ 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 +2063,11 @@ + 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 +2107,60 @@ + 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 */ ++ ++ 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 */ ++ 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; ++#endif /* USE_EAPTLS */ ++ + case EAPT_NOTIFICATION: + dbglog("EAP unexpected Notification; response discarded"); + break; +@@ -1807,6 +2192,13 @@ + 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 +2410,27 @@ + 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 +2556,9 @@ + 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 +2623,24 @@ + } + 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 +2752,25 @@ + } + 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, " "); +@@ -2426,3 +2872,4 @@ + + return (inp - pstart); + } ++ +Index: ppp-2.4.5/pppd/eap.h +=================================================================== +--- ppp-2.4.5.orig/pppd/eap.h 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/eap.h 2013-01-22 15:19:29.000000000 -0600 +@@ -84,6 +84,16 @@ + 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 @@ + + #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 @@ + 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 @@ + * 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 */ + +Index: ppp-2.4.5/pppd/md5.c +=================================================================== +--- ppp-2.4.5.orig/pppd/md5.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/md5.c 2013-01-22 15:19:29.000000000 -0600 +@@ -33,6 +33,8 @@ + *********************************************************************** + */ + ++#ifndef USE_EAPTLS ++ + #include + #include "md5.h" + +@@ -305,3 +307,5 @@ + ** End of md5.c ** + ******************************** (cut) ******************************** + */ ++#endif /* USE_EAPTLS */ ++ +Index: ppp-2.4.5/pppd/md5.h +=================================================================== +--- ppp-2.4.5.orig/pppd/md5.h 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/md5.h 2013-01-22 15:19:29.000000000 -0600 +@@ -36,6 +36,7 @@ + ** documentation and/or software. ** + *********************************************************************** + */ ++#ifndef USE_EAPTLS + + #ifndef __MD5_INCLUDE__ + +@@ -63,3 +64,5 @@ + + #define __MD5_INCLUDE__ + #endif /* __MD5_INCLUDE__ */ ++ ++#endif /* USE_EAPTLS */ +Index: ppp-2.4.5/pppd/options.c +=================================================================== +--- ppp-2.4.5.orig/pppd/options.c 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/options.c 2013-01-22 15:19:29.000000000 -0600 +@@ -121,6 +121,10 @@ + 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 */ ++#ifdef USE_EAPTLS ++bool only_update_crl_server = 0; /* update server crl and exit */ ++bool only_update_crl_client = 0; /* update client crl and exit */ ++#endif /* USE_EAPTLS */ + + #ifdef MAXOCTETS + unsigned int maxoctets = 0; /* default - no limit */ +@@ -329,6 +333,12 @@ + { "mo-timeout", o_int, &maxoctets_timeout, + "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, + #endif ++#ifdef USE_EAPTLS ++ { "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 }, ++#endif /* USE_EAPTLS */ + + { NULL } + }; +Index: ppp-2.4.5/pppd/pathnames.h +=================================================================== +--- ppp-2.4.5.orig/pppd/pathnames.h 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/pathnames.h 2013-01-22 15:19:29.000000000 -0600 +@@ -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" +Index: ppp-2.4.5/pppd/plugins/Makefile.linux +=================================================================== +--- ppp-2.4.5.orig/pppd/plugins/Makefile.linux 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/plugins/Makefile.linux 2013-01-22 15:19:29.000000000 -0600 +@@ -4,6 +4,9 @@ + LDFLAGS = + INSTALL = install + ++# EAP-TLS ++CFLAGS += -DUSE_EAPTLS=1 ++ + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +Index: ppp-2.4.5/pppd/plugins/passprompt.c +=================================================================== +--- ppp-2.4.5.orig/pppd/plugins/passprompt.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/plugins/passprompt.c 2013-01-22 15:19:29.000000000 -0600 +@@ -107,4 +107,7 @@ + { + add_options(options); + pap_passwd_hook = promptpass; ++#ifdef USE_EAPTLS ++ eaptls_passwd_hook = promptpass; ++#endif + } +Index: ppp-2.4.5/pppd/plugins/passwordfd.c +=================================================================== +--- ppp-2.4.5.orig/pppd/plugins/passwordfd.c 2013-01-22 15:19:11.000000000 -0600 ++++ ppp-2.4.5/pppd/plugins/passwordfd.c 2013-01-22 15:19:29.000000000 -0600 +@@ -79,4 +79,8 @@ + + chap_check_hook = pwfd_check; + chap_passwd_hook = pwfd_passwd; ++ ++#ifdef USE_EAPTLS ++ eaptls_passwd_hook = pwfd_passwd; ++#endif + } +Index: ppp-2.4.5/pppd/pppd.h +=================================================================== +--- ppp-2.4.5.orig/pppd/pppd.h 2013-01-22 15:19:29.000000000 -0600 ++++ ppp-2.4.5/pppd/pppd.h 2013-01-22 15:19:29.000000000 -0600 +@@ -322,6 +322,10 @@ + 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; ++#endif /* USE_EAPTLS */ ++ + #ifdef MAXOCTETS + extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ + extern int maxoctets_dir; /* Direction : +@@ -721,6 +725,10 @@ + 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));