]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
ppp: Fix for IPv6.
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 4 Jun 2011 13:26:10 +0000 (15:26 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 4 Jun 2011 13:26:10 +0000 (15:26 +0200)
pppd was not compiled properly for IPv6 and I needed to fix that.
Anyway, there were lots of other fixes applied.

17 files changed:
pkgs/ppp/patches/ppp-2.3.6-sample.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.1-varargs.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.2-change_resolv_conf.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.2-pppoatm-make.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.3-fix.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.3-fix64.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.3-make.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.4-cbcp.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.4-fd_leak.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.4-lib64.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-eaptls-mppe-0.99.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-eth.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-lock.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-man.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-ppp_resolv.patch [new file with mode: 0644]
pkgs/ppp/patches/ppp-2.4.5-var_run_ppp.patch
pkgs/ppp/ppp.nm

diff --git a/pkgs/ppp/patches/ppp-2.3.6-sample.patch b/pkgs/ppp/patches/ppp-2.3.6-sample.patch
new file mode 100644 (file)
index 0000000..92eee6c
--- /dev/null
@@ -0,0 +1,295 @@
+--- ppp-2.3.3/sample/auth-down.sample  Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/auth-down Tue Jan  6 17:53:27 1998
+@@ -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
++# <interface-name> <peer-name> <user-name> <tty-device> <speed>
++#
++
++#
++# 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
+--- ppp-2.3.3/sample/auth-up.sample    Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/auth-up   Tue Jan  6 17:53:27 1998
+@@ -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
++# <interface-name> <peer-name> <user-name> <tty-device> <speed>
++#
++
++#
++# 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
+--- ppp-2.3.3/sample/ip-down.sample    Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/ip-down   Tue Jan  6 17:53:27 1998
+@@ -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
+--- ppp-2.3.3/sample/ip-up.sample      Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/ip-up     Tue Jan  6 17:53:27 1998
+@@ -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
+--- ppp-2.3.3/sample/options.sample    Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/options   Tue Jan  6 17:53:27 1998
+@@ -0,0 +1,153 @@
++# /etc/ppp/options
++
++# The name of this server. Often, the FQDN is used here.
++#name <host>
++
++# 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 <n> for negotiation.  pppd
++# will ask the peer to send packets of no more than <n> 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 <n>. 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 <n>
++
++# Set the interface netmask to <n>, 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 <n>.
++#remotename <n>
++
++# 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
++
++# ---<End of File>---
+--- ppp-2.3.3/sample/options.ttyXX.sample      Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/options.ttyXX     Tue Jan  6 17:53:27 1998
+@@ -0,0 +1,14 @@
++# If you need to set up multiple serial lines then copy this file to
++# options.<ttyname> 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
+--- ppp-2.3.3/sample/pap-secrets.sample        Tue Jan  6 17:53:27 1998
++++ ppp-2.3.3/sample/pap-secrets       Tue Jan  6 17:53:27 1998
+@@ -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        <password>      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        "*"     -
diff --git a/pkgs/ppp/patches/ppp-2.4.1-varargs.patch b/pkgs/ppp/patches/ppp-2.4.1-varargs.patch
new file mode 100644 (file)
index 0000000..0f757ec
--- /dev/null
@@ -0,0 +1,12 @@
+diff -up ppp-2.4.4/pppd/utils.c.varargs ppp-2.4.4/pppd/utils.c
+--- ppp-2.4.4/pppd/utils.c.varargs     2004-11-04 05:02:26.000000000 -0500
++++ ppp-2.4.4/pppd/utils.c     2008-08-28 17:34:29.000000000 -0400
+@@ -290,7 +290,7 @@ vslprintf(buf, buflen, fmt, args)
+ #if 0 /* not used, and breaks on S/390, apparently */
+       case 'r':
+           f = va_arg(args, char *);
+-#ifndef __powerpc__
++#if !defined (__powerpc__) && !defined(__s390__) && !defined(__s390x__) && !defined(__x86_64__)
+           n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
+ #else
+           /* On the powerpc, a va_list is an array of 1 structure */
diff --git a/pkgs/ppp/patches/ppp-2.4.2-change_resolv_conf.patch b/pkgs/ppp/patches/ppp-2.4.2-change_resolv_conf.patch
new file mode 100644 (file)
index 0000000..99c9beb
--- /dev/null
@@ -0,0 +1,61 @@
+diff -urNp --exclude-from=/mdomsch2/excludes --minimal ppp-2.4.3.orig/pppd/pppd.8 ppp-2.4.3/pppd/pppd.8
+--- ppp-2.4.3.orig/pppd/pppd.8 2004-11-13 06:22:49.000000000 -0600
++++ ppp-2.4.3/pppd/pppd.8      2005-08-03 22:10:34.000000000 -0500
+@@ -1035,7 +1035,7 @@ Ask the peer for up to 2 DNS server addr
+ 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
+--- ppp-2.4.2/scripts/ip-down.local.add.change_resolv_conf     1999-02-27 05:32:42.000000000 +0100
++++ ppp-2.4.2/scripts/ip-down.local.add        2004-09-14 14:36:20.058008752 +0200
+@@ -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
+--- ppp-2.4.2/scripts/ip-up.local.add.change_resolv_conf       1999-11-15 04:28:10.000000000 +0100
++++ ppp-2.4.2/scripts/ip-up.local.add  2004-09-14 14:37:39.129061828 +0200
+@@ -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
diff --git a/pkgs/ppp/patches/ppp-2.4.2-pppoatm-make.patch b/pkgs/ppp/patches/ppp-2.4.2-pppoatm-make.patch
new file mode 100644 (file)
index 0000000..897e4fd
--- /dev/null
@@ -0,0 +1,10 @@
+diff -up ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux.atm-make ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux
+--- ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux.atm-make     2008-08-28 17:36:10.000000000 -0400
++++ ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux      2008-08-28 17:36:56.000000000 -0400
+@@ -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/pkgs/ppp/patches/ppp-2.4.3-fix.patch b/pkgs/ppp/patches/ppp-2.4.3-fix.patch
new file mode 100644 (file)
index 0000000..3df6db1
--- /dev/null
@@ -0,0 +1,115 @@
+--- ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c.fix    2004-11-04 11:07:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/discovery.c        2004-11-22 16:00:24.522462124 +0100
+@@ -13,6 +13,8 @@
+ #include "pppoe.h"
+ #include "pppd/pppd.h"
++void warn __P((char *, ...));   /* log a warning message */
++
+ #include <string.h>
+ #include <stdlib.h>
+ #include <errno.h>
+--- ppp-2.4.3/pppd/ipv6cp.c.fix        2004-11-13 03:28:15.000000000 +0100
++++ ppp-2.4.3/pppd/ipv6cp.c    2004-11-22 16:00:27.049114044 +0100
+@@ -151,6 +151,7 @@
+  */
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <netdb.h>
+@@ -1064,7 +1065,9 @@
+     return (rc);                      /* Return final code */
+ }
+-
++#if defined(SOL2) || defined(__linux__)
++int ether_to_eui64(eui64_t *p_eui64);
++#endif
+ /*
+  * ipv6_check_options - check that any IP-related options are OK,
+  * and assign appropriate defaults.
+--- ppp-2.4.3/pppdump/deflate.c.fix    2004-02-02 04:36:46.000000000 +0100
++++ ppp-2.4.3/pppdump/deflate.c        2004-11-22 16:02:18.071820020 +0100
+@@ -39,6 +39,7 @@
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <stddef.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "ppp_defs.h"
+@@ -237,8 +238,8 @@
+ {
+     struct deflate_state *state = (struct deflate_state *) arg;
+     u_char *rptr, *wptr;
+-    int rlen, olen, ospace;
+-    int seq, i, flush, r, decode_proto;
++    int rlen, olen;
++    int seq, r;
+     rptr = mi;
+     if (*rptr == 0)
+--- ppp-2.4.3/pppdump/bsd-comp.c.fix   2004-02-02 04:36:46.000000000 +0100
++++ ppp-2.4.3/pppdump/bsd-comp.c       2004-11-22 16:00:27.052113631 +0100
+@@ -383,7 +383,7 @@
+       || options[0] != CI_BSD_COMPRESS || options[1] != CILEN_BSD_COMPRESS
+       || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
+       || BSD_NBITS(options[2]) != db->maxbits
+-      || decomp && db->lens == NULL)
++      || (decomp && db->lens == NULL))
+       return 0;
+     if (decomp) {
+@@ -556,11 +556,11 @@
+     u_int n_bits = db->n_bits;
+     u_int tgtbitno = 32-n_bits;       /* bitno when we have a code */
+     struct bsd_dict *dictp;
+-    int explen, i, seq, len;
++    int explen, seq, len;
+     u_int incode, oldcode, finchar;
+     u_char *p, *rptr, *wptr;
+     int ilen;
+-    int dlen, space, codelen, extra;
++    int dlen=0, codelen, extra;
+     rptr = cmsg;
+     if (*rptr == 0)
+@@ -616,7 +616,7 @@
+       }
+       if (incode > max_ent + 2 || incode > db->maxmaxcode
+-          || incode > max_ent && oldcode == CLEAR) {
++          || (incode > max_ent && oldcode == CLEAR)) {
+           if (db->debug) {
+               printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+                      db->unit, incode, oldcode);
+--- ppp-2.4.3/pppdump/pppdump.c.fix    2004-02-02 04:36:46.000000000 +0100
++++ ppp-2.4.3/pppdump/pppdump.c        2004-11-22 16:00:27.054113356 +0100
+@@ -34,6 +34,7 @@
+  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+ #include <time.h>
+@@ -191,7 +192,7 @@
+           show_time(f, c);
+           break;
+       default:
+-          printf("?%.2x\n");
++          printf("?%.2x\n", c);
+       }
+     }
+ }
+@@ -421,7 +422,7 @@
+           show_time(f, c);
+           break;
+       default:
+-          printf("?%.2x\n");
++          printf("?%.2x\n", c);
+       }
+     }
+ }
diff --git a/pkgs/ppp/patches/ppp-2.4.3-fix64.patch b/pkgs/ppp/patches/ppp-2.4.3-fix64.patch
new file mode 100644 (file)
index 0000000..8a2c794
--- /dev/null
@@ -0,0 +1,10 @@
+--- ppp-2.4.3/pppd/sha1.c.fix64        2004-10-25 01:28:02.000000000 +0200
++++ ppp-2.4.3/pppd/sha1.c      2004-11-22 16:44:16.850768926 +0100
+@@ -18,6 +18,7 @@
+ #include <string.h>
+ #include <netinet/in.h>       /* htonl() */
++#include <sys/types.h>        /* u_int32_t */
+ #include <net/ppp_defs.h>
+ #include "sha1.h"
diff --git a/pkgs/ppp/patches/ppp-2.4.3-make.patch b/pkgs/ppp/patches/ppp-2.4.3-make.patch
new file mode 100644 (file)
index 0000000..4716ac1
--- /dev/null
@@ -0,0 +1,91 @@
+--- ppp-2.4.3/pppd/Makefile.linux.make 2004-11-13 13:02:22.000000000 +0100
++++ ppp-2.4.3/pppd/Makefile.linux      2004-11-22 15:46:49.871309478 +0100
+@@ -30,10 +30,10 @@
+ include .depend
+ endif
+-# CC = gcc
++CC = gcc
+ #
+-COPTS = -O2 -pipe -Wall -g
+-LIBS =
++COPTS = -Wall $(RPM_OPT_FLAGS)
++LIBS = -lutil
+ # Uncomment the next 2 lines to include support for Microsoft's
+ # MS-CHAP authentication protocol.  Also, edit plugins/radius/Makefile.linux.
+@@ -61,8 +61,8 @@
+ USE_TDB=y
+ HAS_SHADOW=y
+-#USE_PAM=y
+-#HAVE_INET6=y
++USE_PAM=y
++HAVE_INET6=y
+ # Enable plugins
+ PLUGIN=y
+--- ppp-2.4.3/pppd/plugins/Makefile.linux.make 2004-11-14 08:57:35.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/Makefile.linux      2004-11-22 15:46:49.873309203 +0100
+@@ -1,5 +1,5 @@
+ #CC   = gcc
+-COPTS = -O2 -g
++COPTS = $(RPM_OPT_FLAGS)
+ CFLAGS        = $(COPTS) -I.. -I../../include -fPIC
+ LDFLAGS       = -shared
+ INSTALL       = install
+--- ppp-2.4.3/pppd/plugins/radius/Makefile.linux.make  2004-11-14 08:02:31.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/radius/Makefile.linux       2004-11-22 15:49:08.858233692 +0100
+@@ -12,7 +12,7 @@
+ 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.
+--- ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux.make        2004-11-14 08:58:37.000000000 +0100
++++ ppp-2.4.3/pppd/plugins/rp-pppoe/Makefile.linux     2004-11-22 15:46:49.875308929 +0100
+@@ -25,7 +25,7 @@
+ # 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
+--- ppp-2.4.3/pppdump/Makefile.linux.make      2004-10-31 02:36:52.000000000 +0200
++++ ppp-2.4.3/pppdump/Makefile.linux   2004-11-22 15:48:16.795379237 +0100
+@@ -2,7 +2,7 @@
+ 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
+--- ppp-2.4.3/pppstats/Makefile.linux.make     2004-10-31 23:09:03.000000000 +0100
++++ ppp-2.4.3/pppstats/Makefile.linux  2004-11-22 15:46:49.872309341 +0100
+@@ -10,7 +10,7 @@
+ PPPSTATOBJS = pppstats.o
+ #CC = gcc
+-COPTS = -O
++COPTS = $(RPM_OPT_FLAGS)
+ COMPILE_FLAGS = -I../include
+ LIBS =
+--- ppp-2.4.3/chat/Makefile.linux.make 2004-11-03 12:51:47.000000000 +0100
++++ ppp-2.4.3/chat/Makefile.linux      2004-11-22 15:47:59.445760450 +0100
+@@ -10,7 +10,7 @@
+ 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/pkgs/ppp/patches/ppp-2.4.4-cbcp.patch b/pkgs/ppp/patches/ppp-2.4.4-cbcp.patch
new file mode 100644 (file)
index 0000000..da8c6b2
--- /dev/null
@@ -0,0 +1,11 @@
+--- ppp-2.4.4/pppd/Makefile.linux.cbcp 2006-07-19 16:11:41.000000000 +0200
++++ ppp-2.4.4/pppd/Makefile.linux      2006-07-19 16:11:42.000000000 +0200
+@@ -69,7 +69,7 @@
+ PLUGIN=y
+ # Enable Microsoft proprietary Callback Control Protocol
+-#CBCP=y
++CBCP=y
+ # Enable EAP SRP-SHA1 authentication (requires libsrp)
+ #USE_SRP=y
diff --git a/pkgs/ppp/patches/ppp-2.4.4-fd_leak.patch b/pkgs/ppp/patches/ppp-2.4.4-fd_leak.patch
new file mode 100644 (file)
index 0000000..7c3c060
--- /dev/null
@@ -0,0 +1,615 @@
+diff -up ppp-2.4.4/pppd/auth.c.fd_leak ppp-2.4.4/pppd/auth.c
+--- ppp-2.4.4/pppd/auth.c.fd_leak      2006-06-18 13:26:00.000000000 +0200
++++ ppp-2.4.4/pppd/auth.c      2009-10-08 21:22:59.789547513 +0200
+@@ -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_r(fname);
+     if (seteuid(euid) == -1)
+       fatal("unable to regain privileges: %m");
+     if (ufile == NULL) {
+@@ -1414,7 +1414,7 @@ check_passwd(unit, auser, userlen, apass
+     filename = _PATH_UPAPFILE;
+     addrs = opts = NULL;
+     ret = UPAP_AUTHNAK;
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     if (f == NULL) {
+       error("Can't open PAP password file %s: %m", filename);
+@@ -1511,7 +1511,7 @@ null_login(unit)
+     if (ret <= 0) {
+       filename = _PATH_UPAPFILE;
+       addrs = NULL;
+-      f = fopen(filename, "r");
++      f = fopen_r(filename);
+       if (f == NULL)
+           return 0;
+       check_access(f, filename);
+@@ -1558,7 +1558,7 @@ get_pap_passwd(passwd)
+     }
+     filename = _PATH_UPAPFILE;
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     if (f == NULL)
+       return 0;
+     check_access(f, filename);
+@@ -1596,7 +1596,7 @@ have_pap_secret(lacks_ipp)
+     }
+     filename = _PATH_UPAPFILE;
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     if (f == NULL)
+       return 0;
+@@ -1641,7 +1641,7 @@ have_chap_secret(client, server, need_ip
+     }
+     filename = _PATH_CHAPFILE;
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     if (f == NULL)
+       return 0;
+@@ -1683,7 +1683,7 @@ have_srp_secret(client, server, need_ip,
+     struct wordlist *addrs;
+     filename = _PATH_SRPFILE;
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     if (f == NULL)
+       return 0;
+@@ -1739,7 +1739,7 @@ get_secret(unit, client, server, secret,
+       addrs = NULL;
+       secbuf[0] = 0;
+-      f = fopen(filename, "r");
++      f = fopen_r(filename);
+       if (f == NULL) {
+           error("Can't open chap secret file %s: %m", filename);
+           return 0;
+@@ -1796,7 +1796,7 @@ get_srp_secret(unit, client, server, sec
+       filename = _PATH_SRPFILE;
+       addrs = NULL;
+-      fp = fopen(filename, "r");
++      fp = fopen_r(filename);
+       if (fp == NULL) {
+           error("Can't open srp secret file %s: %m", filename);
+           return 0;
+@@ -2202,7 +2202,7 @@ scan_authfile(f, client, server, secret,
+            */
+           if (word[0] == '@' && word[1] == '/') {
+               strlcpy(atfile, word+1, sizeof(atfile));
+-              if ((sf = fopen(atfile, "r")) == NULL) {
++              if ((sf = fopen_r(atfile)) == NULL) {
+                   warn("can't open indirect secret file %s", atfile);
+                   continue;
+               }
+diff -up ppp-2.4.4/pppd/eap.c.fd_leak ppp-2.4.4/pppd/eap.c
+--- ppp-2.4.4/pppd/eap.c.fd_leak       2004-11-09 23:39:25.000000000 +0100
++++ ppp-2.4.4/pppd/eap.c       2009-10-08 21:22:59.791544181 +0200
+@@ -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_fd(path, modebits, S_IRUSR | S_IWUSR);
+       err = errno;
+       free(path);
+       errno = err;
+diff -up ppp-2.4.4/pppd/main.c.fd_leak ppp-2.4.4/pppd/main.c
+--- ppp-2.4.4/pppd/main.c.fd_leak      2009-10-08 21:22:59.769544859 +0200
++++ ppp-2.4.4/pppd/main.c      2009-10-08 21:30:32.356546561 +0200
+@@ -201,6 +201,8 @@ int ngroups;                       /* How many groups valid 
+ static struct timeval start_time;     /* Time when link was started. */
++static int cloexec_works; /* controlls setting FD_CLOEXEC flag up */
++
+ static struct pppd_stats old_link_stats;
+ struct pppd_stats link_stats;
+ unsigned link_connect_time;
+@@ -245,6 +247,7 @@ static void holdoff_end __P((void *));
+ static void forget_child __P((int pid, int status));
+ static int reap_kids __P((void));
+ static void childwait_end __P((void *));
++static void check_cloexec __P((int));
+ #ifdef USE_TDB
+ static void update_db_entry __P((void));
+@@ -419,7 +422,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_fd(_PATH_DEVNULL, O_RDWR);
+     if (fd_devnull < 0)
+       fatal("Couldn't open %s: %m", _PATH_DEVNULL);
+     while (fd_devnull <= 2) {
+@@ -865,6 +866,104 @@ holdoff_end(arg)
+     new_phase(PHASE_DORMANT);
+ }
++
++/*
++ * check_cloexec - checks for FD_CLOEXEC flag and adds it if necessary
++ */
++static void
++check_cloexec(int fd)
++{
++    if (cloexec_works == 0) {
++        int fl = fcntl(fd, F_GETFD);
++        cloexec_works = (fl & FD_CLOEXEC) ? 1 : -1;
++    }
++    if (cloexec_works > 0)
++        return;
++    fcntl(fd, F_SETFD, FD_CLOEXEC);
++    return;
++}
++
++/*
++ * socket_fd - create an endpoint for communication. uses FD_CLOEXEC if supported
++ */
++int
++socket_fd(int domain, int type, int protocol)
++{
++      int fd;
++
++#ifdef SOCK_CLOEXEC
++      if (cloexec_works != -1)
++              type |= SOCK_CLOEXEC;
++#endif
++      fd = socket(domain, type, protocol);
++      if (fd == -1)
++              return -1;
++      check_cloexec(fd);
++      return fd;
++}
++
++/*
++ * open_fd - open file with FD_CLOEXEC flag
++ */
++int
++open_fd(const char *path, int flags)
++{
++    int fd;
++
++#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
++    if (cloexec_works != -1)
++        flags |= O_CLOEXEC;
++#endif
++    fd = open(path, flags);
++    if (fd == -1)
++        return -1;
++    check_cloexec(fd);
++    return fd;
++}
++
++/*
++ * open_fd_mmode - open file with FD_CLOEXEC flag
++ */
++int
++open_fd_mode(const char *path, int flags, int mode)
++{
++    int fd;
++
++#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
++    if (cloexec_works != -1)
++        flags |= O_CLOEXEC;
++#endif
++    fd = open(path, flags, mode);
++    if (fd == -1)
++        return -1;
++    check_cloexec(fd);
++    return fd;
++}
++
++/*
++ * fopen_r - open file with FD_CLOEXEC flag
++ */
++FILE *
++fopen_r(const char *path)
++{
++    FILE *f;
++
++#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
++    if (cloexec_works != -1) {
++        f = fopen(path, "re");
++        if (f != NULL) {
++            check_cloexec(fileno(f));
++            return f;
++        }
++    }
++#endif
++    f = fopen(path, "r");
++    if (f == NULL)
++        return NULL;
++    check_cloexec(fileno(f));
++    return f;
++}
++
+ /* List of protocol names, to make our messages a little more informative. */
+ struct protocol_list {
+     u_short   proto;
+@@ -1618,7 +1717,7 @@ device_script(program, in, out, dont_wai
+     if (log_to_fd >= 0)
+       errfd = log_to_fd;
+     else
+-      errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
++      errfd = open_fd_mode(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
+     ++conn_running;
+     pid = safe_fork(in, out, errfd);
+diff -up ppp-2.4.4/pppd/options.c.fd_leak ppp-2.4.4/pppd/options.c
+--- ppp-2.4.4/pppd/options.c.fd_leak   2006-06-18 13:26:00.000000000 +0200
++++ ppp-2.4.4/pppd/options.c   2009-10-08 21:22:59.797544174 +0200
+@@ -409,7 +409,7 @@ options_from_file(filename, must_exist, 
+       option_error("unable to drop privileges to open %s: %m", filename);
+       return 0;
+     }
+-    f = fopen(filename, "r");
++    f = fopen_r(filename);
+     err = errno;
+     if (check_prot && seteuid(euid) == -1)
+       fatal("unable to regain privileges");
+@@ -1528,9 +1528,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_fd_mode(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
+     if (fd < 0 && errno == EEXIST)
+-      fd = open(*argv, O_WRONLY | O_APPEND);
++      fd = open_fd(*argv, O_WRONLY | O_APPEND);
+     err = errno;
+     if (!privileged_option && seteuid(euid) == -1)
+       fatal("unable to regain privileges: %m");
+diff -up ppp-2.4.4/pppd/pppd.h.fd_leak ppp-2.4.4/pppd/pppd.h
+--- ppp-2.4.4/pppd/pppd.h.fd_leak      2005-08-26 01:59:34.000000000 +0200
++++ ppp-2.4.4/pppd/pppd.h      2009-10-08 21:22:59.800544904 +0200
+@@ -494,6 +494,10 @@ int  ppp_send_config __P((int, int, u_in
+ int  ppp_recv_config __P((int, int, u_int32_t, int, int));
+ const char *protocol_name __P((int));
+ void remove_pidfiles __P((void));
++int socket_fd __P((int, int, int));
++int open_fd __P((const char *, int));
++int open_fd_mode __P((const char *, int, int));
++FILE *fopen_r __P((const char *));
+ void lock_db __P((void));
+ void unlock_db __P((void));
+diff -up ppp-2.4.4/pppd/sys-linux.c.fd_leak ppp-2.4.4/pppd/sys-linux.c
+--- ppp-2.4.4/pppd/sys-linux.c.fd_leak 2009-10-08 21:22:59.778544744 +0200
++++ ppp-2.4.4/pppd/sys-linux.c 2009-10-08 21:22:59.803544377 +0200
+@@ -308,12 +308,12 @@ static int modify_flags(int fd, int clea
+ void sys_init(void)
+ {
+     /* Get an internet socket for doing socket ioctls. */
+-    sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
++    sock_fd = socket_fd(AF_INET, SOCK_DGRAM, 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_fd(AF_INET6, SOCK_DGRAM, 0);
+     if (sock6_fd < 0)
+       sock6_fd = -errno;      /* save errno for later */
+ #endif
+@@ -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_fd("/dev/ppp", O_RDWR);
+       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_fd("/dev/ppp", O_RDWR);
+       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_fd("/dev/ppp", O_RDWR);
+       if (master_fd < 0)
+               fatal("Couldn't open /dev/ppp: %m");
+       if (ioctl(master_fd, PPPIOCATTACH, &ifnum) < 0) {
+@@ -1412,7 +1412,7 @@ static char *path_to_procfs(const char *
+       /* Default the mount location of /proc */
+       strlcpy (proc_path, "/proc", sizeof(proc_path));
+       proc_path_len = 5;
+-      fp = fopen(MOUNTED, "r");
++      fp = fopen_r(MOUNTED);
+       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_r(path);
+     if (route_fd == NULL) {
+       error("can't open routing table %s: %m", path);
+       return 0;
+@@ -1713,7 +1713,7 @@ int sifproxyarp (int unit, u_int32_t his
+       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_fd(forw_path, O_WRONLY);
+               if (fd >= 0) {
+                   if (write(fd, "1", 1) != 1)
+                       error("Couldn't enable IP forwarding: %m");
+@@ -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_fd(AF_INET, SOCK_DGRAM, 0);
+       if (sock_fd < 0)
+               return 0;
+       memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
+@@ -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_fd("/dev/ppp", O_RDWR);
+     if (fd >= 0) {
+       new_style_driver = 1;
+@@ -2068,7 +2068,7 @@ int ppp_available(void)
+ /*
+  * Open a socket for doing the ioctl operations.
+  */
+-    s = socket(AF_INET, SOCK_DGRAM, 0);
++    s = socket_fd(AF_INET, SOCK_DGRAM, 0);
+     if (s < 0)
+       return 0;
+@@ -2318,7 +2318,7 @@ int sifaddr (int unit, u_int32_t our_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_fd(path, O_WRONLY)) >= 0) {
+           if (write(fd, "1", 1) != 1)
+               error("Couldn't enable dynamic IP addressing: %m");
+           close(fd);
+@@ -2494,7 +2494,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
+     /*
+      * Try the unix98 way first.
+      */
+-    mfd = open("/dev/ptmx", O_RDWR);
++    mfd = open_fd("/dev/ptmx", O_RDWR);
+     if (mfd >= 0) {
+       int ptn;
+       if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
+@@ -2505,7 +2505,7 @@ get_pty(master_fdp, slave_fdp, slave_nam
+           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_fd(pty_name, O_RDWR | O_NOCTTY)) < 0)
+               warn("Couldn't open pty slave %s: %m", pty_name);
+       }
+     }
+@@ -2516,10 +2516,10 @@ get_pty(master_fdp, slave_fdp, slave_nam
+       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_fd_mode(pty_name, O_RDWR, 0);
+           if (mfd >= 0) {
+               pty_name[5] = 't';
+-              sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
++              sfd = open_fd_mode(pty_name, O_RDWR | O_NOCTTY, 0);
+               if (sfd >= 0) {
+                   fchown(sfd, uid, -1);
+                   fchmod(sfd, S_IRUSR | S_IWUSR);
+@@ -2784,7 +2784,7 @@ ether_to_eui64(eui64_t *p_eui64)
+     int skfd;
+     const unsigned char *ptr;
+-    skfd = socket(PF_INET6, SOCK_DGRAM, 0);
++    skfd = socket_fd(PF_INET6, SOCK_DGRAM, 0);
+     if(skfd == -1)
+     {
+         warn("could not open IPv6 socket");
+diff -up ppp-2.4.4/pppd/tdb.c.fd_leak ppp-2.4.4/pppd/tdb.c
+--- ppp-2.4.4/pppd/tdb.c.fd_leak       2004-11-13 08:13:07.000000000 +0100
++++ ppp-2.4.4/pppd/tdb.c       2009-10-08 21:22:59.806583590 +0200
+@@ -1724,7 +1724,7 @@ TDB_CONTEXT *tdb_open_ex(const char *nam
+               goto internal;
+       }
+-      if ((tdb->fd = open(name, open_flags, mode)) == -1) {
++      if ((tdb->fd = open_fd_mode(name, open_flags, 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_fd_mode(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0);
+       if (tdb->fd == -1) {
+               TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno)));
+               goto fail;
+diff -up ppp-2.4.4/pppd/tty.c.fd_leak ppp-2.4.4/pppd/tty.c
+--- ppp-2.4.4/pppd/tty.c.fd_leak       2006-06-04 09:04:57.000000000 +0200
++++ ppp-2.4.4/pppd/tty.c       2009-10-08 21:22:59.809544300 +0200
+@@ -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_fd_mode(devnam, O_NONBLOCK | O_RDWR, 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_fd(devnam, O_RDWR)) >= 0)
+                               break;
+                       if (errno != EINTR) {
+                               error("Failed to reopen %s: %m", devnam);
+@@ -896,7 +896,8 @@ 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, 0);
++    sock = socket_fd(PF_INET, SOCK_STREAM, 0);
+     if (sock < 0) {
+       error("Can't create socket: %m");
+       return -1;
+diff -up ppp-2.4.4/pppd/utils.c.fd_leak ppp-2.4.4/pppd/utils.c
+--- ppp-2.4.4/pppd/utils.c.fd_leak     2009-10-08 21:22:59.620325739 +0200
++++ ppp-2.4.4/pppd/utils.c     2009-10-08 21:22:59.811573725 +0200
+@@ -931,14 +931,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_fd_mode(lock_file, O_EXCL | O_CREAT | O_RDWR, 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_fd_mode(lock_file, O_RDONLY, 0);
+       if (fd < 0) {
+           if (errno == ENOENT) /* This is just a timing problem. */
+               continue;
+@@ -1017,7 +1017,7 @@ relock(pid)
+     if (lock_file[0] == 0)
+       return -1;
+-    fd = open(lock_file, O_WRONLY, 0);
++    fd = open_fd_mode(lock_file, O_WRONLY, 0);
+     if (fd < 0) {
+       error("Couldn't reopen lock file %s: %m", lock_file);
+       lock_file[0] = 0;
+diff -up ppp-2.4.5/pppd/plugins/pppoatm/pppoatm.c.test ppp-2.4.5/pppd/plugins/pppoatm/pppoatm.c
+--- ppp-2.4.5/pppd/plugins/pppoatm/pppoatm.c.test      2010-11-16 09:56:56.083707000 +0100
++++ ppp-2.4.5/pppd/plugins/pppoatm/pppoatm.c   2010-11-16 09:56:59.382707272 +0100
+@@ -137,7 +137,11 @@ static int connect_pppoatm(void)
+       if (!device_got_set)
+               no_device_given_pppoatm();
++#ifdef SOCK_CLOEXEC
++      fd = socket(AF_ATMPVC, SOCK_DGRAM | SOCK_CLOEXEC, 0);
++#else
+       fd = socket(AF_ATMPVC, SOCK_DGRAM, 0);
++#endif
+       if (fd < 0)
+               fatal("failed to create socket: %m");
+       memset(&qos, 0, sizeof qos);
+diff -up ppp-2.4.5/pppd/plugins/pppol2tp/openl2tp.c.test ppp-2.4.5/pppd/plugins/pppol2tp/openl2tp.c
+--- ppp-2.4.5/pppd/plugins/pppol2tp/openl2tp.c.test    2010-11-16 09:58:17.499711288 +0100
++++ ppp-2.4.5/pppd/plugins/pppol2tp/openl2tp.c 2010-11-16 10:00:15.791706960 +0100
+@@ -83,7 +83,11 @@ static int openl2tp_client_create(void)
+       int result;
+       if (openl2tp_fd < 0) {
++#ifdef SOCK_CLOEXEC
++              openl2tp_fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
++#else
+               openl2tp_fd = socket(PF_UNIX, SOCK_DGRAM, 0);
++#endif
+               if (openl2tp_fd < 0) {
+                       error("openl2tp connection create: %m");
+                       return -ENOTCONN;
+diff -up ppp-2.4.5/pppd/plugins/pppol2tp/pppol2tp.c.test ppp-2.4.5/pppd/plugins/pppol2tp/pppol2tp.c
+--- ppp-2.4.5/pppd/plugins/pppol2tp/pppol2tp.c.test    2010-11-16 09:57:44.448709467 +0100
++++ ppp-2.4.5/pppd/plugins/pppol2tp/pppol2tp.c 2010-11-16 09:59:32.877707001 +0100
+@@ -208,7 +208,11 @@ static void send_config_pppol2tp(int mtu
+               struct ifreq ifr;
+               int fd;
++#ifdef SOCK_CLOEXEC
++              fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
++#else
+               fd = socket(AF_INET, SOCK_DGRAM, 0);
++#endif
+               if (fd >= 0) {
+                       memset (&ifr, '\0', sizeof (ifr));
+                       strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+diff -up ppp-2.4.5/pppd/plugins/rp-pppoe/if.c.test ppp-2.4.5/pppd/plugins/rp-pppoe/if.c
+--- ppp-2.4.5/pppd/plugins/rp-pppoe/if.c.test  2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5/pppd/plugins/rp-pppoe/if.c       2010-11-16 09:54:03.973706239 +0100
+@@ -116,6 +116,10 @@ openInterface(char const *ifname, UINT16
+     stype = SOCK_PACKET;
+ #endif
++#ifdef SOCK_CLOEXEC
++    stype |= SOCK_CLOEXEC;
++#endif
++
+     if ((fd = socket(domain, stype, htons(type))) < 0) {
+       /* Give a more helpful message for the common error case */
+       if (errno == EPERM) {
+diff -up ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c.test ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c
+--- ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c.test      2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5/pppd/plugins/rp-pppoe/plugin.c   2010-11-16 09:40:23.355707001 +0100
+@@ -158,7 +158,11 @@ PPPOEConnectDevice(void)
+     ppp_session_number = ntohs(conn->session);
+     /* Make the session socket */
++#ifdef SOCK_CLOEXEC
++    conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM | SOCK_CLOEXEC, PX_PROTO_OE);
++#else
+     conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE);
++#endif
+     if (conn->sessionSocket < 0) {
+       error("Failed to create PPPoE socket: %m");
+       goto errout;
+@@ -289,7 +293,11 @@ PPPoEDevnameHook(char *cmd, char **argv,
+     }
+     /* Open a socket */
++#ifdef SOCK_CLOEXEC
++    if ((fd = socket(PF_PACKET, SOCK_RAW | SOCK_CLOEXEC, 0)) < 0) {
++#else
+     if ((fd = socket(PF_PACKET, SOCK_RAW, 0)) < 0) {
++#endif
+       r = 0;
+     }
+diff -up ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c.test ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c
+--- ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c.test     2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c  2010-11-16 09:55:08.726707003 +0100
+@@ -121,6 +121,10 @@ openInterface(char const *ifname, UINT16
+     stype = SOCK_PACKET;
+ #endif
++#ifdef SOCK_CLOEXEC
++    stype |= SOCK_CLOEXEC;
++#endif
++
+     if ((fd = socket(domain, stype, htons(type))) < 0) {
+       /* Give a more helpful message for the common error case */
+       if (errno == EPERM) {
diff --git a/pkgs/ppp/patches/ppp-2.4.4-lib64.patch b/pkgs/ppp/patches/ppp-2.4.4-lib64.patch
new file mode 100644 (file)
index 0000000..b842048
--- /dev/null
@@ -0,0 +1,89 @@
+--- ppp-2.4.4/pppd/plugins/rp-pppoe/Makefile.linux.lib64       2006-07-24 20:43:40.000000000 +0200
++++ ppp-2.4.4/pppd/plugins/rp-pppoe/Makefile.linux     2006-07-24 20:44:56.000000000 +0200
+@@ -15,7 +15,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)
+--- ppp-2.4.4/pppd/plugins/radius/Makefile.linux.lib64 2006-07-24 20:43:40.000000000 +0200
++++ ppp-2.4.4/pppd/plugins/radius/Makefile.linux       2006-07-24 20:44:45.000000000 +0200
+@@ -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)
+--- ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux.lib64        2004-11-14 02:12:10.000000000 +0100
++++ ppp-2.4.4/pppd/plugins/pppoatm/Makefile.linux      2006-07-24 20:44:29.000000000 +0200
+@@ -6,8 +6,8 @@
+ #***********************************************************************
+-DESTDIR = $(INSTROOT)@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)
+--- ppp-2.4.4/pppd/plugins/Makefile.linux.lib64        2006-07-24 20:43:40.000000000 +0200
++++ ppp-2.4.4/pppd/plugins/Makefile.linux      2006-07-24 20:43:40.000000000 +0200
+@@ -7,7 +7,7 @@
+ 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
+--- ppp-2.4.4/pppd/Makefile.linux.lib64        2006-07-24 20:43:40.000000000 +0200
++++ ppp-2.4.4/pppd/Makefile.linux      2006-07-24 20:43:40.000000000 +0200
+@@ -8,6 +8,7 @@
+ 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 @@
+ CC = gcc
+ #
+-COPTS = -Wall $(RPM_OPT_FLAGS)
++COPTS = -Wall $(RPM_OPT_FLAGS) -DLIBDIR=\""$(LIBDIR)"\"
+ LIBS = -lutil
+ # Uncomment the next 2 lines to include support for Microsoft's
+--- ppp-2.4.4/pppd/pathnames.h.lib64   2005-08-26 01:59:34.000000000 +0200
++++ ppp-2.4.4/pppd/pathnames.h 2006-07-24 20:43:40.000000000 +0200
+@@ -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__ */
+--- ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux.lib64       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5/pppd/plugins/pppol2tp/Makefile.linux     2010-08-05 16:33:53.964898629 +0200
+@@ -6,8 +6,8 @@
+ #***********************************************************************
+-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/pkgs/ppp/patches/ppp-2.4.5-eaptls-mppe-0.99.patch b/pkgs/ppp/patches/ppp-2.4.5-eaptls-mppe-0.99.patch
new file mode 100644 (file)
index 0000000..eb6c2a6
--- /dev/null
@@ -0,0 +1,2917 @@
+diff -Naur ppp-2.4.5/README.eap-tls ppp-2.4.5-eaptls-mppe-0.99/README.eap-tls
+--- ppp-2.4.5/README.eap-tls   1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/README.eap-tls  2010-10-01 15:17:54.205272328 +0200
+@@ -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:
++          <engine>:<identifier>
++        e.g.
++          pkcs11:123456
++
++      - The certificate can also be loaded from the 'pkcs11' engine using
++        a special client certificate filename in the /etc/ppp/eaptls-client file:
++          <engine>:<identifier>
++        e.g.
++          pkcs11:123456
++
++      - Create an /etc/ppp/openssl.cnf file to load the right OpenSSL engine prior
++        to starting 'pppd'. A sample openssl.cnf file is
++
++        openssl_conf = openssl_def
++
++        [ openssl_def ]
++        engines = engine_section
++
++        [ engine_section ]
++        pkcs11 = pkcs11_section
++
++        [ pkcs11_section ]
++        engine_id = pkcs11
++        dynamic_path = /usr/lib64/openssl/engines/engine_pkcs11.so
++        MODULE_PATH = /usr/lib64/libeTPkcs11.so
++        init = 0
++
++      - There are two ways to specify a password/PIN for the PKCS11 engine:
++          - inside the openssl.cnf file using
++              PIN = your-secret-pin
++            Note The keyword 'PIN' is case sensitive!
++          - Using the 'password' in the ppp options file.
++        From v0.97 of the eap-tls patch the password can also be supplied
++        using the appropriate 'eaptls_passwd_hook' (see plugins/passprompt.c
++        for an example).
++
++
++4. Options
++
++      These pppd options are available:
++
++        ca <ca-file>
++                      Use the CA public certificate found in <ca-file> in PEM format
++        cert <cert-file>
++                      Use the client public certificate found in <cert-file> in PEM format
++                      or in engine:engine_id format
++        key <key-file>
++                      Use the client private key found in <key-file> in PEM format
++                      or in engine:engine_id format
++      crl-dir <dir>
++              Use CRL files from dir. It contains CRL files in PEM
++              format and each file contains a CRL. The files are looked up 
++              by the issuer name hash value. Use the c_rehash utility 
++              to create necessary links.
++      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 <janjust@nikhef.nl>
++
+diff -Naur ppp-2.4.5/etc.ppp/eaptls-client ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-client
+--- ppp-2.4.5/etc.ppp/eaptls-client    1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-client   2010-10-01 15:17:54.205272328 +0200
+@@ -0,0 +1,10 @@
++# Parameters for authentication using EAP-TLS (client)
++
++# client name (can be *)
++# server name (can be *)
++# client certificate file (required)
++# server certificate file (optional, if unused put '-')
++# CA certificate file (required)
++# client private key file (required)
++
++#client       server  /root/cert/client.crt   -       /root/cert/ca.crt       /root/cert/client.key
+diff -Naur ppp-2.4.5/etc.ppp/eaptls-server ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-server
+--- ppp-2.4.5/etc.ppp/eaptls-server    1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/eaptls-server   2010-10-01 15:17:54.205272328 +0200
+@@ -0,0 +1,11 @@
++# Parameters for authentication using EAP-TLS (server)
++
++# client name (can be *)
++# server name (can be *)
++# client certificate file (optional, if unused put '-')
++# server certificate file (required)
++# CA certificate file (required)
++# server private key file (required)
++# allowed addresses (required, can be *)
++
++#client       server  -       /root/cert/server.crt   /root/cert/ca.crt       /root/cert/server.key   192.168.1.0/24
+diff -Naur ppp-2.4.5/etc.ppp/openssl.cnf ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/openssl.cnf
+--- ppp-2.4.5/etc.ppp/openssl.cnf      1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/etc.ppp/openssl.cnf     2010-10-01 15:17:54.206272162 +0200
+@@ -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 -Naur ppp-2.4.5/linux/Makefile.top ppp-2.4.5-eaptls-mppe-0.99/linux/Makefile.top
+--- ppp-2.4.5/linux/Makefile.top       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/linux/Makefile.top      2010-10-01 15:17:54.206272162 +0200
+@@ -26,7 +26,7 @@
+       cd pppdump; $(MAKE) $(MFLAGS) install
+ install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
+-      $(ETCDIR)/chap-secrets
++      $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client
+ install-devel:
+       cd pppd; $(MAKE) $(MFLAGS) install-devel
+@@ -37,6 +37,10 @@
+       $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
+ $(ETCDIR)/chap-secrets:
+       $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
++$(ETCDIR)/eaptls-server:
++      $(INSTALL) -c -m 600 etc.ppp/eaptls-server $@
++$(ETCDIR)/eaptls-client:
++      $(INSTALL) -c -m 600 etc.ppp/eaptls-client $@
+ $(BINDIR):
+       $(INSTALL) -d -m 755 $@
+diff -Naur ppp-2.4.5/pppd/Makefile.linux ppp-2.4.5-eaptls-mppe-0.99/pppd/Makefile.linux
+--- ppp-2.4.5/pppd/Makefile.linux      2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/Makefile.linux     2010-10-01 15:17:54.207272272 +0200
+@@ -73,6 +73,9 @@
+ # Enable EAP SRP-SHA1 authentication (requires libsrp)
+ #USE_SRP=y
++# Enable EAP-TLS authentication (requires libssl and libcurl)
++USE_EAPTLS=y
++
+ MAXOCTETS=y
+ INCLUDE_DIRS= -I../include
+@@ -112,6 +115,15 @@
+ 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 -Naur ppp-2.4.5/pppd/auth.c ppp-2.4.5-eaptls-mppe-0.99/pppd/auth.c
+--- ppp-2.4.5/pppd/auth.c      2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/auth.c     2010-10-01 15:17:54.210272021 +0200
+@@ -109,6 +109,9 @@
+ #include "upap.h"
+ #include "chap-new.h"
+ #include "eap.h"
++#ifdef USE_EAPTLS
++#include "eap-tls.h"
++#endif
+ #ifdef CBCP_SUPPORT
+ #include "cbcp.h"
+ #endif
+@@ -183,6 +186,11 @@
+ /* Hook for a plugin to get the CHAP password for authenticating us */
+ int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL;
++#ifdef USE_EAPTLS
++/* Hook for a plugin to get the EAP-TLS password for authenticating us */
++int (*eaptls_passwd_hook) __P((char *user, char *passwd)) = NULL;
++#endif
++
+ /* Hook for a plugin to say whether it is OK if the peer
+    refuses to authenticate. */
+ int (*null_auth_hook) __P((struct wordlist **paddrs,
+@@ -238,6 +246,13 @@
+ bool explicit_user = 0;               /* Set if "user" option supplied */
+ bool explicit_passwd = 0;     /* Set if "password" option supplied */
+ char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
++#ifdef USE_EAPTLS
++char *cacert_file  = NULL;    /* CA certificate file (pem format) */
++char *cert_file    = NULL;    /* client certificate file (pem format) */
++char *privkey_file = NULL;    /* client private key file (pem format) */
++char *crl_dir      = NULL;    /* directory containing CRL files */
++bool need_peer_eap = 0;                       /* Require peer to authenticate us */
++#endif
+ static char *uafname;         /* name of most recent +ua file */
+@@ -254,6 +269,19 @@
+ static int  have_chap_secret __P((char *, char *, int, int *));
+ static int  have_srp_secret __P((char *client, char *server, int need_ip,
+     int *lacks_ipp));
++
++#ifdef USE_EAPTLS
++static int  have_eaptls_secret_server
++__P((char *client, char *server, int need_ip, int *lacks_ipp));
++static int  have_eaptls_secret_client __P((char *client, char *server));
++static int  scan_authfile_eaptls __P((FILE * f, char *client, char *server,
++                             char *cli_cert, char *serv_cert,
++                             char *ca_cert, char *pk,
++                             struct wordlist ** addrs,
++                             struct wordlist ** opts,
++                             char *filename, int flags));
++#endif
++
+ static int  ip_addr_check __P((u_int32_t, struct permitted_ip *));
+ static int  scan_authfile __P((FILE *, char *, char *, char *,
+                              struct wordlist **, struct wordlist **,
+@@ -401,6 +429,14 @@
+       "Set telephone number(s) which are allowed to connect",
+       OPT_PRIV | OPT_A2LIST },
++#ifdef USE_EAPTLS
++    { "ca", o_string, &cacert_file,   "EAP-TLS CA certificate in PEM format" },
++    { "cert", o_string, &cert_file,   "EAP-TLS client certificate in PEM format" },
++    { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" },
++    { "crl-dir", o_string, &crl_dir,  "Use CRLs in directory" },
++    { "need-peer-eap", o_bool, &need_peer_eap,
++      "Require the peer to authenticate us", 1 },
++#endif /* USE_EAPTLS */
+     { NULL }
+ };
+@@ -731,6 +767,9 @@
+     lcp_options *wo = &lcp_wantoptions[unit];
+     lcp_options *go = &lcp_gotoptions[unit];
+     lcp_options *ho = &lcp_hisoptions[unit];
++#ifdef USE_EAPTLS
++    lcp_options *ao = &lcp_allowoptions[unit];
++#endif
+     int i;
+     struct protent *protp;
+@@ -765,6 +804,22 @@
+       }
+     }
++#ifdef USE_EAPTLS
++    if (need_peer_eap && !ao->neg_eap) {
++      warn("eap required to authenticate us but no suitable secrets");
++      lcp_close(unit, "couldn't negotiate eap");
++      status = EXIT_AUTH_TOPEER_FAILED;
++      return;
++    }
++
++    if (need_peer_eap && !ho->neg_eap) {
++      warn("peer doesn't want to authenticate us with eap");
++      lcp_close(unit, "couldn't negotiate eap");
++      status = EXIT_PEER_AUTH_FAILED;
++      return;
++    }
++#endif
++
+     new_phase(PHASE_AUTHENTICATE);
+     auth = 0;
+     if (go->neg_eap) {
+@@ -1278,6 +1333,15 @@
+                                   our_name, 1, &lacks_ip);
+     }
++#ifdef USE_EAPTLS
++    if (!can_auth && wo->neg_eap) {
++      can_auth =
++          have_eaptls_secret_server((explicit_remote ? remote_name :
++                                     NULL), our_name, 1, &lacks_ip);
++
++    }
++#endif
++
+     if (auth_required && !can_auth && noauth_addrs == NULL) {
+       if (default_auth) {
+           option_error(
+@@ -1332,7 +1396,11 @@
+       passwd[0] != 0 ||
+       (hadchap == 1 || (hadchap == -1 && have_chap_secret(user,
+           (explicit_remote? remote_name: NULL), 0, NULL))) ||
+-      have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL));
++      have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)
++#ifdef USE_EAPTLS
++              || have_eaptls_secret_client(user, (explicit_remote? remote_name: NULL)))
++#endif
++      ;
+     hadchap = -1;
+     if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
+@@ -1347,8 +1415,14 @@
+           !have_chap_secret((explicit_remote? remote_name: NULL), our_name,
+               1, NULL))) &&
+       !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
+-          NULL))
++          NULL)
++#ifdef USE_EAPTLS
++       && !have_eaptls_secret_server((explicit_remote? remote_name: NULL),
++                                 our_name, 1, NULL)
++#endif
++              )
+       go->neg_eap = 0;
++
+ }
+@@ -1706,6 +1780,7 @@
+ }
++
+ /*
+  * get_secret - open the CHAP secret file and return the secret
+  * for authenticating the given client on the given server.
+@@ -2358,3 +2433,335 @@
+     auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL, 0);
+ }
++
++
++#ifdef USE_EAPTLS
++static int
++have_eaptls_secret_server(client, server, need_ip, lacks_ipp)
++    char *client;
++    char *server;
++    int need_ip;
++    int *lacks_ipp;
++{
++    FILE *f;
++    int ret;
++    char *filename;
++    struct wordlist *addrs;
++    char servcertfile[MAXWORDLEN];
++    char clicertfile[MAXWORDLEN];
++    char cacertfile[MAXWORDLEN];
++    char pkfile[MAXWORDLEN];
++
++    filename = _PATH_EAPTLSSERVFILE;
++    f = fopen(filename, "r");
++    if (f == NULL)
++              return 0;
++
++    if (client != NULL && client[0] == 0)
++              client = NULL;
++    else if (server != NULL && server[0] == 0)
++              server = NULL;
++
++    ret =
++      scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
++                           cacertfile, pkfile, &addrs, NULL, filename,
++                           0);
++
++    fclose(f);
++
++/*
++    if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
++                              clicertfile, pkfile))
++              ret = -1;
++*/
++
++      if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
++              if (lacks_ipp != 0)
++                      *lacks_ipp = 1;
++              ret = -1;
++    }
++    if (addrs != 0)
++              free_wordlist(addrs);
++
++    return ret >= 0;
++}
++
++
++static int
++have_eaptls_secret_client(client, server)
++    char *client;
++    char *server;
++{
++    FILE *f;
++    int ret;
++    char *filename;
++    struct wordlist *addrs = NULL;
++    char servcertfile[MAXWORDLEN];
++    char clicertfile[MAXWORDLEN];
++    char cacertfile[MAXWORDLEN];
++    char pkfile[MAXWORDLEN];
++
++    if (client != NULL && client[0] == 0)
++              client = NULL;
++    else if (server != NULL && server[0] == 0)
++              server = NULL;
++
++      if (cacert_file && cert_file && privkey_file)
++              return 1;
++
++    filename = _PATH_EAPTLSCLIFILE;
++    f = fopen(filename, "r");
++    if (f == NULL)
++              return 0;
++
++    ret =
++      scan_authfile_eaptls(f, client, server, clicertfile, servcertfile,
++                           cacertfile, pkfile, &addrs, NULL, filename,
++                           0);
++    fclose(f);
++
++/*
++    if (ret >= 0 && !eaptls_init_ssl(0, cacertfile, clicertfile,
++                              servcertfile, pkfile))
++              ret = -1;
++*/
++
++    if (addrs != 0)
++              free_wordlist(addrs);
++
++    return ret >= 0;
++}
++
++
++static int
++scan_authfile_eaptls(f, client, server, cli_cert, serv_cert, ca_cert, pk,
++                   addrs, opts, filename, flags)
++    FILE *f;
++    char *client;
++    char *server;
++    char *cli_cert;
++    char *serv_cert;
++    char *ca_cert;
++    char *pk;
++    struct wordlist **addrs;
++    struct wordlist **opts;
++    char *filename;
++    int flags;
++{
++    int newline;
++    int got_flag, best_flag;
++    struct wordlist *ap, *addr_list, *alist, **app;
++    char word[MAXWORDLEN];
++
++    if (addrs != NULL)
++      *addrs = NULL;
++    if (opts != NULL)
++      *opts = NULL;
++    addr_list = NULL;
++    if (!getword(f, word, &newline, filename))
++      return -1;              /* file is empty??? */
++    newline = 1;
++    best_flag = -1;
++    for (;;) {
++      /*
++       * Skip until we find a word at the start of a line.
++       */
++      while (!newline && getword(f, word, &newline, filename));
++      if (!newline)
++          break;              /* got to end of file */
++
++      /*
++       * Got a client - check if it's a match or a wildcard.
++       */
++      got_flag = 0;
++      if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
++          newline = 0;
++          continue;
++      }
++      if (!ISWILD(word))
++          got_flag = NONWILD_CLIENT;
++
++      /*
++       * Now get a server and check if it matches.
++       */
++      if (!getword(f, word, &newline, filename))
++          break;
++      if (newline)
++          continue;
++      if (!ISWILD(word)) {
++          if (server != NULL && strcmp(word, server) != 0)
++              continue;
++          got_flag |= NONWILD_SERVER;
++      }
++
++      /*
++       * Got some sort of a match - see if it's better than what
++       * we have already.
++       */
++      if (got_flag <= best_flag)
++          continue;
++
++      /*
++       * Get the cli_cert
++       */
++      if (!getword(f, word, &newline, filename))
++          break;
++      if (newline)
++          continue;
++      if (strcmp(word, "-") != 0) {
++          strlcpy(cli_cert, word, MAXWORDLEN);
++      } else
++          cli_cert[0] = 0;
++
++      /*
++       * Get serv_cert
++       */
++      if (!getword(f, word, &newline, filename))
++          break;
++      if (newline)
++          continue;
++      if (strcmp(word, "-") != 0) {
++          strlcpy(serv_cert, word, MAXWORDLEN);
++      } else
++          serv_cert[0] = 0;
++
++      /*
++       * Get ca_cert
++       */
++      if (!getword(f, word, &newline, filename))
++          break;
++      if (newline)
++          continue;
++      strlcpy(ca_cert, word, MAXWORDLEN);
++
++      /*
++       * Get pk
++       */
++      if (!getword(f, word, &newline, filename))
++          break;
++      if (newline)
++          continue;
++      strlcpy(pk, word, MAXWORDLEN);
++
++
++      /*
++       * Now read address authorization info and make a wordlist.
++       */
++      app = &alist;
++      for (;;) {
++          if (!getword(f, word, &newline, filename) || newline)
++              break;
++          ap = (struct wordlist *)
++              malloc(sizeof(struct wordlist) + strlen(word) + 1);
++          if (ap == NULL)
++              novm("authorized addresses");
++          ap->word = (char *) (ap + 1);
++          strcpy(ap->word, word);
++          *app = ap;
++          app = &ap->next;
++      }
++      *app = NULL;
++      /*
++       * This is the best so far; remember it.
++       */
++      best_flag = got_flag;
++      if (addr_list)
++          free_wordlist(addr_list);
++      addr_list = alist;
++
++      if (!newline)
++          break;
++    }
++
++    /* scan for a -- word indicating the start of options */
++    for (app = &addr_list; (ap = *app) != NULL; app = &ap->next)
++      if (strcmp(ap->word, "--") == 0)
++          break;
++    /* ap = start of options */
++    if (ap != NULL) {
++      ap = ap->next;          /* first option */
++      free(*app);             /* free the "--" word */
++      *app = NULL;            /* terminate addr list */
++    }
++    if (opts != NULL)
++      *opts = ap;
++    else if (ap != NULL)
++      free_wordlist(ap);
++    if (addrs != NULL)
++      *addrs = addr_list;
++    else if (addr_list != NULL)
++      free_wordlist(addr_list);
++
++    return best_flag;
++}
++
++
++int
++get_eaptls_secret(unit, client, server, clicertfile, servcertfile,
++                cacertfile, pkfile, am_server)
++    int unit;
++    char *client;
++    char *server;
++    char *clicertfile;
++    char *servcertfile;
++    char *cacertfile;
++    char *pkfile;
++    int am_server;
++{
++    FILE *fp;
++    int ret;
++    char *filename         = NULL;
++    struct wordlist *addrs = NULL;
++    struct wordlist *opts  = NULL;
++
++      /* in client mode the ca+cert+privkey can also be specified as options */
++      if (!am_server && cacert_file && cert_file && privkey_file )
++      {
++              strlcpy( clicertfile, cert_file, MAXWORDLEN );
++              strlcpy( cacertfile, cacert_file, MAXWORDLEN );
++              strlcpy( pkfile, privkey_file, MAXWORDLEN );
++              servcertfile[0] = '\0';
++      }
++      else
++      {
++              filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE);
++              addrs = NULL;
++
++              fp = fopen(filename, "r");
++              if (fp == NULL)
++              {
++                      error("Can't open eap-tls secret file %s: %m", filename);
++                      return 0;
++              }
++
++              check_access(fp, filename);
++
++              ret = scan_authfile_eaptls(fp, client, server, clicertfile, servcertfile,
++                              cacertfile, pkfile, &addrs, &opts, filename, 0);
++
++              fclose(fp);
++
++              if (ret < 0) return 0;
++      }
++
++    if (eaptls_passwd_hook)
++    {
++              dbglog( "Calling eaptls password hook" );
++              if ( (*eaptls_passwd_hook)(pkfile, passwd) < 0)
++              {
++                       error("Unable to obtain EAP-TLS password for %s (%s) from plugin", 
++                              client, pkfile);
++                  return 0;
++              }
++      }
++    if (am_server)
++              set_allowed_addrs(unit, addrs, opts);
++    else if (opts != NULL)
++              free_wordlist(opts);
++    if (addrs != NULL)
++              free_wordlist(addrs);
++
++    return 1;
++}
++#endif
++
+diff -Naur ppp-2.4.5/pppd/ccp.c ppp-2.4.5-eaptls-mppe-0.99/pppd/ccp.c
+--- ppp-2.4.5/pppd/ccp.c       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/ccp.c      2010-10-01 15:17:54.211272258 +0200
+@@ -540,6 +540,9 @@
+     if (go->mppe) {
+       ccp_options *ao = &ccp_allowoptions[f->unit];
+       int auth_mschap_bits = auth_done[f->unit];
++#ifdef USE_EAPTLS
++      int auth_eap_bits = auth_done[f->unit];
++#endif
+       int numbits;
+       /*
+@@ -567,8 +570,23 @@
+           lcp_close(f->unit, "MPPE required but not available");
+           return;
+       }
++
++#ifdef USE_EAPTLS
++    /*
++     * MPPE is also possible in combination with EAP-TLS.
++     * It is not possible to detect if we're doing EAP or EAP-TLS
++     * at this stage, hence we accept all forms of EAP. If TLS is
++     * not used then the MPPE keys will not be derived anyway.
++     */
++      /* Leave only the eap auth bits set */
++      auth_eap_bits &= (EAP_WITHPEER | EAP_PEER );
++
++      if ((numbits == 0) && (auth_eap_bits == 0)) {
++          error("MPPE required, but MS-CHAP[v2] nor EAP-TLS auth are performed.");
++#else
+       if (!numbits) {
+-          error("MPPE required, but MS-CHAP[v2] auth not performed.");
++              error("MPPE required, but MS-CHAP[v2] auth not performed.");
++#endif
+           lcp_close(f->unit, "MPPE required but not available");
+           return;
+       }
+diff -Naur ppp-2.4.5/pppd/chap-md5.c ppp-2.4.5-eaptls-mppe-0.99/pppd/chap-md5.c
+--- ppp-2.4.5/pppd/chap-md5.c  2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/chap-md5.c 2010-10-01 15:17:54.212272142 +0200
+@@ -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 -Naur ppp-2.4.5/pppd/eap-tls.c ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.c
+--- ppp-2.4.5/pppd/eap-tls.c   1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.c  2010-10-05 15:12:45.881615580 +0200
+@@ -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 <string.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++
++#include <openssl/conf.h>
++#include <openssl/engine.h>
++#include <openssl/hmac.h>
++#include <openssl/err.h>
++#include <openssl/x509v3.h>
++
++#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 -Naur ppp-2.4.5/pppd/eap-tls.h ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.h
+--- ppp-2.4.5/pppd/eap-tls.h   1970-01-01 01:00:00.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap-tls.h  2010-10-01 15:17:54.213271816 +0200
+@@ -0,0 +1,107 @@
++/*
++ * eap-tls.h
++ *
++ * Copyright (c) Beniamino Galvani 2005 All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. The name(s) of the authors of this software must not be used to
++ *    endorse or promote products derived from this software without
++ *    prior written permission.
++ *
++ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
++ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
++ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
++ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ */
++
++#ifndef __EAP_TLS_H__
++#define __EAP_TLS_H__
++
++#include "eap.h"
++
++#include <openssl/ssl.h>
++#include <openssl/bio.h>
++#include <openssl/md5.h>
++
++#define EAP_TLS_FLAGS_LI        128   /* length included flag */
++#define EAP_TLS_FLAGS_MF        64    /* more fragments flag */
++#define EAP_TLS_FLAGS_START     32    /* start flag */
++
++#define EAP_TLS_MAX_LEN         65536 /* max eap tls packet size */
++
++struct eaptls_session
++{
++      u_char *data;           /* buffered data */
++      int datalen;            /* buffered data len */
++      int offset;             /* from where to send */
++      int tlslen;             /* total length of tls data */
++      bool frag;              /* packet is fragmented */
++      SSL_CTX *ctx;
++      SSL *ssl;               /* ssl connection */
++      BIO *from_ssl;
++      BIO *into_ssl;
++      char peer[MAXWORDLEN];  /* peer name */
++      char peercertfile[MAXWORDLEN];
++      bool alert_sent;
++      u_char alert_sent_desc;
++      bool alert_recv;
++      u_char alert_recv_desc;
++      char rtx[65536];        /* retransmission buffer */
++      int rtx_len;
++      int mtu;                /* unit mtu */
++};
++
++typedef struct pw_cb_data
++{
++      const void *password;
++      const char *prompt_info;
++} PW_CB_DATA;
++
++
++int ssl_verify_callback(int, X509_STORE_CTX *);
++void ssl_msg_callback(int write_p, int version, int ct, const void *buf,
++                    size_t len, SSL * ssl, void *arg);
++
++X509 *get_X509_from_file(char *filename);
++int ssl_cmp_certs(char *filename, X509 * a);
++
++SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile,
++            char *certfile, char *peer_certfile, char *privkeyfile);
++int eaptls_init_ssl_server(eap_state * esp);
++int eaptls_init_ssl_client(eap_state * esp);
++void eaptls_free_session(struct eaptls_session *ets);
++
++int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len);
++int eaptls_send(struct eaptls_session *ets, u_char ** outp);
++void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp);
++
++int get_eaptls_secret(int unit, char *client, char *server,
++                    char *clicertfile, char *servcertfile, char *cacertfile,
++                    char *pkfile, int am_server);
++
++#ifdef MPPE
++#include "mppe.h"   /* MPPE_MAX_KEY_LEN */
++extern u_char mppe_send_key[MPPE_MAX_KEY_LEN];
++extern u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
++extern int mppe_keys_set;
++
++void eaptls_gen_mppe_keys(struct eaptls_session *ets, const char *prf_label, int client);
++
++#endif
++
++#endif
+diff -Naur ppp-2.4.5/pppd/eap.c ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.c
+--- ppp-2.4.5/pppd/eap.c       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.c      2010-01-29 16:31:29.000000000 +0100
+@@ -43,6 +43,11 @@
+  * Based on draft-ietf-pppext-eap-srp-03.txt.
+  */
++/*
++ * Modification by Beniamino Galvani, Mar 2005
++ * Implemented EAP-TLS authentication
++ */
++
+ #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $"
+ /*
+@@ -62,8 +67,12 @@
+ #include "pppd.h"
+ #include "pathnames.h"
+-#include "md5.h"
+ #include "eap.h"
++#ifdef USE_EAPTLS
++#include "eap-tls.h"
++#else
++#include "md5.h"
++#endif /* USE_EAPTLS */
+ #ifdef USE_SRP
+ #include <t_pwd.h>
+@@ -209,6 +218,9 @@
+       esp->es_server.ea_id = (u_char)(drand48() * 0x100);
+       esp->es_client.ea_timeout = EAP_DEFREQTIME;
+       esp->es_client.ea_maxrequests = EAP_DEFALLOWREQ;
++#ifdef USE_EAPTLS
++      esp->es_client.ea_using_eaptls = 0;
++#endif /* USE_EAPTLS */
+ }
+ /*
+@@ -436,8 +448,16 @@
+       u_char vals[2];
+       struct b64state bs;
+ #endif /* USE_SRP */
++#ifdef USE_EAPTLS
++      struct eaptls_session *ets;
++      int secret_len;
++      char secret[MAXWORDLEN];
++#endif /* USE_EAPTLS */
+       esp->es_server.ea_timeout = esp->es_savedtime;
++#ifdef USE_EAPTLS
++      esp->es_server.ea_prev_state = esp->es_server.ea_state;
++#endif /* USE_EAPTLS */
+       switch (esp->es_server.ea_state) {
+       case eapBadAuth:
+               return;
+@@ -562,9 +582,81 @@
+                       break;
+               }
+ #endif /* USE_SRP */
++#ifdef USE_EAPTLS
++                if (!get_secret(esp->es_unit, esp->es_server.ea_peer,
++                    esp->es_server.ea_name, secret, &secret_len, 1)) {
++
++                      esp->es_server.ea_state = eapTlsStart;
++                      break;
++              }
++#endif /* USE_EAPTLS */
++
+               esp->es_server.ea_state = eapMD5Chall;
+               break;
++#ifdef USE_EAPTLS
++      case eapTlsStart:
++              /* Initialize ssl session */
++              if(!eaptls_init_ssl_server(esp)) {
++                      esp->es_server.ea_state = eapBadAuth;
++                      break;
++              }
++
++              esp->es_server.ea_state = eapTlsRecv;
++              break;
++
++      case eapTlsRecv:
++              ets = (struct eaptls_session *) esp->es_server.ea_session;
++              
++              if(ets->alert_sent) {
++                      esp->es_server.ea_state = eapTlsSendAlert;
++                      break;
++              }
++
++              if (status) {
++                      esp->es_server.ea_state = eapBadAuth;
++                      break;  
++              }
++              ets = (struct eaptls_session *) esp->es_server.ea_session;
++
++              if(ets->frag)
++                      esp->es_server.ea_state = eapTlsSendAck;
++              else
++                      esp->es_server.ea_state = eapTlsSend;
++              break;
++
++      case eapTlsSend:
++              ets = (struct eaptls_session *) esp->es_server.ea_session;
++
++              if(SSL_is_init_finished(ets->ssl)) {
++                      esp->es_server.ea_state = eapTlsRecvClient; 
++                      break;
++              }
++
++              if(ets->frag)
++                      esp->es_server.ea_state = eapTlsRecvAck;
++              else
++                      esp->es_server.ea_state = eapTlsRecv;                   
++              break;
++
++      case eapTlsSendAck:
++                      esp->es_server.ea_state = eapTlsRecv;
++              break;
++
++      case eapTlsRecvAck:
++                if (status) {
++                        esp->es_server.ea_state = eapBadAuth;
++                        break;
++                }
++
++              esp->es_server.ea_state = eapTlsSend;
++              break;
++
++      case eapTlsSendAlert:
++              esp->es_server.ea_state = eapTlsRecvAlertAck;
++              break;
++#endif /* USE_EAPTLS */
++
+       case eapSRP1:
+ #ifdef USE_SRP
+               ts = (struct t_server *)esp->es_server.ea_session;
+@@ -718,6 +810,30 @@
+               INCPTR(esp->es_server.ea_namelen, outp);
+               break;
++#ifdef USE_EAPTLS
++      case eapTlsStart:
++              PUTCHAR(EAPT_TLS, outp);
++              PUTCHAR(EAP_TLS_FLAGS_START, outp);
++              eap_figure_next_state(esp, 0);
++              break;
++
++      case eapTlsSend:
++              eaptls_send(esp->es_server.ea_session, &outp);
++              eap_figure_next_state(esp, 0);
++              break;
++
++      case eapTlsSendAck:
++              PUTCHAR(EAPT_TLS, outp);
++              PUTCHAR(0, outp);
++              eap_figure_next_state(esp, 0);
++              break;
++
++      case eapTlsSendAlert:
++              eaptls_send(esp->es_server.ea_session, &outp);
++              eap_figure_next_state(esp, 0);
++              break;
++#endif /* USE_EAPTLS */
++
+ #ifdef USE_SRP
+       case eapSRP1:
+               PUTCHAR(EAPT_SRP, outp);
+@@ -904,11 +1020,57 @@
+ eap_server_timeout(arg)
+ void *arg;
+ {
++#ifdef USE_EAPTLS
++      u_char *outp;
++      u_char *lenloc;
++      int outlen;
++#endif /* USE_EAPTLS */
++
+       eap_state *esp = (eap_state *) arg;
+       if (!eap_server_active(esp))
+               return;
++#ifdef USE_EAPTLS
++      switch(esp->es_server.ea_prev_state) {
++
++      /* 
++       *  In eap-tls the state changes after a request, so we return to
++       *  previous state ...
++       */     
++      case(eapTlsStart):
++      case(eapTlsSendAck):
++              esp->es_server.ea_state = esp->es_server.ea_prev_state;
++              break;
++
++      /*
++       *  ... or resend the stored data
++       */
++      case(eapTlsSend):
++      case(eapTlsSendAlert):
++              outp = outpacket_buf;
++              MAKEHEADER(outp, PPP_EAP);
++              PUTCHAR(EAP_REQUEST, outp);
++              PUTCHAR(esp->es_server.ea_id, outp);
++              lenloc = outp;
++              INCPTR(2, outp);
++
++              eaptls_retransmit(esp->es_server.ea_session, &outp);
++
++              outlen = (outp - outpacket_buf) - PPP_HDRLEN;
++              PUTSHORT(outlen, lenloc);
++              output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN);
++              esp->es_server.ea_requests++;
++
++              if (esp->es_server.ea_timeout > 0)
++                      TIMEOUT(eap_server_timeout, esp, esp->es_server.ea_timeout);
++
++              return;
++      default:
++              break;
++      }
++#endif /* USE_EAPTLS */
++
+       /* EAP ID number must not change on timeout. */
+       eap_send_request(esp);
+ }
+@@ -1166,6 +1328,81 @@
+ }
+ #endif /* USE_SRP */
++#ifdef USE_EAPTLS
++/*
++ * Send an EAP-TLS response message with tls data
++ */
++static void
++eap_tls_response(esp, id)
++eap_state *esp;
++u_char id;
++{
++        u_char *outp;
++        int outlen;
++      u_char *lenloc;
++      
++        outp = outpacket_buf;
++
++        MAKEHEADER(outp, PPP_EAP);
++
++        PUTCHAR(EAP_RESPONSE, outp);
++        PUTCHAR(id, outp);
++
++      lenloc = outp;
++      INCPTR(2, outp);        
++
++      /*
++         If the id in the request is unchanged, we must retransmit
++         the old data
++      */
++      if(id == esp->es_client.ea_id)
++              eaptls_retransmit(esp->es_client.ea_session, &outp);
++      else
++              eaptls_send(esp->es_client.ea_session, &outp);
++
++      outlen = (outp - outpacket_buf) - PPP_HDRLEN;
++      PUTSHORT(outlen, lenloc);
++
++      output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
++
++      esp->es_client.ea_id = id;
++
++}
++
++/*
++ * Send an EAP-TLS ack
++ */
++static void
++eap_tls_sendack(esp, id)
++eap_state *esp;
++u_char id;
++{
++      u_char *outp;
++      int outlen;
++      u_char *lenloc;
++
++      outp = outpacket_buf;
++
++      MAKEHEADER(outp, PPP_EAP);
++
++      PUTCHAR(EAP_RESPONSE, outp);
++      PUTCHAR(id, outp);
++      esp->es_client.ea_id = id;
++
++      lenloc = outp;
++      INCPTR(2, outp);
++
++      PUTCHAR(EAPT_TLS, outp);
++      PUTCHAR(0, outp);
++
++      outlen = (outp - outpacket_buf) - PPP_HDRLEN;
++      PUTSHORT(outlen, lenloc);
++
++      output(esp->es_unit, outpacket_buf, PPP_HDRLEN + outlen);
++
++}
++#endif /* USE_EAPTLS */
++
+ static void
+ eap_send_nak(esp, id, type)
+ eap_state *esp;
+@@ -1320,6 +1557,11 @@
+       char rhostname[256];
+       MD5_CTX mdContext;
+       u_char hash[MD5_SIGNATURE_SIZE];
++#ifdef USE_EAPTLS
++      u_char flags;
++      struct eaptls_session *ets = esp->es_client.ea_session;
++#endif /* USE_EAPTLS */
++
+ #ifdef USE_SRP
+       struct t_client *tc;
+       struct t_num sval, gval, Nval, *Ap, Bval;
+@@ -1456,6 +1698,90 @@
+                   esp->es_client.ea_namelen);
+               break;
++#ifdef USE_EAPTLS
++      case EAPT_TLS:
++
++              switch(esp->es_client.ea_state) {
++              
++              case eapListen:
++
++                      GETCHAR(flags, inp);
++                      if(flags & EAP_TLS_FLAGS_START){
++
++                              esp->es_client.ea_using_eaptls = 1;             
++
++                                if (explicit_remote){
++                                        esp->es_client.ea_peer = strdup(remote_name);
++                                        esp->es_client.ea_peerlen = strlen(remote_name);
++                                } else
++                                        esp->es_client.ea_peer = NULL;
++      
++                              /* Init ssl session */
++                              if(!eaptls_init_ssl_client(esp)) {
++                                      dbglog("cannot init ssl");
++                                      eap_send_nak(esp, id, EAPT_TLS);
++                                      esp->es_client.ea_using_eaptls = 0;
++                                      break;
++                              }
++
++                              ets = esp->es_client.ea_session;
++                              eap_tls_response(esp, id);
++                              esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
++                                                              eapTlsRecv);
++                              break;
++                      }
++
++                      /* The server has sent a bad start packet. */
++                      eap_send_nak(esp, id, EAPT_TLS);
++                      break;
++
++              case eapTlsRecvAck:
++                      eap_tls_response(esp, id);
++                      esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck : 
++                                                      eapTlsRecv);
++                      break;
++
++              case eapTlsRecv:
++                      eaptls_receive(ets, inp, len);  
++              
++                      if(ets->frag) {
++                              eap_tls_sendack(esp, id);
++                              esp->es_client.ea_state = eapTlsRecv;
++                              break;
++                      }       
++
++                      if(ets->alert_recv) {
++                              eap_tls_sendack(esp, id);
++                              esp->es_client.ea_state = eapTlsRecvFailure;
++                              break;
++                      }
++
++                      /* Check if TLS handshake is finished */
++                      if(SSL_is_init_finished(ets->ssl)){
++#ifdef MPPE
++                              eaptls_gen_mppe_keys( ets, "client EAP encryption", 1 );
++#endif
++                              eaptls_free_session(ets);
++                              eap_tls_sendack(esp, id);
++                              esp->es_client.ea_state = eapTlsRecvSuccess;
++                              break;
++                      }
++
++                      eap_tls_response(esp,id);
++                        esp->es_client.ea_state = (ets->frag ? eapTlsRecvAck :
++                                                        eapTlsRecv);
++
++                        break;
++
++              default:
++                      eap_send_nak(esp, id, EAPT_TLS);
++                      esp->es_client.ea_using_eaptls = 0;
++                      break;
++              }
++
++              break;
++#endif /* USE_EAPTLS */
++
+ #ifdef USE_SRP
+       case EAPT_SRP:
+               if (len < 1) {
+@@ -1737,6 +2063,11 @@
+       u_char dig[SHA_DIGESTSIZE];
+ #endif /* USE_SRP */
++#ifdef USE_EAPTLS
++      struct eaptls_session *ets;
++      u_char flags;
++#endif /* USE_EAPTLS */
++
+       if (esp->es_server.ea_id != id) {
+               dbglog("EAP: discarding Response %d; expected ID %d", id,
+                   esp->es_server.ea_id);
+@@ -1776,6 +2107,60 @@
+               eap_figure_next_state(esp, 0);
+               break;
++#ifdef USE_EAPTLS
++      case EAPT_TLS:
++              switch(esp->es_server.ea_state) {
++
++              case eapTlsRecv:
++                      ets = (struct eaptls_session *) esp->es_server.ea_session;
++                      eap_figure_next_state(esp, 
++                              eaptls_receive(esp->es_server.ea_session, inp, len));
++              
++                      if(ets->alert_recv) {
++                              eap_send_failure(esp);
++                              break;
++                      }
++                      break;
++
++              case eapTlsRecvAck:
++                      if(len > 1) {
++                              dbglog("EAP-TLS ACK with extra data");  
++                      }
++                      eap_figure_next_state(esp, 0);
++                      break;
++
++              case eapTlsRecvClient:
++                      /* Receive authentication response from client */
++      
++                      GETCHAR(flags, inp);
++
++                      if(len == 1 && !flags) {        /* Ack = ok */
++#ifdef MPPE
++                              eaptls_gen_mppe_keys( esp->es_server.ea_session, "client EAP encryption", 0 );
++#endif
++                              eap_send_success(esp);
++                      }
++                      else {                  /* failure */
++                              eaptls_receive(esp->es_server.ea_session, inp, len);
++                              warn("Server authentication failed");
++                              eap_send_failure(esp);
++                      }
++
++                      eaptls_free_session(esp->es_server.ea_session);
++
++                      break;
++
++              case eapTlsRecvAlertAck:
++                      eap_send_failure(esp);
++                      break;
++
++              default:
++                      eap_figure_next_state(esp, 1);
++                      break;
++              }
++              break;
++#endif /* USE_EAPTLS */
++
+       case EAPT_NOTIFICATION:
+               dbglog("EAP unexpected Notification; response discarded");
+               break;
+@@ -1807,6 +2192,13 @@
+                       esp->es_server.ea_state = eapMD5Chall;
+                       break;
++#ifdef USE_EAPTLS
++                      /* Send EAP-TLS start packet */
++              case EAPT_TLS:
++                      esp->es_server.ea_state = eapTlsStart;
++                      break;
++#endif /* USE_EAPTLS */
++                      
+               default:
+                       dbglog("EAP: peer requesting unknown Type %d", vallen);
+                       switch (esp->es_server.ea_state) {
+@@ -2018,13 +2410,27 @@
+ int id;
+ int len;
+ {
+-      if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)) {
++      if (esp->es_client.ea_state != eapOpen && !eap_client_active(esp)
++#ifdef USE_EAPTLS
++              && esp->es_client.ea_state != eapTlsRecvSuccess
++#endif /* USE_EAPTLS */
++              ) {
+               dbglog("EAP unexpected success message in state %s (%d)",
+                   eap_state_name(esp->es_client.ea_state),
+                   esp->es_client.ea_state);
+               return;
+       }
++#ifdef USE_EAPTLS
++      if(esp->es_client.ea_using_eaptls && esp->es_client.ea_state != 
++              eapTlsRecvSuccess) {
++              dbglog("EAP-TLS unexpected success message in state %s (%d)",
++                    eap_state_name(esp->es_client.ea_state),
++                    esp->es_client.ea_state);
++              return;
++      }
++#endif /* USE_EAPTLS */
++
+       if (esp->es_client.ea_timeout > 0) {
+               UNTIMEOUT(eap_client_timeout, (void *)esp);
+       }
+@@ -2150,6 +2556,9 @@
+       int code, id, len, rtype, vallen;
+       u_char *pstart;
+       u_int32_t uval;
++#ifdef USE_EAPTLS
++      u_char flags;
++#endif /* USE_EAPTLS */
+       if (inlen < EAP_HEADERLEN)
+               return (0);
+@@ -2214,6 +2623,24 @@
+                       }
+                       break;
++#ifdef USE_EAPTLS
++              case EAPT_TLS:
++                      if (len < 1)
++                              break;
++                      GETCHAR(flags, inp);
++                      len--;
++
++                        if(flags == 0 && len == 0){
++                                printer(arg, " Ack");
++                                break;
++                        }
++
++                      printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
++                      printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
++                      printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
++                      break;
++#endif /* USE_EAPTLS */
++
+               case EAPT_SRP:
+                       if (len < 3)
+                               goto truncated;
+@@ -2325,6 +2752,25 @@
+                       }
+                       break;
++#ifdef USE_EAPTLS
++              case EAPT_TLS:
++                      if (len < 1)
++                              break;
++                      GETCHAR(flags, inp);
++                      len--;
++
++                        if(flags == 0 && len == 0){
++                                printer(arg, " Ack");
++                                break;
++                        }
++
++                      printer(arg, flags & EAP_TLS_FLAGS_LI ? " L":" -");
++                      printer(arg, flags & EAP_TLS_FLAGS_MF ? "M":"-");
++                      printer(arg, flags & EAP_TLS_FLAGS_START ? "S":"- ");
++                      
++                      break;                                                                                          
++#endif /* USE_EAPTLS */
++
+               case EAPT_NAK:
+                       if (len <= 0) {
+                               printer(arg, " <missing hint>");
+@@ -2426,3 +2872,4 @@
+       return (inp - pstart);
+ }
++
+diff -Naur ppp-2.4.5/pppd/eap.h ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.h
+--- ppp-2.4.5/pppd/eap.h       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/eap.h      2010-10-01 15:17:54.214270927 +0200
+@@ -84,6 +84,16 @@
+       eapClosed,      /* Authentication not in use */
+       eapListen,      /* Client ready (and timer running) */
+       eapIdentify,    /* EAP Identify sent */
++      eapTlsStart,    /* Send EAP-TLS start packet */
++      eapTlsRecv,     /* Receive EAP-TLS tls data */
++      eapTlsSendAck,  /* Send EAP-TLS ack */
++      eapTlsSend,     /* Send EAP-TLS tls data */
++      eapTlsRecvAck,  /* Receive EAP-TLS ack */
++      eapTlsRecvClient,       /* Receive EAP-TLS auth response from client*/
++      eapTlsSendAlert,        /* Send EAP-TLS tls alert (server)*/
++      eapTlsRecvAlertAck,     /* Receive EAP-TLS ack after sending alert */
++      eapTlsRecvSuccess,      /* Receive EAP success */
++      eapTlsRecvFailure,      /* Receive EAP failure */
+       eapSRP1,        /* Sent EAP SRP-SHA1 Subtype 1 */
+       eapSRP2,        /* Sent EAP SRP-SHA1 Subtype 2 */
+       eapSRP3,        /* Sent EAP SRP-SHA1 Subtype 3 */
+@@ -95,9 +105,18 @@
+ #define       EAP_STATES      \
+       "Initial", "Pending", "Closed", "Listen", "Identify", \
++      "TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\
++      "TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \
+       "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
+-#define       eap_client_active(esp)  ((esp)->es_client.ea_state == eapListen)
++#ifdef USE_EAPTLS
++#define       eap_client_active(esp)  ((esp)->es_client.ea_state != eapInitial ||\
++                               (esp)->es_client.ea_state != eapPending ||\
++                               (esp)->es_client.ea_state != eapClosed)
++#else
++#define eap_client_active(esp)        ((esp)->es_client.ea_state == eapListen)
++#endif /* USE_EAPTLS */
++
+ #define       eap_server_active(esp)  \
+       ((esp)->es_server.ea_state >= eapIdentify && \
+        (esp)->es_server.ea_state <= eapMD5Chall)
+@@ -112,11 +131,17 @@
+       u_short ea_namelen;     /* Length of our name */
+       u_short ea_peerlen;     /* Length of peer's name */
+       enum eap_state_code ea_state;
++#ifdef USE_EAPTLS
++      enum eap_state_code ea_prev_state;
++#endif
+       u_char ea_id;           /* Current id */
+       u_char ea_requests;     /* Number of Requests sent/received */
+       u_char ea_responses;    /* Number of Responses */
+       u_char ea_type;         /* One of EAPT_* */
+       u_int32_t ea_keyflags;  /* SRP shared key usage flags */
++#ifdef USE_EAPTLS
++      bool ea_using_eaptls;
++#endif
+ };
+ /*
+@@ -139,7 +164,12 @@
+  * Timeouts.
+  */
+ #define       EAP_DEFTIMEOUT          3       /* Timeout (seconds) for rexmit */
++#ifdef USE_EAPTLS
++#define       EAP_DEFTRANSMITS        30      /* max # times to transmit */
++                                      /* certificates can be long ... */
++#else
+ #define       EAP_DEFTRANSMITS        10      /* max # times to transmit */
++#endif /* USE_EAPTLS */
+ #define       EAP_DEFREQTIME          20      /* Time to wait for peer request */
+ #define       EAP_DEFALLOWREQ         20      /* max # times to accept requests */
+diff -Naur ppp-2.4.5/pppd/md5.c ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.c
+--- ppp-2.4.5/pppd/md5.c       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.c      2010-10-01 15:17:54.214270927 +0200
+@@ -33,6 +33,8 @@
+  ***********************************************************************
+  */
++#ifndef USE_EAPTLS
++
+ #include <string.h>
+ #include "md5.h"
+@@ -305,3 +307,5 @@
+  ** End of md5.c                                                      **
+  ******************************** (cut) ********************************
+  */
++#endif /* USE_EAPTLS */
++
+diff -Naur ppp-2.4.5/pppd/md5.h ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.h
+--- ppp-2.4.5/pppd/md5.h       2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/md5.h      2010-10-01 15:17:54.215271014 +0200
+@@ -36,6 +36,7 @@
+  ** documentation and/or software.                                    **
+  ***********************************************************************
+  */
++#ifndef USE_EAPTLS
+ #ifndef __MD5_INCLUDE__
+@@ -63,3 +64,5 @@
+ #define __MD5_INCLUDE__
+ #endif /* __MD5_INCLUDE__ */
++
++#endif /* USE_EAPTLS */
+diff -Naur ppp-2.4.5/pppd/options.c ppp-2.4.5-eaptls-mppe-0.99/pppd/options.c
+--- ppp-2.4.5/pppd/options.c   2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/options.c  2010-10-01 15:17:54.215271014 +0200
+@@ -119,6 +119,10 @@
+ bool  dryrun;                 /* print out option values and exit */
+ char  *domain;                /* domain name set by domain option */
+ int   child_wait = 5;         /* # seconds to wait for children at exit */
++#ifdef USE_EAPTLS
++bool  only_update_crl_server = 0;     /* update server crl and exit */
++bool  only_update_crl_client = 0;     /* update client crl and exit */
++#endif /* USE_EAPTLS */
+ #ifdef MAXOCTETS
+ unsigned int  maxoctets = 0;    /* default - no limit */
+@@ -320,6 +324,12 @@
+     { "mo-timeout", o_int, &maxoctets_timeout,
+       "Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },
+ #endif
++#ifdef USE_EAPTLS
++    { "only-update-crl-server", o_bool, &only_update_crl_server,
++      "Update server CA CRLs and exit", 1 },
++    { "only-update-crl-client", o_bool, &only_update_crl_client,
++      "Update client CA CRLs and exit", 1 },
++#endif /* USE_EAPTLS */
+     { NULL }
+ };
+diff -Naur ppp-2.4.5/pppd/pathnames.h ppp-2.4.5-eaptls-mppe-0.99/pppd/pathnames.h
+--- ppp-2.4.5/pppd/pathnames.h 2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/pathnames.h        2010-10-01 15:17:54.215271014 +0200
+@@ -21,6 +21,13 @@
+ #define _PATH_UPAPFILE         _ROOT_PATH "/etc/ppp/pap-secrets"
+ #define _PATH_CHAPFILE         _ROOT_PATH "/etc/ppp/chap-secrets"
+ #define _PATH_SRPFILE          _ROOT_PATH "/etc/ppp/srp-secrets"
++
++#ifdef USE_EAPTLS
++#define _PATH_EAPTLSCLIFILE   _ROOT_PATH "/etc/ppp/eaptls-client"
++#define _PATH_EAPTLSSERVFILE  _ROOT_PATH "/etc/ppp/eaptls-server"
++#define _PATH_OPENSSLCONFFILE _ROOT_PATH "/etc/ppp/openssl.cnf"
++#endif /* USE_EAPTLS */
++
+ #define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
+ #define _PATH_IPUP     _ROOT_PATH "/etc/ppp/ip-up"
+ #define _PATH_IPDOWN   _ROOT_PATH "/etc/ppp/ip-down"
+diff -Naur ppp-2.4.5/pppd/plugins/Makefile.linux ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/Makefile.linux
+--- ppp-2.4.5/pppd/plugins/Makefile.linux      2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/Makefile.linux     2010-10-01 15:17:54.215271014 +0200
+@@ -4,6 +4,9 @@
+ LDFLAGS       = -shared
+ INSTALL       = install
++# EAP-TLS
++CFLAGS += -DUSE_EAPTLS=1
++
+ DESTDIR = $(INSTROOT)@DESTDIR@
+ BINDIR = $(DESTDIR)/sbin
+ MANDIR = $(DESTDIR)/share/man/man8
+diff -Naur ppp-2.4.5/pppd/plugins/passprompt.c ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passprompt.c
+--- ppp-2.4.5/pppd/plugins/passprompt.c        2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passprompt.c       2010-10-01 15:17:54.215271014 +0200
+@@ -107,4 +107,7 @@
+ {
+     add_options(options);
+     pap_passwd_hook = promptpass;
++#ifdef USE_EAPTLS
++    eaptls_passwd_hook = promptpass;
++#endif
+ }
+diff -Naur ppp-2.4.5/pppd/plugins/passwordfd.c ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passwordfd.c
+--- ppp-2.4.5/pppd/plugins/passwordfd.c        2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/plugins/passwordfd.c       2010-10-01 15:17:54.216270820 +0200
+@@ -79,4 +79,9 @@
+     chap_check_hook = pwfd_check;
+     chap_passwd_hook = pwfd_passwd;
++
++#ifdef USE_EAPTLS
++    eaptls_check_hook = pwfd_check;
++    eaptls_passwd_hook = pwfd_passwd;
++#endif
+ }
+diff -Naur ppp-2.4.5/pppd/pppd.h ppp-2.4.5-eaptls-mppe-0.99/pppd/pppd.h
+--- ppp-2.4.5/pppd/pppd.h      2009-11-16 23:26:07.000000000 +0100
++++ ppp-2.4.5-eaptls-mppe-0.99/pppd/pppd.h     2010-10-01 15:17:54.216270820 +0200
+@@ -320,6 +320,10 @@
+ extern bool   dryrun;         /* check everything, print options, exit */
+ extern int    child_wait;     /* # seconds to wait for children at end */
++#ifdef USE_EAPTLS
++extern char   *crl_dir;
++#endif /* USE_EAPTLS */
++
+ #ifdef MAXOCTETS
+ extern unsigned int maxoctets;             /* Maximum octetes per session (in bytes) */
+ extern int       maxoctets_dir;      /* Direction :
+@@ -717,6 +721,11 @@
+ extern int (*chap_passwd_hook) __P((char *user, char *passwd));
+ extern void (*multilink_join_hook) __P((void));
++#ifdef USE_EAPTLS
++extern int (*eaptls_check_hook) __P((void));
++extern int (*eaptls_passwd_hook) __P((char *user, char *passwd));
++#endif
++
+ /* Let a plugin snoop sent and received packets.  Useful for L2TP */
+ extern void (*snoop_recv_hook) __P((unsigned char *p, int len));
+ extern void (*snoop_send_hook) __P((unsigned char *p, int len));
diff --git a/pkgs/ppp/patches/ppp-2.4.5-eth.patch b/pkgs/ppp/patches/ppp-2.4.5-eth.patch
new file mode 100644 (file)
index 0000000..0e7e525
--- /dev/null
@@ -0,0 +1,124 @@
+diff -up ppp-2.4.5/pppd/ether.c.inc.eth ppp-2.4.5/pppd/ether.c.inc
+--- ppp-2.4.5/pppd/ether.c.inc.eth     2011-06-01 10:28:35.356139063 +0200
++++ ppp-2.4.5/pppd/ether.c.inc 2011-06-01 11:20:37.876897352 +0200
+@@ -0,0 +1,46 @@
++#define PREF_ETH   "eth"
++#define PREF_EM    "em"
++
++static char *dev_file = "/proc/self/net/dev";
++
++/*
++ * get_first_ethernet - return the name of the first ethernet-style
++ * interface on this system.
++ */
++char *
++get_first_ethernet()
++{
++  FILE *f;
++  char buf[255], *dv, *smc;
++  char pci[16];
++
++  memset(pci, 0, sizeof(pci));
++  if ((f = fopen(dev_file, "r")) != NULL)
++  {
++    // go through network dev file
++    while (fgets (buf, sizeof(buf), f) != NULL)
++    {
++      // the line describes interface
++      if ((smc = strchr(buf, ':')) != NULL)
++      {
++        // trim white characters
++        for (dv=buf, *smc=0; *dv <= ' '; dv++) ;
++        // is "eth" (originial ethernet name) or "em" (ethernet on board)
++        if (!strncmp(dv, PREF_ETH, strlen(PREF_ETH)) ||
++            !strncmp(dv, PREF_EM, strlen(PREF_EM)))
++        {
++          return strdup(dv);
++        }
++        // remember the first pci NIC-card
++        if (strlen(pci) == 0 && dv[0] == 'p' && isdigit(dv[1]))
++        {
++          strcpy(pci, dv);
++        }
++      }
++    }
++    fclose(f);
++  }
++  // return pci NIC-card or nil if no if name
++  return strlen(pci) > 0 ? strdup(pci) : 0L;
++}
++
+diff -up ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c.eth ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c
+--- ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c.eth      2011-06-01 09:39:13.099343548 +0200
++++ ppp-2.4.5/pppd/plugins/rp-pppoe/pppoe-discovery.c  2011-06-01 11:41:02.188252304 +0200
+@@ -47,6 +47,8 @@
+ #include <net/if_arp.h>
+ #endif
++#include "../../ether.c.inc"
++
+ char *xstrdup(const char *s);
+ void usage(void);
+@@ -686,7 +688,7 @@ int main(int argc, char *argv[])
+     /* default interface name */
+     if (!conn->ifName)
+-      conn->ifName = strdup("eth0");
++      conn->ifName = get_first_ethernet();
+     conn->discoverySocket = -1;
+     conn->sessionSocket = -1;
+diff -up ppp-2.4.5/pppd/sys-linux.c.eth ppp-2.4.5/pppd/sys-linux.c
+--- ppp-2.4.5/pppd/sys-linux.c.eth     2011-06-01 09:39:13.074343397 +0200
++++ ppp-2.4.5/pppd/sys-linux.c 2011-06-01 11:50:13.736565685 +0200
+@@ -144,6 +144,8 @@
+ #include <sys/locks.h>
+ #endif
++#include "ether.c.inc"
++
+ #ifdef INET6
+ #ifndef _LINUX_IN6_H
+ /*
+@@ -1869,16 +1871,6 @@ get_if_hwaddr(u_char *addr, char *name)
+       return ret;
+ }
+-/*
+- * get_first_ethernet - return the name of the first ethernet-style
+- * interface on this system.
+- */
+-char *
+-get_first_ethernet()
+-{
+-      return "eth0";
+-}
+-
+ /********************************************************************
+  *
+  * Return user specified netmask, modified by any mask we might determine
+@@ -2783,6 +2775,7 @@ ether_to_eui64(eui64_t *p_eui64)
+     struct ifreq ifr;
+     int skfd;
+     const unsigned char *ptr;
++    char warn_msg[80];
+     skfd = socket_fd(PF_INET6, SOCK_DGRAM, 0);
+     if(skfd == -1)
+@@ -2791,11 +2784,13 @@ ether_to_eui64(eui64_t *p_eui64)
+         return 0;
+     }
+-    strcpy(ifr.ifr_name, "eth0");
++    strcpy(ifr.ifr_name, get_first_ethernet());
+     if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
+     {
+         close(skfd);
+-        warn("could not obtain hardware address for eth0");
++        snprintf(warn_msg, sizeof(warn_msg),
++          "could not obtain hardware address for %s", ifr.ifr_name);
++        warn(warn_msg);
+         return 0;
+     }
+     close(skfd);
diff --git a/pkgs/ppp/patches/ppp-2.4.5-lock.patch b/pkgs/ppp/patches/ppp-2.4.5-lock.patch
new file mode 100644 (file)
index 0000000..6bda620
--- /dev/null
@@ -0,0 +1,12 @@
+diff -up ppp-2.4.5/pppd/utils.c.lock ppp-2.4.5/pppd/utils.c
+--- ppp-2.4.5/pppd/utils.c.lock        2011-05-30 15:30:36.432371849 +0200
++++ ppp-2.4.5/pppd/utils.c     2011-05-30 15:30:48.575495854 +0200
+@@ -859,7 +859,7 @@ complete_read(int fd, void *buf, size_t 
+ /* 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"
diff --git a/pkgs/ppp/patches/ppp-2.4.5-man.patch b/pkgs/ppp/patches/ppp-2.4.5-man.patch
new file mode 100644 (file)
index 0000000..9ad4f2e
--- /dev/null
@@ -0,0 +1,94 @@
+--- ppp-2.4.5/chat/chat.8.man  2010-12-16 10:20:08.000000000 +0000
++++ ppp-2.4.5/chat/chat.8      2010-12-19 16:40:31.000000000 +0000
+@@ -50,7 +50,7 @@
+ to \fIstderr\fR.
+ .TP
+ .B \-E
+-Enables environment variable substituion within chat scripts using the
++Enables environment variable substitution within chat scripts using the
+ standard \fI$xxx\fR syntax.
+ .TP
+ .B \-v
+@@ -77,7 +77,7 @@
+ error messages from being sent to the SYSLOG.
+ .TP
+ .B \-T \fI<phone number>
+-Pass in an arbitary string, usually a phone number, that will be
++Pass in an arbitrary string, usually a phone number, that will be
+ substituted for the \\T substitution metacharacter in a send string.
+ .TP
+ .B \-U \fI<phone number 2>
+@@ -204,7 +204,7 @@
+ .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,
+-you must explicitely add them to your string.
++you must explicitly add them to your string.
+ .LP
+ The SAY strings could be used to give progress messages in sections of
+ the script where you want to have 'ECHO OFF' but still let the user
+@@ -457,7 +457,7 @@
+ Environment variables are available within chat scripts, if  the \fI\-E\fR
+ option was specified in the command line. The metacharacter \fI$\fR is used
+ to introduce the name of the environment variable to substitute. If the
+-substition fails, because the requested environment variable is not set,
++substitution fails, because the requested environment variable is not set,
+ \fInothing\fR is replaced for the variable.
+ .SH TERMINATION CODES
+ The \fIchat\fR program will terminate with the following completion
+--- ppp-2.4.5/pppd/pppd.8.man  2010-12-16 10:20:10.000000000 +0000
++++ ppp-2.4.5/pppd/pppd.8      2010-12-21 23:26:50.000000000 +0000
+@@ -195,7 +195,7 @@
+ .TP
+ .B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
+ Set the local and/or remote 64-bit interface identifier. Either one may be
+-omitted. The identifier must be specified in standard ascii notation of
++omitted. The identifier must be specified in standard ASCII notation of
+ IPv6 addresses (e.g. ::dead:beef). If the
+ \fIipv6cp\-use\-ipaddr\fR
+ option is given, the local identifier is the local IPv4 address (see above).
+@@ -328,7 +328,7 @@
+ The \fIdemand\fR option implies the \fIpersist\fR option.  If this
+ behaviour is not desired, use the \fInopersist\fR option after the
+ \fIdemand\fR option.  The \fIidle\fR and \fIholdoff\fR
+-options are also useful in conjuction with the \fIdemand\fR option.
++options are also useful in conjunction with the \fIdemand\fR option.
+ .TP
+ .B domain \fId
+ Append the domain name \fId\fR to the local host name for authentication
+@@ -515,7 +515,7 @@
+ send before it rejects the options. The default value is 3.
+ .TP
+ .B ipxcp\-max\-terminate \fIn
+-Set the maximum nuber of IPXCP terminate request frames before the
++Set the maximum number of IPXCP terminate request frames before the
+ local system considers that the peer is not listening to them. The
+ default value is 3.
+ .TP
+@@ -907,7 +907,7 @@
+ device.  The \fIscript\fR will be run in a child process with the
+ pseudo-tty master as its standard input and output.  An explicit
+ device name may not be given if this option is used.  (Note: if the
+-\fIrecord\fR option is used in conjuction with the \fIpty\fR option,
++\fIrecord\fR option is used in conjunction with the \fIpty\fR option,
+ the child process will have pipes on its standard input and output.)
+ .TP
+ .B receive\-all
+@@ -1015,7 +1015,7 @@
+ .TP
+ .B srp\-use\-pseudonym
+ When operating as an EAP SRP\-SHA1 client, attempt to use the pseudonym
+-stored in ~/.ppp_psuedonym first as the identity, and save in this
++stored in ~/.ppp_pseudonym first as the identity, and save in this
+ file any pseudonym offered by the peer during authentication.
+ .TP
+ .B sync
+@@ -1885,7 +1885,7 @@
+    prior written permission.
+ .LP
+ 4. Redistributions of any form whatsoever must retain the following
+-   acknowledgments:
++   acknowledgements:
+ .br
+    "This product includes software developed by Computing Services
+     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
diff --git a/pkgs/ppp/patches/ppp-2.4.5-ppp_resolv.patch b/pkgs/ppp/patches/ppp-2.4.5-ppp_resolv.patch
new file mode 100644 (file)
index 0000000..e2f0e29
--- /dev/null
@@ -0,0 +1,13 @@
+diff -up ppp-2.4.5/scripts/ip-up.local.add.ppp_resolv ppp-2.4.5/scripts/ip-up.local.add
+--- ppp-2.4.5/scripts/ip-up.local.add.ppp_resolv       2010-07-13 10:29:23.227943994 +0200
++++ ppp-2.4.5/scripts/ip-up.local.add  2010-07-13 10:32:27.729695487 +0200
+@@ -18,6 +18,9 @@ if [ -n "$USEPEERDNS" -a -f /var/run/ppp
+               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
index 2c49927736a4c464ab65bc003e2e13c3f458d7e1..bd01883d8b6797c5bb862675c4732326f4d0570c 100644 (file)
@@ -1,30 +1,30 @@
 diff -up ppp-2.4.5/pppd/pathnames.h.var_run_ppp ppp-2.4.5/pppd/pathnames.h
---- ppp-2.4.5/pppd/pathnames.h.var_run_ppp     2010-02-12 16:36:14.479362718 +0100
-+++ ppp-2.4.5/pppd/pathnames.h 2010-02-12 16:38:24.995330994 +0100
-@@ -7,9 +7,13 @@
+--- ppp-2.4.5/pppd/pathnames.h.var_run_ppp     2010-11-23 10:14:24.557427000 +0100
++++ ppp-2.4.5/pppd/pathnames.h 2010-11-23 10:24:07.432426793 +0100
+@@ -6,8 +6,9 @@
  #ifdef HAVE_PATHS_H
  #include <paths.h>
-+#define _SUBPATH_PPP       "ppp/"
+-
++#define _PPP_SUBDIR   "ppp/"
  #else /* HAVE_PATHS_H */
++#define _PPP_SUBDIR
  #ifndef _PATH_VARRUN
  #define _PATH_VARRUN  "/etc/ppp/"
-+#define _SUBPATH_PPP
-+#else
-+#define _SUBPATH_PPP       "ppp/"
  #endif
- #define _PATH_DEVNULL "/dev/null"
- #endif /* HAVE_PATHS_H */
-@@ -46,10 +50,10 @@
+@@ -46,13 +54,9 @@
  #endif /* IPX_CHANGE */
  
  #ifdef __STDC__
 -#define _PATH_PPPDB   _ROOT_PATH _PATH_VARRUN "pppd2.tdb"
-+#define _PATH_PPPDB   _ROOT_PATH _PATH_VARRUN _SUBPATH_PPP "pppd2.tdb"
++#define _PATH_PPPDB   _ROOT_PATH _PATH_VARRUN _PPP_SUBDIR "pppd2.tdb"
  #else /* __STDC__ */
- #ifdef HAVE_PATHS_H
+-#ifdef HAVE_PATHS_H
 -#define _PATH_PPPDB   "/var/run/pppd2.tdb"
-+#define _PATH_PPPDB   "/var/run/ppp/pppd2.tdb"
- #else
- #define _PATH_PPPDB   "/etc/ppp/pppd2.tdb"
- #endif
+-#else
+-#define _PATH_PPPDB   "/etc/ppp/pppd2.tdb"
+-#endif
++#define _PATH_PPPDB   _PATH_VARRUN _PPP_SUBDIR "pppd2.tdb"
+ #endif /* __STDC__ */
+ #ifdef PLUGIN
index 0eb7774ac0815356bc8d05f95bdddabacb43188a..de1eebbd29780ec07945c53e4a43c309562bf08d 100644 (file)
@@ -26,7 +26,7 @@ include $(PKGROOT)/Include
 
 PKG_NAME       = ppp
 PKG_VER        = 2.4.5
-PKG_REL        = 1
+PKG_REL        = 2
 
 PKG_MAINTAINER =
 PKG_GROUPS     = System/Daemons
@@ -34,7 +34,7 @@ PKG_URL        = ftp://ftp.samba.org/pub/ppp/
 PKG_LICENSE    = BSD and LGPLv2+ and GPLv2+ and Public Domain
 PKG_SUMMARY    = The PPP (Point-to-Point Protocol) daemon.
 
-PKG_BUILD_DEPS+= libpcap-devel linux-atm-devel pam-devel
+PKG_BUILD_DEPS+= libpcap-devel linux-atm-devel openssl-devel pam-devel
 
 define PKG_DESCRIPTION
        The ppp package contains the PPP (Point-to-Point Protocol) daemon and \
@@ -49,8 +49,6 @@ PKG_TARBALL    = $(THISAPP).tar.gz
 PKG_PACKAGES  += $(PKG_NAME)-devel
 
 define STAGE_PREPARE_CMDS
-       cd $(DIR_APP) && sed -e "s/^LIBS =/LIBS=-lutil/" -i pppd/Makefile.linux
-
        cd $(DIR_APP) && sed -e "s@^RUNDIR .*@RUNDIR = /var/run/ppp@" \
                -e "s@^LOGDIR .*@LOGDIR = /var/log/ppp@" \
                -i linux/Makefile.top
@@ -67,8 +65,7 @@ define STAGE_BUILD
                ./configure \
                        --prefix=/usr
 
-       cd $(DIR_APP) && make CC="gcc $(CFLAGS)" $(PARALLELISMFLAGS) \
-               HAVE_INET6=yes USE_PAM=y
+       cd $(DIR_APP) && make CC="gcc $(CFLAGS)" $(PARALLELISMFLAGS)
 endef
 
 define STAGE_INSTALL