diffstat of debian/ for ppp_2.4.7-1+2 ppp_2.4.7-1+2ubuntu1.16.04.1 changelog | 442 ++++ control | 5 patches/CVE-2018-11574.patch | 174 + patches/load_ppp_generic_if_needed | 66 patches/ppp-2.4.6-eaptls-mppe-0.997.patch | 3161 ++++++++++++++++++++++++++++++ patches/series | 5 ppp.preinst | 4 ppp.symbols | 28 8 files changed, 3880 insertions(+), 5 deletions(-) diff -Nru ppp-2.4.7/debian/changelog ppp-2.4.7/debian/changelog --- ppp-2.4.7/debian/changelog 2016-01-27 08:48:44.000000000 +0000 +++ ppp-2.4.7/debian/changelog 2018-06-12 17:28:41.000000000 +0000 @@ -1,3 +1,29 @@ +ppp (2.4.7-1+2ubuntu1.16.04.1) xenial-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:28:33 -0400 + +ppp (2.4.7-1+2ubuntu1) xenial; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + - debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch: EAP-TLS/MPPE support + patch from Jan Just Keijser. + - debian/control: add libssl-dev to Build-Depends for the EAP-TLS patch. + - debian/ppp.preinst: deal with the change in LSB headers start runlevels + of pppd-dns due to dropping our changes (which are no longer necessary + since resolvconf is installed in most systems and has been for a while); + this should probably be kept until the next LTS. + * debian/ppp.symbols: + - Update the symbols to include changes from our Ubuntu patches. + + -- Łukasz 'sil2100' Zemczak Thu, 28 Jan 2016 10:01:37 +0100 + ppp (2.4.7-1+2) unstable; urgency=medium * Replace my email address for my debian.org address. @@ -39,6 +65,21 @@ -- Chris Boot Sat, 05 Dec 2015 13:35:51 +0000 +ppp (2.4.7-1+1ubuntu1) xenial; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + - debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch: EAP-TLS/MPPE support + patch from Jan Just Keijser. + - debian/control: add libssl-dev to Build-Depends for the EAP-TLS patch. + - debian/ppp.preinst: deal with the change in LSB headers start runlevels + of pppd-dns due to dropping our changes (which are no longer necessary + since resolvconf is installed in most systems and has been for a while); + this should probably be kept until the next LTS. + + -- Łukasz 'sil2100' Zemczak Thu, 07 Jan 2016 13:27:59 +0100 + ppp (2.4.7-1+1) unstable; urgency=medium * Upload to unstable. @@ -88,6 +129,23 @@ -- Chris Boot Fri, 06 Nov 2015 15:32:25 +0000 +ppp (2.4.6-3.1ubuntu1) vivid; urgency=low + + * Merge from Debian unstable. Remaining changes: + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + - add EAP-TLS/MPPE support patch from Jan Just Keijser. + - debian/control: add libssl-dev to Build-Depends for the EAP-TLS patch. + * debian/patches/ppp-2.4.5-eaptls-mppe-0.994.patch, + debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch: updated the EAP-TLS/MPPE + support patch to the latest version from its upstream (also refreshed it). + * debian/ppp.preinst: deal with the change in LSB headers start runlevels + of pppd-dns due to dropping our changes (which are no longer necessary + since resolvconf is installed in most systems and has been for a while); + this should probably be kept until the next LTS. + + -- Scott Kitterman Thu, 16 Apr 2015 09:07:29 -0400 + ppp (2.4.6-3.1) unstable; urgency=high * Non-maintainer upload. @@ -101,6 +159,23 @@ -- Emanuele Rocca Tue, 14 Apr 2015 08:18:06 +0200 +ppp (2.4.6-3ubuntu1) vivid; urgency=medium + + * Merge with Debian unstable; remaining changes: + - debian/patches/load_ppp_generic_if_needed: load ppp_generic kernel + module if needed. + - add EAP-TLS/MPPE support patch from Jan Just Keijser. + - debian/control: add libssl-dev to Build-Depends for the EAP-TLS patch. + * debian/patches/ppp-2.4.5-eaptls-mppe-0.994.patch, + debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch: updated the EAP-TLS/MPPE + support patch to the latest version from its upstream (also refreshed it). + * debian/ppp.preinst: deal with the change in LSB headers start runlevels + of pppd-dns due to dropping our changes (which are no longer necessary + since resolvconf is installed in most systems and has been for a while); + this should probably be kept until the next LTS. + + -- Mathieu Trudel-Lapierre Fri, 19 Dec 2014 13:51:52 -0500 + ppp (2.4.6-3) unstable; urgency=high * Urgency high due to fix for CVE-2014-3158. @@ -275,6 +350,39 @@ -- Chris Boot Tue, 28 May 2013 15:56:31 +0100 +ppp (2.4.5-5.1ubuntu3) utopic; urgency=medium + + * Drop gdm dependency from the pppd-dns script, to resolve failing to + configure ppp package without having gdm's init.d script enabled (and + thus gdm installed & configured). + + -- Dimitri John Ledkov Thu, 29 May 2014 08:54:57 +0200 + +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. @@ -282,12 +390,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 @@ -364,6 +509,115 @@ -- 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-10.1) unstable; urgency=low + + * Non-maintainer upload. + * Fix pending l10n issues. Debconf translations: + - Traditional Chinese. Closes: #505952 + - Catalan. Closes: #506336 + - Swedish. Closes: #491421 + - Japanese. Closes: #489333 + - Polish. Closes: #506852 + - Belarusian. Closes: #506927 + + -- Christian Perrier Fri, 28 Nov 2008 18:36:26 +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. @@ -400,6 +654,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 @@ -473,6 +745,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. @@ -485,6 +773,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 ] @@ -538,6 +836,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: @@ -553,6 +857,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: @@ -582,6 +916,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 @@ -597,6 +937,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. @@ -656,6 +1010,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. @@ -674,6 +1034,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) @@ -716,6 +1097,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 @@ -1092,3 +1533,4 @@ just removing selected files within. (Closes: #107910) -- Michael Beattie Sat, 29 Sep 2001 23:15:44 +1200 + diff -Nru ppp-2.4.7/debian/control ppp-2.4.7/debian/control --- ppp-2.4.7/debian/control 2015-12-30 18:31:26.000000000 +0000 +++ ppp-2.4.7/debian/control 2016-01-28 09:00:25.000000000 +0000 @@ -2,10 +2,11 @@ Section: admin Priority: optional Homepage: http://ppp.samba.org/ -Maintainer: Chris Boot +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Chris Boot Uploaders: Marco d'Itri Build-Depends: debhelper (>= 9~), libpcap0.8-dev, libpam0g-dev, zlib1g-dev, - dh-systemd + dh-systemd, libssl-dev Standards-Version: 3.9.6 Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/pkg-ppp.git Vcs-Git: git://anonscm.debian.org/collab-maint/pkg-ppp.git diff -Nru ppp-2.4.7/debian/patches/CVE-2018-11574.patch ppp-2.4.7/debian/patches/CVE-2018-11574.patch --- ppp-2.4.7/debian/patches/CVE-2018-11574.patch 1970-01-01 00:00:00.000000000 +0000 +++ ppp-2.4.7/debian/patches/CVE-2018-11574.patch 2018-06-12 17:28:27.000000000 +0000 @@ -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.7/pppd/eap.c +=================================================================== +--- ppp-2.4.7.orig/pppd/eap.c 2018-06-12 13:24:54.042983060 -0400 ++++ ppp-2.4.7/pppd/eap.c 2018-06-12 13:24:54.038983052 -0400 +@@ -1703,6 +1703,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){ + +@@ -1740,6 +1745,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) { +@@ -2110,6 +2120,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)); +@@ -2130,19 +2141,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.7/pppd/eap-tls.c +=================================================================== +--- ppp-2.4.7.orig/pppd/eap-tls.c 2018-06-12 13:24:54.042983060 -0400 ++++ ppp-2.4.7/pppd/eap-tls.c 2018-06-12 13:26:47.835247118 -0400 +@@ -798,46 +798,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) { + /* +@@ -857,8 +858,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; + } + +@@ -872,7 +878,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; + } + diff -Nru ppp-2.4.7/debian/patches/load_ppp_generic_if_needed ppp-2.4.7/debian/patches/load_ppp_generic_if_needed --- ppp-2.4.7/debian/patches/load_ppp_generic_if_needed 1970-01-01 00:00:00.000000000 +0000 +++ ppp-2.4.7/debian/patches/load_ppp_generic_if_needed 2014-11-04 21:39:49.000000000 +0000 @@ -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" diff -Nru ppp-2.4.7/debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch ppp-2.4.7/debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch --- ppp-2.4.7/debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch 1970-01-01 00:00:00.000000000 +0000 +++ ppp-2.4.7/debian/patches/ppp-2.4.6-eaptls-mppe-0.997.patch 2014-11-05 04:54:51.000000000 +0000 @@ -0,0 +1,3161 @@ +Author: Jan Just Keijser +Description: EAP-TLS patch for pppd +Bug-Ubuntu: https://launchpad.net/bugs/643417 +Bug-Debian: http://bugs.debian.org/602503 +Bug-Fedora: https://bugzilla.redhat.com/556407 +Origin: http://www.nikhef.nl/~janjust/ppp/download.html + +--- + README.eap-tls | 280 ++++++++++ + etc.ppp/eaptls-client | 10 + etc.ppp/eaptls-server | 11 + etc.ppp/openssl.cnf | 14 + linux/Makefile.top | 6 + pppd/Makefile.linux | 12 + pppd/auth.c | 413 ++++++++++++++ + pppd/ccp.c | 20 + pppd/chap-md5.c | 4 + pppd/eap-tls.c | 1212 ++++++++++++++++++++++++++++++++++++++++++++ + pppd/eap-tls.h | 107 +++ + pppd/eap.c | 449 ++++++++++++++++ + pppd/eap.h | 32 + + pppd/md5.c | 4 + pppd/md5.h | 3 + pppd/pathnames.h | 7 + pppd/plugins/Makefile.linux | 3 + pppd/plugins/passprompt.c | 3 + pppd/plugins/passwordfd.c | 4 + pppd/pppd.8 | 33 + + pppd/pppd.h | 9 + 21 files changed, 2629 insertions(+), 7 deletions(-) + +Index: b/README.eap-tls +=================================================================== +--- /dev/null ++++ b/README.eap-tls +@@ -0,0 +1,280 @@ ++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 ++ Use the Certificate Revocation List (CRL) file in PEM format. ++ crl-dir ++ Use CRL files from directory . It contains CRL files in PEM ++ format and each file contains a CRL. The files are looked up ++ by the issuer name hash value. Use the c_rehash utility ++ to create necessary links. ++ need-peer-eap ++ If the peer doesn't ask us to authenticate or doesn't use eap ++ to authenticate us, disconnect. ++ ++ Note: ++ password-encrypted certificates can be used as of v0.94 of this ++ patch. The password for the eap-tls.key file is specified using ++ the regular ++ password .... ++ statement in the ppp options file, or by using the appropriate ++ plugin which supplies a 'eaptls_passwd_hook' routine. ++ ++5. Connecting ++ ++ If you're setting up a pppd server, edit the EAP-TLS configuration file ++ as written above and then run pppd with the 'auth' option to authenticate ++ the client. The EAP-TLS method will be used if the other eap methods can't ++ be used (no secrets). ++ ++ If you're setting up a client, edit the configuration file and then run ++ pppd with 'remotename' option to specify the server name. Add the ++ 'need-peer-eap' option if you want to be sure the peer ask you to ++ authenticate (and to use eap) and to disconnect if it doesn't. ++ ++6. Example ++ ++ The following example can be used to connect a Linux client with the 'pptp' ++ package to a Linux server running the 'pptpd' (PoPToP) package. The server ++ was configured with a certificate with name (CN) 'pptp-server', the client ++ was configured with a certificate with name (CN) 'pptp-client', both ++ signed by the same Certificate Authority (CA). ++ ++ Server side: ++ - /etc/pptpd.conf file: ++ option /etc/ppp/options-pptpd-eaptls ++ localip 172.16.1.1 ++ remoteip 172.16.1.10-20 ++ - /etc/ppp/options-pptpd-eaptls file: ++ name pptp-server ++ lock ++ mtu 1500 ++ mru 1450 ++ auth ++ lcp-echo-failure 3 ++ lcp-echo-interval 5 ++ nodeflate ++ nobsdcomp ++ nopredictor1 ++ nopcomp ++ noaccomp ++ ++ require-eap ++ require-mppe-128 ++ ++ crl /home/janjust/ppp/keys/crl.pem ++ ++ debug ++ logfile /tmp/pppd.log ++ ++ - /etc/ppp/eaptls-server file: ++ * pptp-server - /etc/ppp/pptp-server.crt /etc/ppp/ca.crt /etc/ppp/pptp-server.key * ++ ++ - On the server, run ++ pptdp --conf /etc/pptpd.conf ++ ++ Client side: ++ - Run ++ pppd noauth require-eap require-mppe-128 \ ++ ipcp-accept-local ipcp-accept-remote noipdefault \ ++ cert /etc/ppp/keys/pptp-client.crt \ ++ key /etc/ppp/keys/pptp-client.key \ ++ ca /etc/ppp/keys/ca.crt \ ++ name pptp-client remotename pptp-server \ ++ debug logfile /tmp/pppd.log ++ pty "pptp pptp-server.example.com --nolaunchpppd" ++ ++ Check /var/log/messages and the files /tmp/pppd.log on both sides for debugging info. ++ ++7. Notes ++ ++ This is experimental code. ++ Send suggestions and comments to Jan Just Keijser ++ ++8. Changelog of ppp-<>-eaptls-mppe-* patches ++ ++v0.7 (22-Nov-2005) ++ - First version of the patch to include MPPE support ++ - ppp-2.4.3 only ++v0.9 (25-Jul-2006) ++ - Bug fixes ++ - First version for ppp-2.4.4 ++v0.91 (03-Sep-2006) ++ - Added missing #include for md5.h ++ - Last version for ppp-2.4.3 ++v0.92 (22-Apr-2008) ++ - Fix for openssl 0.9.8 issue with md5 function overload. ++v0.93 (14-Aug-2008) ++ - Make sure 'noauth' option can be used to bypass server certificate verification. ++v0.94 (15-Oct-2008) ++ - Added support for password-protected private keys by (ab)using the 'password' field. ++v0.95 (23-Dec-2009) ++ - First version with OpenSSL engine support. ++v0.96 (27-Jan-2010) ++ - Added fully functional support for OpenSSL engines (PKCS#11) ++ - First version for ppp-2.4.5 ++v0.97 (20-Apr-2010) ++ - Some bug fixes for v0.96 ++ - Added support for entering the password via a plugin. The sample plugin ++ .../pppd/plugins/passprompt.c has been extended with EAP-TLS support. ++ The "old" methods using the password option or the /etc/ppp/openssl.cnf file still work. ++ - Added support for specifying the client CA, certificate and private key on the command-line ++ or via the ppp config file. ++v0.98 (20-Apr-2010) ++ - Fix initialisation bug when using ca/cert/key command-line options. ++ - Last version for ppp-2.4.4 ++v0.99 (05-Oct-2010) ++ - Fix coredump when using multilink option. ++v0.991 (08-Aug-2011) ++ - Fix compilation issue with openssl 1.0. ++v0.992 (01-Dec-2011) ++ - Fix compilation issue with eaptls_check_hook and passwordfd plugin. ++v0.993 (24-Apr-2012) ++ - Fix compilation issue when EAP_TLS=n in pppd/Makefile. ++v0.994 (11-Jun-2012) ++ - Fix compilation issue on Ubuntu 11.10. ++v0.995 (27-May-2014) ++ - Add support for a CRL file using the command-line option 'crl' ++ (prior only 'crl-dir' was supported). ++ - Fix segfault when pkcs11 enginename was not specified correctly. ++ - Fix segfault when client was misconfigured. ++ - Disable SSL Session Ticket support as Windows 8 does not support this. ++v0.996 (28-May-2014) ++ - Fix minor bug where SessionTicket message was printed as 'Unknown SSL3 code 4' ++ - Add EAP-TLS-specific options to pppd.8 manual page. ++ - Updated README.eap-tls file with new option and provide an example. ++v0.997 (19-Jun-2014) ++ - change SSL_OP_NO_TICKETS to SSL_OP_NO_TICKET ++ - fix bug in initialisation code with fragmented packets. ++ +Index: b/etc.ppp/eaptls-client +=================================================================== +--- /dev/null ++++ b/etc.ppp/eaptls-client +@@ -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: b/etc.ppp/eaptls-server +=================================================================== +--- /dev/null ++++ b/etc.ppp/eaptls-server +@@ -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: b/etc.ppp/openssl.cnf +=================================================================== +--- /dev/null ++++ b/etc.ppp/openssl.cnf +@@ -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: b/linux/Makefile.top +=================================================================== +--- a/linux/Makefile.top ++++ b/linux/Makefile.top +@@ -26,7 +26,7 @@ install-progs: + cd pppdump; $(MAKE) $(MFLAGS) install + + install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ +- $(ETCDIR)/chap-secrets ++ $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client + + install-devel: + cd pppd; $(MAKE) $(MFLAGS) install-devel +@@ -37,6 +37,10 @@ $(ETCDIR)/pap-secrets: + $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@ + $(ETCDIR)/chap-secrets: + $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@ ++$(ETCDIR)/eaptls-server: ++ $(INSTALL) -c -m 600 etc.ppp/eaptls-server $@ ++$(ETCDIR)/eaptls-client: ++ $(INSTALL) -c -m 600 etc.ppp/eaptls-client $@ + + $(BINDIR): + $(INSTALL) -d -m 755 $@ +Index: b/pppd/Makefile.linux +=================================================================== +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -76,6 +76,9 @@ CBCP=y + # Use libutil + USE_LIBUTIL=y + ++# Enable EAP-TLS authentication (requires libssl and libcrypto) ++USE_EAPTLS=y ++ + MAXOCTETS=y + + INCLUDE_DIRS= -I../include +@@ -116,6 +119,15 @@ HEADERS += sha1.h + PPPDOBJS += sha1.o + endif + ++# EAP-TLS ++ifdef USE_EAPTLS ++CFLAGS += -DUSE_EAPTLS=1 -I/usr/kerberos/include ++LIBS += -lssl -lcrypto ++PPPDSRC += eap-tls.c ++HEADERS += eap-tls.h ++PPPDOBJS += eap-tls.o ++endif ++ + ifdef HAS_SHADOW + CFLAGS += -DHAS_SHADOW + #LIBS += -lshadow $(LIBS) +Index: b/pppd/auth.c +=================================================================== +--- a/pppd/auth.c ++++ b/pppd/auth.c +@@ -109,6 +109,9 @@ + #include "upap.h" + #include "chap-new.h" + #include "eap.h" ++#ifdef USE_EAPTLS ++#include "eap-tls.h" ++#endif + #ifdef CBCP_SUPPORT + #include "cbcp.h" + #endif +@@ -183,6 +186,11 @@ int (*chap_check_hook) __P((void)) = NUL + /* Hook for a plugin to get the CHAP password for authenticating us */ + int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; + ++#ifdef USE_EAPTLS ++/* Hook for a plugin to get the EAP-TLS password for authenticating us */ ++int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL; ++#endif ++ + /* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ + int (*null_auth_hook) __P((struct wordlist **paddrs, +@@ -238,6 +246,14 @@ bool explicit_remote = 0; /* User specif + bool explicit_user = 0; /* Set if "user" option supplied */ + bool explicit_passwd = 0; /* Set if "password" option supplied */ + char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ ++#ifdef USE_EAPTLS ++char *cacert_file = NULL; /* CA certificate file (pem format) */ ++char *cert_file = NULL; /* client certificate file (pem format) */ ++char *privkey_file = NULL; /* client private key file (pem format) */ ++char *crl_dir = NULL; /* directory containing CRL files */ ++char *crl_file = NULL; /* Certificate Revocation List (CRL) file (pem format) */ ++bool need_peer_eap = 0; /* Require peer to authenticate us */ ++#endif + + static char *uafname; /* name of most recent +ua file */ + +@@ -254,6 +270,19 @@ static int have_pap_secret __P((int *)) + static int have_chap_secret __P((char *, char *, int, int *)); + static int have_srp_secret __P((char *client, char *server, int need_ip, + int *lacks_ipp)); ++ ++#ifdef USE_EAPTLS ++static int have_eaptls_secret_server ++__P((char *client, char *server, int need_ip, int *lacks_ipp)); ++static int have_eaptls_secret_client __P((char *client, char *server)); ++static int scan_authfile_eaptls __P((FILE * f, char *client, char *server, ++ char *cli_cert, char *serv_cert, ++ char *ca_cert, char *pk, ++ struct wordlist ** addrs, ++ struct wordlist ** opts, ++ char *filename, int flags)); ++#endif ++ + static int ip_addr_check __P((u_int32_t, struct permitted_ip *)); + static int scan_authfile __P((FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, +@@ -401,6 +430,15 @@ option_t auth_options[] = { + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + ++#ifdef USE_EAPTLS ++ { "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" }, ++ { "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" }, ++ { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" }, ++ { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" }, ++ { "crl", o_string, &crl_file, "Use specific CRL file" }, ++ { "need-peer-eap", o_bool, &need_peer_eap, ++ "Require the peer to authenticate us", 1 }, ++#endif /* USE_EAPTLS */ + { NULL } + }; + +@@ -730,6 +768,9 @@ link_established(unit) + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ho = &lcp_hisoptions[unit]; ++#ifdef USE_EAPTLS ++ lcp_options *ao = &lcp_allowoptions[unit]; ++#endif + int i; + struct protent *protp; + +@@ -764,6 +805,22 @@ link_established(unit) + } + } + ++#ifdef USE_EAPTLS ++ if (need_peer_eap && !ao->neg_eap) { ++ warn("eap required to authenticate us but no suitable secrets"); ++ lcp_close(unit, "couldn't negotiate eap"); ++ status = EXIT_AUTH_TOPEER_FAILED; ++ return; ++ } ++ ++ if (need_peer_eap && !ho->neg_eap) { ++ warn("peer doesn't want to authenticate us with eap"); ++ lcp_close(unit, "couldn't negotiate eap"); ++ status = EXIT_PEER_AUTH_FAILED; ++ return; ++ } ++#endif ++ + new_phase(PHASE_AUTHENTICATE); + auth = 0; + if (go->neg_eap) { +@@ -1277,6 +1334,15 @@ auth_check_options() + our_name, 1, &lacks_ip); + } + ++#ifdef USE_EAPTLS ++ if (!can_auth && wo->neg_eap) { ++ can_auth = ++ have_eaptls_secret_server((explicit_remote ? remote_name : ++ NULL), our_name, 1, &lacks_ip); ++ ++ } ++#endif ++ + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +@@ -1331,7 +1397,11 @@ auth_reset(unit) + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, + (explicit_remote? remote_name: NULL), 0, NULL))) || +- have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); ++ have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL) ++#ifdef USE_EAPTLS ++ || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL)) ++#endif ++ ); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) +@@ -1346,8 +1416,14 @@ auth_reset(unit) + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, +- NULL)) ++ NULL) ++#ifdef USE_EAPTLS ++ && !have_eaptls_secret_server((explicit_remote? remote_name: NULL), ++ our_name, 1, NULL) ++#endif ++ ) + go->neg_eap = 0; ++ + } + + +@@ -1709,6 +1785,7 @@ have_srp_secret(client, server, need_ip, + } + + ++ + /* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. +@@ -2361,3 +2438,335 @@ auth_script(script) + + auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0); + } ++ ++ ++#ifdef USE_EAPTLS ++static int ++have_eaptls_secret_server(client, server, need_ip, lacks_ipp) ++ char *client; ++ char *server; ++ int need_ip; ++ int *lacks_ipp; ++{ ++ FILE *f; ++ int ret; ++ char *filename; ++ struct wordlist *addrs; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ ++ filename = _PATH_EAPTLSSERVFILE; ++ f = fopen(filename, "r"); ++ if (f == NULL) ++ return 0; ++ ++ if (client != NULL && client[0] == 0) ++ client = NULL; ++ else if (server != NULL && server[0] == 0) ++ server = NULL; ++ ++ ret = ++ scan_authfile_eaptls(f, client, server, clicertfile, servcertfile, ++ cacertfile, pkfile, &addrs, NULL, filename, ++ 0); ++ ++ fclose(f); ++ ++/* ++ if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile, ++ clicertfile, pkfile)) ++ ret = -1; ++*/ ++ ++ if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { ++ if (lacks_ipp != 0) ++ *lacks_ipp = 1; ++ ret = -1; ++ } ++ if (addrs != 0) ++ free_wordlist(addrs); ++ ++ return ret >= 0; ++} ++ ++ ++static int ++have_eaptls_secret_client(client, server) ++ char *client; ++ char *server; ++{ ++ FILE *f; ++ int ret; ++ char *filename; ++ struct wordlist *addrs = NULL; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ ++ if (client != NULL && client[0] == 0) ++ client = NULL; ++ else if (server != NULL && server[0] == 0) ++ server = NULL; ++ ++ if (cacert_file && cert_file && privkey_file) ++ return 1; ++ ++ filename = _PATH_EAPTLSCLIFILE; ++ f = fopen(filename, "r"); ++ if (f == NULL) ++ return 0; ++ ++ ret = ++ scan_authfile_eaptls(f, client, server, clicertfile, servcertfile, ++ cacertfile, pkfile, &addrs, NULL, filename, ++ 0); ++ fclose(f); ++ ++/* ++ if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile, ++ servcertfile, pkfile)) ++ ret = -1; ++*/ ++ ++ if (addrs != 0) ++ free_wordlist(addrs); ++ ++ return ret >= 0; ++} ++ ++ ++static int ++scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk, ++ addrs, opts, filename, flags) ++ FILE *f; ++ char *client; ++ char *server; ++ char *cli_cert; ++ char *serv_cert; ++ char *ca_cert; ++ char *pk; ++ struct wordlist **addrs; ++ struct wordlist **opts; ++ char *filename; ++ int flags; ++{ ++ int newline; ++ int got_flag, best_flag; ++ struct wordlist *ap, *addr_list, *alist, **app; ++ char word[MAXWORDLEN]; ++ ++ if (addrs != NULL) ++ *addrs = NULL; ++ if (opts != NULL) ++ *opts = NULL; ++ addr_list = NULL; ++ if (!getword(f, word, &newline, filename)) ++ return -1; /* file is empty??? */ ++ newline = 1; ++ best_flag = -1; ++ for (;;) { ++ /* ++ * Skip until we find a word at the start of a line. ++ */ ++ while (!newline && getword(f, word, &newline, filename)); ++ if (!newline) ++ break; /* got to end of file */ ++ ++ /* ++ * Got a client - check if it's a match or a wildcard. ++ */ ++ got_flag = 0; ++ if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { ++ newline = 0; ++ continue; ++ } ++ if (!ISWILD(word)) ++ got_flag = NONWILD_CLIENT; ++ ++ /* ++ * Now get a server and check if it matches. ++ */ ++ if (!getword(f, word, &newline, filename)) ++ break; ++ if (newline) ++ continue; ++ if (!ISWILD(word)) { ++ if (server != NULL && strcmp(word, server) != 0) ++ continue; ++ got_flag |= NONWILD_SERVER; ++ } ++ ++ /* ++ * Got some sort of a match - see if it's better than what ++ * we have already. ++ */ ++ if (got_flag <= best_flag) ++ continue; ++ ++ /* ++ * Get the cli_cert ++ */ ++ if (!getword(f, word, &newline, filename)) ++ break; ++ if (newline) ++ continue; ++ if (strcmp(word, "-") != 0) { ++ strlcpy(cli_cert, word, MAXWORDLEN); ++ } else ++ cli_cert[0] = 0; ++ ++ /* ++ * Get serv_cert ++ */ ++ if (!getword(f, word, &newline, filename)) ++ break; ++ if (newline) ++ continue; ++ if (strcmp(word, "-") != 0) { ++ strlcpy(serv_cert, word, MAXWORDLEN); ++ } else ++ serv_cert[0] = 0; ++ ++ /* ++ * Get ca_cert ++ */ ++ if (!getword(f, word, &newline, filename)) ++ break; ++ if (newline) ++ continue; ++ strlcpy(ca_cert, word, MAXWORDLEN); ++ ++ /* ++ * Get pk ++ */ ++ if (!getword(f, word, &newline, filename)) ++ break; ++ if (newline) ++ continue; ++ strlcpy(pk, word, MAXWORDLEN); ++ ++ ++ /* ++ * Now read address authorization info and make a wordlist. ++ */ ++ app = &alist; ++ for (;;) { ++ if (!getword(f, word, &newline, filename) || newline) ++ break; ++ ap = (struct wordlist *) ++ malloc(sizeof(struct wordlist) + strlen(word) + 1); ++ if (ap == NULL) ++ novm("authorized addresses"); ++ ap->word = (char *) (ap + 1); ++ strcpy(ap->word, word); ++ *app = ap; ++ app = &ap->next; ++ } ++ *app = NULL; ++ /* ++ * This is the best so far; remember it. ++ */ ++ best_flag = got_flag; ++ if (addr_list) ++ free_wordlist(addr_list); ++ addr_list = alist; ++ ++ if (!newline) ++ break; ++ } ++ ++ /* scan for a -- word indicating the start of options */ ++ for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) ++ if (strcmp(ap->word, "--") == 0) ++ break; ++ /* ap = start of options */ ++ if (ap != NULL) { ++ ap = ap->next; /* first option */ ++ free(*app); /* free the "--" word */ ++ *app = NULL; /* terminate addr list */ ++ } ++ if (opts != NULL) ++ *opts = ap; ++ else if (ap != NULL) ++ free_wordlist(ap); ++ if (addrs != NULL) ++ *addrs = addr_list; ++ else if (addr_list != NULL) ++ free_wordlist(addr_list); ++ ++ return best_flag; ++} ++ ++ ++int ++get_eaptls_secret(unit, client, server, clicertfile, servcertfile, ++ cacertfile, pkfile, am_server) ++ int unit; ++ char *client; ++ char *server; ++ char *clicertfile; ++ char *servcertfile; ++ char *cacertfile; ++ char *pkfile; ++ int am_server; ++{ ++ FILE *fp; ++ int ret; ++ char *filename = NULL; ++ struct wordlist *addrs = NULL; ++ struct wordlist *opts = NULL; ++ ++ /* in client mode the ca+cert+privkey can also be specified as options */ ++ if (!am_server && cacert_file && cert_file && privkey_file ) ++ { ++ strlcpy( clicertfile, cert_file, MAXWORDLEN ); ++ strlcpy( cacertfile, cacert_file, MAXWORDLEN ); ++ strlcpy( pkfile, privkey_file, MAXWORDLEN ); ++ servcertfile[0] = '\0'; ++ } ++ else ++ { ++ filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE); ++ addrs = NULL; ++ ++ fp = fopen(filename, "r"); ++ if (fp == NULL) ++ { ++ error("Can't open eap-tls secret file %s: %m", filename); ++ return 0; ++ } ++ ++ check_access(fp, filename); ++ ++ ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile, ++ cacertfile, pkfile, &addrs, &opts, filename, 0); ++ ++ fclose(fp); ++ ++ if (ret < 0) return 0; ++ } ++ ++ if (eaptls_passwd_hook) ++ { ++ dbglog( "Calling eaptls password hook" ); ++ if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0) ++ { ++ error("Unable to obtain EAP-TLS password for %s (%s) from plugin", ++ client, pkfile); ++ return 0; ++ } ++ } ++ if (am_server) ++ set_allowed_addrs(unit, addrs, opts); ++ else if (opts != NULL) ++ free_wordlist(opts); ++ if (addrs != NULL) ++ free_wordlist(addrs); ++ ++ return 1; ++} ++#endif ++ +Index: b/pppd/ccp.c +=================================================================== +--- a/pppd/ccp.c ++++ b/pppd/ccp.c +@@ -540,6 +540,9 @@ ccp_resetci(f) + if (go->mppe) { + ccp_options *ao = &ccp_allowoptions[f->unit]; + int auth_mschap_bits = auth_done[f->unit]; ++#ifdef USE_EAPTLS ++ int auth_eap_bits = auth_done[f->unit]; ++#endif + int numbits; + + /* +@@ -567,8 +570,23 @@ ccp_resetci(f) + lcp_close(f->unit, "MPPE required but not available"); + return; + } ++ ++#ifdef USE_EAPTLS ++ /* ++ * MPPE is also possible in combination with EAP-TLS. ++ * It is not possible to detect if we're doing EAP or EAP-TLS ++ * at this stage, hence we accept all forms of EAP. If TLS is ++ * not used then the MPPE keys will not be derived anyway. ++ */ ++ /* Leave only the eap auth bits set */ ++ auth_eap_bits &= (EAP_WITHPEER | EAP_PEER ); ++ ++ if ((numbits == 0) && (auth_eap_bits == 0)) { ++ error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed."); ++#else + if (!numbits) { +- error("MPPE required, but MS-CHAP[v2] auth not performed."); ++ error("MPPE required, but MS-CHAP[v2] auth not performed."); ++#endif + lcp_close(f->unit, "MPPE required but not available"); + return; + } +Index: b/pppd/chap-md5.c +=================================================================== +--- a/pppd/chap-md5.c ++++ b/pppd/chap-md5.c +@@ -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: b/pppd/eap-tls.c +=================================================================== +--- /dev/null ++++ b/pppd/eap-tls.c +@@ -0,0 +1,1212 @@ ++/* ++ * 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 ( cert_engine && 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; ++ } ++ ++ /* Explicitly set the NO_TICKETS flag to support Win7/Win8 clients */ ++ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ++#ifdef SSL_OP_NO_TICKET ++ | SSL_OP_NO_TICKET ++#endif ++); ++ 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 (crl_file) { ++ FILE *fp = NULL; ++ X509_CRL *crl = NULL; ++ ++ fp = fopen(crl_file, "r"); ++ if (!fp) { ++ error("EAP-TLS: Cannot open CRL file '%s'", crl_file); ++ goto fail; ++ } ++ ++ crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL); ++ if (!crl) { ++ error("EAP-TLS: Cannot read CRL file '%s'", crl_file); ++ goto fail; ++ } ++ ++ if (!(certstore = SSL_CTX_get_cert_store(ctx))) { ++ error("EAP-TLS: Failed to get certificate store"); ++ goto fail; ++ } ++ if (!X509_STORE_add_crl(certstore, crl)) { ++ error("EAP-TLS: Cannot add CRL to certificate store"); ++ goto fail; ++ } ++ 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, ++ ets->peer, clicertfile, ++ servcertfile, cacertfile, pkfile, 0)) { ++ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", ++ esp->es_client.ea_name, ets->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; ++#ifdef SSL3_MT_NEWSESSION_TICKET ++ case SSL3_MT_NEWSESSION_TICKET: ++ strcat(string,"New Session Ticket"); ++ break; ++#endif ++ 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: b/pppd/eap-tls.h +=================================================================== +--- /dev/null ++++ b/pppd/eap-tls.h +@@ -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: b/pppd/eap.c +=================================================================== +--- a/pppd/eap.c ++++ b/pppd/eap.c +@@ -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 @@ int unit; + esp->es_server.ea_id = (u_char)(drand48() * 0x100); + esp->es_client.ea_timeout = EAP_DEFREQTIME; + esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ; ++#ifdef USE_EAPTLS ++ esp->es_client.ea_using_eaptls = 0; ++#endif /* USE_EAPTLS */ + } + + /* +@@ -436,8 +448,16 @@ int status; + u_char vals[2]; + struct b64state bs; + #endif /* USE_SRP */ ++#ifdef USE_EAPTLS ++ struct eaptls_session *ets; ++ int secret_len; ++ char secret[MAXWORDLEN]; ++#endif /* USE_EAPTLS */ + + esp->es_server.ea_timeout = esp->es_savedtime; ++#ifdef USE_EAPTLS ++ esp->es_server.ea_prev_state = esp->es_server.ea_state; ++#endif /* USE_EAPTLS */ + switch (esp->es_server.ea_state) { + case eapBadAuth: + return; +@@ -562,9 +582,79 @@ int status; + break; + } + #endif /* USE_SRP */ ++#ifdef USE_EAPTLS ++ if (!get_secret(esp->es_unit, esp->es_server.ea_peer, ++ esp->es_server.ea_name, secret, &secret_len, 1)) { ++ ++ esp->es_server.ea_state = eapTlsStart; ++ break; ++ } ++#endif /* USE_EAPTLS */ ++ + esp->es_server.ea_state = eapMD5Chall; + break; + ++#ifdef USE_EAPTLS ++ case eapTlsStart: ++ /* Initialize ssl session */ ++ if(!eaptls_init_ssl_server(esp)) { ++ esp->es_server.ea_state = eapBadAuth; ++ break; ++ } ++ ++ esp->es_server.ea_state = eapTlsRecv; ++ break; ++ ++ case eapTlsRecv: ++ ets = (struct eaptls_session *) esp->es_server.ea_session; ++ ++ if(ets->alert_sent) { ++ esp->es_server.ea_state = eapTlsSendAlert; ++ break; ++ } ++ ++ if (status) { ++ esp->es_server.ea_state = eapBadAuth; ++ break; ++ } ++ ets = (struct eaptls_session *) esp->es_server.ea_session; ++ ++ if(ets->frag) ++ esp->es_server.ea_state = eapTlsSendAck; ++ else ++ esp->es_server.ea_state = eapTlsSend; ++ break; ++ ++ case eapTlsSend: ++ ets = (struct eaptls_session *) esp->es_server.ea_session; ++ ++ if(ets->frag) ++ esp->es_server.ea_state = eapTlsRecvAck; ++ else ++ if(SSL_is_init_finished(ets->ssl)) ++ esp->es_server.ea_state = eapTlsRecvClient; ++ else ++ esp->es_server.ea_state = eapTlsRecv; ++ break; ++ ++ case eapTlsSendAck: ++ esp->es_server.ea_state = eapTlsRecv; ++ break; ++ ++ case eapTlsRecvAck: ++ if (status) { ++ esp->es_server.ea_state = eapBadAuth; ++ break; ++ } ++ ++ esp->es_server.ea_state = eapTlsSend; ++ break; ++ ++ case eapTlsSendAlert: ++ esp->es_server.ea_state = eapTlsRecvAlertAck; ++ break; ++#endif /* USE_EAPTLS */ ++ + case eapSRP1: + #ifdef USE_SRP + ts = (struct t_server *)esp->es_server.ea_session; +@@ -718,6 +808,30 @@ eap_state *esp; + INCPTR(esp->es_server.ea_namelen, outp); + break; + ++#ifdef USE_EAPTLS ++ case eapTlsStart: ++ PUTCHAR(EAPT_TLS, outp); ++ PUTCHAR(EAP_TLS_FLAGS_START, outp); ++ eap_figure_next_state(esp, 0); ++ break; ++ ++ case eapTlsSend: ++ eaptls_send(esp->es_server.ea_session, &outp); ++ eap_figure_next_state(esp, 0); ++ break; ++ ++ case eapTlsSendAck: ++ PUTCHAR(EAPT_TLS, outp); ++ PUTCHAR(0, outp); ++ eap_figure_next_state(esp, 0); ++ break; ++ ++ case eapTlsSendAlert: ++ eaptls_send(esp->es_server.ea_session, &outp); ++ eap_figure_next_state(esp, 0); ++ break; ++#endif /* USE_EAPTLS */ ++ + #ifdef USE_SRP + case eapSRP1: + PUTCHAR(EAPT_SRP, outp); +@@ -904,11 +1018,57 @@ static void + eap_server_timeout(arg) + void *arg; + { ++#ifdef USE_EAPTLS ++ u_char *outp; ++ u_char *lenloc; ++ int outlen; ++#endif /* USE_EAPTLS */ ++ + eap_state *esp = (eap_state *) arg; + + if (!eap_server_active(esp)) + return; + ++#ifdef USE_EAPTLS ++ switch(esp->es_server.ea_prev_state) { ++ ++ /* ++ * In eap-tls the state changes after a request, so we return to ++ * previous state ... ++ */ ++ case(eapTlsStart): ++ case(eapTlsSendAck): ++ esp->es_server.ea_state = esp->es_server.ea_prev_state; ++ break; ++ ++ /* ++ * ... or resend the stored data ++ */ ++ case(eapTlsSend): ++ case(eapTlsSendAlert): ++ outp = outpacket_buf; ++ MAKEHEADER(outp, PPP_EAP); ++ PUTCHAR(EAP_REQUEST, outp); ++ PUTCHAR(esp->es_server.ea_id, outp); ++ lenloc = outp; ++ INCPTR(2, outp); ++ ++ eaptls_retransmit(esp->es_server.ea_session, &outp); ++ ++ outlen = (outp - outpacket_buf) - PPP_HDRLEN; ++ PUTSHORT(outlen, lenloc); ++ output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN); ++ esp->es_server.ea_requests++; ++ ++ if (esp->es_server.ea_timeout > 0) ++ TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout); ++ ++ return; ++ default: ++ break; ++ } ++#endif /* USE_EAPTLS */ ++ + /* EAP ID number must not change on timeout. */ + eap_send_request(esp); + } +@@ -1166,6 +1326,81 @@ u_char *str; + } + #endif /* USE_SRP */ + ++#ifdef USE_EAPTLS ++/* ++ * Send an EAP-TLS response message with tls data ++ */ ++static void ++eap_tls_response(esp, id) ++eap_state *esp; ++u_char id; ++{ ++ u_char *outp; ++ int outlen; ++ u_char *lenloc; ++ ++ outp = outpacket_buf; ++ ++ MAKEHEADER(outp, PPP_EAP); ++ ++ PUTCHAR(EAP_RESPONSE, outp); ++ PUTCHAR(id, outp); ++ ++ lenloc = outp; ++ INCPTR(2, outp); ++ ++ /* ++ If the id in the request is unchanged, we must retransmit ++ the old data ++ */ ++ if(id == esp->es_client.ea_id) ++ eaptls_retransmit(esp->es_client.ea_session, &outp); ++ else ++ eaptls_send(esp->es_client.ea_session, &outp); ++ ++ outlen = (outp - outpacket_buf) - PPP_HDRLEN; ++ PUTSHORT(outlen, lenloc); ++ ++ output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen); ++ ++ esp->es_client.ea_id = id; ++ ++} ++ ++/* ++ * Send an EAP-TLS ack ++ */ ++static void ++eap_tls_sendack(esp, id) ++eap_state *esp; ++u_char id; ++{ ++ u_char *outp; ++ int outlen; ++ u_char *lenloc; ++ ++ outp = outpacket_buf; ++ ++ MAKEHEADER(outp, PPP_EAP); ++ ++ PUTCHAR(EAP_RESPONSE, outp); ++ PUTCHAR(id, outp); ++ esp->es_client.ea_id = id; ++ ++ lenloc = outp; ++ INCPTR(2, outp); ++ ++ PUTCHAR(EAPT_TLS, outp); ++ PUTCHAR(0, outp); ++ ++ outlen = (outp - outpacket_buf) - PPP_HDRLEN; ++ PUTSHORT(outlen, lenloc); ++ ++ output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen); ++ ++} ++#endif /* USE_EAPTLS */ ++ + static void + eap_send_nak(esp, id, type) + eap_state *esp; +@@ -1320,6 +1555,11 @@ int len; + char rhostname[256]; + MD5_CTX mdContext; + u_char hash[MD5_SIGNATURE_SIZE]; ++#ifdef USE_EAPTLS ++ u_char flags; ++ struct eaptls_session *ets = esp->es_client.ea_session; ++#endif /* USE_EAPTLS */ ++ + #ifdef USE_SRP + struct t_client *tc; + struct t_num sval, gval, Nval, *Ap, Bval; +@@ -1456,6 +1696,90 @@ int len; + 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 +2061,11 @@ int len; + u_char dig[SHA_DIGESTSIZE]; + #endif /* USE_SRP */ + ++#ifdef USE_EAPTLS ++ struct eaptls_session *ets; ++ u_char flags; ++#endif /* USE_EAPTLS */ ++ + if (esp->es_server.ea_id != id) { + dbglog("EAP: discarding Response %d; expected ID %d", id, + esp->es_server.ea_id); +@@ -1776,6 +2105,60 @@ int len; + eap_figure_next_state(esp, 0); + break; + ++#ifdef USE_EAPTLS ++ case EAPT_TLS: ++ switch(esp->es_server.ea_state) { ++ ++ case eapTlsRecv: ++ ets = (struct eaptls_session *) esp->es_server.ea_session; ++ eap_figure_next_state(esp, ++ eaptls_receive(esp->es_server.ea_session, inp, len)); ++ ++ if(ets->alert_recv) { ++ eap_send_failure(esp); ++ break; ++ } ++ break; ++ ++ case eapTlsRecvAck: ++ if(len > 1) { ++ dbglog("EAP-TLS ACK with extra data"); ++ } ++ eap_figure_next_state(esp, 0); ++ break; ++ ++ case eapTlsRecvClient: ++ /* Receive authentication response from client */ ++ ++ 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 +2190,13 @@ int len; + esp->es_server.ea_state = eapMD5Chall; + break; + ++#ifdef USE_EAPTLS ++ /* Send EAP-TLS start packet */ ++ case EAPT_TLS: ++ esp->es_server.ea_state = eapTlsStart; ++ break; ++#endif /* USE_EAPTLS */ ++ + default: + dbglog("EAP: peer requesting unknown Type %d", vallen); + switch (esp->es_server.ea_state) { +@@ -2018,13 +2408,27 @@ u_char *inp; + int id; + int len; + { +- if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) { ++ if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp) ++#ifdef USE_EAPTLS ++ && esp->es_client.ea_state != eapTlsRecvSuccess ++#endif /* USE_EAPTLS */ ++ ) { + dbglog("EAP unexpected success message in state %s (%d)", + eap_state_name(esp->es_client.ea_state), + esp->es_client.ea_state); + return; + } + ++#ifdef USE_EAPTLS ++ if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state != ++ eapTlsRecvSuccess) { ++ dbglog("EAP-TLS unexpected success message in state %s (%d)", ++ eap_state_name(esp->es_client.ea_state), ++ esp->es_client.ea_state); ++ return; ++ } ++#endif /* USE_EAPTLS */ ++ + if (esp->es_client.ea_timeout > 0) { + UNTIMEOUT(eap_client_timeout, (void *)esp); + } +@@ -2150,6 +2554,9 @@ void *arg; + int code, id, len, rtype, vallen; + u_char *pstart; + u_int32_t uval; ++#ifdef USE_EAPTLS ++ u_char flags; ++#endif /* USE_EAPTLS */ + + if (inlen < EAP_HEADERLEN) + return (0); +@@ -2214,6 +2621,24 @@ void *arg; + } + break; + ++#ifdef USE_EAPTLS ++ case EAPT_TLS: ++ if (len < 1) ++ break; ++ GETCHAR(flags, inp); ++ len--; ++ ++ if(flags == 0 && len == 0){ ++ printer(arg, " Ack"); ++ break; ++ } ++ ++ printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -"); ++ printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-"); ++ printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- "); ++ break; ++#endif /* USE_EAPTLS */ ++ + case EAPT_SRP: + if (len < 3) + goto truncated; +@@ -2325,6 +2750,25 @@ void *arg; + } + break; + ++#ifdef USE_EAPTLS ++ case EAPT_TLS: ++ if (len < 1) ++ break; ++ GETCHAR(flags, inp); ++ len--; ++ ++ if(flags == 0 && len == 0){ ++ printer(arg, " Ack"); ++ break; ++ } ++ ++ printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -"); ++ printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-"); ++ printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- "); ++ ++ break; ++#endif /* USE_EAPTLS */ ++ + case EAPT_NAK: + if (len <= 0) { + printer(arg, " "); +@@ -2426,3 +2870,4 @@ void *arg; + + return (inp - pstart); + } ++ +Index: b/pppd/eap.h +=================================================================== +--- a/pppd/eap.h ++++ b/pppd/eap.h +@@ -84,6 +84,16 @@ enum eap_state_code { + eapClosed, /* Authentication not in use */ + eapListen, /* Client ready (and timer running) */ + eapIdentify, /* EAP Identify sent */ ++ eapTlsStart, /* Send EAP-TLS start packet */ ++ eapTlsRecv, /* Receive EAP-TLS tls data */ ++ eapTlsSendAck, /* Send EAP-TLS ack */ ++ eapTlsSend, /* Send EAP-TLS tls data */ ++ eapTlsRecvAck, /* Receive EAP-TLS ack */ ++ eapTlsRecvClient, /* Receive EAP-TLS auth response from client*/ ++ eapTlsSendAlert, /* Send EAP-TLS tls alert (server)*/ ++ eapTlsRecvAlertAck, /* Receive EAP-TLS ack after sending alert */ ++ eapTlsRecvSuccess, /* Receive EAP success */ ++ eapTlsRecvFailure, /* Receive EAP failure */ + eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ + eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ + eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ +@@ -95,9 +105,18 @@ enum eap_state_code { + + #define EAP_STATES \ + "Initial", "Pending", "Closed", "Listen", "Identify", \ ++ "TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\ ++ "TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \ + "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" + +-#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen) ++#ifdef USE_EAPTLS ++#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial ||\ ++ (esp)->es_client.ea_state != eapPending ||\ ++ (esp)->es_client.ea_state != eapClosed) ++#else ++#define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen) ++#endif /* USE_EAPTLS */ ++ + #define eap_server_active(esp) \ + ((esp)->es_server.ea_state >= eapIdentify && \ + (esp)->es_server.ea_state <= eapMD5Chall) +@@ -112,11 +131,17 @@ struct eap_auth { + u_short ea_namelen; /* Length of our name */ + u_short ea_peerlen; /* Length of peer's name */ + enum eap_state_code ea_state; ++#ifdef USE_EAPTLS ++ enum eap_state_code ea_prev_state; ++#endif + u_char ea_id; /* Current id */ + u_char ea_requests; /* Number of Requests sent/received */ + u_char ea_responses; /* Number of Responses */ + u_char ea_type; /* One of EAPT_* */ + u_int32_t ea_keyflags; /* SRP shared key usage flags */ ++#ifdef USE_EAPTLS ++ bool ea_using_eaptls; ++#endif + }; + + /* +@@ -139,7 +164,12 @@ typedef struct eap_state { + * Timeouts. + */ + #define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ ++#ifdef USE_EAPTLS ++#define EAP_DEFTRANSMITS 30 /* max # times to transmit */ ++ /* certificates can be long ... */ ++#else + #define EAP_DEFTRANSMITS 10 /* max # times to transmit */ ++#endif /* USE_EAPTLS */ + #define EAP_DEFREQTIME 20 /* Time to wait for peer request */ + #define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ + +Index: b/pppd/md5.c +=================================================================== +--- a/pppd/md5.c ++++ b/pppd/md5.c +@@ -33,6 +33,8 @@ + *********************************************************************** + */ + ++#ifndef USE_EAPTLS ++ + #include + #include "md5.h" + +@@ -305,3 +307,5 @@ UINT4 *in; + ** End of md5.c ** + ******************************** (cut) ******************************** + */ ++#endif /* USE_EAPTLS */ ++ +Index: b/pppd/md5.h +=================================================================== +--- a/pppd/md5.h ++++ b/pppd/md5.h +@@ -36,6 +36,7 @@ + ** documentation and/or software. ** + *********************************************************************** + */ ++#ifndef USE_EAPTLS + + #ifndef __MD5_INCLUDE__ + +@@ -63,3 +64,5 @@ void MD5_Final (unsigned char hash[], MD + + #define __MD5_INCLUDE__ + #endif /* __MD5_INCLUDE__ */ ++ ++#endif /* USE_EAPTLS */ +Index: b/pppd/pathnames.h +=================================================================== +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -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: b/pppd/plugins/Makefile.linux +=================================================================== +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -4,6 +4,9 @@ CFLAGS = $(COPTS) -I.. -I../../include - + LDFLAGS = $(LDOPTS) + INSTALL = install + ++# EAP-TLS ++CFLAGS += -DUSE_EAPTLS=1 ++ + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +Index: b/pppd/plugins/passprompt.c +=================================================================== +--- a/pppd/plugins/passprompt.c ++++ b/pppd/plugins/passprompt.c +@@ -107,4 +107,7 @@ void plugin_init(void) + { + add_options(options); + pap_passwd_hook = promptpass; ++#ifdef USE_EAPTLS ++ eaptls_passwd_hook = promptpass; ++#endif + } +Index: b/pppd/plugins/passwordfd.c +=================================================================== +--- a/pppd/plugins/passwordfd.c ++++ b/pppd/plugins/passwordfd.c +@@ -79,4 +79,8 @@ void plugin_init (void) + + chap_check_hook = pwfd_check; + chap_passwd_hook = pwfd_passwd; ++ ++#ifdef USE_EAPTLS ++ eaptls_passwd_hook = pwfd_passwd; ++#endif + } +Index: b/pppd/pppd.8 +=================================================================== +--- a/pppd/pppd.8 ++++ b/pppd/pppd.8 +@@ -253,6 +253,12 @@ Alternatively, a value of 0 for \fInr\fR + compression in the corresponding direction. Use \fInobsdcomp\fR or + \fIbsdcomp 0\fR to disable BSD-Compress compression entirely. + .TP ++.B ca \fIca-file ++(EAP-TLS) Use the file \fIca-file\fR as the X.509 Certificate Authority ++(CA) file (in PEM format), needed for setting up an EAP-TLS connection. ++This option is used on the client-side in conjunction with the \fBcert\fR ++and \fBkey\fR options. ++.TP + .B cdtrcts + Use a non-standard hardware flow control (i.e. DTR/CTS) to control + the flow of data on the serial port. If neither the \fIcrtscts\fR, +@@ -264,6 +270,12 @@ RTS output. Such serial ports use this m + bi-directional flow control. The sacrifice is that this flow + control mode does not permit using DTR as a modem control line. + .TP ++.B cert \fIcertfile ++(EAP-TLS) Use the file \fIcertfile\fR as the X.509 certificate (in PEM ++format), needed for setting up an EAP-TLS connection. This option is ++used on the client-side in conjunction with the \fBca\fR and ++\fBkey\fR options. ++.TP + .B chap\-interval \fIn + If this option is given, pppd will rechallenge the peer every \fIn\fR + seconds. +@@ -292,6 +304,18 @@ negotiation by sending its first LCP pac + 1000 (1 second). This wait period only applies if the \fBconnect\fR + or \fBpty\fR option is used. + .TP ++.B crl \fIfilename ++(EAP-TLS) Use the file \fIfilename\fR as the Certificate Revocation List ++to check for the validity of the peer's certificate. This option is not ++mandatory for setting up an EAP-TLS connection. Also see the \fBcrl-dir\fR ++option. ++.TP ++.B crl-dir \fIdirectory ++(EAP-TLS) Use the directory \fIdirectory\fR to scan for CRL files in ++has format ($hash.r0) to check for the validity of the peer's certificate. ++This option is not mandatory for setting up an EAP-TLS connection. ++Also see the \fBcrl\fR option. ++.TP + .B debug + Enables connection debugging facilities. + If this option is given, pppd will log the contents of all +@@ -561,6 +585,12 @@ transmitted packets be printed. On most + the kernel are logged by syslog(1) to a file as directed in the + /etc/syslog.conf configuration file. + .TP ++.B key \fIkeyfile ++(EAP-TLS) Use the file \fIkeyfile\fR as the private key file (in PEM ++format), needed for setting up an EAP-TLS connection. This option is ++used on the client-side in conjunction with the \fBca\fR and ++\fBcert\fR options. ++.TP + .B ktune + Enables pppd to alter kernel settings as appropriate. Under Linux, + pppd will enable IP forwarding (i.e. set /proc/sys/net/ipv4/ip_forward +@@ -724,6 +754,9 @@ name to \fIname\fR.) + Disable Address/Control compression in both directions (send and + receive). + .TP ++.B need-peer-eap ++(EAP-TLS) Require the peer to verify our authentication credentials. ++.TP + .B noauth + Do not require the peer to authenticate itself. This option is + privileged. +Index: b/pppd/pppd.h +=================================================================== +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -337,6 +337,11 @@ extern bool dump_options; /* print out o + extern bool dryrun; /* check everything, print options, exit */ + extern int child_wait; /* # seconds to wait for children at end */ + ++#ifdef USE_EAPTLS ++extern char *crl_dir; ++extern char *crl_file; ++#endif /* USE_EAPTLS */ ++ + #ifdef MAXOCTETS + extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ + extern int maxoctets_dir; /* Direction : +@@ -757,6 +762,10 @@ extern int (*chap_check_hook) __P((void) + extern int (*chap_passwd_hook) __P((char *user, char *passwd)); + extern void (*multilink_join_hook) __P((void)); + ++#ifdef USE_EAPTLS ++extern int (*eaptls_passwd_hook) __P((char *user, char *passwd)); ++#endif ++ + /* Let a plugin snoop sent and received packets. Useful for L2TP */ + extern void (*snoop_recv_hook) __P((unsigned char *p, int len)); + extern void (*snoop_send_hook) __P((unsigned char *p, int len)); diff -Nru ppp-2.4.7/debian/patches/series ppp-2.4.7/debian/patches/series --- ppp-2.4.7/debian/patches/series 2015-12-05 11:13:04.000000000 +0000 +++ ppp-2.4.7/debian/patches/series 2018-06-12 17:28:27.000000000 +0000 @@ -34,3 +34,8 @@ secure-card-interpreter-fix rc_mksid-no-buffer-overflow pppd-soname-hack.patch + +# ubuntu +load_ppp_generic_if_needed +ppp-2.4.6-eaptls-mppe-0.997.patch +CVE-2018-11574.patch diff -Nru ppp-2.4.7/debian/ppp.preinst ppp-2.4.7/debian/ppp.preinst --- ppp-2.4.7/debian/ppp.preinst 2015-12-04 09:29:47.000000000 +0000 +++ ppp-2.4.7/debian/ppp.preinst 2016-01-27 16:19:52.000000000 +0000 @@ -3,6 +3,10 @@ case "$1" in install|upgrade) + if dpkg --compare-versions "$2" lt "2.4.6-3ubuntu1"; then + update-rc.d pppd-dns remove + fi + if dpkg --compare-versions "$2" le "2.4.5-4"; then if dpkg --compare-versions "$2" le "2.4.4b1-1"; then diff -Nru ppp-2.4.7/debian/ppp.symbols ppp-2.4.7/debian/ppp.symbols --- ppp-2.4.7/debian/ppp.symbols 2015-12-30 10:07:29.000000000 +0000 +++ ppp-2.4.7/debian/ppp.symbols 2016-01-29 09:22:27.000000000 +0000 @@ -18,9 +18,6 @@ MD4Init@Base 2.4.7-1+2~ MD4Print@Base 2.4.7-1+2~ MD4Update@Base 2.4.7-1+2~ - MD5_Final@Base 2.4.7-1+2~ - MD5_Init@Base 2.4.7-1+2~ - MD5_Update@Base 2.4.7-1+2~ SHA1_Final@Base 2.4.7-1+2~ SHA1_Init@Base 2.4.7-1+2~ SHA1_Update@Base 2.4.7-1+2~ @@ -51,6 +48,7 @@ bundle_id@Base 2.4.7-1+2~ bundle_name@Base 2.4.7-1+2~ bundle_terminating@Base 2.4.7-1+2~ + cacert_file@Base 2.4.7-1+2ubuntu1~ callback_script@Base 2.4.7-1+2~ cbcp@Base 2.4.7-1+2~ cbcp_codenames@Base 2.4.7-1+2~ @@ -65,6 +63,7 @@ ccp_protent@Base 2.4.7-1+2~ ccp_test@Base 2.4.7-1+2~ ccp_wantoptions@Base 2.4.7-1+2~ + cert_file@Base 2.4.7-1+2ubuntu1~ cfg_bundle@Base 2.4.7-1+2~ chap_auth_peer@Base 2.4.7-1+2~ chap_auth_with_peer@Base 2.4.7-1+2~ @@ -97,6 +96,8 @@ connect_script@Base 2.4.7-1+2~ connect_tty@Base 2.4.7-1+2~ continue_networks@Base 2.4.7-1+2~ + crl_dir@Base 2.4.7-1+2ubuntu1~ + crl_file@Base 2.4.7-1+2ubuntu1~ crtscts@Base 2.4.7-1+2~ cryptpap@Base 2.4.7-1+2~ current_option@Base 2.4.7-1+2~ @@ -134,6 +135,18 @@ eap_authwithpeer@Base 2.4.7-1+2~ eap_protent@Base 2.4.7-1+2~ eap_states@Base 2.4.7-1+2~ + eaptls_free_session@Base 2.4.7-1+2ubuntu1~ + eaptls_gen_mppe_keys@Base 2.4.7-1+2ubuntu1~ + eaptls_get_mtu@Base 2.4.7-1+2ubuntu1~ + eaptls_init_ssl@Base 2.4.7-1+2ubuntu1~ + eaptls_init_ssl_client@Base 2.4.7-1+2ubuntu1~ + eaptls_init_ssl_server@Base 2.4.7-1+2ubuntu1~ + eaptls_passwd_hook@Base 2.4.7-1+2ubuntu1~ + eaptls_receive@Base 2.4.7-1+2ubuntu1~ + eaptls_retransmit@Base 2.4.7-1+2ubuntu1~ + eaptls_send@Base 2.4.7-1+2ubuntu1~ + eaptls_ssl_load_config@Base 2.4.7-1+2ubuntu1~ + eaptls_ssl_load_engine@Base 2.4.7-1+2ubuntu1~ ecp_allowoptions@Base 2.4.7-1+2~ ecp_fsm@Base 2.4.7-1+2~ ecp_gotoptions@Base 2.4.7-1+2~ @@ -172,6 +185,8 @@ general_options@Base 2.4.7-1+2~ generic_disestablish_ppp@Base 2.4.7-1+2~ generic_establish_ppp@Base 2.4.7-1+2~ + get_X509_from_file@Base 2.4.7-1+2ubuntu1~ + get_eaptls_secret@Base 2.4.7-1+2ubuntu1~ get_first_ethernet@Base 2.4.7-1+2~ get_host_seed@Base 2.4.7-1+2~ get_idle_time@Base 2.4.7-1+2~ @@ -265,6 +280,7 @@ locked@Base 2.4.7-1+2~ lockflag@Base 2.4.7-1+2~ log_default@Base 2.4.7-1+2~ + log_ssl_errors@Base 2.4.7-1+2ubuntu1~ log_to_fd@Base 2.4.7-1+2~ loop_chars@Base 2.4.7-1+2~ loop_frame@Base 2.4.7-1+2~ @@ -293,6 +309,7 @@ multilink_join_hook@Base 2.4.7-1+2~ multilink_master@Base 2.4.7-1+2~ need_holdoff@Base 2.4.7-1+2~ + need_peer_eap@Base 2.4.7-1+2ubuntu1~ netif_get_mtu@Base 2.4.7-1+2~ netif_set_mtu@Base 2.4.7-1+2~ netmask@Base 2.4.7-1+2~ @@ -335,6 +352,7 @@ parse_dotted_ip@Base 2.4.7-1+2~ pass_filter@Base 2.4.7-1+2~ passwd@Base 2.4.7-1+2~ + password_callback@Base 2.4.7-1+2ubuntu1~ path_ipdown@Base 2.4.7-1+2~ path_ipup@Base 2.4.7-1+2~ peer_authname@Base 2.4.7-1+2~ @@ -358,6 +376,7 @@ print_string@Base 2.4.7-1+2~ privileged@Base 2.4.7-1+2~ privileged_option@Base 2.4.7-1+2~ + privkey_file@Base 2.4.7-1+2ubuntu1~ privopen@Base 2.4.7-1+2~ progname@Base 2.4.7-1+2~ protocol_list@Base 2.4.7-1+2~ @@ -418,6 +437,9 @@ snoop_recv_hook@Base 2.4.7-1+2~ snoop_send_hook@Base 2.4.7-1+2~ speeds@Base 2.4.7-1+2~ + ssl_cmp_certs@Base 2.4.7-1+2ubuntu1~ + ssl_msg_callback@Base 2.4.7-1+2ubuntu1~ + ssl_verify_callback@Base 2.4.7-1+2ubuntu1~ start_link@Base 2.4.7-1+2~ start_networks@Base 2.4.7-1+2~ status@Base 2.4.7-1+2~