From d2e1ce41ee1c4d8614904efb6b71e9d9a4e935a1 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Fri, 20 Jun 2014 10:44:27 +0200 Subject: [PATCH] spec: v0.997 of EAP-TLS patch Regenerated all patches from ppp-2.4.6-fedora git repo See: http://www.nikhef.nl/~janjust/ppp/download.html See: https://github.com/msekletar/ppp-2.4.6-fedora --- ...ys-use-gcc-as-our-compiler-of-choice.patch | 25 + 0002-build-sys-enable-PAM-support.patch | 25 + ...e-compiler-flags-handed-to-us-by-rpm.patch | 121 + 0004-doc-add-configuration-samples.patch | 341 ++ ...hardcode-LIBDIR-but-set-it-according.patch | 120 + ...itps-use-change_resolv_conf-function.patch | 85 + ...t-strip-binaries-during-installation.patch | 111 + ...-use-prefix-usr-instead-of-usr-local.patch | 89 + 0009-pppd-introduce-ipv6-accept-remote.patch | 57 + 0010-build-sys-enable-CBCP.patch | 26 + ...-t-put-connect-errors-log-to-etc-ppp.patch | 77 + ...-don-t-want-to-accidentally-leak-fds.patch | 143 + 0013-everywhere-O_CLOEXEC-harder.patch | 241 ++ ...se-SOCK_CLOEXEC-when-creating-socket.patch | 174 + ...pd-move-pppd-database-to-var-run-ppp.patch | 44 + ...ppoe-add-manpage-for-pppoe-discovery.patch | 126 + 0017-pppd-rebase-EAP-TLS-patch-v0.994.patch | 3045 ++++++++++++++++ 0018-scritps-fix-ip-up.local-sample.patch | 27 + ...-sys-linux-rework-get_first_ethernet.patch | 383 ++ ...-pppd-put-lock-files-in-var-lock-ppp.patch | 26 + ...e-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch | 23 + ...pile-pppol2tp-with-multilink-support.patch | 24 + ...l-rp-pppoe-plugin-files-with-standar.patch | 32 + ...l-pppoatm-plugin-files-with-standard.patch | 26 + ...pppd-binary-using-standard-perms-755.patch | 29 + ...ert-pppd-rebase-EAP-TLS-patch-v0.994.patch | 3046 ++++++++++++++++ 0027-pppd-EAP-TLS-patch-v0.997.patch | 3175 +++++++++++++++++ ppp.spec | 27 + 28 files changed, 11668 insertions(+) create mode 100644 0001-build-sys-use-gcc-as-our-compiler-of-choice.patch create mode 100644 0002-build-sys-enable-PAM-support.patch create mode 100644 0003-build-sys-utilize-compiler-flags-handed-to-us-by-rpm.patch create mode 100644 0004-doc-add-configuration-samples.patch create mode 100644 0005-build-sys-don-t-hardcode-LIBDIR-but-set-it-according.patch create mode 100644 0006-scritps-use-change_resolv_conf-function.patch create mode 100644 0007-build-sys-don-t-strip-binaries-during-installation.patch create mode 100644 0008-build-sys-use-prefix-usr-instead-of-usr-local.patch create mode 100644 0009-pppd-introduce-ipv6-accept-remote.patch create mode 100644 0010-build-sys-enable-CBCP.patch create mode 100644 0011-build-sys-don-t-put-connect-errors-log-to-etc-ppp.patch create mode 100644 0012-pppd-we-don-t-want-to-accidentally-leak-fds.patch create mode 100644 0013-everywhere-O_CLOEXEC-harder.patch create mode 100644 0014-everywhere-use-SOCK_CLOEXEC-when-creating-socket.patch create mode 100644 0015-pppd-move-pppd-database-to-var-run-ppp.patch create mode 100644 0016-rp-pppoe-add-manpage-for-pppoe-discovery.patch create mode 100644 0017-pppd-rebase-EAP-TLS-patch-v0.994.patch create mode 100644 0018-scritps-fix-ip-up.local-sample.patch create mode 100644 0019-sys-linux-rework-get_first_ethernet.patch create mode 100644 0020-pppd-put-lock-files-in-var-lock-ppp.patch create mode 100644 0021-build-sys-compile-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch create mode 100644 0022-build-sys-compile-pppol2tp-with-multilink-support.patch create mode 100644 0023-build-sys-install-rp-pppoe-plugin-files-with-standar.patch create mode 100644 0024-build-sys-install-pppoatm-plugin-files-with-standard.patch create mode 100644 0025-pppd-install-pppd-binary-using-standard-perms-755.patch create mode 100644 0026-Revert-pppd-rebase-EAP-TLS-patch-v0.994.patch create mode 100644 0027-pppd-EAP-TLS-patch-v0.997.patch diff --git a/0001-build-sys-use-gcc-as-our-compiler-of-choice.patch b/0001-build-sys-use-gcc-as-our-compiler-of-choice.patch new file mode 100644 index 0000000..b8a76ca --- /dev/null +++ b/0001-build-sys-use-gcc-as-our-compiler-of-choice.patch @@ -0,0 +1,25 @@ +From 486e36d184cbaee7e34bb582ea6fdf3bfa9ca531 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 11:23:42 +0200 +Subject: [PATCH 01/27] build-sys: use gcc as our compiler of choice + +--- + pppd/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index a74c914..1d9ea78 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -30,7 +30,7 @@ ifeq (.depend,$(wildcard .depend)) + include .depend + endif + +-# CC = gcc ++CC = gcc + # + COPTS = -O2 -pipe -Wall -g + LIBS = +-- +1.8.3.1 + diff --git a/0002-build-sys-enable-PAM-support.patch b/0002-build-sys-enable-PAM-support.patch new file mode 100644 index 0000000..2f1c53b --- /dev/null +++ b/0002-build-sys-enable-PAM-support.patch @@ -0,0 +1,25 @@ +From 0d71a32b73b71c9793d0b304320858062faf00d1 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 11:25:43 +0200 +Subject: [PATCH 02/27] build-sys: enable PAM support + +--- + pppd/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 1d9ea78..5a44d30 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -61,7 +61,7 @@ HAVE_MULTILINK=y + USE_TDB=y + + HAS_SHADOW=y +-#USE_PAM=y ++USE_PAM=y + HAVE_INET6=y + + # Enable plugins +-- +1.8.3.1 + diff --git a/0003-build-sys-utilize-compiler-flags-handed-to-us-by-rpm.patch b/0003-build-sys-utilize-compiler-flags-handed-to-us-by-rpm.patch new file mode 100644 index 0000000..87da38b --- /dev/null +++ b/0003-build-sys-utilize-compiler-flags-handed-to-us-by-rpm.patch @@ -0,0 +1,121 @@ +From d729b06f0ac7a5ebd3648ef60bef0499b59bf82d Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 11:29:39 +0200 +Subject: [PATCH 03/27] build-sys: utilize compiler flags handed to us by + rpmbuild + +--- + chat/Makefile.linux | 2 +- + pppd/Makefile.linux | 3 +-- + pppd/plugins/Makefile.linux | 2 +- + pppd/plugins/pppoatm/Makefile.linux | 2 +- + pppd/plugins/radius/Makefile.linux | 2 +- + pppd/plugins/rp-pppoe/Makefile.linux | 2 +- + pppdump/Makefile.linux | 2 +- + pppstats/Makefile.linux | 2 +- + 8 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/chat/Makefile.linux b/chat/Makefile.linux +index 1065ac5..848cd8d 100644 +--- a/chat/Makefile.linux ++++ b/chat/Makefile.linux +@@ -10,7 +10,7 @@ CDEF3= -UNO_SLEEP # Use the usleep function + CDEF4= -DFNDELAY=O_NDELAY # Old name value + CDEFS= $(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4) + +-COPTS= -O2 -g -pipe ++COPTS= $(RPM_OPT_FLAGS) + CFLAGS= $(COPTS) $(CDEFS) + + INSTALL= install +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 5a44d30..63872eb 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -32,8 +32,7 @@ endif + + CC = gcc + # +-COPTS = -O2 -pipe -Wall -g +-LIBS = ++COPTS = -Wall $(RPM_OPT_FLAGS) + + # Uncomment the next 2 lines to include support for Microsoft's + # MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. +diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux +index 0a7ec7b..e09a369 100644 +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -1,5 +1,5 @@ + #CC = gcc +-COPTS = -O2 -g ++COPTS = $(RPM_OPT_FLAGS) + CFLAGS = $(COPTS) -I.. -I../../include -fPIC + LDFLAGS = -shared + INSTALL = install +diff --git a/pppd/plugins/pppoatm/Makefile.linux b/pppd/plugins/pppoatm/Makefile.linux +index 20f62e6..5a81447 100644 +--- a/pppd/plugins/pppoatm/Makefile.linux ++++ b/pppd/plugins/pppoatm/Makefile.linux +@@ -1,5 +1,5 @@ + #CC = gcc +-COPTS = -O2 -g ++COPTS = $(RPM_OPT_FLAGS) + CFLAGS = $(COPTS) -I../.. -I../../../include -fPIC + LDFLAGS = -shared + INSTALL = install +diff --git a/pppd/plugins/radius/Makefile.linux b/pppd/plugins/radius/Makefile.linux +index 24ed3e5..45b3b8d 100644 +--- a/pppd/plugins/radius/Makefile.linux ++++ b/pppd/plugins/radius/Makefile.linux +@@ -12,7 +12,7 @@ VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) + INSTALL = install + + PLUGIN=radius.so radattr.so radrealms.so +-CFLAGS=-I. -I../.. -I../../../include -O2 -fPIC -DRC_LOG_FACILITY=LOG_DAEMON ++CFLAGS=-I. -I../.. -I../../../include $(RPM_OPT_FLAGS) -DRC_LOG_FACILITY=LOG_DAEMON + + # Uncomment the next line to include support for Microsoft's + # MS-CHAP authentication protocol. +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index 5d7a271..352991a 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -25,7 +25,7 @@ INSTALL = install + # Version is set ONLY IN THE MAKEFILE! Don't delete this! + RP_VERSION=3.8p + +-COPTS=-O2 -g ++COPTS=$(RPM_OPT_FLAGS) + CFLAGS=$(COPTS) -I../../../include '-DRP_VERSION="$(RP_VERSION)"' + all: rp-pppoe.so pppoe-discovery + +diff --git a/pppdump/Makefile.linux b/pppdump/Makefile.linux +index ac028f6..d0a5032 100644 +--- a/pppdump/Makefile.linux ++++ b/pppdump/Makefile.linux +@@ -2,7 +2,7 @@ DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 + +-CFLAGS= -O -I../include/net ++CFLAGS= $(RPM_OPT_FLAGS) -I../include/net + OBJS = pppdump.o bsd-comp.o deflate.o zlib.o + + INSTALL= install +diff --git a/pppstats/Makefile.linux b/pppstats/Makefile.linux +index cca6f0f..42aba73 100644 +--- a/pppstats/Makefile.linux ++++ b/pppstats/Makefile.linux +@@ -10,7 +10,7 @@ PPPSTATSRCS = pppstats.c + PPPSTATOBJS = pppstats.o + + #CC = gcc +-COPTS = -O ++COPTS = $(RPM_OPT_FLAGS) + COMPILE_FLAGS = -I../include + LIBS = + +-- +1.8.3.1 + diff --git a/0004-doc-add-configuration-samples.patch b/0004-doc-add-configuration-samples.patch new file mode 100644 index 0000000..0cea037 --- /dev/null +++ b/0004-doc-add-configuration-samples.patch @@ -0,0 +1,341 @@ +From d7faeb88f684c8b2ae193b2c5b5b358ac757fcfa Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 11:39:09 +0200 +Subject: [PATCH 04/27] doc: add configuration samples + +--- + sample/auth-down | 17 ++++++ + sample/auth-up | 17 ++++++ + sample/ip-down | 22 ++++++++ + sample/ip-up | 23 ++++++++ + sample/options | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++ + sample/options.ttyXX | 14 +++++ + sample/pap-secrets | 28 ++++++++++ + 7 files changed, 274 insertions(+) + create mode 100644 sample/auth-down + create mode 100644 sample/auth-up + create mode 100644 sample/ip-down + create mode 100644 sample/ip-up + create mode 100644 sample/options + create mode 100644 sample/options.ttyXX + create mode 100644 sample/pap-secrets + +diff --git a/sample/auth-down b/sample/auth-down +new file mode 100644 +index 0000000..edde65d +--- /dev/null ++++ b/sample/auth-down +@@ -0,0 +1,17 @@ ++#!/bin/sh ++# ++# A program or script which is executed after the remote system ++# successfully authenticates itself. It is executed with the parameters ++# ++# ++ ++# ++# The environment is cleared before executing this script ++# so the path must be reset ++# ++PATH=/usr/sbin:/sbin:/usr/bin:/bin ++export PATH ++ ++echo auth-down `date +'%y/%m/%d %T'` $* >> /var/log/pppstats ++ ++# last line +diff --git a/sample/auth-up b/sample/auth-up +new file mode 100644 +index 0000000..54722a3 +--- /dev/null ++++ b/sample/auth-up +@@ -0,0 +1,17 @@ ++#!/bin/sh ++# ++# A program or script which is executed after the remote system ++# successfully authenticates itself. It is executed with the parameters ++# ++# ++ ++# ++# The environment is cleared before executing this script ++# so the path must be reset ++# ++PATH=/usr/sbin:/sbin:/usr/bin:/bin ++export PATH ++ ++echo auth-up `date +'%y/%m/%d %T'` $* >> /var/log/pppstats ++ ++# last line +diff --git a/sample/ip-down b/sample/ip-down +new file mode 100644 +index 0000000..b771fb6 +--- /dev/null ++++ b/sample/ip-down +@@ -0,0 +1,22 @@ ++#!/bin/sh ++# ++# This script is run by the pppd _after_ the link is brought down. ++# It should be used to delete routes, unset IP addresses etc. ++# ++# This script is called with the following arguments: ++# Arg Name Example ++# $1 Interface name ppp0 ++# $2 The tty ttyS1 ++# $3 The link speed 38400 ++# $4 Local IP number 12.34.56.78 ++# $5 Peer IP number 12.34.56.99 ++# ++ ++# ++# The environment is cleared before executing this script ++# so the path must be reset ++# ++PATH=/usr/sbin:/sbin:/usr/bin:/bin ++export PATH ++ ++# last line +diff --git a/sample/ip-up b/sample/ip-up +new file mode 100644 +index 0000000..7ce7c8d +--- /dev/null ++++ b/sample/ip-up +@@ -0,0 +1,23 @@ ++#!/bin/sh ++# ++# This script is run by the pppd after the link is established. ++# It should be used to add routes, set IP address, run the mailq ++# etc. ++# ++# This script is called with the following arguments: ++# Arg Name Example ++# $1 Interface name ppp0 ++# $2 The tty ttyS1 ++# $3 The link speed 38400 ++# $4 Local IP number 12.34.56.78 ++# $5 Peer IP number 12.34.56.99 ++# ++ ++# ++# The environment is cleared before executing this script ++# so the path must be reset ++# ++PATH=/usr/sbin:/sbin:/usr/bin:/bin ++export PATH ++ ++# last line +diff --git a/sample/options b/sample/options +new file mode 100644 +index 0000000..8d0a3f9 +--- /dev/null ++++ b/sample/options +@@ -0,0 +1,153 @@ ++# /etc/ppp/options ++ ++# The name of this server. Often, the FQDN is used here. ++#name ++ ++# Enforce the use of the hostname as the name of the local system for ++# authentication purposes (overrides the name option). ++usehostname ++ ++# If no local IP address is given, pppd will use the first IP address ++# that belongs to the local hostname. If "noipdefault" is given, this ++# is disabled and the peer will have to supply an IP address. ++noipdefault ++ ++# With this option, pppd will accept the peer's idea of our local IP ++# address, even if the local IP address was specified in an option. ++#ipcp-accept-local ++ ++# With this option, pppd will accept the peer's idea of its (remote) IP ++# address, even if the remote IP address was specified in an option. ++#ipcp-accept-remote ++ ++# Specify which DNS Servers the incoming Win95 or WinNT Connection should use ++# Two Servers can be remotely configured ++#ms-dns 192.168.1.1 ++#ms-dns 192.168.1.2 ++ ++# Specify which WINS Servers the incoming connection Win95 or WinNT should use ++#wins-addr 192.168.1.50 ++#wins-addr 192.168.1.51 ++ ++# enable this on a server that already has a permanent default route ++#nodefaultroute ++ ++# Run the executable or shell command specified after pppd has terminated ++# the link. This script could, for example, issue commands to the modem ++# to cause it to hang up if hardware modem control signals were not ++# available. ++# If mgetty is running, it will reset the modem anyway. So there is no need ++# to do it here. ++#disconnect "chat -- \d+++\d\c OK ath0 OK" ++ ++# Increase debugging level (same as -d). The debug output is written ++# to syslog LOG_LOCAL2. ++debug ++ ++# Enable debugging code in the kernel-level PPP driver. The argument n ++# is a number which is the sum of the following values: 1 to enable ++# general debug messages, 2 to request that the contents of received ++# packets be printed, and 4 to request that the contents of transmitted ++# packets be printed. ++#kdebug n ++ ++# Require the peer to authenticate itself before allowing network ++# packets to be sent or received. ++# Please do not disable this setting. It is expected to be standard in ++# future releases of pppd. Use the call option (see manpage) to disable ++# authentication for specific peers. ++#auth ++ ++# authentication can either be pap or chap. As most people only want to ++# use pap, you can also disable chap: ++#require-pap ++#refuse-chap ++ ++# Use hardware flow control (i.e. RTS/CTS) to control the flow of data ++# on the serial port. ++crtscts ++ ++# Specifies that pppd should use a UUCP-style lock on the serial device ++# to ensure exclusive access to the device. ++lock ++ ++# Use the modem control lines. ++modem ++ ++# async character map -- 32-bit hex; each bit is a character ++# that needs to be escaped for pppd to receive it. 0x00000001 ++# represents '\x01', and 0x80000000 represents '\x1f'. ++# To allow pppd to work over a rlogin/telnet connection, ou should escape ++# XON (^Q), XOFF (^S) and ^]: (The peer should use "escape ff".) ++#asyncmap 200a0000 ++asyncmap 0 ++ ++# Specifies that certain characters should be escaped on transmission ++# (regardless of whether the peer requests them to be escaped with its ++# async control character map). The characters to be escaped are ++# specified as a list of hex numbers separated by commas. Note that ++# almost any character can be specified for the escape option, unlike ++# the asyncmap option which only allows control characters to be ++# specified. The characters which may not be escaped are those with hex ++# values 0x20 - 0x3f or 0x5e. ++#escape 11,13,ff ++ ++# Set the MRU [Maximum Receive Unit] value to for negotiation. pppd ++# will ask the peer to send packets of no more than bytes. The ++# minimum MRU value is 128. The default MRU value is 1500. A value of ++# 296 is recommended for slow links (40 bytes for TCP/IP header + 256 ++# bytes of data). ++#mru 542 ++ ++# Set the MTU [Maximum Transmit Unit] value to . Unless the peer ++# requests a smaller value via MRU negotiation, pppd will request that ++# the kernel networking code send data packets of no more than n bytes ++# through the PPP network interface. ++#mtu ++ ++# Set the interface netmask to , a 32 bit netmask in "decimal dot" ++# notation (e.g. 255.255.255.0). ++#netmask 255.255.255.0 ++ ++# Don't fork to become a background process (otherwise pppd will do so ++# if a serial device is specified). ++nodetach ++ ++# Set the assumed name of the remote system for authentication purposes ++# to . ++#remotename ++ ++# Add an entry to this system's ARP [Address Resolution Protocol] ++# table with the IP address of the peer and the Ethernet address of this ++# system. {proxyarp,noproxyarp} ++proxyarp ++ ++# Use the system password database for authenticating the peer using ++# PAP. Note: mgetty already provides this option. If this is specified ++# then dialin from users using a script under Linux to fire up ppp wont work. ++#login ++ ++# If this option is given, pppd will send an LCP echo-request frame to ++# the peer every n seconds. Under Linux, the echo-request is sent when ++# no packets have been received from the peer for n seconds. Normally ++# the peer should respond to the echo-request by sending an echo-reply. ++# This option can be used with the lcp-echo-failure option to detect ++# that the peer is no longer connected. ++lcp-echo-interval 30 ++ ++# If this option is given, pppd will presume the peer to be dead if n ++# LCP echo-requests are sent without receiving a valid LCP echo-reply. ++# If this happens, pppd will terminate the connection. Use of this ++# option requires a non-zero value for the lcp-echo-interval parameter. ++# This option can be used to enable pppd to terminate after the physical ++# connection has been broken (e.g., the modem has hung up) in ++# situations where no hardware modem control lines are available. ++lcp-echo-failure 4 ++ ++# Specifies that pppd should disconnect if the link is idle for n seconds. ++idle 600 ++ ++# Disable the IPXCP and IPX protocols. ++noipx ++ ++# ------ +diff --git a/sample/options.ttyXX b/sample/options.ttyXX +new file mode 100644 +index 0000000..d4202f5 +--- /dev/null ++++ b/sample/options.ttyXX +@@ -0,0 +1,14 @@ ++# If you need to set up multiple serial lines then copy this file to ++# options. for each tty with a modem on it. ++# ++# The options.tty file will assign an IP address to each PPP connection ++# as it comes up. They must all be distinct! ++# ++# Example: ++# options.ttyS1 for com2 under DOS. ++# ++# Edit the following line so that the first IP address ++# mentioned is the ip address of the serial port while the second ++# is the IP address of your host ++# ++hostname-s1:hostname +diff --git a/sample/pap-secrets b/sample/pap-secrets +new file mode 100644 +index 0000000..098971b +--- /dev/null ++++ b/sample/pap-secrets +@@ -0,0 +1,28 @@ ++# Secrets for authentication using PAP ++# client server secret IP addresses ++ ++# OUTBOUND CONNECTIONS ++# Here you should add your userid password to connect to your providers via ++# pap. The * means that the password is to be used for ANY host you connect ++# to. Thus you do not have to worry about the foreign machine name. Just ++# replace password with your password. ++# If you have different providers with different passwords then you better ++# remove the following line. ++#hostname * password ++ ++# INBOUND CONNECTIONS ++#client hostname 192.168.1.1 ++ ++# If you add "auth login -chap +pap" to /etc/mgetty+sendfax/login.config, ++# all users in /etc/passwd can use their password for pap-authentication. ++# ++# Every regular user can use PPP and has to use passwords from /etc/passwd ++#* hostname "" ++# UserIDs that cannot use PPP at all. Check your /etc/passwd and add any ++# other accounts that should not be able to use pppd! Replace hostname ++# with your local hostname. ++#guest hostname "*" - ++#master hostname "*" - ++#root hostname "*" - ++#support hostname "*" - ++#stats hostname "*" - +-- +1.8.3.1 + diff --git a/0005-build-sys-don-t-hardcode-LIBDIR-but-set-it-according.patch b/0005-build-sys-don-t-hardcode-LIBDIR-but-set-it-according.patch new file mode 100644 index 0000000..48190ed --- /dev/null +++ b/0005-build-sys-don-t-hardcode-LIBDIR-but-set-it-according.patch @@ -0,0 +1,120 @@ +From 69711944745af0078da77e108d30f89fd7e06108 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 12:01:33 +0200 +Subject: [PATCH 05/27] build-sys: don't hardcode LIBDIR, but set it according + to the target platform + +--- + pppd/Makefile.linux | 3 ++- + pppd/pathnames.h | 2 +- + pppd/plugins/Makefile.linux | 2 +- + pppd/plugins/pppoatm/Makefile.linux | 2 +- + pppd/plugins/pppol2tp/Makefile.linux | 4 ++-- + pppd/plugins/radius/Makefile.linux | 2 +- + pppd/plugins/rp-pppoe/Makefile.linux | 2 +- + 7 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 63872eb..8ed56c1 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -8,6 +8,7 @@ DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 + INCDIR = $(DESTDIR)/include ++LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null) + + TARGETS = pppd + +@@ -32,7 +33,7 @@ endif + + CC = gcc + # +-COPTS = -Wall $(RPM_OPT_FLAGS) ++COPTS = -Wall $(RPM_OPT_FLAGS) -DLIBDIR=\""$(LIBDIR)"\" + + # Uncomment the next 2 lines to include support for Microsoft's + # MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index a33f046..a427cb8 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -57,7 +57,7 @@ + + #ifdef PLUGIN + #ifdef __STDC__ +-#define _PATH_PLUGIN DESTDIR "/lib/pppd/" VERSION ++#define _PATH_PLUGIN LIBDIR "/pppd/" VERSION + #else /* __STDC__ */ + #define _PATH_PLUGIN "/usr/lib/pppd" + #endif /* __STDC__ */ +diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux +index e09a369..b474a19 100644 +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -7,7 +7,7 @@ INSTALL = install + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +-LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) ++LIBDIR = $(DESTDIR)/lib/$(shell $(CC) -print-multi-os-directory 2> /dev/null)/pppd/$(VERSION) + + SUBDIRS := rp-pppoe pppoatm pppol2tp + # Uncomment the next line to include the radius authentication plugin +diff --git a/pppd/plugins/pppoatm/Makefile.linux b/pppd/plugins/pppoatm/Makefile.linux +index 5a81447..769794b 100644 +--- a/pppd/plugins/pppoatm/Makefile.linux ++++ b/pppd/plugins/pppoatm/Makefile.linux +@@ -7,7 +7,7 @@ INSTALL = install + #*********************************************************************** + + DESTDIR = $(INSTROOT)@DESTDIR@ +-LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) ++LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null)/pppd/$(VERSION) + + VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) + +diff --git a/pppd/plugins/pppol2tp/Makefile.linux b/pppd/plugins/pppol2tp/Makefile.linux +index ea3538e..4339566 100644 +--- a/pppd/plugins/pppol2tp/Makefile.linux ++++ b/pppd/plugins/pppol2tp/Makefile.linux +@@ -6,8 +6,8 @@ INSTALL = install + + #*********************************************************************** + +-DESTDIR = @DESTDIR@ +-LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) ++DESTDIR = $(INSTROOT)@DESTDIR@ ++LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null)/pppd/$(VERSION) + + VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) + +diff --git a/pppd/plugins/radius/Makefile.linux b/pppd/plugins/radius/Makefile.linux +index 45b3b8d..179d0b7 100644 +--- a/pppd/plugins/radius/Makefile.linux ++++ b/pppd/plugins/radius/Makefile.linux +@@ -5,7 +5,7 @@ + + DESTDIR = $(INSTROOT)@DESTDIR@ + MANDIR = $(DESTDIR)/share/man/man8 +-LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) ++LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null)/pppd/$(VERSION) + + VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) + +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index 352991a..1305ed8 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -16,7 +16,7 @@ + + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin +-LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION) ++LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null)/pppd/$(PPPDVERSION) + + PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) + +-- +1.8.3.1 + diff --git a/0006-scritps-use-change_resolv_conf-function.patch b/0006-scritps-use-change_resolv_conf-function.patch new file mode 100644 index 0000000..cbf8713 --- /dev/null +++ b/0006-scritps-use-change_resolv_conf-function.patch @@ -0,0 +1,85 @@ +From 01419dfb684d501b57f1c24dcfdbcf9da93ccca2 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 18:12:47 +0200 +Subject: [PATCH 06/27] scritps: use change_resolv_conf function + +Don't handle /etc/resolv.conf manually, but use a helper function from +initscripts. Also change path where we save DNS servers supplied by peer while +we are at it. + +Resolves: #132482 +--- + pppd/pppd.8 | 2 +- + scripts/ip-down.local.add | 9 +++++---- + scripts/ip-up.local.add | 17 ++++++++++------- + 3 files changed, 16 insertions(+), 12 deletions(-) + +diff --git a/pppd/pppd.8 b/pppd/pppd.8 +index e2768b1..2dd6e1a 100644 +--- a/pppd/pppd.8 ++++ b/pppd/pppd.8 +@@ -1099,7 +1099,7 @@ Ask the peer for up to 2 DNS server addresses. The addresses supplied + by the peer (if any) are passed to the /etc/ppp/ip\-up script in the + environment variables DNS1 and DNS2, and the environment variable + USEPEERDNS will be set to 1. In addition, pppd will create an +-/etc/ppp/resolv.conf file containing one or two nameserver lines with ++/var/run/ppp/resolv.conf file containing one or two nameserver lines with + the address(es) supplied by the peer. + .TP + .B user \fIname +diff --git a/scripts/ip-down.local.add b/scripts/ip-down.local.add +index b93590e..163f71e 100644 +--- a/scripts/ip-down.local.add ++++ b/scripts/ip-down.local.add +@@ -9,12 +9,13 @@ + # + # Nick Walker (nickwalker@email.com) + # ++. /etc/sysconfig/network-scripts/network-functions + +-if [ -n "$USEPEERDNS" -a -f /etc/ppp/resolv.conf ]; then +- if [ -f /etc/ppp/resolv.prev ]; then +- cp -f /etc/ppp/resolv.prev /etc/resolv.conf ++if [ -n "$USEPEERDNS" -a -f /var/run/ppp/resolv.conf ]; then ++ if [ -f /var/run/ppp/resolv.prev ]; then ++ change_resolv_conf /var/run/ppp/resolv.prev + else +- rm -f /etc/resolv.conf ++ change_resolv_conf + fi + fi + +diff --git a/scripts/ip-up.local.add b/scripts/ip-up.local.add +index 8017209..26cf5f8 100644 +--- a/scripts/ip-up.local.add ++++ b/scripts/ip-up.local.add +@@ -9,16 +9,19 @@ + # + # Nick Walker (nickwalker@email.com) + # ++. /etc/sysconfig/network-scripts/network-functions + +-if [ -n "$USEPEERDNS" -a -f /etc/ppp/resolv.conf ]; then +- rm -f /etc/ppp/resolv.prev ++if [ -n "$USEPEERDNS" -a -f /var/run/ppp/resolv.conf ]; then ++ rm -f /var/run/ppp/resolv.prev + if [ -f /etc/resolv.conf ]; then +- cp /etc/resolv.conf /etc/ppp/resolv.prev +- grep domain /etc/ppp/resolv.prev > /etc/resolv.conf +- grep search /etc/ppp/resolv.prev >> /etc/resolv.conf +- cat /etc/ppp/resolv.conf >> /etc/resolv.conf ++ cp /etc/resolv.conf /var/run/ppp/resolv.prev ++ rscf=/var/run/ppp/resolv.new ++ grep domain /var/run/ppp/resolv.prev > $rscf ++ grep search /var/run/ppp/resolv.prev >> $rscf ++ change_resolv_conf $rscf ++ rm -f $rscf + else +- cp /etc/ppp/resolv.conf /etc ++ change_resolv_conf /var/run/ppp/resolv.conf + fi + fi + +-- +1.8.3.1 + diff --git a/0007-build-sys-don-t-strip-binaries-during-installation.patch b/0007-build-sys-don-t-strip-binaries-during-installation.patch new file mode 100644 index 0000000..9f542a6 --- /dev/null +++ b/0007-build-sys-don-t-strip-binaries-during-installation.patch @@ -0,0 +1,111 @@ +From b9fb631a493c5f1b490c8e9645eb6ebab4b25cc8 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 18:37:00 +0200 +Subject: [PATCH 07/27] build-sys: don't strip binaries during installation + +We don't want that when building rpms. rpmbuild does final stripping of binaries +for us and generetes debuginfo rpm. +--- + chat/Makefile.linux | 2 +- + pppd/Makefile.linux | 4 ++-- + pppd/plugins/radius/Makefile.linux | 6 +++--- + pppd/plugins/rp-pppoe/Makefile.linux | 4 ++-- + pppdump/Makefile.linux | 2 +- + pppstats/Makefile.linux | 2 +- + 6 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/chat/Makefile.linux b/chat/Makefile.linux +index 848cd8d..2445637 100644 +--- a/chat/Makefile.linux ++++ b/chat/Makefile.linux +@@ -25,7 +25,7 @@ chat.o: chat.c + + install: chat + mkdir -p $(BINDIR) $(MANDIR) +- $(INSTALL) -s -c chat $(BINDIR) ++ $(INSTALL) -c chat $(BINDIR) + $(INSTALL) -c -m 644 chat.8 $(MANDIR) + + clean: +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 8ed56c1..4f27100 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -102,7 +102,7 @@ ifdef USE_SRP + CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include + LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto + TARGETS += srp-entry +-EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry ++EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry + MANPAGES += srp-entry.8 + EXTRACLEAN += srp-entry.o + NEEDDES=y +@@ -208,7 +208,7 @@ all: $(TARGETS) + install: pppd + mkdir -p $(BINDIR) $(MANDIR) + $(EXTRAINSTALL) +- $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd ++ $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd + if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \ + chmod o-rx,u+s $(BINDIR)/pppd; fi + $(INSTALL) -c -m 444 pppd.8 $(MANDIR) +diff --git a/pppd/plugins/radius/Makefile.linux b/pppd/plugins/radius/Makefile.linux +index 179d0b7..707326b 100644 +--- a/pppd/plugins/radius/Makefile.linux ++++ b/pppd/plugins/radius/Makefile.linux +@@ -36,9 +36,9 @@ all: $(PLUGIN) + + install: all + $(INSTALL) -d -m 755 $(LIBDIR) +- $(INSTALL) -s -c -m 755 radius.so $(LIBDIR) +- $(INSTALL) -s -c -m 755 radattr.so $(LIBDIR) +- $(INSTALL) -s -c -m 755 radrealms.so $(LIBDIR) ++ $(INSTALL) -c -m 755 radius.so $(LIBDIR) ++ $(INSTALL) -c -m 755 radattr.so $(LIBDIR) ++ $(INSTALL) -c -m 755 radrealms.so $(LIBDIR) + $(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR) + $(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR) + +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index 1305ed8..3cd9101 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -43,9 +43,9 @@ rp-pppoe.so: plugin.o discovery.o if.o common.o + + install: all + $(INSTALL) -d -m 755 $(LIBDIR) +- $(INSTALL) -s -c -m 4550 rp-pppoe.so $(LIBDIR) ++ $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR) + $(INSTALL) -d -m 755 $(BINDIR) +- $(INSTALL) -s -c -m 555 pppoe-discovery $(BINDIR) ++ $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR) + + clean: + rm -f *.o *.so pppoe-discovery +diff --git a/pppdump/Makefile.linux b/pppdump/Makefile.linux +index d0a5032..95c6805 100644 +--- a/pppdump/Makefile.linux ++++ b/pppdump/Makefile.linux +@@ -17,5 +17,5 @@ clean: + + install: + mkdir -p $(BINDIR) $(MANDIR) +- $(INSTALL) -s -c pppdump $(BINDIR) ++ $(INSTALL) -c pppdump $(BINDIR) + $(INSTALL) -c -m 444 pppdump.8 $(MANDIR) +diff --git a/pppstats/Makefile.linux b/pppstats/Makefile.linux +index 42aba73..c5ba3b1 100644 +--- a/pppstats/Makefile.linux ++++ b/pppstats/Makefile.linux +@@ -22,7 +22,7 @@ all: pppstats + + install: pppstats + -mkdir -p $(MANDIR) +- $(INSTALL) -s -c pppstats $(BINDIR) ++ $(INSTALL) -c pppstats $(BINDIR) + $(INSTALL) -c -m 444 pppstats.8 $(MANDIR) + + pppstats: $(PPPSTATSRCS) +-- +1.8.3.1 + diff --git a/0008-build-sys-use-prefix-usr-instead-of-usr-local.patch b/0008-build-sys-use-prefix-usr-instead-of-usr-local.patch new file mode 100644 index 0000000..e82c957 --- /dev/null +++ b/0008-build-sys-use-prefix-usr-instead-of-usr-local.patch @@ -0,0 +1,89 @@ +From 343728d5de6e44bd67923503e62eefaad50760a4 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 18:47:01 +0200 +Subject: [PATCH 08/27] build-sys: use prefix /usr instead of /usr/local + +--- + configure | 2 +- + pppd/Makefile.linux | 4 ++-- + scripts/ppp-on-rsh | 2 +- + scripts/ppp-on-ssh | 4 ++-- + scripts/secure-card | 2 +- + 5 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/configure b/configure +index 6a55e0f..db54d77 100755 +--- a/configure ++++ b/configure +@@ -2,7 +2,7 @@ + # $Id: configure,v 1.38 2008/06/15 07:08:49 paulus Exp $ + + # Where to install stuff by default +-DESTDIR=/usr/local ++DESTDIR=/usr + SYSCONF=/etc + + # if [ -d /NextApps ]; then +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 4f27100..95c2598 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -99,8 +99,8 @@ endif + + # EAP SRP-SHA1 + ifdef USE_SRP +-CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include +-LIBS += -lsrp -L/usr/local/ssl/lib -lcrypto ++CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/include/openssl ++LIBS += -lsrp -L/usr/lib -lcrypto + TARGETS += srp-entry + EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry + MANPAGES += srp-entry.8 +diff --git a/scripts/ppp-on-rsh b/scripts/ppp-on-rsh +index 30a50db..a80616a 100755 +--- a/scripts/ppp-on-rsh ++++ b/scripts/ppp-on-rsh +@@ -26,7 +26,7 @@ PPPD_RHOST=myremotehost + # For this example, we assume that pppd on both local and remote + # machines reside in the same place, /usr/local/bin/pppd + # +-PPPD_LOC=/usr/local/bin/pppd ++PPPD_LOC=/usr/sbin/pppd + + # + # The location of local options file (where rsh client is running). +diff --git a/scripts/ppp-on-ssh b/scripts/ppp-on-ssh +index 0e41aca..c27e80a 100755 +--- a/scripts/ppp-on-ssh ++++ b/scripts/ppp-on-ssh +@@ -26,7 +26,7 @@ PPPD_RHOST=myremotehost + # For this example, we assume that pppd on both local and remote + # machines reside in the same place, /usr/local/bin/pppd + # +-PPPD_LOC=/usr/local/bin/pppd ++PPPD_LOC=/usr/sbin/pppd + + # + # The location of local options file (where ssh client is running). +@@ -52,7 +52,7 @@ PPPD_REM_OPT=/etc/ppp/options-ssh-rem + # + # The location of ssh client on the local machine + # +-SSH_LOC=/usr/local/bin/ssh ++SSH_LOC=/usr/bin/ssh + + export PPPD_LOC PPPD_LOC_OPT PPPD_REM_OPT PPPD_RHOST SSH_LOC + +diff --git a/scripts/secure-card b/scripts/secure-card +index 0002365..ae3ae50 100755 +--- a/scripts/secure-card ++++ b/scripts/secure-card +@@ -1,4 +1,4 @@ +-#!/usr/local/bin/expect -f ++#!/usr/bin/expect -f + # + # This script was written by Jim Isaacson . It is + # designed to work as a script to use the SecureCARD(tm) device. This +-- +1.8.3.1 + diff --git a/0009-pppd-introduce-ipv6-accept-remote.patch b/0009-pppd-introduce-ipv6-accept-remote.patch new file mode 100644 index 0000000..af0f015 --- /dev/null +++ b/0009-pppd-introduce-ipv6-accept-remote.patch @@ -0,0 +1,57 @@ +From abef895f9d144f05a83045136b77277352dc450f Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Fri, 4 Apr 2014 18:53:33 +0200 +Subject: [PATCH 09/27] pppd: introduce ipv6-accept-remote + +--- + pppd/ipv6cp.c | 5 ++++- + pppd/ipv6cp.h | 3 ++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c +index caa2b26..5a56c95 100644 +--- a/pppd/ipv6cp.c ++++ b/pppd/ipv6cp.c +@@ -245,6 +245,8 @@ static option_t ipv6cp_option_list[] = { + + { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + "Accept peer's interface identifier for us", 1 }, ++ { "ipv6cp-accept-remote", o_bool, &ipv6cp_allowoptions[0].accept_remote, ++ "Accept peer's interface identifier for itself", 1 }, + + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, + "Use (default) IPv4 address as interface identifier", 1 }, +@@ -437,6 +439,7 @@ ipv6cp_init(unit) + memset(ao, 0, sizeof(*ao)); + + wo->accept_local = 1; ++ wo->accept_remote = 1; + wo->neg_ifaceid = 1; + ao->neg_ifaceid = 1; + +@@ -962,7 +965,7 @@ ipv6cp_reqci(f, inp, len, reject_if_disagree) + orc = CONFREJ; /* Reject CI */ + break; + } +- if (!eui64_iszero(wo->hisid) && ++ if (!eui64_iszero(wo->hisid) && !wo->accept_remote && + !eui64_equals(ifaceid, wo->hisid) && + eui64_iszero(go->hisid)) { + +diff --git a/pppd/ipv6cp.h b/pppd/ipv6cp.h +index cc4568d..8c7552e 100644 +--- a/pppd/ipv6cp.h ++++ b/pppd/ipv6cp.h +@@ -150,7 +150,8 @@ + typedef struct ipv6cp_options { + int neg_ifaceid; /* Negotiate interface identifier? */ + int req_ifaceid; /* Ask peer to send interface identifier? */ +- int accept_local; /* accept peer's value for iface id? */ ++ int accept_local; /* accept peer's value for our iface id? */ ++ int accept_remote; /* accept peer's value for his iface id? */ + int opt_local; /* ourtoken set by option */ + int opt_remote; /* histoken set by option */ + int use_ip; /* use IP as interface identifier */ +-- +1.8.3.1 + diff --git a/0010-build-sys-enable-CBCP.patch b/0010-build-sys-enable-CBCP.patch new file mode 100644 index 0000000..87c3b72 --- /dev/null +++ b/0010-build-sys-enable-CBCP.patch @@ -0,0 +1,26 @@ +From 8015a0ef23a874f288d5e77ffafe1d7f4281725d Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 18:59:24 +0200 +Subject: [PATCH 10/27] build-sys: enable CBCP + +Resolves: #199278 +--- + pppd/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 95c2598..65700fa 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -68,7 +68,7 @@ HAVE_INET6=y + PLUGIN=y + + # Enable Microsoft proprietary Callback Control Protocol +-#CBCP=y ++CBCP=y + + # Enable EAP SRP-SHA1 authentication (requires libsrp) + #USE_SRP=y +-- +1.8.3.1 + diff --git a/0011-build-sys-don-t-put-connect-errors-log-to-etc-ppp.patch b/0011-build-sys-don-t-put-connect-errors-log-to-etc-ppp.patch new file mode 100644 index 0000000..56ac388 --- /dev/null +++ b/0011-build-sys-don-t-put-connect-errors-log-to-etc-ppp.patch @@ -0,0 +1,77 @@ +From b4ef433be936c90e356da7a590b032cdee219a3f Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 4 Apr 2014 19:06:05 +0200 +Subject: [PATCH 11/27] build-sys: don't put connect-errors log to /etc/ppp/ + +Resolves: #118837 +--- + chat/chat.8 | 2 +- + linux/Makefile.top | 8 +++++++- + pppd/pathnames.h | 4 ++-- + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/chat/chat.8 b/chat/chat.8 +index 6d10836..78d6939 100644 +--- a/chat/chat.8 ++++ b/chat/chat.8 +@@ -200,7 +200,7 @@ The \fBSAY\fR directive allows the script to send strings to the user + at the terminal via standard error. If \fBchat\fR is being run by + pppd, and pppd is running as a daemon (detached from its controlling + terminal), standard error will normally be redirected to the file +-/etc/ppp/connect\-errors. ++/var/log/ppp/connect\-errors. + .LP + \fBSAY\fR strings must be enclosed in single or double quotes. If + carriage return and line feed are needed in the string to be output, +diff --git a/linux/Makefile.top b/linux/Makefile.top +index f63d45e..f42efd5 100644 +--- a/linux/Makefile.top ++++ b/linux/Makefile.top +@@ -5,6 +5,8 @@ BINDIR = $(DESTDIR)/sbin + INCDIR = $(DESTDIR)/include + MANDIR = $(DESTDIR)/share/man + ETCDIR = $(INSTROOT)@SYSCONF@/ppp ++RUNDIR = $(DESTDIR)/var/run/ppp ++LOGDIR = $(DESTDIR)/var/log/ppp + + # uid 0 = root + INSTALL= install +@@ -16,7 +18,7 @@ all: + cd pppstats; $(MAKE) $(MFLAGS) all + cd pppdump; $(MAKE) $(MFLAGS) all + +-install: $(BINDIR) $(MANDIR)/man8 install-progs install-devel ++install: $(BINDIR) $(RUNDIR) $(LOGDIR) $(MANDIR)/man8 install-progs install-devel + + install-progs: + cd chat; $(MAKE) $(MFLAGS) install +@@ -44,6 +46,10 @@ $(MANDIR)/man8: + $(INSTALL) -d -m 755 $@ + $(ETCDIR): + $(INSTALL) -d -m 755 $@ ++$(RUNDIR): ++ $(INSTALL) -d -m 755 $@ ++$(LOGDIR): ++ $(INSTALL) -d -m 755 $@ + + clean: + rm -f `find . -name '*.[oas]' -print` +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index a427cb8..bef3160 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -28,9 +28,9 @@ + #define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up" + #define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down" + #define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options." +-#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors" ++#define _PATH_CONNERRS _ROOT_PATH "/var/log/ppp/connect-errors" + #define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/" +-#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf" ++#define _PATH_RESOLV _ROOT_PATH "/var/run/ppp/resolv.conf" + + #define _PATH_USEROPT ".ppprc" + #define _PATH_PSEUDONYM ".ppp_pseudonym" +-- +1.8.3.1 + diff --git a/0012-pppd-we-don-t-want-to-accidentally-leak-fds.patch b/0012-pppd-we-don-t-want-to-accidentally-leak-fds.patch new file mode 100644 index 0000000..cf25dba --- /dev/null +++ b/0012-pppd-we-don-t-want-to-accidentally-leak-fds.patch @@ -0,0 +1,143 @@ +From 82cd789df0f022eb6f3d28646e7a61d1d0715805 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 7 Apr 2014 12:23:36 +0200 +Subject: [PATCH 12/27] pppd: we don't want to accidentally leak fds + +--- + pppd/auth.c | 20 ++++++++++---------- + pppd/options.c | 2 +- + pppd/sys-linux.c | 4 ++-- + 3 files changed, 13 insertions(+), 13 deletions(-) + +diff --git a/pppd/auth.c b/pppd/auth.c +index 4271af6..9e957fa 100644 +--- a/pppd/auth.c ++++ b/pppd/auth.c +@@ -428,7 +428,7 @@ setupapfile(argv) + option_error("unable to reset uid before opening %s: %m", fname); + return 0; + } +- ufile = fopen(fname, "r"); ++ ufile = fopen(fname, "re"); + if (seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); + if (ufile == NULL) { +@@ -1413,7 +1413,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) + filename = _PATH_UPAPFILE; + addrs = opts = NULL; + ret = UPAP_AUTHNAK; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) { + error("Can't open PAP password file %s: %m", filename); + +@@ -1512,7 +1512,7 @@ null_login(unit) + if (ret <= 0) { + filename = _PATH_UPAPFILE; + addrs = NULL; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) + return 0; + check_access(f, filename); +@@ -1559,7 +1559,7 @@ get_pap_passwd(passwd) + } + + filename = _PATH_UPAPFILE; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) + return 0; + check_access(f, filename); +@@ -1597,7 +1597,7 @@ have_pap_secret(lacks_ipp) + } + + filename = _PATH_UPAPFILE; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) + return 0; + +@@ -1642,7 +1642,7 @@ have_chap_secret(client, server, need_ip, lacks_ipp) + } + + filename = _PATH_CHAPFILE; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) + return 0; + +@@ -1684,7 +1684,7 @@ have_srp_secret(client, server, need_ip, lacks_ipp) + struct wordlist *addrs; + + filename = _PATH_SRPFILE; +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) + return 0; + +@@ -1740,7 +1740,7 @@ get_secret(unit, client, server, secret, secret_len, am_server) + addrs = NULL; + secbuf[0] = 0; + +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + if (f == NULL) { + error("Can't open chap secret file %s: %m", filename); + return 0; +@@ -1797,7 +1797,7 @@ get_srp_secret(unit, client, server, secret, am_server) + filename = _PATH_SRPFILE; + addrs = NULL; + +- fp = fopen(filename, "r"); ++ fp = fopen(filename, "re"); + if (fp == NULL) { + error("Can't open srp secret file %s: %m", filename); + return 0; +@@ -2203,7 +2203,7 @@ scan_authfile(f, client, server, secret, addrs, opts, filename, flags) + */ + if (word[0] == '@' && word[1] == '/') { + strlcpy(atfile, word+1, sizeof(atfile)); +- if ((sf = fopen(atfile, "r")) == NULL) { ++ if ((sf = fopen(atfile, "re")) == NULL) { + warn("can't open indirect secret file %s", atfile); + continue; + } +diff --git a/pppd/options.c b/pppd/options.c +index 45fa742..1d754ae 100644 +--- a/pppd/options.c ++++ b/pppd/options.c +@@ -427,7 +427,7 @@ options_from_file(filename, must_exist, check_prot, priv) + option_error("unable to drop privileges to open %s: %m", filename); + return 0; + } +- f = fopen(filename, "r"); ++ f = fopen(filename, "re"); + err = errno; + if (check_prot && seteuid(euid) == -1) + fatal("unable to regain privileges"); +diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c +index 72a7727..8a12fa0 100644 +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -1412,7 +1412,7 @@ static char *path_to_procfs(const char *tail) + /* Default the mount location of /proc */ + strlcpy (proc_path, "/proc", sizeof(proc_path)); + proc_path_len = 5; +- fp = fopen(MOUNTED, "r"); ++ fp = fopen(MOUNTED, "re"); + if (fp != NULL) { + while ((mntent = getmntent(fp)) != NULL) { + if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0) +@@ -1472,7 +1472,7 @@ static int open_route_table (void) + close_route_table(); + + path = path_to_procfs("/net/route"); +- route_fd = fopen (path, "r"); ++ route_fd = fopen (path, "re"); + if (route_fd == NULL) { + error("can't open routing table %s: %m", path); + return 0; +-- +1.8.3.1 + diff --git a/0013-everywhere-O_CLOEXEC-harder.patch b/0013-everywhere-O_CLOEXEC-harder.patch new file mode 100644 index 0000000..d720c36 --- /dev/null +++ b/0013-everywhere-O_CLOEXEC-harder.patch @@ -0,0 +1,241 @@ +From 302c1b736cb656c7885a0cba270fd953a672d8a8 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 7 Apr 2014 13:56:34 +0200 +Subject: [PATCH 13/27] everywhere: O_CLOEXEC harder + +--- + pppd/eap.c | 2 +- + pppd/main.c | 4 ++-- + pppd/options.c | 4 ++-- + pppd/sys-linux.c | 22 +++++++++++----------- + pppd/tdb.c | 4 ++-- + pppd/tty.c | 4 ++-- + pppd/utils.c | 6 +++--- + 7 files changed, 23 insertions(+), 23 deletions(-) + +diff --git a/pppd/eap.c b/pppd/eap.c +index 6ea6c1f..faced53 100644 +--- a/pppd/eap.c ++++ b/pppd/eap.c +@@ -1226,7 +1226,7 @@ mode_t modebits; + + if ((path = name_of_pn_file()) == NULL) + return (-1); +- fd = open(path, modebits, S_IRUSR | S_IWUSR); ++ fd = open(path, modebits, S_IRUSR | S_IWUSR | O_CLOEXEC); + err = errno; + free(path); + errno = err; +diff --git a/pppd/main.c b/pppd/main.c +index 6d50d1b..4880377 100644 +--- a/pppd/main.c ++++ b/pppd/main.c +@@ -420,7 +420,7 @@ main(argc, argv) + die(0); + + /* Make sure fds 0, 1, 2 are open to somewhere. */ +- fd_devnull = open(_PATH_DEVNULL, O_RDWR); ++ fd_devnull = open(_PATH_DEVNULL, O_RDWR | O_CLOEXEC); + if (fd_devnull < 0) + fatal("Couldn't open %s: %m", _PATH_DEVNULL); + while (fd_devnull <= 2) { +@@ -1679,7 +1679,7 @@ device_script(program, in, out, dont_wait) + if (log_to_fd >= 0) + errfd = log_to_fd; + else +- errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600); ++ errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0600); + + ++conn_running; + pid = safe_fork(in, out, errfd); +diff --git a/pppd/options.c b/pppd/options.c +index 1d754ae..8e62635 100644 +--- a/pppd/options.c ++++ b/pppd/options.c +@@ -1544,9 +1544,9 @@ setlogfile(argv) + option_error("unable to drop permissions to open %s: %m", *argv); + return 0; + } +- fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); ++ fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL | O_CLOEXEC, 0644); + if (fd < 0 && errno == EEXIST) +- fd = open(*argv, O_WRONLY | O_APPEND); ++ fd = open(*argv, O_WRONLY | O_APPEND | O_CLOEXEC); + err = errno; + if (!privileged_option && seteuid(euid) == -1) + fatal("unable to regain privileges: %m"); +diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c +index 8a12fa0..00a2cf5 100644 +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -459,7 +459,7 @@ int generic_establish_ppp (int fd) + goto err; + } + dbglog("using channel %d", chindex); +- fd = open("/dev/ppp", O_RDWR); ++ fd = open("/dev/ppp", O_RDWR | O_CLOEXEC); + if (fd < 0) { + error("Couldn't reopen /dev/ppp: %m"); + goto err; +@@ -619,7 +619,7 @@ static int make_ppp_unit() + dbglog("in make_ppp_unit, already had /dev/ppp open?"); + close(ppp_dev_fd); + } +- ppp_dev_fd = open("/dev/ppp", O_RDWR); ++ ppp_dev_fd = open("/dev/ppp", O_RDWR | O_CLOEXEC); + if (ppp_dev_fd < 0) + fatal("Couldn't open /dev/ppp: %m"); + flags = fcntl(ppp_dev_fd, F_GETFL); +@@ -693,7 +693,7 @@ int bundle_attach(int ifnum) + if (!new_style_driver) + return -1; + +- master_fd = open("/dev/ppp", O_RDWR); ++ master_fd = open("/dev/ppp", O_RDWR | O_CLOEXEC); + if (master_fd < 0) + fatal("Couldn't open /dev/ppp: %m"); + if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) { +@@ -1715,7 +1715,7 @@ int sifproxyarp (int unit, u_int32_t his_adr) + if (tune_kernel) { + forw_path = path_to_procfs("/sys/net/ipv4/ip_forward"); + if (forw_path != 0) { +- int fd = open(forw_path, O_WRONLY); ++ int fd = open(forw_path, O_WRONLY | O_CLOEXEC); + if (fd >= 0) { + if (write(fd, "1", 1) != 1) + error("Couldn't enable IP forwarding: %m"); +@@ -2030,7 +2030,7 @@ int ppp_available(void) + sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); + kernel_version = KVERSION(osmaj, osmin, ospatch); + +- fd = open("/dev/ppp", O_RDWR); ++ fd = open("/dev/ppp", O_RDWR | O_CLOEXEC); + if (fd >= 0) { + new_style_driver = 1; + +@@ -2208,7 +2208,7 @@ void logwtmp (const char *line, const char *name, const char *host) + #if __GLIBC__ >= 2 + updwtmp(_PATH_WTMP, &ut); + #else +- wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY); ++ wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY|O_CLOEXEC); + if (wtmp >= 0) { + flock(wtmp, LOCK_EX); + +@@ -2394,7 +2394,7 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr, + int fd; + + path = path_to_procfs("/sys/net/ipv4/ip_dynaddr"); +- if (path != 0 && (fd = open(path, O_WRONLY)) >= 0) { ++ if (path != 0 && (fd = open(path, O_WRONLY | O_CLOEXEC)) >= 0) { + if (write(fd, "1", 1) != 1) + error("Couldn't enable dynamic IP addressing: %m"); + close(fd); +@@ -2570,7 +2570,7 @@ get_pty(master_fdp, slave_fdp, slave_name, uid) + /* + * Try the unix98 way first. + */ +- mfd = open("/dev/ptmx", O_RDWR); ++ mfd = open("/dev/ptmx", O_RDWR | O_CLOEXEC); + if (mfd >= 0) { + int ptn; + if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) { +@@ -2581,7 +2581,7 @@ get_pty(master_fdp, slave_fdp, slave_name, uid) + if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0) + warn("Couldn't unlock pty slave %s: %m", pty_name); + #endif +- if ((sfd = open(pty_name, O_RDWR | O_NOCTTY)) < 0) ++ if ((sfd = open(pty_name, O_RDWR | O_NOCTTY | O_CLOEXEC)) < 0) + warn("Couldn't open pty slave %s: %m", pty_name); + } + } +@@ -2592,10 +2592,10 @@ get_pty(master_fdp, slave_fdp, slave_name, uid) + for (i = 0; i < 64; ++i) { + slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x", + 'p' + i / 16, i % 16); +- mfd = open(pty_name, O_RDWR, 0); ++ mfd = open(pty_name, O_RDWR | O_CLOEXEC, 0); + if (mfd >= 0) { + pty_name[5] = 't'; +- sfd = open(pty_name, O_RDWR | O_NOCTTY, 0); ++ sfd = open(pty_name, O_RDWR | O_NOCTTY | O_CLOEXEC, 0); + if (sfd >= 0) { + fchown(sfd, uid, -1); + fchmod(sfd, S_IRUSR | S_IWUSR); +diff --git a/pppd/tdb.c b/pppd/tdb.c +index bdc5828..c7ab71c 100644 +--- a/pppd/tdb.c ++++ b/pppd/tdb.c +@@ -1724,7 +1724,7 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags, + goto internal; + } + +- if ((tdb->fd = open(name, open_flags, mode)) == -1) { ++ if ((tdb->fd = open(name, open_flags | O_CLOEXEC, mode)) == -1) { + TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + name, strerror(errno))); + goto fail; /* errno set by open(2) */ +@@ -1967,7 +1967,7 @@ int tdb_reopen(TDB_CONTEXT *tdb) + } + if (close(tdb->fd) != 0) + TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); +- tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); ++ tdb->fd = open(tdb->name, (tdb->open_flags & ~(O_CREAT|O_TRUNC)) | O_CLOEXEC, 0); + if (tdb->fd == -1) { + TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + goto fail; +diff --git a/pppd/tty.c b/pppd/tty.c +index d571b11..bc96695 100644 +--- a/pppd/tty.c ++++ b/pppd/tty.c +@@ -569,7 +569,7 @@ int connect_tty() + status = EXIT_OPEN_FAILED; + goto errret; + } +- real_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); ++ real_ttyfd = open(devnam, O_NONBLOCK | O_RDWR | O_CLOEXEC, 0); + err = errno; + if (prio < OPRIO_ROOT && seteuid(0) == -1) + fatal("Unable to regain privileges"); +@@ -723,7 +723,7 @@ int connect_tty() + if (connector == NULL && modem && devnam[0] != 0) { + int i; + for (;;) { +- if ((i = open(devnam, O_RDWR)) >= 0) ++ if ((i = open(devnam, O_RDWR | O_CLOEXEC)) >= 0) + break; + if (errno != EINTR) { + error("Failed to reopen %s: %m", devnam); +diff --git a/pppd/utils.c b/pppd/utils.c +index 29bf970..6051b9a 100644 +--- a/pppd/utils.c ++++ b/pppd/utils.c +@@ -918,14 +918,14 @@ lock(dev) + slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); + #endif + +- while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { ++ while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR | O_CLOEXEC, 0644)) < 0) { + if (errno != EEXIST) { + error("Can't create lock file %s: %m", lock_file); + break; + } + + /* Read the lock file to find out who has the device locked. */ +- fd = open(lock_file, O_RDONLY, 0); ++ fd = open(lock_file, O_RDONLY | O_CLOEXEC, 0); + if (fd < 0) { + if (errno == ENOENT) /* This is just a timing problem. */ + continue; +@@ -1004,7 +1004,7 @@ relock(pid) + + if (lock_file[0] == 0) + return -1; +- fd = open(lock_file, O_WRONLY, 0); ++ fd = open(lock_file, O_WRONLY | O_CLOEXEC, 0); + if (fd < 0) { + error("Couldn't reopen lock file %s: %m", lock_file); + lock_file[0] = 0; +-- +1.8.3.1 + diff --git a/0014-everywhere-use-SOCK_CLOEXEC-when-creating-socket.patch b/0014-everywhere-use-SOCK_CLOEXEC-when-creating-socket.patch new file mode 100644 index 0000000..08d67f7 --- /dev/null +++ b/0014-everywhere-use-SOCK_CLOEXEC-when-creating-socket.patch @@ -0,0 +1,174 @@ +From 2a97ab28ee00586e5f06b3ef3a0e43ea0c7c6499 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 7 Apr 2014 14:21:41 +0200 +Subject: [PATCH 14/27] everywhere: use SOCK_CLOEXEC when creating socket + +--- + pppd/plugins/pppoatm/pppoatm.c | 2 +- + pppd/plugins/pppol2tp/openl2tp.c | 2 +- + pppd/plugins/pppol2tp/pppol2tp.c | 2 +- + pppd/plugins/rp-pppoe/if.c | 2 +- + pppd/plugins/rp-pppoe/plugin.c | 6 +++--- + pppd/plugins/rp-pppoe/pppoe-discovery.c | 2 +- + pppd/sys-linux.c | 10 +++++----- + pppd/tty.c | 2 +- + 8 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/pppd/plugins/pppoatm/pppoatm.c b/pppd/plugins/pppoatm/pppoatm.c +index d693350..c31bb34 100644 +--- a/pppd/plugins/pppoatm/pppoatm.c ++++ b/pppd/plugins/pppoatm/pppoatm.c +@@ -135,7 +135,7 @@ static int connect_pppoatm(void) + + if (!device_got_set) + no_device_given_pppoatm(); +- fd = socket(AF_ATMPVC, SOCK_DGRAM, 0); ++ fd = socket(AF_ATMPVC, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) + fatal("failed to create socket: %m"); + memset(&qos, 0, sizeof qos); +diff --git a/pppd/plugins/pppol2tp/openl2tp.c b/pppd/plugins/pppol2tp/openl2tp.c +index 9643b96..1099575 100644 +--- a/pppd/plugins/pppol2tp/openl2tp.c ++++ b/pppd/plugins/pppol2tp/openl2tp.c +@@ -83,7 +83,7 @@ static int openl2tp_client_create(void) + int result; + + if (openl2tp_fd < 0) { +- openl2tp_fd = socket(PF_UNIX, SOCK_DGRAM, 0); ++ openl2tp_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (openl2tp_fd < 0) { + error("openl2tp connection create: %m"); + return -ENOTCONN; +diff --git a/pppd/plugins/pppol2tp/pppol2tp.c b/pppd/plugins/pppol2tp/pppol2tp.c +index a7e3400..e64a778 100644 +--- a/pppd/plugins/pppol2tp/pppol2tp.c ++++ b/pppd/plugins/pppol2tp/pppol2tp.c +@@ -208,7 +208,7 @@ static void send_config_pppol2tp(int mtu, + struct ifreq ifr; + int fd; + +- fd = socket(AF_INET, SOCK_DGRAM, 0); ++ fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd >= 0) { + memset (&ifr, '\0', sizeof (ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); +diff --git a/pppd/plugins/rp-pppoe/if.c b/pppd/plugins/rp-pppoe/if.c +index 91e9a57..72aba41 100644 +--- a/pppd/plugins/rp-pppoe/if.c ++++ b/pppd/plugins/rp-pppoe/if.c +@@ -116,7 +116,7 @@ openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr) + stype = SOCK_PACKET; + #endif + +- if ((fd = socket(domain, stype, htons(type))) < 0) { ++ if ((fd = socket(domain, stype | SOCK_CLOEXEC, htons(type))) < 0) { + /* Give a more helpful message for the common error case */ + if (errno == EPERM) { + fatal("Cannot create raw socket -- pppoe must be run as root."); +diff --git a/pppd/plugins/rp-pppoe/plugin.c b/pppd/plugins/rp-pppoe/plugin.c +index a8c2bb4..24bdf8f 100644 +--- a/pppd/plugins/rp-pppoe/plugin.c ++++ b/pppd/plugins/rp-pppoe/plugin.c +@@ -137,7 +137,7 @@ PPPOEConnectDevice(void) + /* server equipment). */ + /* Opening this socket just before waitForPADS in the discovery() */ + /* function would be more appropriate, but it would mess-up the code */ +- conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); ++ conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM | SOCK_CLOEXEC, PX_PROTO_OE); + if (conn->sessionSocket < 0) { + error("Failed to create PPPoE socket: %m"); + return -1; +@@ -148,7 +148,7 @@ PPPOEConnectDevice(void) + lcp_wantoptions[0].mru = conn->mru; + + /* Update maximum MRU */ +- s = socket(AF_INET, SOCK_DGRAM, 0); ++ s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (s < 0) { + error("Can't get MTU for %s: %m", conn->ifName); + goto errout; +@@ -320,7 +320,7 @@ PPPoEDevnameHook(char *cmd, char **argv, int doit) + } + + /* Open a socket */ +- if ((fd = socket(PF_PACKET, SOCK_RAW, 0)) < 0) { ++ if ((fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0)) < 0) { + r = 0; + } + +diff --git a/pppd/plugins/rp-pppoe/pppoe-discovery.c b/pppd/plugins/rp-pppoe/pppoe-discovery.c +index 3d3bf4e..c0d927d 100644 +--- a/pppd/plugins/rp-pppoe/pppoe-discovery.c ++++ b/pppd/plugins/rp-pppoe/pppoe-discovery.c +@@ -121,7 +121,7 @@ openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr) + stype = SOCK_PACKET; + #endif + +- if ((fd = socket(domain, stype, htons(type))) < 0) { ++ if ((fd = socket(domain, stype | SOCK_CLOEXEC, htons(type))) < 0) { + /* Give a more helpful message for the common error case */ + if (errno == EPERM) { + rp_fatal("Cannot create raw socket -- pppoe must be run as root."); +diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c +index 00a2cf5..0690019 100644 +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -308,12 +308,12 @@ static int modify_flags(int fd, int clear_bits, int set_bits) + void sys_init(void) + { + /* Get an internet socket for doing socket ioctls. */ +- sock_fd = socket(AF_INET, SOCK_DGRAM, 0); ++ sock_fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sock_fd < 0) + fatal("Couldn't create IP socket: %m(%d)", errno); + + #ifdef INET6 +- sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0); ++ sock6_fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sock6_fd < 0) + sock6_fd = -errno; /* save errno for later */ + #endif +@@ -1857,7 +1857,7 @@ get_if_hwaddr(u_char *addr, char *name) + struct ifreq ifreq; + int ret, sock_fd; + +- sock_fd = socket(AF_INET, SOCK_DGRAM, 0); ++ sock_fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sock_fd < 0) + return 0; + memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr)); +@@ -2067,7 +2067,7 @@ int ppp_available(void) + /* + * Open a socket for doing the ioctl operations. + */ +- s = socket(AF_INET, SOCK_DGRAM, 0); ++ s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (s < 0) + return 0; + +@@ -2860,7 +2860,7 @@ ether_to_eui64(eui64_t *p_eui64) + int skfd; + const unsigned char *ptr; + +- skfd = socket(PF_INET6, SOCK_DGRAM, 0); ++ skfd = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if(skfd == -1) + { + warn("could not open IPv6 socket"); +diff --git a/pppd/tty.c b/pppd/tty.c +index bc96695..8e76a5d 100644 +--- a/pppd/tty.c ++++ b/pppd/tty.c +@@ -896,7 +896,7 @@ open_socket(dest) + *sep = ':'; + + /* get a socket and connect it to the other end */ +- sock = socket(PF_INET, SOCK_STREAM, 0); ++ sock = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (sock < 0) { + error("Can't create socket: %m"); + return -1; +-- +1.8.3.1 + diff --git a/0015-pppd-move-pppd-database-to-var-run-ppp.patch b/0015-pppd-move-pppd-database-to-var-run-ppp.patch new file mode 100644 index 0000000..88b84d5 --- /dev/null +++ b/0015-pppd-move-pppd-database-to-var-run-ppp.patch @@ -0,0 +1,44 @@ +From f2c855462ff56be4121409c7e048cd2503fe0ccf Mon Sep 17 00:00:00 2001 +From: Jiri Skala +Date: Mon, 7 Apr 2014 14:26:20 +0200 +Subject: [PATCH 15/27] pppd: move pppd database to /var/run/ppp + +Resolves: #560014 +--- + pppd/pathnames.h | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index bef3160..24e010c 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -6,8 +6,9 @@ + + #ifdef HAVE_PATHS_H + #include +- ++#define _PPP_SUBDIR "ppp/" + #else /* HAVE_PATHS_H */ ++#define _PPP_SUBDIR + #ifndef _PATH_VARRUN + #define _PATH_VARRUN "/etc/ppp/" + #endif +@@ -46,13 +47,9 @@ + #endif /* IPX_CHANGE */ + + #ifdef __STDC__ +-#define _PATH_PPPDB _ROOT_PATH _PATH_VARRUN "pppd2.tdb" ++#define _PATH_PPPDB _ROOT_PATH _PATH_VARRUN _PPP_SUBDIR "pppd2.tdb" + #else /* __STDC__ */ +-#ifdef HAVE_PATHS_H +-#define _PATH_PPPDB "/var/run/pppd2.tdb" +-#else +-#define _PATH_PPPDB "/etc/ppp/pppd2.tdb" +-#endif ++#define _PATH_PPPDB _PATH_VARRUN _PPP_SUBDIR "pppd2.tdb" + #endif /* __STDC__ */ + + #ifdef PLUGIN +-- +1.8.3.1 + diff --git a/0016-rp-pppoe-add-manpage-for-pppoe-discovery.patch b/0016-rp-pppoe-add-manpage-for-pppoe-discovery.patch new file mode 100644 index 0000000..a13fe79 --- /dev/null +++ b/0016-rp-pppoe-add-manpage-for-pppoe-discovery.patch @@ -0,0 +1,126 @@ +From a30efa2cc99a5b6ab220de04cbcc7db38888a17a Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 7 Apr 2014 14:29:45 +0200 +Subject: [PATCH 16/27] rp-pppoe: add manpage for pppoe-discovery + +--- + pppd/plugins/rp-pppoe/Makefile.linux | 2 + + pppd/plugins/rp-pppoe/pppoe-discovery.8 | 86 +++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + create mode 100644 pppd/plugins/rp-pppoe/pppoe-discovery.8 + +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index 3cd9101..9918091 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -16,6 +16,7 @@ + + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin ++MANDIR = $(DESTDIR)/share/man/man8 + LIBDIR = $(DESTDIR)/lib/$(shell gcc -print-multi-os-directory 2> /dev/null)/pppd/$(PPPDVERSION) + + PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) +@@ -46,6 +47,7 @@ install: all + $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR) + $(INSTALL) -d -m 755 $(BINDIR) + $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR) ++ $(INSTALL) -c -m 444 pppoe-discovery.8 $(MANDIR) + + clean: + rm -f *.o *.so pppoe-discovery +diff --git a/pppd/plugins/rp-pppoe/pppoe-discovery.8 b/pppd/plugins/rp-pppoe/pppoe-discovery.8 +new file mode 100644 +index 0000000..d0a93db +--- /dev/null ++++ b/pppd/plugins/rp-pppoe/pppoe-discovery.8 +@@ -0,0 +1,86 @@ ++.\" pppoe-discovery.8 written by ++.\" Ben Hutchings , based on pppoe.8. ++.\" Licenced under the GPL version 2 or later. ++.TH PPPOE-DISCOVERY 8 ++.SH NAME ++pppoe\-discovery \- perform PPPoE discovery ++.SH SYNOPSIS ++.B pppoe\-discovery ++[ ++.I options ++] ++.br ++.BR pppoe\-discovery " { " \-V " | " \-h " }" ++.SH DESCRIPTION ++.LP ++\fBpppoe\-discovery\fR performs the same discovery process as ++\fBpppoe\fR, but does not initiate a session. ++It sends a PADI packet and then prints the names of access ++concentrators in each PADO packet it receives. ++.SH OPTIONS ++.TP ++.BI \-I " interface" ++.RS ++The \fB\-I\fR option specifies the Ethernet interface to use. ++Under Linux, it is typically eth0 or eth1. ++The interface should be \(lqup\(rq before you start ++\fBpppoe\-discovery\fR, but should \fInot\fR be configured to have an ++IP address. ++The default interface is eth0. ++.RE ++.TP ++.BI \-D " file_name" ++.RS ++The \fB\-D\fR option causes every packet to be dumped to the specified ++\fIfile_name\fR. ++This is intended for debugging only. ++.RE ++.TP ++.B \-U ++.RS ++Causes \fBpppoe\-discovery\fR to use the Host-Uniq tag in its discovery ++packets. ++This lets you run multiple instances of \fBpppoe\-discovery\fR and/or ++\fBpppoe\fR without having their discovery packets interfere with one ++another. ++You must supply this option to \fIall\fR instances that you intend to ++run simultaneously. ++.RE ++.TP ++.BI \-S " service_name" ++.RS ++Specifies the desired service name. ++\fBpppoe\-discovery\fR will only accept access concentrators which can ++provide the specified service. ++In most cases, you should \fInot\fR specify this option. ++Use it only if you know that there are multiple access concentrators ++or know that you need a specific service name. ++.RE ++.TP ++.BI \-C " ac_name" ++.RS ++Specifies the desired access concentrator name. ++\fBpppoe\-discovery\fR will only accept the specified access ++concentrator. ++In most cases, you should \fInot\fR specify this option. ++Use it only if you know that there are multiple access concentrators. ++If both the \fB\-S\fR and \fB\-C\fR options are specified, they must ++\fIboth\fR match. ++.RE ++.TP ++.B \-A ++.RS ++This option is accepted for compatibility with \fBpppoe\fR, but has no ++effect. ++.RE ++.TP ++.BR \-V " | " \-h ++.RS ++Either of these options causes \fBpppoe\-discovery\fR to print its ++version number and usage information, then exit. ++.RE ++.SH AUTHORS ++\fBpppoe\-discovery\fR was written by Marco d'Itri , ++based on \fBpppoe\fR by David F. Skoll . ++.SH SEE ALSO ++pppoe(8), pppoe-sniff(8) +-- +1.8.3.1 + diff --git a/0017-pppd-rebase-EAP-TLS-patch-v0.994.patch b/0017-pppd-rebase-EAP-TLS-patch-v0.994.patch new file mode 100644 index 0000000..991355d --- /dev/null +++ b/0017-pppd-rebase-EAP-TLS-patch-v0.994.patch @@ -0,0 +1,3045 @@ +From 044a5b1e5d878c519143b71a44b3d5b0ca91de3b Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 7 Apr 2014 14:56:56 +0200 +Subject: [PATCH 17/27] pppd: rebase EAP-TLS patch v0.994 + +--- + README.eap-tls | 169 +++++++ + 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 | 414 ++++++++++++++- + pppd/ccp.c | 20 +- + pppd/chap-md5.c | 4 + + pppd/eap-tls.c | 1174 +++++++++++++++++++++++++++++++++++++++++++ + pppd/eap-tls.h | 107 ++++ + pppd/eap.c | 462 ++++++++++++++++- + pppd/eap.h | 32 +- + pppd/md5.c | 3 + + pppd/md5.h | 3 + + pppd/options.c | 10 + + pppd/pathnames.h | 7 + + pppd/plugins/Makefile.linux | 3 + + pppd/plugins/passprompt.c | 3 + + pppd/plugins/passwordfd.c | 4 + + pppd/pppd.h | 8 + + 21 files changed, 2461 insertions(+), 15 deletions(-) + create mode 100644 README.eap-tls + create mode 100644 etc.ppp/eaptls-client + create mode 100644 etc.ppp/eaptls-server + create mode 100644 etc.ppp/openssl.cnf + create mode 100644 pppd/eap-tls.c + create mode 100644 pppd/eap-tls.h + +diff --git a/README.eap-tls b/README.eap-tls +new file mode 100644 +index 0000000..0a4fee9 +--- /dev/null ++++ b/README.eap-tls +@@ -0,0 +1,169 @@ ++EAP-TLS authentication support for PPP ++====================================== ++ ++1. Intro ++ ++ The Extensible Authentication Protocol (EAP; RFC 3748) is a ++ security protocol that can be used with PPP. It provides a means ++ to plug in multiple optional authentication methods. ++ ++ Transport Level Security (TLS; RFC 2246) provides for mutual ++ authentication, integrity-protected ciphersuite negotiation and ++ key exchange between two endpoints. It also provides for optional ++ MPPE encryption. ++ ++ EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets, ++ allowing TLS mutual authentication to be used as a generic EAP ++ mechanism. It also provides optional encryption using the MPPE ++ protocol. ++ ++ This patch provide EAP-TLS support to pppd. ++ This authentication method can be used in both client or server ++ mode. ++ ++2. Building ++ ++ To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org) ++ is required. Any version from 0.9.7 should work. ++ ++ Configure, compile, and install as usual. ++ ++3. Configuration ++ ++ On the client side there are two ways to configure EAP-TLS: ++ ++ 1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters ++ ++ 2. edit the /etc/ppp/eaptls-client file. ++ Insert a line for each system with which you use EAP-TLS. ++ The line is composed of this fields separated by tab: ++ ++ - Client name ++ The name used by the client for authentication, can be * ++ - Server name ++ The name of the server, can be * ++ - Client certificate file ++ The file containing the certificate chain for the ++ client in PEM format ++ - Server certificate file ++ If you want to specify the certificate that the ++ server is allowed to use, put the certificate file name. ++ Else put a dash '-'. ++ - CA certificate file ++ The file containing the trusted CA certificates in PEM ++ format. ++ - Client private key file ++ The file containing the client private key in PEM format. ++ ++ ++ On the server side edit the /etc/ppp/eaptls-server file. ++ Insert a line for each system with which you use EAP-TLS. ++ The line is composed of this fields separated by tab: ++ ++ - Client name ++ The name used by the client for authentication, can be * ++ - Server name ++ The name of the server, can be * ++ - Client certificate file ++ If you want to specify the certificate that the ++ client is allowed to use, put the certificate file name. ++ Else put a dash '-'. ++ - Server certificate file ++ The file containing the certificate chain for the ++ server in PEM format ++ - CA certificate file ++ The file containing the trusted CA certificates in PEM ++ format. ++ - Client private key file ++ The file containing the server private key in PEM format. ++ - addresses ++ A list of IP addresses the client is allowed to use. ++ ++ ++ OpenSSL engine support is included starting with v0.95 of this patch. ++ Currently the only engine tested is the 'pkcs11' engine (hardware token ++ support). To use the 'pksc11' engine: ++ - Use a special private key fileiname in the /etc/ppp/eaptls-client file: ++ : ++ e.g. ++ pkcs11:123456 ++ ++ - The certificate can also be loaded from the 'pkcs11' engine using ++ a special client certificate filename in the /etc/ppp/eaptls-client file: ++ : ++ e.g. ++ pkcs11:123456 ++ ++ - Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior ++ to starting 'pppd'. A sample openssl.cnf file is ++ ++ openssl_conf = openssl_def ++ ++ [ openssl_def ] ++ engines = engine_section ++ ++ [ engine_section ] ++ pkcs11 = pkcs11_section ++ ++ [ pkcs11_section ] ++ engine_id = pkcs11 ++ dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so ++ MODULE_PATH = /usr/lib64/libeTPkcs11.so ++ init = 0 ++ ++ - There are two ways to specify a password/PIN for the PKCS11 engine: ++ - inside the openssl.cnf file using ++ PIN = your-secret-pin ++ Note The keyword 'PIN' is case sensitive! ++ - Using the 'password' in the ppp options file. ++ From v0.97 of the eap-tls patch the password can also be supplied ++ using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c ++ for an example). ++ ++ ++4. Options ++ ++ These pppd options are available: ++ ++ ca ++ Use the CA public certificate found in in PEM format ++ cert ++ Use the client public certificate found in in PEM format ++ or in engine:engine_id format ++ key ++ Use the client private key found in in PEM format ++ or in engine:engine_id format ++ crl-dir ++ Use CRL files from dir. It contains CRL files in PEM ++ format and each file contains a CRL. The files are looked up ++ by the issuer name hash value. Use the c_rehash utility ++ to create necessary links. ++ need-peer-eap ++ If the peer doesn't ask us to authenticate or doesn't use eap ++ to authenticate us, disconnect. ++ ++ Note: ++ password-encrypted certificates can be used as of v0.94 of this ++ patch. The password for the eap-tls.key file is specified using ++ the regular ++ password .... ++ statement in the ppp options file, or by using the appropriate ++ plugin which supplies a 'eaptls_passwd_hook' routine. ++ ++5. Connecting ++ ++ If you're setting up a pppd server, edit the EAP-TLS configuration file ++ as written above and then run pppd with the 'auth' option to authenticate ++ the client. The EAP-TLS method will be used if the other eap methods can't ++ be used (no secrets). ++ ++ If you're setting up a client, edit the configuration file and then run ++ pppd with 'remotename' option to specify the server name. Add the ++ 'need-peer-eap' option if you want to be sure the peer ask you to ++ authenticate (and to use eap) and to disconnect if it doesn't. ++ ++6. Notes ++ ++ This is experimental code. ++ Send suggestions and comments to Jan Just Keijser ++ +diff --git a/etc.ppp/eaptls-client b/etc.ppp/eaptls-client +new file mode 100644 +index 0000000..7782f0e +--- /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 +diff --git a/etc.ppp/eaptls-server b/etc.ppp/eaptls-server +new file mode 100644 +index 0000000..fa53cbd +--- /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 +diff --git a/etc.ppp/openssl.cnf b/etc.ppp/openssl.cnf +new file mode 100644 +index 0000000..dd32f30 +--- /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 ++ +diff --git a/linux/Makefile.top b/linux/Makefile.top +index f42efd5..9a8945a 100644 +--- a/linux/Makefile.top ++++ b/linux/Makefile.top +@@ -28,7 +28,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 +@@ -39,6 +39,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 $@ +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 65700fa..53df4d2 100644 +--- 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 +@@ -115,6 +118,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) +diff --git a/pppd/auth.c b/pppd/auth.c +index 9e957fa..88cbdb6 100644 +--- 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)) = NULL; + /* Hook for a plugin to get the CHAP password for authenticating us */ + int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; + ++#ifdef USE_EAPTLS ++/* Hook for a plugin to get the EAP-TLS password for authenticating us */ ++int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL; ++#endif ++ + /* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ + int (*null_auth_hook) __P((struct wordlist **paddrs, +@@ -238,6 +246,13 @@ bool explicit_remote = 0; /* User specified explicit remote name */ + bool explicit_user = 0; /* Set if "user" option supplied */ + bool explicit_passwd = 0; /* Set if "password" option supplied */ + char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ ++#ifdef USE_EAPTLS ++char *cacert_file = NULL; /* CA certificate file (pem format) */ ++char *cert_file = NULL; /* client certificate file (pem format) */ ++char *privkey_file = NULL; /* client private key file (pem format) */ ++char *crl_dir = NULL; /* directory containing CRL files */ ++bool need_peer_eap = 0; /* Require peer to authenticate us */ ++#endif + + static char *uafname; /* name of most recent +ua file */ + +@@ -254,6 +269,19 @@ static int have_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 +429,14 @@ 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" }, ++ { "need-peer-eap", o_bool, &need_peer_eap, ++ "Require the peer to authenticate us", 1 }, ++#endif /* USE_EAPTLS */ + { NULL } + }; + +@@ -730,6 +766,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 +803,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) { +@@ -1117,7 +1172,7 @@ np_down(unit, proto) + UNTIMEOUT(connect_time_expired, NULL); + #ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +-#endif ++#endif + new_phase(PHASE_NETWORK); + } + } +@@ -1144,7 +1199,7 @@ check_maxoctets(arg) + + update_link_stats(ifunit); + link_stats_valid=0; +- ++ + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; +@@ -1277,6 +1332,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 +1395,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 +1414,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; ++ + } + + +@@ -1707,6 +1781,7 @@ have_srp_secret(client, server, need_ip, lacks_ipp) + } + + ++ + /* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. +@@ -2359,3 +2434,334 @@ 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 +diff --git a/pppd/ccp.c b/pppd/ccp.c +index 5814f35..7dead23 100644 +--- 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; + } +diff --git a/pppd/chap-md5.c b/pppd/chap-md5.c +index 77dd4ec..269b52c 100644 +--- 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 +diff --git a/pppd/eap-tls.c b/pppd/eap-tls.c +new file mode 100644 +index 0000000..a3aea5a +--- /dev/null ++++ b/pppd/eap-tls.c +@@ -0,0 +1,1174 @@ ++/* ++ * eap-tls.c - EAP-TLS implementation for PPP ++ * ++ * Copyright (c) Beniamino Galvani 2005 All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * 3. The name(s) of the authors of this software must not be used to ++ * endorse or promote products derived from this software without ++ * prior written permission. ++ * ++ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO ++ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY ++ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ++ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "pppd.h" ++#include "eap.h" ++#include "eap-tls.h" ++#include "fsm.h" ++#include "lcp.h" ++#include "pathnames.h" ++ ++/* The openssl configuration file and engines can be loaded only once */ ++static CONF *ssl_config = NULL; ++static ENGINE *cert_engine = NULL; ++static ENGINE *pkey_engine = NULL; ++ ++#ifdef MPPE ++ ++/* ++ * TLS PRF from RFC 2246 ++ */ ++static void P_hash(const EVP_MD *evp_md, ++ const unsigned char *secret, unsigned int secret_len, ++ const unsigned char *seed, unsigned int seed_len, ++ unsigned char *out, unsigned int out_len) ++{ ++ HMAC_CTX ctx_a, ctx_out; ++ unsigned char a[HMAC_MAX_MD_CBLOCK]; ++ unsigned int size; ++ ++ HMAC_CTX_init(&ctx_a); ++ HMAC_CTX_init(&ctx_out); ++ HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL); ++ HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL); ++ ++ size = HMAC_size(&ctx_out); ++ ++ /* Calculate A(1) */ ++ HMAC_Update(&ctx_a, seed, seed_len); ++ HMAC_Final(&ctx_a, a, NULL); ++ ++ while (1) { ++ /* Calculate next part of output */ ++ HMAC_Update(&ctx_out, a, size); ++ HMAC_Update(&ctx_out, seed, seed_len); ++ ++ /* Check if last part */ ++ if (out_len < size) { ++ HMAC_Final(&ctx_out, a, NULL); ++ memcpy(out, a, out_len); ++ break; ++ } ++ ++ /* Place digest in output buffer */ ++ HMAC_Final(&ctx_out, out, NULL); ++ HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL); ++ out += size; ++ out_len -= size; ++ ++ /* Calculate next A(i) */ ++ HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL); ++ HMAC_Update(&ctx_a, a, size); ++ HMAC_Final(&ctx_a, a, NULL); ++ } ++ ++ HMAC_CTX_cleanup(&ctx_a); ++ HMAC_CTX_cleanup(&ctx_out); ++ memset(a, 0, sizeof(a)); ++} ++ ++static void PRF(const unsigned char *secret, unsigned int secret_len, ++ const unsigned char *seed, unsigned int seed_len, ++ unsigned char *out, unsigned char *buf, unsigned int out_len) ++{ ++ unsigned int i; ++ unsigned int len = (secret_len + 1) / 2; ++ const unsigned char *s1 = secret; ++ const unsigned char *s2 = secret + (secret_len - len); ++ ++ P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len); ++ P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len); ++ ++ for (i=0; i < out_len; i++) { ++ out[i] ^= buf[i]; ++ } ++} ++ ++#define EAPTLS_MPPE_KEY_LEN 32 ++ ++/* ++ * Generate keys according to RFC 2716 and add to reply ++ */ ++void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, ++ int client) ++{ ++ unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN]; ++ unsigned char seed[64 + 2*SSL3_RANDOM_SIZE]; ++ unsigned char *p = seed; ++ SSL *s = ets->ssl; ++ size_t prf_size; ++ ++ prf_size = strlen(prf_label); ++ ++ memcpy(p, prf_label, prf_size); ++ p += prf_size; ++ ++ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); ++ p += SSL3_RANDOM_SIZE; ++ prf_size += SSL3_RANDOM_SIZE; ++ ++ memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); ++ prf_size += SSL3_RANDOM_SIZE; ++ ++ PRF(s->session->master_key, s->session->master_key_length, ++ seed, prf_size, out, buf, sizeof(out)); ++ ++ /* ++ * We now have the master send and receive keys. ++ * From these, generate the session send and receive keys. ++ * (see RFC3079 / draft-ietf-pppext-mppe-keys-03.txt for details) ++ */ ++ if (client) ++ { ++ p = out; ++ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); ++ p += EAPTLS_MPPE_KEY_LEN; ++ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); ++ } ++ else ++ { ++ p = out; ++ BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); ++ p += EAPTLS_MPPE_KEY_LEN; ++ BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); ++ } ++ ++ mppe_keys_set = 1; ++} ++ ++#endif ++ ++void log_ssl_errors( void ) ++{ ++ unsigned long ssl_err = ERR_get_error(); ++ ++ if (ssl_err != 0) ++ dbglog("EAP-TLS SSL error stack:"); ++ while (ssl_err != 0) { ++ dbglog( ERR_error_string( ssl_err, NULL ) ); ++ ssl_err = ERR_get_error(); ++ } ++} ++ ++ ++int password_callback (char *buf, int size, int rwflag, void *u) ++{ ++ if (buf) ++ { ++ strncpy (buf, passwd, size); ++ return strlen (buf); ++ } ++ return 0; ++} ++ ++ ++CONF *eaptls_ssl_load_config( void ) ++{ ++ CONF *config; ++ int ret_code; ++ long error_line = 33; ++ ++ config = NCONF_new( NULL ); ++ dbglog( "Loading OpenSSL config file" ); ++ ret_code = NCONF_load( config, _PATH_OPENSSLCONFFILE, &error_line ); ++ if (ret_code == 0) ++ { ++ warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line ); ++ NCONF_free( config ); ++ config = NULL; ++ ERR_clear_error(); ++ } ++ ++ dbglog( "Loading OpenSSL built-ins" ); ++ ENGINE_load_builtin_engines(); ++ OPENSSL_load_builtin_modules(); ++ ++ dbglog( "Loading OpenSSL configured modules" ); ++ if (CONF_modules_load( config, NULL, 0 ) <= 0 ) ++ { ++ warn( "EAP-TLS: Error loading OpenSSL modules" ); ++ log_ssl_errors(); ++ config = NULL; ++ } ++ ++ return config; ++} ++ ++ENGINE *eaptls_ssl_load_engine( char *engine_name ) ++{ ++ ENGINE *e = NULL; ++ ++ dbglog( "Enabling OpenSSL auto engines" ); ++ ENGINE_register_all_complete(); ++ ++ dbglog( "Loading OpenSSL '%s' engine support", engine_name ); ++ e = ENGINE_by_id( engine_name ); ++ if (!e) ++ { ++ dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name ); ++ e = ENGINE_by_id( "dynamic" ); ++ if (e) ++ { ++ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0) ++ || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) ++ { ++ warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name ); ++ log_ssl_errors(); ++ ENGINE_free(e); ++ e = NULL; ++ } ++ } ++ else ++ { ++ warn( "EAP-TLS: Cannot load dynamic engine support" ); ++ } ++ } ++ ++ if (e) ++ { ++ dbglog( "Initialising engine" ); ++ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) ++ { ++ warn( "EAP-TLS: Cannot use that engine" ); ++ log_ssl_errors(); ++ ENGINE_free(e); ++ e = NULL; ++ } ++ } ++ ++ return e; ++} ++ ++/* ++ * Initialize the SSL stacks and tests if certificates, key and crl ++ * for client or server use can be loaded. ++ */ ++SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, ++ char *certfile, char *peer_certfile, char *privkeyfile) ++{ ++ char *cert_engine_name = NULL; ++ char *cert_identifier = NULL; ++ char *pkey_engine_name = NULL; ++ char *pkey_identifier = NULL; ++ SSL_CTX *ctx; ++ X509_STORE *certstore; ++ X509_LOOKUP *lookup; ++ X509 *tmp; ++ ++ /* ++ * Without these can't continue ++ */ ++ if (!cacertfile[0]) ++ { ++ error("EAP-TLS: CA certificate missing"); ++ return NULL; ++ } ++ ++ if (!certfile[0]) ++ { ++ error("EAP-TLS: User certificate missing"); ++ return NULL; ++ } ++ ++ if (!privkeyfile[0]) ++ { ++ error("EAP-TLS: User private key missing"); ++ return NULL; ++ } ++ ++ SSL_library_init(); ++ SSL_load_error_strings(); ++ ++ ctx = SSL_CTX_new(TLSv1_method()); ++ ++ if (!ctx) { ++ error("EAP-TLS: Cannot initialize SSL CTX context"); ++ goto fail; ++ } ++ ++ /* if the certificate filename is of the form engine:id. e.g. ++ pkcs11:12345 ++ then we try to load and use this engine. ++ If the certificate filename starts with a / or . then we ++ ALWAYS assume it is a file and not an engine/pkcs11 identifier ++ */ ++ if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL ) ++ { ++ cert_identifier = index( certfile, ':' ); ++ ++ if (cert_identifier) ++ { ++ cert_engine_name = certfile; ++ *cert_identifier = '\0'; ++ cert_identifier++; ++ ++ dbglog( "Found certificate engine '%s'", cert_engine_name ); ++ dbglog( "Found certificate identifier '%s'", cert_identifier ); ++ } ++ } ++ ++ /* if the privatekey filename is of the form engine:id. e.g. ++ pkcs11:12345 ++ then we try to load and use this engine. ++ If the privatekey filename starts with a / or . then we ++ ALWAYS assume it is a file and not an engine/pkcs11 identifier ++ */ ++ if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL ) ++ { ++ pkey_identifier = index( privkeyfile, ':' ); ++ ++ if (pkey_identifier) ++ { ++ pkey_engine_name = privkeyfile; ++ *pkey_identifier = '\0'; ++ pkey_identifier++; ++ ++ dbglog( "Found privatekey engine '%s'", pkey_engine_name ); ++ dbglog( "Found privatekey identifier '%s'", pkey_identifier ); ++ } ++ } ++ ++ if (cert_identifier && pkey_identifier) ++ { ++ if (strlen( cert_identifier ) == 0) ++ { ++ if (strlen( pkey_identifier ) == 0) ++ error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" ); ++ else ++ { ++ dbglog( "Substituting privatekey identifier for certificate identifier" ); ++ cert_identifier = pkey_identifier; ++ } ++ } ++ else ++ { ++ if (strlen( pkey_identifier ) == 0) ++ { ++ dbglog( "Substituting certificate identifier for privatekey identifier" ); ++ pkey_identifier = cert_identifier; ++ } ++ } ++ ++ } ++ ++ /* load the openssl config file only once */ ++ if (!ssl_config) ++ { ++ if (cert_engine_name || pkey_engine_name) ++ ssl_config = eaptls_ssl_load_config(); ++ ++ if (ssl_config && cert_engine_name) ++ cert_engine = eaptls_ssl_load_engine( cert_engine_name ); ++ ++ if (ssl_config && pkey_engine_name) ++ { ++ /* don't load the same engine twice */ ++ if ( strcmp( cert_engine_name, pkey_engine_name) == 0 ) ++ pkey_engine = cert_engine; ++ else ++ pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); ++ } ++ } ++ ++ SSL_CTX_set_default_passwd_cb (ctx, password_callback); ++ ++ if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) ++ { ++ error("EAP-TLS: Cannot load or verify CA file %s", cacertfile); ++ goto fail; ++ } ++ ++ if (init_server) ++ SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); ++ ++ if (cert_engine) ++ { ++ struct ++ { ++ const char *s_slot_cert_id; ++ X509 *cert; ++ } cert_info; ++ ++ cert_info.s_slot_cert_id = cert_identifier; ++ cert_info.cert = NULL; ++ ++ if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) ) ++ { ++ error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier ); ++ goto fail; ++ } ++ ++ if (cert_info.cert) ++ { ++ dbglog( "Got the certificate, adding it to SSL context" ); ++ dbglog( "subject = %s", X509_NAME_oneline( X509_get_subject_name( cert_info.cert ), NULL, 0 ) ); ++ if (SSL_CTX_use_certificate(ctx, cert_info.cert) <= 0) ++ { ++ error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier); ++ goto fail; ++ } ++ } ++ else ++ { ++ warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier); ++ log_ssl_errors(); ++ } ++ } ++ else ++ { ++ if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) ++ { ++ error( "EAP-TLS: Cannot use public certificate %s", certfile ); ++ goto fail; ++ } ++ } ++ ++ if (pkey_engine) ++ { ++ EVP_PKEY *pkey = NULL; ++ PW_CB_DATA cb_data; ++ ++ cb_data.password = passwd; ++ cb_data.prompt_info = pkey_identifier; ++ ++ dbglog( "Loading private key '%s' from engine", pkey_identifier ); ++ pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data); ++ if (pkey) ++ { ++ dbglog( "Got the private key, adding it to SSL context" ); ++ if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) ++ { ++ error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier); ++ goto fail; ++ } ++ } ++ else ++ { ++ warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier); ++ log_ssl_errors(); ++ } ++ } ++ else ++ { ++ if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) ++ { ++ error("EAP-TLS: Cannot use private key %s", privkeyfile); ++ goto fail; ++ } ++ } ++ ++ if (SSL_CTX_check_private_key(ctx) != 1) { ++ error("EAP-TLS: Private key %s fails security check", privkeyfile); ++ goto fail; ++ } ++ ++ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); ++ SSL_CTX_set_verify_depth(ctx, 5); ++ SSL_CTX_set_verify(ctx, ++ SSL_VERIFY_PEER | ++ SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ++ &ssl_verify_callback); ++ ++ if (crl_dir) { ++ if (!(certstore = SSL_CTX_get_cert_store(ctx))) { ++ error("EAP-TLS: Failed to get certificate store"); ++ goto fail; ++ } ++ ++ if (!(lookup = ++ X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) { ++ error("EAP-TLS: Store lookup for CRL failed"); ++ ++ goto fail; ++ } ++ ++ X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); ++ X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); ++ } ++ ++ /* ++ * If a peer certificate file was specified, it must be valid, else fail ++ */ ++ if (peer_certfile[0]) { ++ if (!(tmp = get_X509_from_file(peer_certfile))) { ++ error("EAP-TLS: Error loading client certificate from file %s", ++ peer_certfile); ++ goto fail; ++ } ++ X509_free(tmp); ++ } ++ ++ return ctx; ++ ++fail: ++ log_ssl_errors(); ++ SSL_CTX_free(ctx); ++ return NULL; ++} ++ ++/* ++ * Determine the maximum packet size by looking at the LCP handshake ++ */ ++ ++int eaptls_get_mtu(int unit) ++{ ++ int mtu, mru; ++ ++ lcp_options *wo = &lcp_wantoptions[unit]; ++ lcp_options *go = &lcp_gotoptions[unit]; ++ lcp_options *ho = &lcp_hisoptions[unit]; ++ lcp_options *ao = &lcp_allowoptions[unit]; ++ ++ mtu = ho->neg_mru? ho->mru: PPP_MRU; ++ mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU; ++ mtu = MIN(MIN(mtu, mru), ao->mru)- PPP_HDRLEN - 10; ++ ++ dbglog("MTU = %d", mtu); ++ return mtu; ++} ++ ++ ++/* ++ * Init the ssl handshake (server mode) ++ */ ++int eaptls_init_ssl_server(eap_state * esp) ++{ ++ struct eaptls_session *ets; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ /* ++ * Allocate new eaptls session ++ */ ++ esp->es_server.ea_session = malloc(sizeof(struct eaptls_session)); ++ if (!esp->es_server.ea_session) ++ fatal("Allocation error"); ++ ets = esp->es_server.ea_session; ++ ++ if (!esp->es_server.ea_peer) { ++ error("EAP-TLS: Error: client name not set (BUG)"); ++ return 0; ++ } ++ ++ strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN); ++ ++ dbglog( "getting eaptls secret" ); ++ if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, ++ esp->es_server.ea_name, clicertfile, ++ servcertfile, cacertfile, pkfile, 1)) { ++ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", ++ esp->es_server.ea_peer, esp->es_server.ea_name ); ++ return 0; ++ } ++ ++ ets->mtu = eaptls_get_mtu(esp->es_unit); ++ ++ ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile); ++ if (!ets->ctx) ++ goto fail; ++ ++ if (!(ets->ssl = SSL_new(ets->ctx))) ++ goto fail; ++ ++ /* ++ * Set auto-retry to avoid timeouts on BIO_read ++ */ ++ SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY); ++ ++ /* ++ * Initialize the BIOs we use to read/write to ssl engine ++ */ ++ ets->into_ssl = BIO_new(BIO_s_mem()); ++ ets->from_ssl = BIO_new(BIO_s_mem()); ++ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); ++ ++ SSL_set_msg_callback(ets->ssl, ssl_msg_callback); ++ SSL_set_msg_callback_arg(ets->ssl, ets); ++ ++ /* ++ * Attach the session struct to the connection, so we can later ++ * retrieve it when doing certificate verification ++ */ ++ SSL_set_ex_data(ets->ssl, 0, ets); ++ ++ SSL_set_accept_state(ets->ssl); ++ ++ ets->data = NULL; ++ ets->datalen = 0; ++ ets->alert_sent = 0; ++ ets->alert_recv = 0; ++ ++ /* ++ * If we specified the client certificate file, store it in ets->peercertfile, ++ * so we can check it later in ssl_verify_callback() ++ */ ++ if (clicertfile[0]) ++ strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN); ++ else ++ ets->peercertfile[0] = 0; ++ ++ return 1; ++ ++fail: ++ SSL_CTX_free(ets->ctx); ++ return 0; ++} ++ ++/* ++ * Init the ssl handshake (client mode) ++ */ ++int eaptls_init_ssl_client(eap_state * esp) ++{ ++ struct eaptls_session *ets; ++ char servcertfile[MAXWORDLEN]; ++ char clicertfile[MAXWORDLEN]; ++ char cacertfile[MAXWORDLEN]; ++ char pkfile[MAXWORDLEN]; ++ ++ /* ++ * Allocate new eaptls session ++ */ ++ esp->es_client.ea_session = malloc(sizeof(struct eaptls_session)); ++ if (!esp->es_client.ea_session) ++ fatal("Allocation error"); ++ ets = esp->es_client.ea_session; ++ ++ /* ++ * If available, copy server name in ets; it will be used in cert ++ * verify ++ */ ++ if (esp->es_client.ea_peer) ++ strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN); ++ else ++ ets->peer[0] = 0; ++ ++ ets->mtu = eaptls_get_mtu(esp->es_unit); ++ ++ dbglog( "calling get_eaptls_secret" ); ++ if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, ++ esp->es_client.ea_peer, clicertfile, ++ servcertfile, cacertfile, pkfile, 0)) { ++ error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", ++ esp->es_client.ea_name, esp->es_client.ea_peer ); ++ return 0; ++ } ++ ++ dbglog( "calling eaptls_init_ssl" ); ++ ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile); ++ if (!ets->ctx) ++ goto fail; ++ ++ ets->ssl = SSL_new(ets->ctx); ++ ++ if (!ets->ssl) ++ goto fail; ++ ++ /* ++ * Initialize the BIOs we use to read/write to ssl engine ++ */ ++ dbglog( "Initializing SSL BIOs" ); ++ ets->into_ssl = BIO_new(BIO_s_mem()); ++ ets->from_ssl = BIO_new(BIO_s_mem()); ++ SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); ++ ++ SSL_set_msg_callback(ets->ssl, ssl_msg_callback); ++ SSL_set_msg_callback_arg(ets->ssl, ets); ++ ++ /* ++ * Attach the session struct to the connection, so we can later ++ * retrieve it when doing certificate verification ++ */ ++ SSL_set_ex_data(ets->ssl, 0, ets); ++ ++ SSL_set_connect_state(ets->ssl); ++ ++ ets->data = NULL; ++ ets->datalen = 0; ++ ets->alert_sent = 0; ++ ets->alert_recv = 0; ++ ++ /* ++ * If we specified the server certificate file, store it in ++ * ets->peercertfile, so we can check it later in ++ * ssl_verify_callback() ++ */ ++ if (servcertfile[0]) ++ strncpy(ets->peercertfile, servcertfile, MAXWORDLEN); ++ else ++ ets->peercertfile[0] = 0; ++ ++ return 1; ++ ++fail: ++ dbglog( "eaptls_init_ssl_client: fail" ); ++ SSL_CTX_free(ets->ctx); ++ return 0; ++ ++} ++ ++void eaptls_free_session(struct eaptls_session *ets) ++{ ++ if (ets->ssl) ++ SSL_free(ets->ssl); ++ ++ if (ets->ctx) ++ SSL_CTX_free(ets->ctx); ++ ++ free(ets); ++} ++ ++/* ++ * Handle a received packet, reassembling fragmented messages and ++ * passing them to the ssl engine ++ */ ++int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) ++{ ++ u_char flags; ++ u_int tlslen; ++ u_char dummy[65536]; ++ ++ GETCHAR(flags, inp); ++ len--; ++ ++ if (flags & EAP_TLS_FLAGS_LI && !ets->data) { ++ ++ /* ++ * This is the first packet of a message ++ */ ++ ++ GETLONG(tlslen, inp); ++ len -= 4; ++ ++ if (tlslen > EAP_TLS_MAX_LEN) { ++ error("Error: tls message length > %d, truncated", ++ EAP_TLS_MAX_LEN); ++ tlslen = EAP_TLS_MAX_LEN; ++ } ++ ++ /* ++ * Allocate memory for the whole message ++ */ ++ ets->data = malloc(tlslen); ++ if (!ets->data) ++ fatal("EAP TLS: allocation error\n"); ++ ++ ets->datalen = 0; ++ ets->tlslen = tlslen; ++ ++ } ++ else if (flags & EAP_TLS_FLAGS_LI && ets->data) { ++ /* ++ * Non first with LI (strange...) ++ */ ++ ++ GETLONG(tlslen, inp); ++ len -= 4; ++ ++ } ++ else if (!ets->data) { ++ /* ++ * A non fragmented message without LI flag ++ */ ++ ++ ets->data = malloc(len); ++ if (!ets->data) ++ fatal("EAP TLS: allocation error\n"); ++ ++ ets->datalen = 0; ++ ets->tlslen = len; ++ } ++ ++ if (flags & EAP_TLS_FLAGS_MF) ++ ets->frag = 1; ++ else ++ ets->frag = 0; ++ ++ if (len + ets->datalen > ets->tlslen) { ++ warn("EAP TLS: received data > TLS message length"); ++ return 1; ++ } ++ ++ BCOPY(inp, ets->data + ets->datalen, len); ++ ets->datalen += len; ++ ++ if (!ets->frag) { ++ ++ /* ++ * If we have the whole message, pass it to ssl ++ */ ++ ++ if (ets->datalen != ets->tlslen) { ++ warn("EAP TLS: received data != TLS message length"); ++ return 1; ++ } ++ ++ if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1) ++ log_ssl_errors(); ++ ++ SSL_read(ets->ssl, dummy, 65536); ++ ++ free(ets->data); ++ ets->data = NULL; ++ ets->datalen = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Return an eap-tls packet in outp. ++ * A TLS message read from the ssl engine is buffered in ets->data. ++ * At each call we control if there is buffered data and send a ++ * packet of mtu bytes. ++ */ ++int eaptls_send(struct eaptls_session *ets, u_char ** outp) ++{ ++ bool first = 0; ++ int size; ++ u_char fromtls[65536]; ++ int res; ++ u_char *start; ++ ++ start = *outp; ++ ++ if (!ets->data) { ++ ++ if(!ets->alert_sent) ++ SSL_read(ets->ssl, fromtls, 65536); ++ ++ /* ++ * Read from ssl ++ */ ++ if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1) ++ fatal("No data from BIO_read"); ++ ++ ets->datalen = res; ++ ++ ets->data = malloc(ets->datalen); ++ BCOPY(fromtls, ets->data, ets->datalen); ++ ++ ets->offset = 0; ++ first = 1; ++ ++ } ++ ++ size = ets->datalen - ets->offset; ++ ++ if (size > ets->mtu) { ++ size = ets->mtu; ++ ets->frag = 1; ++ } else ++ ets->frag = 0; ++ ++ PUTCHAR(EAPT_TLS, *outp); ++ ++ /* ++ * Set right flags and length if necessary ++ */ ++ if (ets->frag && first) { ++ PUTCHAR(EAP_TLS_FLAGS_LI | EAP_TLS_FLAGS_MF, *outp); ++ PUTLONG(ets->datalen, *outp); ++ } else if (ets->frag) { ++ PUTCHAR(EAP_TLS_FLAGS_MF, *outp); ++ } else ++ PUTCHAR(0, *outp); ++ ++ /* ++ * Copy the data in outp ++ */ ++ BCOPY(ets->data + ets->offset, *outp, size); ++ INCPTR(size, *outp); ++ ++ /* ++ * Copy the packet in retransmission buffer ++ */ ++ BCOPY(start, &ets->rtx[0], *outp - start); ++ ets->rtx_len = *outp - start; ++ ++ ets->offset += size; ++ ++ if (ets->offset >= ets->datalen) { ++ ++ /* ++ * The whole message has been sent ++ */ ++ ++ free(ets->data); ++ ets->data = NULL; ++ ets->datalen = 0; ++ ets->offset = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Get the sent packet from the retransmission buffer ++ */ ++void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp) ++{ ++ BCOPY(ets->rtx, *outp, ets->rtx_len); ++ INCPTR(ets->rtx_len, *outp); ++} ++ ++/* ++ * Verify a certificate. ++ * Most of the work (signatures and issuer attributes checking) ++ * is done by ssl; we check the CN in the peer certificate ++ * against the peer name. ++ */ ++int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx) ++{ ++ char subject[256]; ++ char cn_str[256]; ++ X509 *peer_cert; ++ int err, depth; ++ int ok = preverify_ok; ++ SSL *ssl; ++ struct eaptls_session *ets; ++ ++ peer_cert = X509_STORE_CTX_get_current_cert(ctx); ++ err = X509_STORE_CTX_get_error(ctx); ++ depth = X509_STORE_CTX_get_error_depth(ctx); ++ ++ dbglog("certificate verify depth: %d", depth); ++ ++ if (auth_required && !ok) { ++ X509_NAME_oneline(X509_get_subject_name(peer_cert), ++ subject, 256); ++ ++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), ++ NID_commonName, cn_str, 256); ++ ++ dbglog("Certificate verification error:\n depth: %d CN: %s" ++ "\n err: %d (%s)\n", depth, cn_str, err, ++ X509_verify_cert_error_string(err)); ++ ++ return 0; ++ } ++ ++ ssl = X509_STORE_CTX_get_ex_data(ctx, ++ SSL_get_ex_data_X509_STORE_CTX_idx()); ++ ++ ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0); ++ ++ if (ets == NULL) { ++ error("Error: SSL_get_ex_data returned NULL"); ++ return 0; ++ } ++ ++ log_ssl_errors(); ++ ++ if (!depth) { /* This is the peer certificate */ ++ ++ X509_NAME_oneline(X509_get_subject_name(peer_cert), ++ subject, 256); ++ ++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), ++ NID_commonName, cn_str, 256); ++ ++ /* ++ * If acting as client and the name of the server wasn't specified ++ * explicitely, we can't verify the server authenticity ++ */ ++ if (!ets->peer[0]) { ++ warn("Peer name not specified: no check"); ++ return 1; ++ } ++ ++ /* ++ * Check the CN ++ */ ++ if (strcmp(cn_str, ets->peer)) { ++ error ++ ("Certificate verification error: CN (%s) != peer_name (%s)", ++ cn_str, ets->peer); ++ return 0; ++ } ++ ++ warn("Certificate CN: %s , peer name %s", cn_str, ets->peer); ++ ++ /* ++ * If a peer certificate file was specified, here we check it ++ */ ++ if (ets->peercertfile[0]) { ++ if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert) ++ != 0) { ++ error ++ ("Peer certificate doesn't match stored certificate"); ++ return 0; ++ } ++ } ++ } ++ ++ return 1; ++} ++ ++/* ++ * Compare a certificate with the one stored in a file ++ */ ++int ssl_cmp_certs(char *filename, X509 * a) ++{ ++ X509 *b; ++ int ret; ++ ++ if (!(b = get_X509_from_file(filename))) ++ return 1; ++ ++ ret = X509_cmp(a, b); ++ X509_free(b); ++ ++ return ret; ++ ++} ++ ++X509 *get_X509_from_file(char *filename) ++{ ++ FILE *fp; ++ X509 *ret; ++ ++ if (!(fp = fopen(filename, "r"))) ++ return NULL; ++ ++ ret = PEM_read_X509(fp, NULL, NULL, NULL); ++ ++ fclose(fp); ++ ++ return ret; ++} ++ ++/* ++ * Every sent & received message this callback function is invoked, ++ * so we know when alert messages have arrived or are sent and ++ * we can print debug information about TLS handshake. ++ */ ++void ++ssl_msg_callback(int write_p, int version, int content_type, ++ const void *buf, size_t len, SSL * ssl, void *arg) ++{ ++ char string[256]; ++ struct eaptls_session *ets = (struct eaptls_session *)arg; ++ unsigned char code; ++ ++ if(write_p) ++ strcpy(string, " -> "); ++ else ++ strcpy(string, " <- "); ++ ++ ++ switch(content_type) { ++ ++ case SSL3_RT_ALERT: ++ strcat(string, "Alert: "); ++ code = ((const unsigned char *)buf)[1]; ++ ++ if (write_p) { ++ ets->alert_sent = 1; ++ ets->alert_sent_desc = code; ++ } else { ++ ets->alert_recv = 1; ++ ets->alert_recv_desc = code; ++ } ++ ++ strcat(string, SSL_alert_desc_string_long(code)); ++ break; ++ ++ case SSL3_RT_CHANGE_CIPHER_SPEC: ++ strcat(string, "ChangeCipherSpec"); ++ break; ++ ++ case SSL3_RT_HANDSHAKE: ++ ++ strcat(string, "Handshake: "); ++ code = ((const unsigned char *)buf)[0]; ++ ++ switch(code) { ++ case SSL3_MT_HELLO_REQUEST: ++ strcat(string,"Hello Request"); ++ break; ++ case SSL3_MT_CLIENT_HELLO: ++ strcat(string,"Client Hello"); ++ break; ++ case SSL3_MT_SERVER_HELLO: ++ strcat(string,"Server Hello"); ++ break; ++ case SSL3_MT_CERTIFICATE: ++ strcat(string,"Certificate"); ++ break; ++ case SSL3_MT_SERVER_KEY_EXCHANGE: ++ strcat(string,"Server Key Exchange"); ++ break; ++ case SSL3_MT_CERTIFICATE_REQUEST: ++ strcat(string,"Certificate Request"); ++ break; ++ case SSL3_MT_SERVER_DONE: ++ strcat(string,"Server Hello Done"); ++ break; ++ case SSL3_MT_CERTIFICATE_VERIFY: ++ strcat(string,"Certificate Verify"); ++ break; ++ case SSL3_MT_CLIENT_KEY_EXCHANGE: ++ strcat(string,"Client Key Exchange"); ++ break; ++ case SSL3_MT_FINISHED: ++ strcat(string,"Finished"); ++ break; ++ ++ default: ++ sprintf( string, "Handshake: Unknown SSL3 code received: %d", code ); ++ } ++ break; ++ ++ default: ++ sprintf( string, "SSL message contains unknown content type: %d", content_type ); ++ ++ } ++ ++ /* Alert messages must always be displayed */ ++ if(content_type == SSL3_RT_ALERT) ++ error("%s", string); ++ else ++ dbglog("%s", string); ++} ++ +diff --git a/pppd/eap-tls.h b/pppd/eap-tls.h +new file mode 100644 +index 0000000..2d45a0b +--- /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 +diff --git a/pppd/eap.c b/pppd/eap.c +index faced53..e2270af 100644 +--- 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 */ + } + + /* +@@ -268,7 +280,7 @@ eap_state *esp; + u_char *outp; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); +@@ -293,7 +305,7 @@ eap_state *esp; + u_char *outp; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); +@@ -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,81 @@ 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(SSL_is_init_finished(ets->ssl)) { ++ esp->es_server.ea_state = eapTlsRecvClient; ++ break; ++ } ++ ++ if(ets->frag) ++ esp->es_server.ea_state = eapTlsRecvAck; ++ else ++ esp->es_server.ea_state = eapTlsRecv; ++ break; ++ ++ case eapTlsSendAck: ++ esp->es_server.ea_state = eapTlsRecv; ++ break; ++ ++ case eapTlsRecvAck: ++ if (status) { ++ esp->es_server.ea_state = eapBadAuth; ++ break; ++ } ++ ++ esp->es_server.ea_state = eapTlsSend; ++ break; ++ ++ case eapTlsSendAlert: ++ esp->es_server.ea_state = eapTlsRecvAlertAck; ++ break; ++#endif /* USE_EAPTLS */ ++ + case eapSRP1: + #ifdef USE_SRP + ts = (struct t_server *)esp->es_server.ea_session; +@@ -681,7 +773,7 @@ eap_state *esp; + } + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); +@@ -718,6 +810,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 +1020,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); + } +@@ -1081,7 +1243,7 @@ int namelen; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1117,7 +1279,7 @@ int lenstr; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1148,7 +1310,7 @@ u_char *str; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1166,6 +1328,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 +1557,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 +1698,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 +2063,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 +2107,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 +2192,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 +2410,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 +2556,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 +2623,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 +2752,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, " "); +diff --git a/pppd/eap.h b/pppd/eap.h +index 199d184..3fa5391 100644 +--- 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 */ + +diff --git a/pppd/md5.c b/pppd/md5.c +index f1291ce..2ee0c80 100644 +--- a/pppd/md5.c ++++ b/pppd/md5.c +@@ -33,6 +33,8 @@ + *********************************************************************** + */ + ++#ifndef USE_EAPTLS ++ + #include + #include "md5.h" + +@@ -305,3 +307,4 @@ UINT4 *in; + ** End of md5.c ** + ******************************** (cut) ******************************** + */ ++#endif /* USE_EAPTLS */ +diff --git a/pppd/md5.h b/pppd/md5.h +index 71e8b00..14d7121 100644 +--- 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[], MD5_CTX *mdContext); + + #define __MD5_INCLUDE__ + #endif /* __MD5_INCLUDE__ */ ++ ++#endif /* USE_EAPTLS */ +diff --git a/pppd/options.c b/pppd/options.c +index 8e62635..6915b2d 100644 +--- a/pppd/options.c ++++ b/pppd/options.c +@@ -120,6 +120,10 @@ bool dump_options; /* print out option values */ + bool dryrun; /* print out option values and exit */ + char *domain; /* domain name set by domain option */ + int child_wait = 5; /* # seconds to wait for children at exit */ ++#ifdef USE_EAPTLS ++bool only_update_crl_server = 0; /* update server crl and exit */ ++bool only_update_crl_client = 0; /* update client crl and exit */ ++#endif /* USE_EAPTLS */ + struct userenv *userenv_list; /* user environment variables */ + + #ifdef MAXOCTETS +@@ -338,6 +342,12 @@ option_t general_options[] = { + { "mo-timeout", o_int, &maxoctets_timeout, + "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, + #endif ++#ifdef USE_EAPTLS ++ { "only-update-crl-server", o_bool, &only_update_crl_server, ++ "Update server CA CRLs and exit", 1 }, ++ { "only-update-crl-client", o_bool, &only_update_crl_client, ++ "Update client CA CRLs and exit", 1 }, ++#endif /* USE_EAPTLS */ + + { NULL } + }; +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index 24e010c..6275df6 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -22,6 +22,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" +diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux +index b474a19..760cad4 100644 +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -4,6 +4,9 @@ CFLAGS = $(COPTS) -I.. -I../../include -fPIC + LDFLAGS = -shared + INSTALL = install + ++# EAP-TLS ++CFLAGS += -DUSE_EAPTLS=1 ++ + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +diff --git a/pppd/plugins/passprompt.c b/pppd/plugins/passprompt.c +index babb6dc..6ba73ca 100644 +--- 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 + } +diff --git a/pppd/plugins/passwordfd.c b/pppd/plugins/passwordfd.c +index d718f3b..c3f9793 100644 +--- 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 + } +diff --git a/pppd/pppd.h b/pppd/pppd.h +index 47e4d9a..de271c1 100644 +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -324,6 +324,10 @@ extern bool dump_options; /* print out option values */ + extern bool dryrun; /* check everything, print options, exit */ + extern int child_wait; /* # seconds to wait for children at end */ + ++#ifdef USE_EAPTLS ++extern char *crl_dir; ++#endif /* USE_EAPTLS */ ++ + #ifdef MAXOCTETS + extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ + extern int maxoctets_dir; /* Direction : +@@ -738,6 +742,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)); +-- +1.8.3.1 + diff --git a/0018-scritps-fix-ip-up.local-sample.patch b/0018-scritps-fix-ip-up.local-sample.patch new file mode 100644 index 0000000..c36e0b8 --- /dev/null +++ b/0018-scritps-fix-ip-up.local-sample.patch @@ -0,0 +1,27 @@ +From 40960f91cdd06da387616ec838ae2599e7f01cee Mon Sep 17 00:00:00 2001 +From: Jiri Skala +Date: Mon, 7 Apr 2014 15:24:01 +0200 +Subject: [PATCH 18/27] scritps: fix ip-up.local sample + +Resolves: #613717 +--- + scripts/ip-up.local.add | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/scripts/ip-up.local.add b/scripts/ip-up.local.add +index 26cf5f8..282337c 100644 +--- a/scripts/ip-up.local.add ++++ b/scripts/ip-up.local.add +@@ -18,6 +18,9 @@ if [ -n "$USEPEERDNS" -a -f /var/run/ppp/resolv.conf ]; then + rscf=/var/run/ppp/resolv.new + grep domain /var/run/ppp/resolv.prev > $rscf + grep search /var/run/ppp/resolv.prev >> $rscf ++ if [ -f /var/run/ppp/resolv.conf ]; then ++ cat /var/run/ppp/resolv.conf >> $rscf ++ fi + change_resolv_conf $rscf + rm -f $rscf + else +-- +1.8.3.1 + diff --git a/0019-sys-linux-rework-get_first_ethernet.patch b/0019-sys-linux-rework-get_first_ethernet.patch new file mode 100644 index 0000000..9a8c3dd --- /dev/null +++ b/0019-sys-linux-rework-get_first_ethernet.patch @@ -0,0 +1,383 @@ +From 6edc865bd02ab591b9121d4a5f6dc3cdbe5af809 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 9 Apr 2014 09:18:24 +0200 +Subject: [PATCH 19/27] sys-linux: rework get_first_ethernet() + +We can't assume that host has ethernet NIC named "eth0". Rather than guessing we +better ask udev. We iterate over symlinks symlinks in /sys/class/net and +for each device we determine if it is ethernet device and additionally we query +udev database for sub-type of the device. If we find PCI or USB device which has +ethernet datalink type and appropriate sub-type we return its name. If we don't +succeed in determining more information about device we will return "good +enough" device which in turn is first device with ethernet datalink type. + +Note that we now have two copies of get_first_ethernet() in the source code. This +is bad and should be fixed in the future. + +This commit replaces ppp-2.4.5-eth.patch. + +Resolves: #682381 +--- + pppd/Makefile.linux | 3 + + pppd/multilink.c | 4 +- + pppd/plugins/rp-pppoe/Makefile.linux | 4 +- + pppd/plugins/rp-pppoe/pppoe-discovery.c | 117 +++++++++++++++++++++++++++++++- + pppd/pppd.h | 2 +- + pppd/sys-linux.c | 115 +++++++++++++++++++++++++++++-- + 6 files changed, 232 insertions(+), 13 deletions(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 53df4d2..0e8107f 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -32,6 +32,9 @@ include .depend + endif + + CC = gcc ++ ++LIBS = -ludev ++ + # + COPTS = -Wall $(RPM_OPT_FLAGS) -DLIBDIR=\""$(LIBDIR)"\" + +diff --git a/pppd/multilink.c b/pppd/multilink.c +index 135cab0..2f0ed50 100644 +--- a/pppd/multilink.c ++++ b/pppd/multilink.c +@@ -436,12 +436,12 @@ static int + get_default_epdisc(ep) + struct epdisc *ep; + { +- char *p; ++ char *p = NULL; + struct hostent *hp; + u_int32_t addr; + + /* First try for an ethernet MAC address */ +- p = get_first_ethernet(); ++ get_first_ethernet(&p); + if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { + ep->class = EPD_MAC; + ep->length = 6; +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index 9918091..b949716 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -30,8 +30,8 @@ COPTS=$(RPM_OPT_FLAGS) + CFLAGS=$(COPTS) -I../../../include '-DRP_VERSION="$(RP_VERSION)"' + all: rp-pppoe.so pppoe-discovery + +-pppoe-discovery: pppoe-discovery.o debug.o +- $(CC) -o pppoe-discovery pppoe-discovery.o debug.o ++pppoe-discovery: pppoe-discovery.o debug.o common.o ++ $(CC) -o pppoe-discovery pppoe-discovery.o debug.o -ludev + + pppoe-discovery.o: pppoe-discovery.c + $(CC) $(CFLAGS) -c -o pppoe-discovery.o pppoe-discovery.c +diff --git a/pppd/plugins/rp-pppoe/pppoe-discovery.c b/pppd/plugins/rp-pppoe/pppoe-discovery.c +index c0d927d..2bd910f 100644 +--- a/pppd/plugins/rp-pppoe/pppoe-discovery.c ++++ b/pppd/plugins/rp-pppoe/pppoe-discovery.c +@@ -47,8 +47,13 @@ + #include + #endif + ++#include ++#include ++#include ++ + char *xstrdup(const char *s); + void usage(void); ++int get_first_ethernet(char **_r); + + void die(int status) + { +@@ -681,8 +686,15 @@ int main(int argc, char *argv[]) + } + + /* default interface name */ +- if (!conn->ifName) +- conn->ifName = strdup("eth0"); ++ if (!conn->ifName) { ++ char *eth_dev; ++ if (get_first_ethernet(ð_dev) < 0) { ++ fprintf(stderr, "No ethernet device on the host.\n"); ++ exit(1); ++ } ++ conn->ifName = eth_dev; ++ } ++ + + conn->discoverySocket = -1; + conn->sessionSocket = -1; +@@ -722,3 +734,104 @@ void usage(void) + fprintf(stderr, "Usage: pppoe-discovery [options]\n"); + fprintf(stderr, "\nVersion " RP_VERSION "\n"); + } ++ ++/* ++ * get_first_ethernet - return the name of the first ethernet-style ++ * interface on this system. ++ */ ++int ++get_first_ethernet(char **_r) ++{ ++ int r = 0; ++ DIR *d = NULL; ++ struct dirent *entry = NULL; ++ struct udev *udev = NULL; ++ struct udev_device *dev = NULL; ++ char *eth_dev = NULL; ++ ++ d = opendir("/sys/class/net"); ++ if (!d) { ++ fprintf(stderr, "Failed to open dir /sys/class/net : %m\n"); ++ r = -errno; ++ goto fail; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ fprintf(stderr, "Failed to talk to systemd-udevd\n"); ++ r = -EIO; ++ goto fail; ++ } ++ ++ while ((entry = readdir(d)) != NULL) { ++ char syspath[PATH_MAX] = {}; ++ const char *type = NULL; ++ ++ if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) ++ continue; ++ ++ sprintf(syspath, "/sys/class/net/%s", entry->d_name); ++ ++ dev = udev_device_new_from_syspath(udev, syspath); ++ if (!dev) ++ continue; ++ ++ type = udev_device_get_sysattr_value(dev, "type"); ++ if (strcmp(type, "1") == 0) { ++ const char *pci_dev_subclass = NULL, *usb_dev_subclass = NULL; ++ ++ pci_dev_subclass = udev_device_get_property_value(dev, ++ "ID_PCI_SUBCLASS_FROM_DATABASE"); ++ usb_dev_subclass = udev_device_get_property_value(dev, ++ "ID_USB_SUBCLASS_FROM_DATABASE"); ++ ++ if ((pci_dev_subclass && strcmp(pci_dev_subclass, "Ethernet controller") == 0) || ++ (usb_dev_subclass && (strcmp(usb_dev_subclass, "Ethernet Networking") == 0 || ++ strcmp(usb_dev_subclass, "Ethernet Emulation") == 0))) { ++ char *d = NULL; ++ ++ d = strdup(entry->d_name); ++ if (!d) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ free(eth_dev); ++ eth_dev = d; ++ break; ++ } else if (!eth_dev) { ++ eth_dev = strdup(entry->d_name); ++ if (!eth_dev) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ } ++ } ++ ++ udev_device_unref(dev); ++ dev = NULL; ++ } ++ ++ if (dev) ++ udev_device_unref(dev); ++ udev_unref(udev); ++ closedir(d); ++ ++ *_r = eth_dev; ++ ++ return 0; ++ ++fail: ++ if (dev) ++ udev_device_unref(dev); ++ ++ if (udev) ++ udev_unref(udev); ++ ++ if (d) ++ closedir(d); ++ ++ free(eth_dev); ++ ++ return r; ++} +diff --git a/pppd/pppd.h b/pppd/pppd.h +index de271c1..aaddba1 100644 +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -691,7 +691,7 @@ int sipxfaddr __P((int, unsigned long, unsigned char *)); + int cipxfaddr __P((int)); + #endif + int get_if_hwaddr __P((u_char *addr, char *name)); +-char *get_first_ethernet __P((void)); ++int get_first_ethernet __P((char **_r)); + + /* Procedures exported from options.c */ + int setipaddr __P((char *, char **, int)); /* Set local/remote ip addresses */ +diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c +index 0690019..ec09c50 100644 +--- a/pppd/sys-linux.c ++++ b/pppd/sys-linux.c +@@ -92,6 +92,9 @@ + #include + #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 +@@ -1873,10 +1876,101 @@ get_if_hwaddr(u_char *addr, char *name) + * get_first_ethernet - return the name of the first ethernet-style + * interface on this system. + */ +-char * +-get_first_ethernet() +-{ +- return "eth0"; ++int ++get_first_ethernet(char **_r) ++{ ++ int r = 0; ++ DIR *d = NULL; ++ struct dirent *entry = NULL; ++ struct udev *udev = NULL; ++ struct udev_device *dev = NULL; ++ char *eth_dev = NULL; ++ ++ d = opendir("/sys/class/net"); ++ if (!d) { ++ fprintf(stderr, "Failed to open dir /sys/class/net : %m\n"); ++ r = -errno; ++ goto fail; ++ } ++ ++ udev = udev_new(); ++ if (!udev) { ++ fprintf(stderr, "Failed to talk to systemd-udevd\n"); ++ r = -EIO; ++ goto fail; ++ } ++ ++ while ((entry = readdir(d)) != NULL) { ++ char syspath[PATH_MAX] = {}; ++ const char *type = NULL; ++ ++ if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) ++ continue; ++ ++ sprintf(syspath, "/sys/class/net/%s", entry->d_name); ++ ++ dev = udev_device_new_from_syspath(udev, syspath); ++ if (!dev) ++ continue; ++ ++ type = udev_device_get_sysattr_value(dev, "type"); ++ if (strcmp(type, "1") == 0) { ++ const char *pci_dev_subclass = NULL, *usb_dev_subclass = NULL; ++ ++ pci_dev_subclass = udev_device_get_property_value(dev, ++ "ID_PCI_SUBCLASS_FROM_DATABASE"); ++ usb_dev_subclass = udev_device_get_property_value(dev, ++ "ID_USB_SUBCLASS_FROM_DATABASE"); ++ ++ if ((pci_dev_subclass && strcmp(pci_dev_subclass, "Ethernet controller") == 0) || ++ (usb_dev_subclass && (strcmp(usb_dev_subclass, "Ethernet Networking") == 0 || ++ strcmp(usb_dev_subclass, "Ethernet Emulation") == 0))) { ++ char *d = NULL; ++ ++ d = strdup(entry->d_name); ++ if (!d) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ free(eth_dev); ++ eth_dev = d; ++ break; ++ } else if (!eth_dev) { ++ eth_dev = strdup(entry->d_name); ++ if (!eth_dev) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ } ++ } ++ ++ udev_device_unref(dev); ++ dev = NULL; ++ } ++ ++ if (dev) ++ udev_device_unref(dev); ++ udev_unref(udev); ++ closedir(d); ++ ++ *_r = eth_dev; ++ ++ return 0; ++ ++fail: ++ if (dev) ++ udev_device_unref(dev); ++ ++ if (udev) ++ udev_unref(udev); ++ ++ if (d) ++ closedir(d); ++ ++ free(eth_dev); ++ ++ return r; + } + + /******************************************************************** +@@ -2859,6 +2953,7 @@ ether_to_eui64(eui64_t *p_eui64) + struct ifreq ifr; + int skfd; + const unsigned char *ptr; ++ char *eth_dev = NULL; + + skfd = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if(skfd == -1) +@@ -2867,11 +2962,19 @@ ether_to_eui64(eui64_t *p_eui64) + return 0; + } + +- strcpy(ifr.ifr_name, "eth0"); ++ if (get_first_ethernet(ð_dev) < 0) ++ { ++ warn("no ethernet device present on the host"); ++ return 0; ++ } ++ ++ strcpy(ifr.ifr_name, eth_dev); ++ free(eth_dev); ++ + if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) + { + close(skfd); +- warn("could not obtain hardware address for eth0"); ++ warn("could not obtain hardware address for %s", ifr.ifr_name); + return 0; + } + close(skfd); +-- +1.8.3.1 + diff --git a/0020-pppd-put-lock-files-in-var-lock-ppp.patch b/0020-pppd-put-lock-files-in-var-lock-ppp.patch new file mode 100644 index 0000000..93d26c5 --- /dev/null +++ b/0020-pppd-put-lock-files-in-var-lock-ppp.patch @@ -0,0 +1,26 @@ +From c5a5f795b1defcb6d168e79c4d1fc371dfc556ca Mon Sep 17 00:00:00 2001 +From: Jiri Skala +Date: Wed, 9 Apr 2014 09:29:50 +0200 +Subject: [PATCH 20/27] pppd: put lock files in /var/lock/ppp + +Resolves: #708260 +--- + pppd/utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/utils.c b/pppd/utils.c +index 6051b9a..8407492 100644 +--- a/pppd/utils.c ++++ b/pppd/utils.c +@@ -846,7 +846,7 @@ complete_read(int fd, void *buf, size_t count) + /* Procedures for locking the serial device using a lock file. */ + #ifndef LOCK_DIR + #ifdef __linux__ +-#define LOCK_DIR "/var/lock" ++#define LOCK_DIR "/var/lock/ppp" + #else + #ifdef SVR4 + #define LOCK_DIR "/var/spool/locks" +-- +1.8.3.1 + diff --git a/0021-build-sys-compile-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch b/0021-build-sys-compile-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch new file mode 100644 index 0000000..8340271 --- /dev/null +++ b/0021-build-sys-compile-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch @@ -0,0 +1,23 @@ +From d69eb9a8aa284014dd7dd282813989eda9d84d74 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 9 Apr 2014 09:56:09 +0200 +Subject: [PATCH 21/27] build-sys: compile pppol2tp plugin with RPM_OPT_FLAGS + +--- + pppd/plugins/pppol2tp/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/plugins/pppol2tp/Makefile.linux b/pppd/plugins/pppol2tp/Makefile.linux +index 4339566..9a635b8 100644 +--- a/pppd/plugins/pppol2tp/Makefile.linux ++++ b/pppd/plugins/pppol2tp/Makefile.linux +@@ -1,5 +1,5 @@ + #CC = gcc +-COPTS = -O2 -g ++COPTS = $(RPM_OPT_FLAGS) + CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC + LDFLAGS = -shared + INSTALL = install +-- +1.8.3.1 + diff --git a/0022-build-sys-compile-pppol2tp-with-multilink-support.patch b/0022-build-sys-compile-pppol2tp-with-multilink-support.patch new file mode 100644 index 0000000..945933e --- /dev/null +++ b/0022-build-sys-compile-pppol2tp-with-multilink-support.patch @@ -0,0 +1,24 @@ +From a0060c5d48ef742bff4fe9ba9c276a5c21795ce8 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 9 Apr 2014 09:58:38 +0200 +Subject: [PATCH 22/27] build-sys: compile pppol2tp with multilink support + +Resolves: #817013 +--- + pppd/plugins/pppol2tp/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/plugins/pppol2tp/Makefile.linux b/pppd/plugins/pppol2tp/Makefile.linux +index 9a635b8..9cb316d 100644 +--- a/pppd/plugins/pppol2tp/Makefile.linux ++++ b/pppd/plugins/pppol2tp/Makefile.linux +@@ -1,5 +1,5 @@ + #CC = gcc +-COPTS = $(RPM_OPT_FLAGS) ++COPTS = $(RPM_OPT_FLAGS) -DHAVE_MULTILINK + CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC + LDFLAGS = -shared + INSTALL = install +-- +1.8.3.1 + diff --git a/0023-build-sys-install-rp-pppoe-plugin-files-with-standar.patch b/0023-build-sys-install-rp-pppoe-plugin-files-with-standar.patch new file mode 100644 index 0000000..7a18e07 --- /dev/null +++ b/0023-build-sys-install-rp-pppoe-plugin-files-with-standar.patch @@ -0,0 +1,32 @@ +From 769521a3798fd554ddc7333cb1255cd1b40790e8 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 10 Apr 2014 10:00:55 +0200 +Subject: [PATCH 23/27] build-sys: install rp-pppoe plugin files with standard + perms + +This is needed to properly generate debuginfo package. +--- + pppd/plugins/rp-pppoe/Makefile.linux | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pppd/plugins/rp-pppoe/Makefile.linux b/pppd/plugins/rp-pppoe/Makefile.linux +index b949716..fa49efb 100644 +--- a/pppd/plugins/rp-pppoe/Makefile.linux ++++ b/pppd/plugins/rp-pppoe/Makefile.linux +@@ -44,10 +44,10 @@ rp-pppoe.so: plugin.o discovery.o if.o common.o + + install: all + $(INSTALL) -d -m 755 $(LIBDIR) +- $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR) ++ $(INSTALL) -c -m 755 rp-pppoe.so $(LIBDIR) + $(INSTALL) -d -m 755 $(BINDIR) +- $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR) +- $(INSTALL) -c -m 444 pppoe-discovery.8 $(MANDIR) ++ $(INSTALL) -c -m 755 pppoe-discovery $(BINDIR) ++ $(INSTALL) -c -m 644 pppoe-discovery.8 $(MANDIR) + + clean: + rm -f *.o *.so pppoe-discovery +-- +1.8.3.1 + diff --git a/0024-build-sys-install-pppoatm-plugin-files-with-standard.patch b/0024-build-sys-install-pppoatm-plugin-files-with-standard.patch new file mode 100644 index 0000000..9982d92 --- /dev/null +++ b/0024-build-sys-install-pppoatm-plugin-files-with-standard.patch @@ -0,0 +1,26 @@ +From 0fdb22ef3d3cc3b297372451d60bd6c61d047d27 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 10 Apr 2014 10:08:41 +0200 +Subject: [PATCH 24/27] build-sys: install pppoatm plugin files with standard + perms + +--- + pppd/plugins/pppoatm/Makefile.linux | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pppd/plugins/pppoatm/Makefile.linux b/pppd/plugins/pppoatm/Makefile.linux +index 769794b..4c5826f 100644 +--- a/pppd/plugins/pppoatm/Makefile.linux ++++ b/pppd/plugins/pppoatm/Makefile.linux +@@ -37,7 +37,7 @@ $(PLUGIN): $(PLUGIN_OBJS) + + install: all + $(INSTALL) -d -m 755 $(LIBDIR) +- $(INSTALL) -c -m 4550 $(PLUGIN) $(LIBDIR) ++ $(INSTALL) -c -m 755 $(PLUGIN) $(LIBDIR) + + clean: + rm -f *.o *.so +-- +1.8.3.1 + diff --git a/0025-pppd-install-pppd-binary-using-standard-perms-755.patch b/0025-pppd-install-pppd-binary-using-standard-perms-755.patch new file mode 100644 index 0000000..428d71a --- /dev/null +++ b/0025-pppd-install-pppd-binary-using-standard-perms-755.patch @@ -0,0 +1,29 @@ +From ab8b06cdc1075abc67f77e7c3bb684e20071d614 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 10 Apr 2014 10:09:41 +0200 +Subject: [PATCH 25/27] pppd: install pppd binary using standard perms (755) + +--- + pppd/Makefile.linux | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 0e8107f..534ccc2 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -223,10 +223,10 @@ all: $(TARGETS) + install: pppd + mkdir -p $(BINDIR) $(MANDIR) + $(EXTRAINSTALL) +- $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd ++ $(INSTALL) -c -m 755 pppd $(BINDIR)/pppd + if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \ + chmod o-rx,u+s $(BINDIR)/pppd; fi +- $(INSTALL) -c -m 444 pppd.8 $(MANDIR) ++ $(INSTALL) -c -m 644 pppd.8 $(MANDIR) + + pppd: $(PPPDOBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o pppd $(PPPDOBJS) $(LIBS) +-- +1.8.3.1 + diff --git a/0026-Revert-pppd-rebase-EAP-TLS-patch-v0.994.patch b/0026-Revert-pppd-rebase-EAP-TLS-patch-v0.994.patch new file mode 100644 index 0000000..515a5f4 --- /dev/null +++ b/0026-Revert-pppd-rebase-EAP-TLS-patch-v0.994.patch @@ -0,0 +1,3046 @@ +From 1c5d747dac840a633aebd3eef882b11321993009 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 20 Jun 2014 10:26:32 +0200 +Subject: [PATCH 26/27] Revert "pppd: rebase EAP-TLS patch v0.994" + +This reverts commit 044a5b1e5d878c519143b71a44b3d5b0ca91de3b. +--- + README.eap-tls | 169 ------- + 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 | 414 +-------------- + pppd/ccp.c | 20 +- + pppd/chap-md5.c | 4 - + pppd/eap-tls.c | 1174 ------------------------------------------- + pppd/eap-tls.h | 107 ---- + pppd/eap.c | 462 +---------------- + pppd/eap.h | 32 +- + pppd/md5.c | 3 - + pppd/md5.h | 3 - + pppd/options.c | 10 - + pppd/pathnames.h | 7 - + pppd/plugins/Makefile.linux | 3 - + pppd/plugins/passprompt.c | 3 - + pppd/plugins/passwordfd.c | 4 - + pppd/pppd.h | 8 - + 21 files changed, 15 insertions(+), 2461 deletions(-) + delete mode 100644 README.eap-tls + delete mode 100644 etc.ppp/eaptls-client + delete mode 100644 etc.ppp/eaptls-server + delete mode 100644 etc.ppp/openssl.cnf + delete mode 100644 pppd/eap-tls.c + delete mode 100644 pppd/eap-tls.h + +diff --git a/README.eap-tls b/README.eap-tls +deleted file mode 100644 +index 0a4fee9..0000000 +--- a/README.eap-tls ++++ /dev/null +@@ -1,169 +0,0 @@ +-EAP-TLS authentication support for PPP +-====================================== +- +-1. Intro +- +- The Extensible Authentication Protocol (EAP; RFC 3748) is a +- security protocol that can be used with PPP. It provides a means +- to plug in multiple optional authentication methods. +- +- Transport Level Security (TLS; RFC 2246) provides for mutual +- authentication, integrity-protected ciphersuite negotiation and +- key exchange between two endpoints. It also provides for optional +- MPPE encryption. +- +- EAP-TLS (RFC 2716) incapsulates the TLS messages in EAP packets, +- allowing TLS mutual authentication to be used as a generic EAP +- mechanism. It also provides optional encryption using the MPPE +- protocol. +- +- This patch provide EAP-TLS support to pppd. +- This authentication method can be used in both client or server +- mode. +- +-2. Building +- +- To build pppd with EAP-TLS support, OpenSSL (http://www.openssl.org) +- is required. Any version from 0.9.7 should work. +- +- Configure, compile, and install as usual. +- +-3. Configuration +- +- On the client side there are two ways to configure EAP-TLS: +- +- 1. supply the appropriate 'ca', 'cert' and 'key' command-line parameters +- +- 2. edit the /etc/ppp/eaptls-client file. +- Insert a line for each system with which you use EAP-TLS. +- The line is composed of this fields separated by tab: +- +- - Client name +- The name used by the client for authentication, can be * +- - Server name +- The name of the server, can be * +- - Client certificate file +- The file containing the certificate chain for the +- client in PEM format +- - Server certificate file +- If you want to specify the certificate that the +- server is allowed to use, put the certificate file name. +- Else put a dash '-'. +- - CA certificate file +- The file containing the trusted CA certificates in PEM +- format. +- - Client private key file +- The file containing the client private key in PEM format. +- +- +- On the server side edit the /etc/ppp/eaptls-server file. +- Insert a line for each system with which you use EAP-TLS. +- The line is composed of this fields separated by tab: +- +- - Client name +- The name used by the client for authentication, can be * +- - Server name +- The name of the server, can be * +- - Client certificate file +- If you want to specify the certificate that the +- client is allowed to use, put the certificate file name. +- Else put a dash '-'. +- - Server certificate file +- The file containing the certificate chain for the +- server in PEM format +- - CA certificate file +- The file containing the trusted CA certificates in PEM +- format. +- - Client private key file +- The file containing the server private key in PEM format. +- - addresses +- A list of IP addresses the client is allowed to use. +- +- +- OpenSSL engine support is included starting with v0.95 of this patch. +- Currently the only engine tested is the 'pkcs11' engine (hardware token +- support). To use the 'pksc11' engine: +- - Use a special private key fileiname in the /etc/ppp/eaptls-client file: +- : +- e.g. +- pkcs11:123456 +- +- - The certificate can also be loaded from the 'pkcs11' engine using +- a special client certificate filename in the /etc/ppp/eaptls-client file: +- : +- e.g. +- pkcs11:123456 +- +- - Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior +- to starting 'pppd'. A sample openssl.cnf file is +- +- openssl_conf = openssl_def +- +- [ openssl_def ] +- engines = engine_section +- +- [ engine_section ] +- pkcs11 = pkcs11_section +- +- [ pkcs11_section ] +- engine_id = pkcs11 +- dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so +- MODULE_PATH = /usr/lib64/libeTPkcs11.so +- init = 0 +- +- - There are two ways to specify a password/PIN for the PKCS11 engine: +- - inside the openssl.cnf file using +- PIN = your-secret-pin +- Note The keyword 'PIN' is case sensitive! +- - Using the 'password' in the ppp options file. +- From v0.97 of the eap-tls patch the password can also be supplied +- using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c +- for an example). +- +- +-4. Options +- +- These pppd options are available: +- +- ca +- Use the CA public certificate found in in PEM format +- cert +- Use the client public certificate found in in PEM format +- or in engine:engine_id format +- key +- Use the client private key found in in PEM format +- or in engine:engine_id format +- crl-dir +- Use CRL files from dir. It contains CRL files in PEM +- format and each file contains a CRL. The files are looked up +- by the issuer name hash value. Use the c_rehash utility +- to create necessary links. +- need-peer-eap +- If the peer doesn't ask us to authenticate or doesn't use eap +- to authenticate us, disconnect. +- +- Note: +- password-encrypted certificates can be used as of v0.94 of this +- patch. The password for the eap-tls.key file is specified using +- the regular +- password .... +- statement in the ppp options file, or by using the appropriate +- plugin which supplies a 'eaptls_passwd_hook' routine. +- +-5. Connecting +- +- If you're setting up a pppd server, edit the EAP-TLS configuration file +- as written above and then run pppd with the 'auth' option to authenticate +- the client. The EAP-TLS method will be used if the other eap methods can't +- be used (no secrets). +- +- If you're setting up a client, edit the configuration file and then run +- pppd with 'remotename' option to specify the server name. Add the +- 'need-peer-eap' option if you want to be sure the peer ask you to +- authenticate (and to use eap) and to disconnect if it doesn't. +- +-6. Notes +- +- This is experimental code. +- Send suggestions and comments to Jan Just Keijser +- +diff --git a/etc.ppp/eaptls-client b/etc.ppp/eaptls-client +deleted file mode 100644 +index 7782f0e..0000000 +--- a/etc.ppp/eaptls-client ++++ /dev/null +@@ -1,10 +0,0 @@ +-# Parameters for authentication using EAP-TLS (client) +- +-# client name (can be *) +-# server name (can be *) +-# client certificate file (required) +-# server certificate file (optional, if unused put '-') +-# CA certificate file (required) +-# client private key file (required) +- +-#client server /root/cert/client.crt - /root/cert/ca.crt /root/cert/client.key +diff --git a/etc.ppp/eaptls-server b/etc.ppp/eaptls-server +deleted file mode 100644 +index fa53cbd..0000000 +--- a/etc.ppp/eaptls-server ++++ /dev/null +@@ -1,11 +0,0 @@ +-# Parameters for authentication using EAP-TLS (server) +- +-# client name (can be *) +-# server name (can be *) +-# client certificate file (optional, if unused put '-') +-# server certificate file (required) +-# CA certificate file (required) +-# server private key file (required) +-# allowed addresses (required, can be *) +- +-#client server - /root/cert/server.crt /root/cert/ca.crt /root/cert/server.key 192.168.1.0/24 +diff --git a/etc.ppp/openssl.cnf b/etc.ppp/openssl.cnf +deleted file mode 100644 +index dd32f30..0000000 +--- a/etc.ppp/openssl.cnf ++++ /dev/null +@@ -1,14 +0,0 @@ +-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 +- +diff --git a/linux/Makefile.top b/linux/Makefile.top +index 9a8945a..f42efd5 100644 +--- a/linux/Makefile.top ++++ b/linux/Makefile.top +@@ -28,7 +28,7 @@ install-progs: + cd pppdump; $(MAKE) $(MFLAGS) install + + install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ +- $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client ++ $(ETCDIR)/chap-secrets + + install-devel: + cd pppd; $(MAKE) $(MFLAGS) install-devel +@@ -39,10 +39,6 @@ $(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 $@ +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 534ccc2..943cf83 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -79,9 +79,6 @@ CBCP=y + # Use libutil + USE_LIBUTIL=y + +-# Enable EAP-TLS authentication (requires libssl and libcrypto) +-USE_EAPTLS=y +- + MAXOCTETS=y + + INCLUDE_DIRS= -I../include +@@ -121,15 +118,6 @@ 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) +diff --git a/pppd/auth.c b/pppd/auth.c +index 88cbdb6..9e957fa 100644 +--- a/pppd/auth.c ++++ b/pppd/auth.c +@@ -109,9 +109,6 @@ + #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 +@@ -186,11 +183,6 @@ int (*chap_check_hook) __P((void)) = NULL; + /* Hook for a plugin to get the CHAP password for authenticating us */ + int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; + +-#ifdef USE_EAPTLS +-/* Hook for a plugin to get the EAP-TLS password for authenticating us */ +-int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL; +-#endif +- + /* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ + int (*null_auth_hook) __P((struct wordlist **paddrs, +@@ -246,13 +238,6 @@ bool explicit_remote = 0; /* User specified explicit remote name */ + bool explicit_user = 0; /* Set if "user" option supplied */ + bool explicit_passwd = 0; /* Set if "password" option supplied */ + char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +-#ifdef USE_EAPTLS +-char *cacert_file = NULL; /* CA certificate file (pem format) */ +-char *cert_file = NULL; /* client certificate file (pem format) */ +-char *privkey_file = NULL; /* client private key file (pem format) */ +-char *crl_dir = NULL; /* directory containing CRL files */ +-bool need_peer_eap = 0; /* Require peer to authenticate us */ +-#endif + + static char *uafname; /* name of most recent +ua file */ + +@@ -269,19 +254,6 @@ 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 **, +@@ -429,14 +401,6 @@ 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" }, +- { "need-peer-eap", o_bool, &need_peer_eap, +- "Require the peer to authenticate us", 1 }, +-#endif /* USE_EAPTLS */ + { NULL } + }; + +@@ -766,9 +730,6 @@ 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; + +@@ -803,22 +764,6 @@ 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) { +@@ -1172,7 +1117,7 @@ np_down(unit, proto) + UNTIMEOUT(connect_time_expired, NULL); + #ifdef MAXOCTETS + UNTIMEOUT(check_maxoctets, NULL); +-#endif ++#endif + new_phase(PHASE_NETWORK); + } + } +@@ -1199,7 +1144,7 @@ check_maxoctets(arg) + + update_link_stats(ifunit); + link_stats_valid=0; +- ++ + switch(maxoctets_dir) { + case PPP_OCTETS_DIRECTION_IN: + used = link_stats.bytes_in; +@@ -1332,15 +1277,6 @@ 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( +@@ -1395,11 +1331,7 @@ 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) +-#ifdef USE_EAPTLS +- || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL)) +-#endif +- ); ++ have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) +@@ -1414,14 +1346,8 @@ 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) +-#ifdef USE_EAPTLS +- && !have_eaptls_secret_server((explicit_remote? remote_name: NULL), +- our_name, 1, NULL) +-#endif +- ) ++ NULL)) + go->neg_eap = 0; +- + } + + +@@ -1781,7 +1707,6 @@ have_srp_secret(client, server, need_ip, lacks_ipp) + } + + +- + /* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. +@@ -2434,334 +2359,3 @@ 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 +diff --git a/pppd/ccp.c b/pppd/ccp.c +index 7dead23..5814f35 100644 +--- a/pppd/ccp.c ++++ b/pppd/ccp.c +@@ -540,9 +540,6 @@ 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; + + /* +@@ -570,23 +567,8 @@ 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."); +-#endif ++ error("MPPE required, but MS-CHAP[v2] auth not performed."); + lcp_close(f->unit, "MPPE required but not available"); + return; + } +diff --git a/pppd/chap-md5.c b/pppd/chap-md5.c +index 269b52c..77dd4ec 100644 +--- a/pppd/chap-md5.c ++++ b/pppd/chap-md5.c +@@ -36,11 +36,7 @@ + #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 +diff --git a/pppd/eap-tls.c b/pppd/eap-tls.c +deleted file mode 100644 +index a3aea5a..0000000 +--- a/pppd/eap-tls.c ++++ /dev/null +@@ -1,1174 +0,0 @@ +-/* +- * eap-tls.c - EAP-TLS implementation for PPP +- * +- * Copyright (c) Beniamino Galvani 2005 All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in +- * the documentation and/or other materials provided with the +- * distribution. +- * +- * 3. The name(s) of the authors of this software must not be used to +- * endorse or promote products derived from this software without +- * prior written permission. +- * +- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO +- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- * +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include "pppd.h" +-#include "eap.h" +-#include "eap-tls.h" +-#include "fsm.h" +-#include "lcp.h" +-#include "pathnames.h" +- +-/* The openssl configuration file and engines can be loaded only once */ +-static CONF *ssl_config = NULL; +-static ENGINE *cert_engine = NULL; +-static ENGINE *pkey_engine = NULL; +- +-#ifdef MPPE +- +-/* +- * TLS PRF from RFC 2246 +- */ +-static void P_hash(const EVP_MD *evp_md, +- const unsigned char *secret, unsigned int secret_len, +- const unsigned char *seed, unsigned int seed_len, +- unsigned char *out, unsigned int out_len) +-{ +- HMAC_CTX ctx_a, ctx_out; +- unsigned char a[HMAC_MAX_MD_CBLOCK]; +- unsigned int size; +- +- HMAC_CTX_init(&ctx_a); +- HMAC_CTX_init(&ctx_out); +- HMAC_Init_ex(&ctx_a, secret, secret_len, evp_md, NULL); +- HMAC_Init_ex(&ctx_out, secret, secret_len, evp_md, NULL); +- +- size = HMAC_size(&ctx_out); +- +- /* Calculate A(1) */ +- HMAC_Update(&ctx_a, seed, seed_len); +- HMAC_Final(&ctx_a, a, NULL); +- +- while (1) { +- /* Calculate next part of output */ +- HMAC_Update(&ctx_out, a, size); +- HMAC_Update(&ctx_out, seed, seed_len); +- +- /* Check if last part */ +- if (out_len < size) { +- HMAC_Final(&ctx_out, a, NULL); +- memcpy(out, a, out_len); +- break; +- } +- +- /* Place digest in output buffer */ +- HMAC_Final(&ctx_out, out, NULL); +- HMAC_Init_ex(&ctx_out, NULL, 0, NULL, NULL); +- out += size; +- out_len -= size; +- +- /* Calculate next A(i) */ +- HMAC_Init_ex(&ctx_a, NULL, 0, NULL, NULL); +- HMAC_Update(&ctx_a, a, size); +- HMAC_Final(&ctx_a, a, NULL); +- } +- +- HMAC_CTX_cleanup(&ctx_a); +- HMAC_CTX_cleanup(&ctx_out); +- memset(a, 0, sizeof(a)); +-} +- +-static void PRF(const unsigned char *secret, unsigned int secret_len, +- const unsigned char *seed, unsigned int seed_len, +- unsigned char *out, unsigned char *buf, unsigned int out_len) +-{ +- unsigned int i; +- unsigned int len = (secret_len + 1) / 2; +- const unsigned char *s1 = secret; +- const unsigned char *s2 = secret + (secret_len - len); +- +- P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len); +- P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len); +- +- for (i=0; i < out_len; i++) { +- out[i] ^= buf[i]; +- } +-} +- +-#define EAPTLS_MPPE_KEY_LEN 32 +- +-/* +- * Generate keys according to RFC 2716 and add to reply +- */ +-void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, +- int client) +-{ +- unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN]; +- unsigned char seed[64 + 2*SSL3_RANDOM_SIZE]; +- unsigned char *p = seed; +- SSL *s = ets->ssl; +- size_t prf_size; +- +- prf_size = strlen(prf_label); +- +- memcpy(p, prf_label, prf_size); +- p += prf_size; +- +- memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); +- p += SSL3_RANDOM_SIZE; +- prf_size += SSL3_RANDOM_SIZE; +- +- memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); +- prf_size += SSL3_RANDOM_SIZE; +- +- PRF(s->session->master_key, s->session->master_key_length, +- seed, prf_size, out, buf, sizeof(out)); +- +- /* +- * We now have the master send and receive keys. +- * From these, generate the session send and receive keys. +- * (see RFC3079 / draft-ietf-pppext-mppe-keys-03.txt for details) +- */ +- if (client) +- { +- p = out; +- BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); +- p += EAPTLS_MPPE_KEY_LEN; +- BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); +- } +- else +- { +- p = out; +- BCOPY( p, mppe_recv_key, sizeof(mppe_recv_key) ); +- p += EAPTLS_MPPE_KEY_LEN; +- BCOPY( p, mppe_send_key, sizeof(mppe_send_key) ); +- } +- +- mppe_keys_set = 1; +-} +- +-#endif +- +-void log_ssl_errors( void ) +-{ +- unsigned long ssl_err = ERR_get_error(); +- +- if (ssl_err != 0) +- dbglog("EAP-TLS SSL error stack:"); +- while (ssl_err != 0) { +- dbglog( ERR_error_string( ssl_err, NULL ) ); +- ssl_err = ERR_get_error(); +- } +-} +- +- +-int password_callback (char *buf, int size, int rwflag, void *u) +-{ +- if (buf) +- { +- strncpy (buf, passwd, size); +- return strlen (buf); +- } +- return 0; +-} +- +- +-CONF *eaptls_ssl_load_config( void ) +-{ +- CONF *config; +- int ret_code; +- long error_line = 33; +- +- config = NCONF_new( NULL ); +- dbglog( "Loading OpenSSL config file" ); +- ret_code = NCONF_load( config, _PATH_OPENSSLCONFFILE, &error_line ); +- if (ret_code == 0) +- { +- warn( "EAP-TLS: Error in OpenSSL config file %s at line %d", _PATH_OPENSSLCONFFILE, error_line ); +- NCONF_free( config ); +- config = NULL; +- ERR_clear_error(); +- } +- +- dbglog( "Loading OpenSSL built-ins" ); +- ENGINE_load_builtin_engines(); +- OPENSSL_load_builtin_modules(); +- +- dbglog( "Loading OpenSSL configured modules" ); +- if (CONF_modules_load( config, NULL, 0 ) <= 0 ) +- { +- warn( "EAP-TLS: Error loading OpenSSL modules" ); +- log_ssl_errors(); +- config = NULL; +- } +- +- return config; +-} +- +-ENGINE *eaptls_ssl_load_engine( char *engine_name ) +-{ +- ENGINE *e = NULL; +- +- dbglog( "Enabling OpenSSL auto engines" ); +- ENGINE_register_all_complete(); +- +- dbglog( "Loading OpenSSL '%s' engine support", engine_name ); +- e = ENGINE_by_id( engine_name ); +- if (!e) +- { +- dbglog( "EAP-TLS: Cannot load '%s' engine support, trying 'dynamic'", engine_name ); +- e = ENGINE_by_id( "dynamic" ); +- if (e) +- { +- if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine_name, 0) +- || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) +- { +- warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name ); +- log_ssl_errors(); +- ENGINE_free(e); +- e = NULL; +- } +- } +- else +- { +- warn( "EAP-TLS: Cannot load dynamic engine support" ); +- } +- } +- +- if (e) +- { +- dbglog( "Initialising engine" ); +- if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) +- { +- warn( "EAP-TLS: Cannot use that engine" ); +- log_ssl_errors(); +- ENGINE_free(e); +- e = NULL; +- } +- } +- +- return e; +-} +- +-/* +- * Initialize the SSL stacks and tests if certificates, key and crl +- * for client or server use can be loaded. +- */ +-SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, +- char *certfile, char *peer_certfile, char *privkeyfile) +-{ +- char *cert_engine_name = NULL; +- char *cert_identifier = NULL; +- char *pkey_engine_name = NULL; +- char *pkey_identifier = NULL; +- SSL_CTX *ctx; +- X509_STORE *certstore; +- X509_LOOKUP *lookup; +- X509 *tmp; +- +- /* +- * Without these can't continue +- */ +- if (!cacertfile[0]) +- { +- error("EAP-TLS: CA certificate missing"); +- return NULL; +- } +- +- if (!certfile[0]) +- { +- error("EAP-TLS: User certificate missing"); +- return NULL; +- } +- +- if (!privkeyfile[0]) +- { +- error("EAP-TLS: User private key missing"); +- return NULL; +- } +- +- SSL_library_init(); +- SSL_load_error_strings(); +- +- ctx = SSL_CTX_new(TLSv1_method()); +- +- if (!ctx) { +- error("EAP-TLS: Cannot initialize SSL CTX context"); +- goto fail; +- } +- +- /* if the certificate filename is of the form engine:id. e.g. +- pkcs11:12345 +- then we try to load and use this engine. +- If the certificate filename starts with a / or . then we +- ALWAYS assume it is a file and not an engine/pkcs11 identifier +- */ +- if ( index( certfile, '/' ) == NULL && index( certfile, '.') == NULL ) +- { +- cert_identifier = index( certfile, ':' ); +- +- if (cert_identifier) +- { +- cert_engine_name = certfile; +- *cert_identifier = '\0'; +- cert_identifier++; +- +- dbglog( "Found certificate engine '%s'", cert_engine_name ); +- dbglog( "Found certificate identifier '%s'", cert_identifier ); +- } +- } +- +- /* if the privatekey filename is of the form engine:id. e.g. +- pkcs11:12345 +- then we try to load and use this engine. +- If the privatekey filename starts with a / or . then we +- ALWAYS assume it is a file and not an engine/pkcs11 identifier +- */ +- if ( index( privkeyfile, '/' ) == NULL && index( privkeyfile, '.') == NULL ) +- { +- pkey_identifier = index( privkeyfile, ':' ); +- +- if (pkey_identifier) +- { +- pkey_engine_name = privkeyfile; +- *pkey_identifier = '\0'; +- pkey_identifier++; +- +- dbglog( "Found privatekey engine '%s'", pkey_engine_name ); +- dbglog( "Found privatekey identifier '%s'", pkey_identifier ); +- } +- } +- +- if (cert_identifier && pkey_identifier) +- { +- if (strlen( cert_identifier ) == 0) +- { +- if (strlen( pkey_identifier ) == 0) +- error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" ); +- else +- { +- dbglog( "Substituting privatekey identifier for certificate identifier" ); +- cert_identifier = pkey_identifier; +- } +- } +- else +- { +- if (strlen( pkey_identifier ) == 0) +- { +- dbglog( "Substituting certificate identifier for privatekey identifier" ); +- pkey_identifier = cert_identifier; +- } +- } +- +- } +- +- /* load the openssl config file only once */ +- if (!ssl_config) +- { +- if (cert_engine_name || pkey_engine_name) +- ssl_config = eaptls_ssl_load_config(); +- +- if (ssl_config && cert_engine_name) +- cert_engine = eaptls_ssl_load_engine( cert_engine_name ); +- +- if (ssl_config && pkey_engine_name) +- { +- /* don't load the same engine twice */ +- if ( strcmp( cert_engine_name, pkey_engine_name) == 0 ) +- pkey_engine = cert_engine; +- else +- pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); +- } +- } +- +- SSL_CTX_set_default_passwd_cb (ctx, password_callback); +- +- if (!SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) +- { +- error("EAP-TLS: Cannot load or verify CA file %s", cacertfile); +- goto fail; +- } +- +- if (init_server) +- SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); +- +- if (cert_engine) +- { +- struct +- { +- const char *s_slot_cert_id; +- X509 *cert; +- } cert_info; +- +- cert_info.s_slot_cert_id = cert_identifier; +- cert_info.cert = NULL; +- +- if (!ENGINE_ctrl_cmd( cert_engine, "LOAD_CERT_CTRL", 0, &cert_info, NULL, 0 ) ) +- { +- error( "EAP-TLS: Error loading certificate with id '%s' from engine", cert_identifier ); +- goto fail; +- } +- +- if (cert_info.cert) +- { +- dbglog( "Got the certificate, adding it to SSL context" ); +- dbglog( "subject = %s", X509_NAME_oneline( X509_get_subject_name( cert_info.cert ), NULL, 0 ) ); +- if (SSL_CTX_use_certificate(ctx, cert_info.cert) <= 0) +- { +- error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier); +- goto fail; +- } +- } +- else +- { +- warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier); +- log_ssl_errors(); +- } +- } +- else +- { +- if (!SSL_CTX_use_certificate_file(ctx, certfile, SSL_FILETYPE_PEM)) +- { +- error( "EAP-TLS: Cannot use public certificate %s", certfile ); +- goto fail; +- } +- } +- +- if (pkey_engine) +- { +- EVP_PKEY *pkey = NULL; +- PW_CB_DATA cb_data; +- +- cb_data.password = passwd; +- cb_data.prompt_info = pkey_identifier; +- +- dbglog( "Loading private key '%s' from engine", pkey_identifier ); +- pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, &cb_data); +- if (pkey) +- { +- dbglog( "Got the private key, adding it to SSL context" ); +- if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) +- { +- error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier); +- goto fail; +- } +- } +- else +- { +- warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier); +- log_ssl_errors(); +- } +- } +- else +- { +- if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) +- { +- error("EAP-TLS: Cannot use private key %s", privkeyfile); +- goto fail; +- } +- } +- +- if (SSL_CTX_check_private_key(ctx) != 1) { +- error("EAP-TLS: Private key %s fails security check", privkeyfile); +- goto fail; +- } +- +- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +- SSL_CTX_set_verify_depth(ctx, 5); +- SSL_CTX_set_verify(ctx, +- SSL_VERIFY_PEER | +- SSL_VERIFY_FAIL_IF_NO_PEER_CERT, +- &ssl_verify_callback); +- +- if (crl_dir) { +- if (!(certstore = SSL_CTX_get_cert_store(ctx))) { +- error("EAP-TLS: Failed to get certificate store"); +- goto fail; +- } +- +- if (!(lookup = +- X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) { +- error("EAP-TLS: Store lookup for CRL failed"); +- +- goto fail; +- } +- +- X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); +- X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); +- } +- +- /* +- * If a peer certificate file was specified, it must be valid, else fail +- */ +- if (peer_certfile[0]) { +- if (!(tmp = get_X509_from_file(peer_certfile))) { +- error("EAP-TLS: Error loading client certificate from file %s", +- peer_certfile); +- goto fail; +- } +- X509_free(tmp); +- } +- +- return ctx; +- +-fail: +- log_ssl_errors(); +- SSL_CTX_free(ctx); +- return NULL; +-} +- +-/* +- * Determine the maximum packet size by looking at the LCP handshake +- */ +- +-int eaptls_get_mtu(int unit) +-{ +- int mtu, mru; +- +- lcp_options *wo = &lcp_wantoptions[unit]; +- lcp_options *go = &lcp_gotoptions[unit]; +- lcp_options *ho = &lcp_hisoptions[unit]; +- lcp_options *ao = &lcp_allowoptions[unit]; +- +- mtu = ho->neg_mru? ho->mru: PPP_MRU; +- mru = go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU; +- mtu = MIN(MIN(mtu, mru), ao->mru)- PPP_HDRLEN - 10; +- +- dbglog("MTU = %d", mtu); +- return mtu; +-} +- +- +-/* +- * Init the ssl handshake (server mode) +- */ +-int eaptls_init_ssl_server(eap_state * esp) +-{ +- struct eaptls_session *ets; +- char servcertfile[MAXWORDLEN]; +- char clicertfile[MAXWORDLEN]; +- char cacertfile[MAXWORDLEN]; +- char pkfile[MAXWORDLEN]; +- /* +- * Allocate new eaptls session +- */ +- esp->es_server.ea_session = malloc(sizeof(struct eaptls_session)); +- if (!esp->es_server.ea_session) +- fatal("Allocation error"); +- ets = esp->es_server.ea_session; +- +- if (!esp->es_server.ea_peer) { +- error("EAP-TLS: Error: client name not set (BUG)"); +- return 0; +- } +- +- strncpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN); +- +- dbglog( "getting eaptls secret" ); +- if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, +- esp->es_server.ea_name, clicertfile, +- servcertfile, cacertfile, pkfile, 1)) { +- error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", +- esp->es_server.ea_peer, esp->es_server.ea_name ); +- return 0; +- } +- +- ets->mtu = eaptls_get_mtu(esp->es_unit); +- +- ets->ctx = eaptls_init_ssl(1, cacertfile, servcertfile, clicertfile, pkfile); +- if (!ets->ctx) +- goto fail; +- +- if (!(ets->ssl = SSL_new(ets->ctx))) +- goto fail; +- +- /* +- * Set auto-retry to avoid timeouts on BIO_read +- */ +- SSL_set_mode(ets->ssl, SSL_MODE_AUTO_RETRY); +- +- /* +- * Initialize the BIOs we use to read/write to ssl engine +- */ +- ets->into_ssl = BIO_new(BIO_s_mem()); +- ets->from_ssl = BIO_new(BIO_s_mem()); +- SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); +- +- SSL_set_msg_callback(ets->ssl, ssl_msg_callback); +- SSL_set_msg_callback_arg(ets->ssl, ets); +- +- /* +- * Attach the session struct to the connection, so we can later +- * retrieve it when doing certificate verification +- */ +- SSL_set_ex_data(ets->ssl, 0, ets); +- +- SSL_set_accept_state(ets->ssl); +- +- ets->data = NULL; +- ets->datalen = 0; +- ets->alert_sent = 0; +- ets->alert_recv = 0; +- +- /* +- * If we specified the client certificate file, store it in ets->peercertfile, +- * so we can check it later in ssl_verify_callback() +- */ +- if (clicertfile[0]) +- strncpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN); +- else +- ets->peercertfile[0] = 0; +- +- return 1; +- +-fail: +- SSL_CTX_free(ets->ctx); +- return 0; +-} +- +-/* +- * Init the ssl handshake (client mode) +- */ +-int eaptls_init_ssl_client(eap_state * esp) +-{ +- struct eaptls_session *ets; +- char servcertfile[MAXWORDLEN]; +- char clicertfile[MAXWORDLEN]; +- char cacertfile[MAXWORDLEN]; +- char pkfile[MAXWORDLEN]; +- +- /* +- * Allocate new eaptls session +- */ +- esp->es_client.ea_session = malloc(sizeof(struct eaptls_session)); +- if (!esp->es_client.ea_session) +- fatal("Allocation error"); +- ets = esp->es_client.ea_session; +- +- /* +- * If available, copy server name in ets; it will be used in cert +- * verify +- */ +- if (esp->es_client.ea_peer) +- strncpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN); +- else +- ets->peer[0] = 0; +- +- ets->mtu = eaptls_get_mtu(esp->es_unit); +- +- dbglog( "calling get_eaptls_secret" ); +- if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, +- esp->es_client.ea_peer, clicertfile, +- servcertfile, cacertfile, pkfile, 0)) { +- error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", +- esp->es_client.ea_name, esp->es_client.ea_peer ); +- return 0; +- } +- +- dbglog( "calling eaptls_init_ssl" ); +- ets->ctx = eaptls_init_ssl(0, cacertfile, clicertfile, servcertfile, pkfile); +- if (!ets->ctx) +- goto fail; +- +- ets->ssl = SSL_new(ets->ctx); +- +- if (!ets->ssl) +- goto fail; +- +- /* +- * Initialize the BIOs we use to read/write to ssl engine +- */ +- dbglog( "Initializing SSL BIOs" ); +- ets->into_ssl = BIO_new(BIO_s_mem()); +- ets->from_ssl = BIO_new(BIO_s_mem()); +- SSL_set_bio(ets->ssl, ets->into_ssl, ets->from_ssl); +- +- SSL_set_msg_callback(ets->ssl, ssl_msg_callback); +- SSL_set_msg_callback_arg(ets->ssl, ets); +- +- /* +- * Attach the session struct to the connection, so we can later +- * retrieve it when doing certificate verification +- */ +- SSL_set_ex_data(ets->ssl, 0, ets); +- +- SSL_set_connect_state(ets->ssl); +- +- ets->data = NULL; +- ets->datalen = 0; +- ets->alert_sent = 0; +- ets->alert_recv = 0; +- +- /* +- * If we specified the server certificate file, store it in +- * ets->peercertfile, so we can check it later in +- * ssl_verify_callback() +- */ +- if (servcertfile[0]) +- strncpy(ets->peercertfile, servcertfile, MAXWORDLEN); +- else +- ets->peercertfile[0] = 0; +- +- return 1; +- +-fail: +- dbglog( "eaptls_init_ssl_client: fail" ); +- SSL_CTX_free(ets->ctx); +- return 0; +- +-} +- +-void eaptls_free_session(struct eaptls_session *ets) +-{ +- if (ets->ssl) +- SSL_free(ets->ssl); +- +- if (ets->ctx) +- SSL_CTX_free(ets->ctx); +- +- free(ets); +-} +- +-/* +- * Handle a received packet, reassembling fragmented messages and +- * passing them to the ssl engine +- */ +-int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) +-{ +- u_char flags; +- u_int tlslen; +- u_char dummy[65536]; +- +- GETCHAR(flags, inp); +- len--; +- +- if (flags & EAP_TLS_FLAGS_LI && !ets->data) { +- +- /* +- * This is the first packet of a message +- */ +- +- GETLONG(tlslen, inp); +- len -= 4; +- +- if (tlslen > EAP_TLS_MAX_LEN) { +- error("Error: tls message length > %d, truncated", +- EAP_TLS_MAX_LEN); +- tlslen = EAP_TLS_MAX_LEN; +- } +- +- /* +- * Allocate memory for the whole message +- */ +- ets->data = malloc(tlslen); +- if (!ets->data) +- fatal("EAP TLS: allocation error\n"); +- +- ets->datalen = 0; +- ets->tlslen = tlslen; +- +- } +- else if (flags & EAP_TLS_FLAGS_LI && ets->data) { +- /* +- * Non first with LI (strange...) +- */ +- +- GETLONG(tlslen, inp); +- len -= 4; +- +- } +- else if (!ets->data) { +- /* +- * A non fragmented message without LI flag +- */ +- +- ets->data = malloc(len); +- if (!ets->data) +- fatal("EAP TLS: allocation error\n"); +- +- ets->datalen = 0; +- ets->tlslen = len; +- } +- +- if (flags & EAP_TLS_FLAGS_MF) +- ets->frag = 1; +- else +- ets->frag = 0; +- +- if (len + ets->datalen > ets->tlslen) { +- warn("EAP TLS: received data > TLS message length"); +- return 1; +- } +- +- BCOPY(inp, ets->data + ets->datalen, len); +- ets->datalen += len; +- +- if (!ets->frag) { +- +- /* +- * If we have the whole message, pass it to ssl +- */ +- +- if (ets->datalen != ets->tlslen) { +- warn("EAP TLS: received data != TLS message length"); +- return 1; +- } +- +- if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1) +- log_ssl_errors(); +- +- SSL_read(ets->ssl, dummy, 65536); +- +- free(ets->data); +- ets->data = NULL; +- ets->datalen = 0; +- } +- +- return 0; +-} +- +-/* +- * Return an eap-tls packet in outp. +- * A TLS message read from the ssl engine is buffered in ets->data. +- * At each call we control if there is buffered data and send a +- * packet of mtu bytes. +- */ +-int eaptls_send(struct eaptls_session *ets, u_char ** outp) +-{ +- bool first = 0; +- int size; +- u_char fromtls[65536]; +- int res; +- u_char *start; +- +- start = *outp; +- +- if (!ets->data) { +- +- if(!ets->alert_sent) +- SSL_read(ets->ssl, fromtls, 65536); +- +- /* +- * Read from ssl +- */ +- if ((res = BIO_read(ets->from_ssl, fromtls, 65536)) == -1) +- fatal("No data from BIO_read"); +- +- ets->datalen = res; +- +- ets->data = malloc(ets->datalen); +- BCOPY(fromtls, ets->data, ets->datalen); +- +- ets->offset = 0; +- first = 1; +- +- } +- +- size = ets->datalen - ets->offset; +- +- if (size > ets->mtu) { +- size = ets->mtu; +- ets->frag = 1; +- } else +- ets->frag = 0; +- +- PUTCHAR(EAPT_TLS, *outp); +- +- /* +- * Set right flags and length if necessary +- */ +- if (ets->frag && first) { +- PUTCHAR(EAP_TLS_FLAGS_LI | EAP_TLS_FLAGS_MF, *outp); +- PUTLONG(ets->datalen, *outp); +- } else if (ets->frag) { +- PUTCHAR(EAP_TLS_FLAGS_MF, *outp); +- } else +- PUTCHAR(0, *outp); +- +- /* +- * Copy the data in outp +- */ +- BCOPY(ets->data + ets->offset, *outp, size); +- INCPTR(size, *outp); +- +- /* +- * Copy the packet in retransmission buffer +- */ +- BCOPY(start, &ets->rtx[0], *outp - start); +- ets->rtx_len = *outp - start; +- +- ets->offset += size; +- +- if (ets->offset >= ets->datalen) { +- +- /* +- * The whole message has been sent +- */ +- +- free(ets->data); +- ets->data = NULL; +- ets->datalen = 0; +- ets->offset = 0; +- } +- +- return 0; +-} +- +-/* +- * Get the sent packet from the retransmission buffer +- */ +-void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp) +-{ +- BCOPY(ets->rtx, *outp, ets->rtx_len); +- INCPTR(ets->rtx_len, *outp); +-} +- +-/* +- * Verify a certificate. +- * Most of the work (signatures and issuer attributes checking) +- * is done by ssl; we check the CN in the peer certificate +- * against the peer name. +- */ +-int ssl_verify_callback(int preverify_ok, X509_STORE_CTX * ctx) +-{ +- char subject[256]; +- char cn_str[256]; +- X509 *peer_cert; +- int err, depth; +- int ok = preverify_ok; +- SSL *ssl; +- struct eaptls_session *ets; +- +- peer_cert = X509_STORE_CTX_get_current_cert(ctx); +- err = X509_STORE_CTX_get_error(ctx); +- depth = X509_STORE_CTX_get_error_depth(ctx); +- +- dbglog("certificate verify depth: %d", depth); +- +- if (auth_required && !ok) { +- X509_NAME_oneline(X509_get_subject_name(peer_cert), +- subject, 256); +- +- X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), +- NID_commonName, cn_str, 256); +- +- dbglog("Certificate verification error:\n depth: %d CN: %s" +- "\n err: %d (%s)\n", depth, cn_str, err, +- X509_verify_cert_error_string(err)); +- +- return 0; +- } +- +- ssl = X509_STORE_CTX_get_ex_data(ctx, +- SSL_get_ex_data_X509_STORE_CTX_idx()); +- +- ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0); +- +- if (ets == NULL) { +- error("Error: SSL_get_ex_data returned NULL"); +- return 0; +- } +- +- log_ssl_errors(); +- +- if (!depth) { /* This is the peer certificate */ +- +- X509_NAME_oneline(X509_get_subject_name(peer_cert), +- subject, 256); +- +- X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert), +- NID_commonName, cn_str, 256); +- +- /* +- * If acting as client and the name of the server wasn't specified +- * explicitely, we can't verify the server authenticity +- */ +- if (!ets->peer[0]) { +- warn("Peer name not specified: no check"); +- return 1; +- } +- +- /* +- * Check the CN +- */ +- if (strcmp(cn_str, ets->peer)) { +- error +- ("Certificate verification error: CN (%s) != peer_name (%s)", +- cn_str, ets->peer); +- return 0; +- } +- +- warn("Certificate CN: %s , peer name %s", cn_str, ets->peer); +- +- /* +- * If a peer certificate file was specified, here we check it +- */ +- if (ets->peercertfile[0]) { +- if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert) +- != 0) { +- error +- ("Peer certificate doesn't match stored certificate"); +- return 0; +- } +- } +- } +- +- return 1; +-} +- +-/* +- * Compare a certificate with the one stored in a file +- */ +-int ssl_cmp_certs(char *filename, X509 * a) +-{ +- X509 *b; +- int ret; +- +- if (!(b = get_X509_from_file(filename))) +- return 1; +- +- ret = X509_cmp(a, b); +- X509_free(b); +- +- return ret; +- +-} +- +-X509 *get_X509_from_file(char *filename) +-{ +- FILE *fp; +- X509 *ret; +- +- if (!(fp = fopen(filename, "r"))) +- return NULL; +- +- ret = PEM_read_X509(fp, NULL, NULL, NULL); +- +- fclose(fp); +- +- return ret; +-} +- +-/* +- * Every sent & received message this callback function is invoked, +- * so we know when alert messages have arrived or are sent and +- * we can print debug information about TLS handshake. +- */ +-void +-ssl_msg_callback(int write_p, int version, int content_type, +- const void *buf, size_t len, SSL * ssl, void *arg) +-{ +- char string[256]; +- struct eaptls_session *ets = (struct eaptls_session *)arg; +- unsigned char code; +- +- if(write_p) +- strcpy(string, " -> "); +- else +- strcpy(string, " <- "); +- +- +- switch(content_type) { +- +- case SSL3_RT_ALERT: +- strcat(string, "Alert: "); +- code = ((const unsigned char *)buf)[1]; +- +- if (write_p) { +- ets->alert_sent = 1; +- ets->alert_sent_desc = code; +- } else { +- ets->alert_recv = 1; +- ets->alert_recv_desc = code; +- } +- +- strcat(string, SSL_alert_desc_string_long(code)); +- break; +- +- case SSL3_RT_CHANGE_CIPHER_SPEC: +- strcat(string, "ChangeCipherSpec"); +- break; +- +- case SSL3_RT_HANDSHAKE: +- +- strcat(string, "Handshake: "); +- code = ((const unsigned char *)buf)[0]; +- +- switch(code) { +- case SSL3_MT_HELLO_REQUEST: +- strcat(string,"Hello Request"); +- break; +- case SSL3_MT_CLIENT_HELLO: +- strcat(string,"Client Hello"); +- break; +- case SSL3_MT_SERVER_HELLO: +- strcat(string,"Server Hello"); +- break; +- case SSL3_MT_CERTIFICATE: +- strcat(string,"Certificate"); +- break; +- case SSL3_MT_SERVER_KEY_EXCHANGE: +- strcat(string,"Server Key Exchange"); +- break; +- case SSL3_MT_CERTIFICATE_REQUEST: +- strcat(string,"Certificate Request"); +- break; +- case SSL3_MT_SERVER_DONE: +- strcat(string,"Server Hello Done"); +- break; +- case SSL3_MT_CERTIFICATE_VERIFY: +- strcat(string,"Certificate Verify"); +- break; +- case SSL3_MT_CLIENT_KEY_EXCHANGE: +- strcat(string,"Client Key Exchange"); +- break; +- case SSL3_MT_FINISHED: +- strcat(string,"Finished"); +- break; +- +- default: +- sprintf( string, "Handshake: Unknown SSL3 code received: %d", code ); +- } +- break; +- +- default: +- sprintf( string, "SSL message contains unknown content type: %d", content_type ); +- +- } +- +- /* Alert messages must always be displayed */ +- if(content_type == SSL3_RT_ALERT) +- error("%s", string); +- else +- dbglog("%s", string); +-} +- +diff --git a/pppd/eap-tls.h b/pppd/eap-tls.h +deleted file mode 100644 +index 2d45a0b..0000000 +--- a/pppd/eap-tls.h ++++ /dev/null +@@ -1,107 +0,0 @@ +-/* +- * 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 +diff --git a/pppd/eap.c b/pppd/eap.c +index e2270af..faced53 100644 +--- a/pppd/eap.c ++++ b/pppd/eap.c +@@ -43,11 +43,6 @@ + * 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 $" + + /* +@@ -67,12 +62,8 @@ + + #include "pppd.h" + #include "pathnames.h" +-#include "eap.h" +-#ifdef USE_EAPTLS +-#include "eap-tls.h" +-#else + #include "md5.h" +-#endif /* USE_EAPTLS */ ++#include "eap.h" + + #ifdef USE_SRP + #include +@@ -218,9 +209,6 @@ 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 */ + } + + /* +@@ -280,7 +268,7 @@ eap_state *esp; + u_char *outp; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_FAILURE, outp); +@@ -305,7 +293,7 @@ eap_state *esp; + u_char *outp; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_SUCCESS, outp); +@@ -448,16 +436,8 @@ 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; +@@ -582,81 +562,9 @@ 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(SSL_is_init_finished(ets->ssl)) { +- esp->es_server.ea_state = eapTlsRecvClient; +- break; +- } +- +- if(ets->frag) +- esp->es_server.ea_state = eapTlsRecvAck; +- else +- esp->es_server.ea_state = eapTlsRecv; +- break; +- +- case eapTlsSendAck: +- esp->es_server.ea_state = eapTlsRecv; +- break; +- +- case eapTlsRecvAck: +- if (status) { +- esp->es_server.ea_state = eapBadAuth; +- break; +- } +- +- esp->es_server.ea_state = eapTlsSend; +- break; +- +- case eapTlsSendAlert: +- esp->es_server.ea_state = eapTlsRecvAlertAck; +- break; +-#endif /* USE_EAPTLS */ +- + case eapSRP1: + #ifdef USE_SRP + ts = (struct t_server *)esp->es_server.ea_session; +@@ -773,7 +681,7 @@ eap_state *esp; + } + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_REQUEST, outp); +@@ -810,30 +718,6 @@ 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); +@@ -1020,57 +904,11 @@ 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); + } +@@ -1243,7 +1081,7 @@ int namelen; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1279,7 +1117,7 @@ int lenstr; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1310,7 +1148,7 @@ u_char *str; + int msglen; + + outp = outpacket_buf; +- ++ + MAKEHEADER(outp, PPP_EAP); + + PUTCHAR(EAP_RESPONSE, outp); +@@ -1328,81 +1166,6 @@ 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; +@@ -1557,11 +1320,6 @@ 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; +@@ -1698,90 +1456,6 @@ 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) { +@@ -2063,11 +1737,6 @@ 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); +@@ -2107,60 +1776,6 @@ 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; +@@ -2192,13 +1807,6 @@ 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) { +@@ -2410,27 +2018,13 @@ u_char *inp; + int id; + int len; + { +- if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp) +-#ifdef USE_EAPTLS +- && esp->es_client.ea_state != eapTlsRecvSuccess +-#endif /* USE_EAPTLS */ +- ) { ++ if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) { + 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); + } +@@ -2556,9 +2150,6 @@ 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); +@@ -2623,24 +2214,6 @@ 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; +@@ -2752,25 +2325,6 @@ 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, " "); +diff --git a/pppd/eap.h b/pppd/eap.h +index 3fa5391..199d184 100644 +--- a/pppd/eap.h ++++ b/pppd/eap.h +@@ -84,16 +84,6 @@ 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 */ +@@ -105,18 +95,9 @@ 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" + +-#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_client_active(esp) ((esp)->es_client.ea_state == eapListen) + #define eap_server_active(esp) \ + ((esp)->es_server.ea_state >= eapIdentify && \ + (esp)->es_server.ea_state <= eapMD5Chall) +@@ -131,17 +112,11 @@ 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 + }; + + /* +@@ -164,12 +139,7 @@ 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 */ + +diff --git a/pppd/md5.c b/pppd/md5.c +index 2ee0c80..f1291ce 100644 +--- a/pppd/md5.c ++++ b/pppd/md5.c +@@ -33,8 +33,6 @@ + *********************************************************************** + */ + +-#ifndef USE_EAPTLS +- + #include + #include "md5.h" + +@@ -307,4 +305,3 @@ UINT4 *in; + ** End of md5.c ** + ******************************** (cut) ******************************** + */ +-#endif /* USE_EAPTLS */ +diff --git a/pppd/md5.h b/pppd/md5.h +index 14d7121..71e8b00 100644 +--- a/pppd/md5.h ++++ b/pppd/md5.h +@@ -36,7 +36,6 @@ + ** documentation and/or software. ** + *********************************************************************** + */ +-#ifndef USE_EAPTLS + + #ifndef __MD5_INCLUDE__ + +@@ -64,5 +63,3 @@ void MD5_Final (unsigned char hash[], MD5_CTX *mdContext); + + #define __MD5_INCLUDE__ + #endif /* __MD5_INCLUDE__ */ +- +-#endif /* USE_EAPTLS */ +diff --git a/pppd/options.c b/pppd/options.c +index 6915b2d..8e62635 100644 +--- a/pppd/options.c ++++ b/pppd/options.c +@@ -120,10 +120,6 @@ bool dump_options; /* print out option values */ + bool dryrun; /* print out option values and exit */ + char *domain; /* domain name set by domain option */ + int child_wait = 5; /* # seconds to wait for children at exit */ +-#ifdef USE_EAPTLS +-bool only_update_crl_server = 0; /* update server crl and exit */ +-bool only_update_crl_client = 0; /* update client crl and exit */ +-#endif /* USE_EAPTLS */ + struct userenv *userenv_list; /* user environment variables */ + + #ifdef MAXOCTETS +@@ -342,12 +338,6 @@ option_t general_options[] = { + { "mo-timeout", o_int, &maxoctets_timeout, + "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 }, + #endif +-#ifdef USE_EAPTLS +- { "only-update-crl-server", o_bool, &only_update_crl_server, +- "Update server CA CRLs and exit", 1 }, +- { "only-update-crl-client", o_bool, &only_update_crl_client, +- "Update client CA CRLs and exit", 1 }, +-#endif /* USE_EAPTLS */ + + { NULL } + }; +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index 6275df6..24e010c 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -22,13 +22,6 @@ + #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" +diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux +index 760cad4..b474a19 100644 +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -4,9 +4,6 @@ CFLAGS = $(COPTS) -I.. -I../../include -fPIC + LDFLAGS = -shared + INSTALL = install + +-# EAP-TLS +-CFLAGS += -DUSE_EAPTLS=1 +- + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +diff --git a/pppd/plugins/passprompt.c b/pppd/plugins/passprompt.c +index 6ba73ca..babb6dc 100644 +--- a/pppd/plugins/passprompt.c ++++ b/pppd/plugins/passprompt.c +@@ -107,7 +107,4 @@ void plugin_init(void) + { + add_options(options); + pap_passwd_hook = promptpass; +-#ifdef USE_EAPTLS +- eaptls_passwd_hook = promptpass; +-#endif + } +diff --git a/pppd/plugins/passwordfd.c b/pppd/plugins/passwordfd.c +index c3f9793..d718f3b 100644 +--- a/pppd/plugins/passwordfd.c ++++ b/pppd/plugins/passwordfd.c +@@ -79,8 +79,4 @@ void plugin_init (void) + + chap_check_hook = pwfd_check; + chap_passwd_hook = pwfd_passwd; +- +-#ifdef USE_EAPTLS +- eaptls_passwd_hook = pwfd_passwd; +-#endif + } +diff --git a/pppd/pppd.h b/pppd/pppd.h +index aaddba1..5f72f72 100644 +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -324,10 +324,6 @@ extern bool dump_options; /* print out option values */ + extern bool dryrun; /* check everything, print options, exit */ + extern int child_wait; /* # seconds to wait for children at end */ + +-#ifdef USE_EAPTLS +-extern char *crl_dir; +-#endif /* USE_EAPTLS */ +- + #ifdef MAXOCTETS + extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ + extern int maxoctets_dir; /* Direction : +@@ -742,10 +738,6 @@ 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)); +-- +1.8.3.1 + diff --git a/0027-pppd-EAP-TLS-patch-v0.997.patch b/0027-pppd-EAP-TLS-patch-v0.997.patch new file mode 100644 index 0000000..79ef893 --- /dev/null +++ b/0027-pppd-EAP-TLS-patch-v0.997.patch @@ -0,0 +1,3175 @@ +From 7887b3d84468e1ebfbe5adc373f0816eda2b995a Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 20 Jun 2014 10:31:43 +0200 +Subject: [PATCH 27/27] pppd: EAP-TLS patch v0.997 + +See: 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(-) + create mode 100644 README.eap-tls + create mode 100644 etc.ppp/eaptls-client + create mode 100644 etc.ppp/eaptls-server + create mode 100644 etc.ppp/openssl.cnf + create mode 100644 pppd/eap-tls.c + create mode 100644 pppd/eap-tls.h + +diff --git a/README.eap-tls b/README.eap-tls +new file mode 100644 +index 0000000..037be0a +--- /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. ++ +diff --git a/etc.ppp/eaptls-client b/etc.ppp/eaptls-client +new file mode 100644 +index 0000000..7782f0e +--- /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 +diff --git a/etc.ppp/eaptls-server b/etc.ppp/eaptls-server +new file mode 100644 +index 0000000..fa53cbd +--- /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 +diff --git a/etc.ppp/openssl.cnf b/etc.ppp/openssl.cnf +new file mode 100644 +index 0000000..dd32f30 +--- /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 ++ +diff --git a/linux/Makefile.top b/linux/Makefile.top +index f42efd5..9a8945a 100644 +--- a/linux/Makefile.top ++++ b/linux/Makefile.top +@@ -28,7 +28,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 +@@ -39,6 +39,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 $@ +diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux +index 943cf83..534ccc2 100644 +--- a/pppd/Makefile.linux ++++ b/pppd/Makefile.linux +@@ -79,6 +79,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 +@@ -118,6 +121,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) +diff --git a/pppd/auth.c b/pppd/auth.c +index 9e957fa..656ffe9 100644 +--- 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)) = NULL; + /* Hook for a plugin to get the CHAP password for authenticating us */ + int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; + ++#ifdef USE_EAPTLS ++/* Hook for a plugin to get the EAP-TLS password for authenticating us */ ++int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL; ++#endif ++ + /* Hook for a plugin to say whether it is OK if the peer + refuses to authenticate. */ + int (*null_auth_hook) __P((struct wordlist **paddrs, +@@ -238,6 +246,14 @@ bool explicit_remote = 0; /* User specified explicit remote name */ + bool explicit_user = 0; /* Set if "user" option supplied */ + bool explicit_passwd = 0; /* Set if "password" option supplied */ + char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ ++#ifdef USE_EAPTLS ++char *cacert_file = NULL; /* CA certificate file (pem format) */ ++char *cert_file = NULL; /* client certificate file (pem format) */ ++char *privkey_file = NULL; /* client private key file (pem format) */ ++char *crl_dir = NULL; /* directory containing CRL files */ ++char *crl_file = NULL; /* Certificate Revocation List (CRL) file (pem format) */ ++bool need_peer_eap = 0; /* Require peer to authenticate us */ ++#endif + + static char *uafname; /* name of most recent +ua file */ + +@@ -254,6 +270,19 @@ static int have_pap_secret __P((int *)); + static int have_chap_secret __P((char *, char *, int, int *)); + static int have_srp_secret __P((char *client, char *server, int need_ip, + int *lacks_ipp)); ++ ++#ifdef USE_EAPTLS ++static int have_eaptls_secret_server ++__P((char *client, char *server, int need_ip, int *lacks_ipp)); ++static int have_eaptls_secret_client __P((char *client, char *server)); ++static int scan_authfile_eaptls __P((FILE * f, char *client, char *server, ++ char *cli_cert, char *serv_cert, ++ char *ca_cert, char *pk, ++ struct wordlist ** addrs, ++ struct wordlist ** opts, ++ char *filename, int flags)); ++#endif ++ + static int ip_addr_check __P((u_int32_t, struct permitted_ip *)); + static int scan_authfile __P((FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, +@@ -401,6 +430,15 @@ option_t auth_options[] = { + "Set telephone number(s) which are allowed to connect", + OPT_PRIV | OPT_A2LIST }, + ++#ifdef USE_EAPTLS ++ { "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" }, ++ { "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" }, ++ { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" }, ++ { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" }, ++ { "crl", o_string, &crl_file, "Use specific CRL file" }, ++ { "need-peer-eap", o_bool, &need_peer_eap, ++ "Require the peer to authenticate us", 1 }, ++#endif /* USE_EAPTLS */ + { NULL } + }; + +@@ -730,6 +768,9 @@ link_established(unit) + lcp_options *wo = &lcp_wantoptions[unit]; + lcp_options *go = &lcp_gotoptions[unit]; + lcp_options *ho = &lcp_hisoptions[unit]; ++#ifdef USE_EAPTLS ++ lcp_options *ao = &lcp_allowoptions[unit]; ++#endif + int i; + struct protent *protp; + +@@ -764,6 +805,22 @@ link_established(unit) + } + } + ++#ifdef USE_EAPTLS ++ if (need_peer_eap && !ao->neg_eap) { ++ warn("eap required to authenticate us but no suitable secrets"); ++ lcp_close(unit, "couldn't negotiate eap"); ++ status = EXIT_AUTH_TOPEER_FAILED; ++ return; ++ } ++ ++ if (need_peer_eap && !ho->neg_eap) { ++ warn("peer doesn't want to authenticate us with eap"); ++ lcp_close(unit, "couldn't negotiate eap"); ++ status = EXIT_PEER_AUTH_FAILED; ++ return; ++ } ++#endif ++ + new_phase(PHASE_AUTHENTICATE); + auth = 0; + if (go->neg_eap) { +@@ -1277,6 +1334,15 @@ auth_check_options() + our_name, 1, &lacks_ip); + } + ++#ifdef USE_EAPTLS ++ if (!can_auth && wo->neg_eap) { ++ can_auth = ++ have_eaptls_secret_server((explicit_remote ? remote_name : ++ NULL), our_name, 1, &lacks_ip); ++ ++ } ++#endif ++ + if (auth_required && !can_auth && noauth_addrs == NULL) { + if (default_auth) { + option_error( +@@ -1331,7 +1397,11 @@ auth_reset(unit) + passwd[0] != 0 || + (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, + (explicit_remote? remote_name: NULL), 0, NULL))) || +- have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); ++ have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL) ++#ifdef USE_EAPTLS ++ || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL)) ++#endif ++ ); + + hadchap = -1; + if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) +@@ -1346,8 +1416,14 @@ auth_reset(unit) + !have_chap_secret((explicit_remote? remote_name: NULL), our_name, + 1, NULL))) && + !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, +- NULL)) ++ NULL) ++#ifdef USE_EAPTLS ++ && !have_eaptls_secret_server((explicit_remote? remote_name: NULL), ++ our_name, 1, NULL) ++#endif ++ ) + go->neg_eap = 0; ++ + } + + +@@ -1707,6 +1783,7 @@ have_srp_secret(client, server, need_ip, lacks_ipp) + } + + ++ + /* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. +@@ -2359,3 +2436,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 ++ +diff --git a/pppd/ccp.c b/pppd/ccp.c +index 5814f35..7dead23 100644 +--- 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; + } +diff --git a/pppd/chap-md5.c b/pppd/chap-md5.c +index 77dd4ec..269b52c 100644 +--- 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 +diff --git a/pppd/eap-tls.c b/pppd/eap-tls.c +new file mode 100644 +index 0000000..edcb0cb +--- /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); ++} ++ +diff --git a/pppd/eap-tls.h b/pppd/eap-tls.h +new file mode 100644 +index 0000000..2d45a0b +--- /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 +diff --git a/pppd/eap.c b/pppd/eap.c +index faced53..bfbce95 100644 +--- 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); + } ++ +diff --git a/pppd/eap.h b/pppd/eap.h +index 199d184..3fa5391 100644 +--- 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 */ + +diff --git a/pppd/md5.c b/pppd/md5.c +index f1291ce..6f8f720 100644 +--- 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 */ ++ +diff --git a/pppd/md5.h b/pppd/md5.h +index 71e8b00..14d7121 100644 +--- 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[], MD5_CTX *mdContext); + + #define __MD5_INCLUDE__ + #endif /* __MD5_INCLUDE__ */ ++ ++#endif /* USE_EAPTLS */ +diff --git a/pppd/pathnames.h b/pppd/pathnames.h +index 24e010c..6275df6 100644 +--- a/pppd/pathnames.h ++++ b/pppd/pathnames.h +@@ -22,6 +22,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" +diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux +index b474a19..760cad4 100644 +--- a/pppd/plugins/Makefile.linux ++++ b/pppd/plugins/Makefile.linux +@@ -4,6 +4,9 @@ CFLAGS = $(COPTS) -I.. -I../../include -fPIC + LDFLAGS = -shared + INSTALL = install + ++# EAP-TLS ++CFLAGS += -DUSE_EAPTLS=1 ++ + DESTDIR = $(INSTROOT)@DESTDIR@ + BINDIR = $(DESTDIR)/sbin + MANDIR = $(DESTDIR)/share/man/man8 +diff --git a/pppd/plugins/passprompt.c b/pppd/plugins/passprompt.c +index babb6dc..6ba73ca 100644 +--- 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 + } +diff --git a/pppd/plugins/passwordfd.c b/pppd/plugins/passwordfd.c +index d718f3b..c3f9793 100644 +--- 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 + } +diff --git a/pppd/pppd.8 b/pppd/pppd.8 +index 2dd6e1a..75dd6f3 100644 +--- a/pppd/pppd.8 ++++ b/pppd/pppd.8 +@@ -248,6 +248,12 @@ Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables + compression in the corresponding direction. Use \fInobsdcomp\fR or + \fIbsdcomp 0\fR to disable BSD-Compress compression entirely. + .TP ++.B ca \fIca-file ++(EAP-TLS) Use the file \fIca-file\fR as the X.509 Certificate Authority ++(CA) file (in PEM format), needed for setting up an EAP-TLS connection. ++This option is used on the client-side in conjunction with the \fBcert\fR ++and \fBkey\fR options. ++.TP + .B cdtrcts + Use a non-standard hardware flow control (i.e. DTR/CTS) to control + the flow of data on the serial port. If neither the \fIcrtscts\fR, +@@ -259,6 +265,12 @@ RTS output. Such serial ports use this mode to implement true + bi-directional flow control. The sacrifice is that this flow + control mode does not permit using DTR as a modem control line. + .TP ++.B cert \fIcertfile ++(EAP-TLS) Use the file \fIcertfile\fR as the X.509 certificate (in PEM ++format), needed for setting up an EAP-TLS connection. This option is ++used on the client-side in conjunction with the \fBca\fR and ++\fBkey\fR options. ++.TP + .B chap\-interval \fIn + If this option is given, pppd will rechallenge the peer every \fIn\fR + seconds. +@@ -287,6 +299,18 @@ negotiation by sending its first LCP packet. The default value is + 1000 (1 second). This wait period only applies if the \fBconnect\fR + or \fBpty\fR option is used. + .TP ++.B crl \fIfilename ++(EAP-TLS) Use the file \fIfilename\fR as the Certificate Revocation List ++to check for the validity of the peer's certificate. This option is not ++mandatory for setting up an EAP-TLS connection. Also see the \fBcrl-dir\fR ++option. ++.TP ++.B crl-dir \fIdirectory ++(EAP-TLS) Use the directory \fIdirectory\fR to scan for CRL files in ++has format ($hash.r0) to check for the validity of the peer's certificate. ++This option is not mandatory for setting up an EAP-TLS connection. ++Also see the \fBcrl\fR option. ++.TP + .B debug + Enables connection debugging facilities. + If this option is given, pppd will log the contents of all +@@ -551,6 +575,12 @@ transmitted packets be printed. On most systems, messages printed by + the kernel are logged by syslog(1) to a file as directed in the + /etc/syslog.conf configuration file. + .TP ++.B key \fIkeyfile ++(EAP-TLS) Use the file \fIkeyfile\fR as the private key file (in PEM ++format), needed for setting up an EAP-TLS connection. This option is ++used on the client-side in conjunction with the \fBca\fR and ++\fBcert\fR options. ++.TP + .B ktune + Enables pppd to alter kernel settings as appropriate. Under Linux, + pppd will enable IP forwarding (i.e. set /proc/sys/net/ipv4/ip_forward +@@ -709,6 +739,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. +diff --git a/pppd/pppd.h b/pppd/pppd.h +index 5f72f72..523f226 100644 +--- a/pppd/pppd.h ++++ b/pppd/pppd.h +@@ -324,6 +324,11 @@ extern bool dump_options; /* print out option values */ + extern bool dryrun; /* check everything, print options, exit */ + extern int child_wait; /* # seconds to wait for children at end */ + ++#ifdef USE_EAPTLS ++extern char *crl_dir; ++extern char *crl_file; ++#endif /* USE_EAPTLS */ ++ + #ifdef MAXOCTETS + extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ + extern int maxoctets_dir; /* Direction : +@@ -738,6 +743,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)); +-- +1.8.3.1 + diff --git a/ppp.spec b/ppp.spec index afa968c..59c9f1f 100644 --- a/ppp.spec +++ b/ppp.spec @@ -22,6 +22,33 @@ Source11: ifdown-ppp Source12: ppp-watch.tar.xz # Fedora-specific +Patch0001: 0001-build-sys-use-gcc-as-our-compiler-of-choice.patch +Patch0002: 0002-build-sys-enable-PAM-support.patch +Patch0003: 0003-build-sys-utilize-compiler-flags-handed-to-us-by-rpm.patch +Patch0004: 0004-doc-add-configuration-samples.patch +Patch0005: 0005-build-sys-don-t-hardcode-LIBDIR-but-set-it-according.patch +Patch0006: 0006-scritps-use-change_resolv_conf-function.patch +Patch0007: 0007-build-sys-don-t-strip-binaries-during-installation.patch +Patch0008: 0008-build-sys-use-prefix-usr-instead-of-usr-local.patch +Patch0009: 0009-pppd-introduce-ipv6-accept-remote.patch +Patch0010: 0010-build-sys-enable-CBCP.patch +Patch0011: 0011-build-sys-don-t-put-connect-errors-log-to-etc-ppp.patch +Patch0012: 0012-pppd-we-don-t-want-to-accidentally-leak-fds.patch +Patch0013: 0013-everywhere-O_CLOEXEC-harder.patch +Patch0014: 0014-everywhere-use-SOCK_CLOEXEC-when-creating-socket.patch +Patch0015: 0015-pppd-move-pppd-database-to-var-run-ppp.patch +Patch0016: 0016-rp-pppoe-add-manpage-for-pppoe-discovery.patch +Patch0017: 0017-pppd-rebase-EAP-TLS-patch-v0.994.patch +Patch0018: 0018-scritps-fix-ip-up.local-sample.patch +Patch0019: 0019-sys-linux-rework-get_first_ethernet.patch +Patch0020: 0020-pppd-put-lock-files-in-var-lock-ppp.patch +Patch0021: 0021-build-sys-compile-pppol2tp-plugin-with-RPM_OPT_FLAGS.patch +Patch0022: 0022-build-sys-compile-pppol2tp-with-multilink-support.patch +Patch0023: 0023-build-sys-install-rp-pppoe-plugin-files-with-standar.patch +Patch0024: 0024-build-sys-install-pppoatm-plugin-files-with-standard.patch +Patch0025: 0025-pppd-install-pppd-binary-using-standard-perms-755.patch +Patch0026: 0026-Revert-pppd-rebase-EAP-TLS-patch-v0.994.patch +Patch0027: 0027-pppd-EAP-TLS-patch-v0.997.patch BuildRequires: pam-devel, libpcap-devel, openssl-devel, systemd, systemd-devel, glib2-devel Requires: glibc >= 2.0.6, /etc/pam.d/system-auth, libpcap >= 14:0.8.3-6, systemd, initscripts >= 9.54