From: Paul Mackerras Date: Fri, 26 Nov 2021 00:05:06 +0000 (+1100) Subject: Merge branch 'pppoe-discovery' of https://github.com/pali/ppp X-Git-Tag: ppp-2.5.0~50 X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=032020241d270c53dff479a7b0eb7fe487c56a78;hp=e94a5fcb7620cf399ad1c2666b8093d6ca3df24b Merge branch 'pppoe-discovery' of https://github.com/pali/ppp Signed-off-by: Paul Mackerras --- diff --git a/.github/workflows/buildroot.yaml b/.github/workflows/buildroot.yaml index 4da78dd..3429d17 100644 --- a/.github/workflows/buildroot.yaml +++ b/.github/workflows/buildroot.yaml @@ -10,7 +10,7 @@ jobs: libc_name: [glibc, uclibc, musl] steps: - name: Checkout Buildroot sources - run: git clone --depth=1 --branch=2020.11.1 https://git.busybox.net/buildroot + run: git clone --depth=1 --branch=2021.02.3 https://git.busybox.net/buildroot - name: Select latest PPP version working-directory: buildroot/package/pppd run: | @@ -24,10 +24,26 @@ jobs: rm -f 0001-pppd-Fix-bounds-check.patch # Get package sources from head of master branch sed -i "/PPPD_VERSION =/c\\PPPD_VERSION = ${GITHUB_SHA}" pppd.mk - sed -i '/PPPD_SITE =/c\\PPPD_SITE = https://github.com/paulusmack/ppp' pppd.mk + sed -i '/PPPD_SITE =/c\\PPPD_SITE = https://github.com/ppp-project/ppp' pppd.mk sed -i '9iPPPD_SITE_METHOD = git' pppd.mk - # Plugin rp-pppoe has been renamed in "pppoe" - sed -i 's/rp-pppoe/pppoe/g' pppd.mk + # Tell Buildroot to run autoreconf.sh + sed -i '16iPPPD_AUTORECONF = YES' pppd.mk + # Filters feature needs libpcap + sed -i '17iPPPD_DEPENDENCIES = libpcap openssl' pppd.mk + # Enable verbose build commands and force OpenSSL directory, otherwise the host system one might be used instead of Buildroot one + sed -i '18iPPPD_CONF_OPTS = --disable-silent-rules --with-openssl="$(STAGING_DIR)/usr"' pppd.mk + # Do not install build artifacts to staging directory + sed -i 's/PPPD_INSTALL_STAGING = YES/PPPD_INSTALL_STAGING = NO/' pppd.mk + # Delete custom configuration tool, it is now automatically handled by Buildroot + sed -i '/PPPD_CONFIGURE_CMDS/,+4d' pppd.mk + # Delete custom build rule, it is now generated by Autotools + sed -i '/define PPPD_BUILD_CMDS/,+4d' pppd.mk + # Delete custom installation to target rule, it is now generated by Autotools + sed -i '/define PPPD_INSTALL_TARGET_CMDS/,+27d' pppd.mk + # Delete custom staging installation rule as PPP does not need to be installed to staging in this CI + sed -i '/define PPPD_INSTALL_STAGING_CMDS/,+3d' pppd.mk + # Tell Buildroot that this package uses Autotools + sed -i 's/$(eval $(generic-package))/$(eval $(autotools-package))/' pppd.mk - name: Enable PPP build working-directory: buildroot run: | diff --git a/.github/workflows/solaris.yaml b/.github/workflows/solaris.yaml index 32ef909..b36b1b5 100644 --- a/.github/workflows/solaris.yaml +++ b/.github/workflows/solaris.yaml @@ -12,6 +12,7 @@ jobs: with: run: | pkg update - pkg install gcc - ./configure + pkg install gcc automake autoconf libtool + ./autogen.sh CFLAGS="-Wno-deprecated-declarations" make + make install diff --git a/.github/workflows/ubuntu.yaml b/.github/workflows/ubuntu.yaml new file mode 100644 index 0000000..028193b --- /dev/null +++ b/.github/workflows/ubuntu.yaml @@ -0,0 +1,23 @@ +name: Build and Test +on: [push, pull_request] + +jobs: + build_and_test: + runs-on: ubuntu-latest + env: + configure_flags: --enable-ipxcp --enable-multilink + + steps: + - uses: actions/checkout@v2 + + - name: install required packages + run: sudo DEBIAN_FRONTEND=noninteractive apt-get -y -qq install build-essential autoconf automake pkg-config libtool m4 autoconf-archive libssl-dev libatm1-dev libpcap-dev + + - name: configure + run: ./autogen.sh ${{ env.configure_flags }} + + - name: build + run: make V=1 CFLAGS="-O2 -g -Wno-unused-result" + + - name: distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS="${{ env.configure_flags }}" diff --git a/.gitignore b/.gitignore index eb7087c..133a3df 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,57 @@ *.o *.so *.a +*.pc *.cat8 +*.lo +*.la +*.swp +.deps +.libs + + +# http://www.gnu.org/software/autoconf +autom4te.cache +/autoscan.log +/autoscan-*.log +/aclocal.m4 +/compile +/config.cache +/config.guess +/config.log +/config.status +/config.sub +/configure +/configure.scan +/depcomp +/install-sh +/test-driver +/missing +/INSTALL +/pppd/stamp-h1 +/pppd/stamp-h2 +/pppd/config.h +/pppd/config.h.in +/pppd/pppdconf.h + +# https://www.gnu.org/software/libtool/ +/libtool +/ltmain.sh + +# http://www.gnu.org/software/m4/ +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 + +# Generated Makefile Makefile +Makefile.in + +# Test related stuff +utest_* +test-suite.log + +# Distfiles +/ppp-*.tar.gz diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..ff1a48f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +The pppd Project +https://github.com/ppp-project/ppp + +Primary Author of this package: +Linux Paul Mackerras +Solaris James Carlson + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b3846c7 --- /dev/null +++ b/COPYING @@ -0,0 +1,7 @@ +Copyrights: +*********** + +All of the code can be freely used and redistributed. The individual +source files each have their own copyright and permission notice. +Pppd, pppstats and pppdump are under BSD-style notices. Some of the +pppd plugins are GPL'd. Chat is public domain. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..f9fadce --- /dev/null +++ b/ChangeLog @@ -0,0 +1,4 @@ +2021-07-11 Eivind Naess + + Introduction of Autotools to pppd project + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..15b2d09 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,80 @@ +ACLOCAL_AMFLAGS="-Im4" + +SUBDIRS = chat contrib pppd pppstats pppdump + +if WITH_PLUGINS +SUBDIRS += pppd/plugins +endif + +DIST_SUBDIRS = $(SUBDIRS) common include modules scripts + +# +# *HACK* +# This is to work around the kernel module for PPP on Sun Solaris +if SUNOS +all-am: + (cd solaris ; $(MAKE) -f Makefile) + +clean-generic: + (cd solaris ; $(MAKE) -f Makefile clean) + +install-am: + (cd solaris ; $(MAKE) -f Makefile install) +endif + +install-data-hook: + (cd $(DESTDIR)/$(sysconfdir)/$(PACKAGE) ; \ + chmod 600 chap-secrets pap-secrets eaptls-server eaptls-client) + +sampledir = $(sysconfdir)/$(PACKAGE) +sample_DATA = \ + etc.ppp/options \ + etc.ppp/chap-secrets \ + etc.ppp/pap-secrets \ + etc.ppp/eaptls-server \ + etc.ppp/eaptls-client \ + etc.ppp/openssl.cnf + +EXTRA_README = \ + Changes-2.3 \ + FAQ \ + README \ + README.cbcp \ + README.eap-srp \ + README.eap-tls \ + README.linux \ + README.MPPE \ + README.MSCHAP80 \ + README.MSCHAP81 \ + README.pppoe \ + README.pppol2tp \ + README.pwfd \ + README.sol2 \ + PLUGINS \ + SETUP \ + Submitting-patches.md + +EXTRA_SOLARIS = \ + solaris/Makedefs \ + solaris/Makedefs.gcc \ + solaris/Makedefs.sol2 \ + solaris/Makefile.sol2 \ + solaris/Makefile.sol2-64 \ + solaris/Makefile.sol2-64x \ + solaris/Makefile.sol2gcc \ + solaris/Makefile.sol2gcc-64 \ + solaris/Makefile.sol2gcc-64x \ + solaris/Makefile.top \ + solaris/ppp_ahdlc.c \ + solaris/ppp_ahdlc_mod.c \ + solaris/ppp.c \ + solaris/ppp_comp.c \ + solaris/ppp_comp_mod.c \ + solaris/ppp.conf \ + solaris/ppp_mod.c \ + solaris/ppp_mod.h + +EXTRA_DIST= \ + $(sample_DATA) \ + $(EXTRA_README) \ + $(EXTRA_SOLARIS) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..53a5e1a --- /dev/null +++ b/NEWS @@ -0,0 +1,285 @@ +What's new since ppp-2.4.9 (unreleased) +*************************************** + +* New pppd options: + - ipv6-up-script + - ipv6-down-script + +What's new in ppp-2.4.9. +************************ + +* Support for new EAP (Extensible Authentication Protocol) methods: + - Support for EAP-TLS, from Jan Just Keijser and others + - Support for EAP-MSCHAPv2, from Eivind Næss, Thomas Omerzu, Tijs + Van Buggenhout and others + +* New pppd options: + - chap-timeout + - chapms-strip-domain + - replacedefaultroute + - noreplacedefaultroute + - ipv6cp-accept-remote + - lcp-echo-adaptive + - ip-up-script + - ip-down-script + - ca + - capath + - cert + - key + - crl-dir + - crl + - max-tls-version + - need-peer-eap + +* Fixes for CVE-2020-8597 and CVE-2015-3310. + +* libpcap is now required when compiling on Linux (previously, if + libpcap was not present, pppd would be compiled without packet + filtering support). + +* The rp-pppoe plugin has been renamed to pppoe, to distinguish it + from the upstream rp-pppoe code. Its options have changed names, + but the old names are kept as aliases. + +* The configure script now supports cross-compilation. + +* Many bug fixes and cleanups. + + +What was new in ppp-2.4.8. +************************** + +* New pppd options have been added: + - ifname, to set the name for the PPP interface device + - defaultroute-metric, to set the metric for the default route + - defaultroute6, to add an IPv6 default route (with nodefaultroute6 + to prevent adding an IPv6 default route) + - up_sdnotify, to have pppd notify systemd when the link is up. + +* The rp-pppoe plugin has new options: + - host-uniq, to set the Host-Uniq value to send + - pppoe-padi-timeout, to set the timeout for discovery packets + - pppoe-padi-attempts, to set the number of discovery attempts. + +* Added the CLASS attribute in radius packets. + +* Sundry bug fixes. + +* Fixed warnings and issues found by static analysis. + +* Added Submitting-patches.md. + + +What was new in ppp-2.4.7. +************************** + +* Fixed a potential security issue in parsing option files (CVE-2014-3158). + +* There is a new "stop-bits" option, which takes an argument of 1 or 2, + indicating the number of stop bits to use for async serial ports. + +* Various bug fixes. + + +What was new in ppp-2.4.6. +************************** + +* Man page updates. + +* Several bug fixes. + +* Options files can now set and unset environment variables for + scripts. + +* The timeout for chat scripts can now be taken from an environment + variable. + +* There is a new option, master_detach, which allows pppd to detach + from the controlling terminal when it is the multilink bundle master + but its own link has terminated, even if the nodetach option has + been given. + + +What was new in ppp-2.4.5. +************************** + +* Under Linux, pppd can now operate in a mode where it doesn't request + the peer's IP address, as some peers refuse to supply an IP address. + Since Linux supports device routes as well as gateway routes, it's + possible to have no remote IP address assigned to the ppp interface + and still route traffic over it. + +* Pppd now works better with 3G modems that do strange things such as + sending IPCP Configure-Naks with the same values over and over again. + +* The PPP over L2TP plugin is included, which works with the pppol2tp + PPP channel code in the Linux kernel. This allows pppd to be used + to set up tunnels using the Layer 2 Tunneling Protocol. + +* A new 'enable-session' option has been added, which enables session + accounting via PAM or wtwp/wtmpx, as appropriate. See the pppd man + page for details. + +* Several bugs have been fixed. + + +What was new in ppp-2.4.4. +************************** + +* Pppd will now run /etc/ppp/ip-pre-up, if it exists, after creating + the ppp interface and configuring its IP addresses but before + bringing it up. This can be used, for example, for adding firewall + rules for the interface. + +* Lots of bugs fixed, particularly in the area of demand-dialled and + persistent connections. + +* The rp-pppoe plugin now accepts any interface name (that isn't an + existing pppd option name) without putting "nic-" on the front of + it, not just eth*, nas*, tap* and br*. + + +What was new in ppp-2.4.3. +************************** + +* The configure script now accepts --prefix and --sysconfdir options. + These default to /usr/local and /etc. If you want pppd put in + /usr/sbin as before, use ./configure --prefix=/usr. + +* Doing `make install' no longer puts example configuration files in + /etc/ppp. Use `make install-etcppp' if you want that. + +* The code has been updated to work with version 0.8.3 of libpcap. + Unfortunately the libpcap maintainers removed support for the + "inbound" and "outbound" keywords on PPP links, meaning that if you + link pppd with libpcap-0.8.3, you can't use those keywords in the + active-filter and pass-filter expressions. The support has been + reinstated in the CVS version and should be in future libpcap + releases. If you need the in/outbound keywords, use a later release + than 0.8.3, or get the CVS version from http://www.tcpdump.org. + +* There is a new option, child-timeout, which sets the length of time + that pppd will wait for child processes (such as the command + specified with the pty option) to exit before exiting itself. It + defaults to 5 seconds. After the timeout, pppd will send a SIGTERM + to any remaining child processes and exit. A value of 0 means no + timeout. + +* Various bugs have been fixed, including some CBCP packet parsing + bugs that could lead to the peer being able to crash pppd if CBCP + support is enabled. + +* Various fixes and enhancements to the radius and rp-pppoe plugins + have been added. + +* There is a new winbind plugin, from Andrew Bartlet of the Samba + team, which provides the ability to authenticate the peer against an + NT domain controller using MS-CHAP or MS-CHAPV2. + +* There is a new pppoatm plugin, by various authors, sent in by David + Woodhouse. + +* The multilink code has been substantially reworked. The first pppd + for a bundle still controls the ppp interface, but it doesn't exit + until all the links in the bundle have terminated. If the first + pppd is signalled to exit, it signals all the other pppds + controlling links in the bundle. + +* The TDB code has been updated to the latest version. This should + eliminate the problem that some people have seen where the database + file (/var/run/pppd.tdb) keeps on growing. Unfortunately, however, + the new code uses an incompatible database format. For this reason, + pppd now uses /var/run/pppd2.tdb as the database filename. + + +What was new in ppp-2.4.2. +************************** + +* The CHAP code has been rewritten. Pppd now has support for MS-CHAP + V1 and V2 authentication, both as server and client. The new CHAP + code is cleaner than the old code and avoids some copyright problems + that existed in the old code. + +* MPPE (Microsoft Point-to-Point Encryption) support has been added, + although the current implementation shouldn't be considered + completely secure. (There is no assurance that the current code + won't ever transmit an unencrypted packet.) + +* James Carlson's implementation of the Extensible Authentication + Protocol (EAP) has been added. + +* Support for the Encryption Control Protocol (ECP) has been added. + +* Some new plug-ins have been included: + - A plug-in for kernel-mode PPPoE (PPP over Ethernet) + - A plug-in for supplying the PAP password over a pipe from another + process + - A plug-in for authenticating using a Radius server. + +* Updates and bug-fixes for the Solaris port. + +* The CBCP (Call Back Control Protocol) code has been updated. There + are new options `remotenumber' and `allow-number'. + +* Extra hooks for plugins to use have been added. + +* There is now a `maxoctets' option, which causes pppd to terminate + the link once the number of bytes passed on the link exceeds a given + value. + +* There are now options to control whether pppd can use the IPCP + IP-Address and IP-Addresses options: `ipcp-no-address' and + `ipcp-no-addresses'. + +* Fixed several bugs, including potential buffer overflows in chat. + + +What was new in ppp-2.4.1. +************************** + +* Pppd can now print out the set of options that are in effect. The + new `dump' option causes pppd to print out the option values after + option parsing is complete. The `dryrun' option causes pppd to + print the options and then exit. + +* The option parsing code has been fixed so that options in the + per-tty options file are parsed correctly, and don't override values + from the command line in most cases. + +* The plugin option now looks in /usr/lib/pppd/ (for + example, /usr/lib/pppd/2.4.1b1) for shared objects for plugins if + there is no slash in the plugin name. + +* When loading a plugin, pppd will now check the version of pppd for + which the plugin was compiled, and refuse to load it if it is + different to pppd's version string. To enable this, the plugin + source needs to #include "pppd.h" and have a line saying: + char pppd_version[] = VERSION; + +* There is a bug in zlib, discovered by James Carlson, which can cause + kernel memory corruption if Deflate is used with the lowest setting, + 8. As a workaround pppd will now insist on using at least 9. + +* Pppd should compile on Solaris and SunOS again. + +* Pppd should now set the MTU correctly on demand-dialled interfaces. + + +What was new in ppp-2.4.0. +************************** + +* Multilink: this package now allows you to combine multiple serial + links into one logical link or `bundle', for increased bandwidth and + reduced latency. This is currently only supported under the + 2.4.x and later Linux kernels. + +* All the pppd processes running on a system now write information + into a common database. I used the `tdb' code from samba for this. + +* New hooks have been added. + +For a list of the changes made during the 2.3 series releases of this +package, see the Changes-2.3 file. + + + diff --git a/README.eap-tls b/README.eap-tls index ab3794e..ad81ab2 100644 --- a/README.eap-tls +++ b/README.eap-tls @@ -126,7 +126,7 @@ EAP-TLS authentication support for PPP ca Use the CA public certificate found in in PEM format - ca-path + capath Use the directory as the CA public certificate directory cert Use the client public certificate found in in PEM format @@ -134,6 +134,9 @@ EAP-TLS authentication support for PPP key Use the client private key found in in PEM format or in engine:engine_id format + pkcs12 + Use a pkcs12 envelope as a substitute for cert and key. A password may be + required to use this file. crl Use the Certificate Revocation List (CRL) file in PEM format. crl-dir @@ -147,6 +150,11 @@ EAP-TLS authentication support for PPP max-tls-version <1.0|1.1|1.2 (default)|1.3> Specify the maximum TLS protocol version to negotiate with peers. Defaults to TLSv1.2 as the TLSv1.3 code is experimental. + tls-verify-key-usage + Validate certificate purpose and extended key usage + tls-verify-method + Compare the remotename against the subject, certificate name, or + match by suffix. Default is 'name'. Note: password-encrypted certificates can be used as of v0.94 of this diff --git a/README.pppoe b/README.pppoe index 2909e13..7fe0139 100644 --- a/README.pppoe +++ b/README.pppoe @@ -60,7 +60,7 @@ to connect to their ISP who is providing PPPoE based services. 5. Add the necessary authentication options to your pppd configuration (i.e. PAP/CHAP information). If you wish to - maintain seperate configurations for different devices you may + maintain separate configurations for different devices you may place configuration options in device-specific configuration files: /etc/ppp/options.devname (devname=ttyS0, ttyS1, eth0, eth1 or any other valid device name). diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e27d631 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. +REQUIRED_AUTOMAKE_VERSION=1.9 +PKG_NAME=pppd + +(test -f $srcdir/configure.ac \ + && test -f $srcdir/pppd/main.c) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level $PKG_NAME directory" + exit 1 + } + +(cd $srcdir; + autoreconf --install --symlink && + autoreconf && + ./configure --enable-maintainer-mode $@ +) + diff --git a/chat/Makefile.am b/chat/Makefile.am new file mode 100644 index 0000000..0a29869 --- /dev/null +++ b/chat/Makefile.am @@ -0,0 +1,5 @@ +sbin_PROGRAMS = chat +dist_man8_MANS = chat.8 + +chat_SOURCES = chat.c +chat_CPPFLAGS = -DTERMIOS -DSIGTYPE=void -UNO_SLEEP -DFNDELAY=O_NDELAY diff --git a/chat/Makefile.linux b/chat/Makefile.linux deleted file mode 100644 index 407cc12..0000000 --- a/chat/Makefile.linux +++ /dev/null @@ -1,33 +0,0 @@ -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -MANDIR = $(DESTDIR)/share/man/man8 - -CDEF1= -DTERMIOS # Use the termios structure -CDEF2= -DSIGTYPE=void # Standard definition -CDEF3= -UNO_SLEEP # Use the usleep function -CDEF4= -DFNDELAY=O_NDELAY # Old name value -CDEFS= $(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4) - -CFLAGS= $(COPTS) $(CDEFS) - -INSTALL= install - -all: chat - -chat: chat.o - $(CC) $(LDFLAGS) -o chat chat.o - -chat.o: chat.c - $(CC) -c $(CFLAGS) -o chat.o chat.c - -install: chat - mkdir -p $(BINDIR) $(MANDIR) - $(INSTALL) -c chat $(BINDIR) - $(INSTALL) -c -m 644 chat.8 $(MANDIR) - -clean: - rm -f chat.o chat *~ diff --git a/chat/Makefile.sol2 b/chat/Makefile.sol2 deleted file mode 100644 index 10d3314..0000000 --- a/chat/Makefile.sol2 +++ /dev/null @@ -1,19 +0,0 @@ -# -# Makefile for chat on Solaris 2 -# - -include ../Makedefs.com - -CFLAGS = $(COPTS) -DNO_USLEEP -DSOL2 - -all: chat - -chat: chat.o - $(CC) -o chat chat.o - -install: chat - $(INSTALL) -f $(BINDIR) chat - $(INSTALL) -m 444 -f $(MANDIR)/man8 chat.8 - -clean: - rm -f *~ *.o chat diff --git a/chat/chat.c b/chat/chat.c index 1639b3e..64d96c2 100644 --- a/chat/chat.c +++ b/chat/chat.c @@ -201,7 +201,7 @@ SIGTYPE sighup (int signo); void unalarm (void); void init (void); void set_tty_parameters (void); -void echo_stderr (int); +int echo_stderr (int); void break_sequence (void); void terminate (int status); void do_file (char *chat_file); @@ -210,7 +210,7 @@ int put_string (register char *s); int write_char (int c); int put_char (int c); int get_char (void); -void chat_send (register char *s); +int chat_send (register char *s); char *character (int c); void chat_expect (register char *s); char *clean (register char *s, int sending); @@ -983,16 +983,18 @@ char *character(int c) /* * process the reply string */ -void chat_send (register char *s) +int chat_send (register char *s) { char file_data[STR_LEN]; + int len, ret = 0; if (say_next) { say_next = 0; s = clean(s, 1); - write(2, s, strlen(s)); + len = strlen(s); + ret = write(2, s, len) != len; free(s); - return; + return ret; } if (hup_next) { @@ -1001,13 +1003,13 @@ void chat_send (register char *s) signal(SIGHUP, SIG_IGN); else signal(SIGHUP, sighup); - return; + return 0; } if (echo_next) { echo_next = 0; echo = (strcmp(s, "ON") == 0); - return; + return 0; } if (abort_next) { @@ -1020,15 +1022,14 @@ void chat_send (register char *s) s1 = clean(s, 0); - if (strlen(s1) > strlen(s) - || strlen(s1) + 1 > sizeof(fail_buffer)) + if (strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long ABORT string ('%v')", s); abort_string[n_aborts++] = s1; if (verbose) - msgf("abort on (%v)", s); - return; + msgf("abort on (%v)", s1); + return 0; } if (clear_abort_next) { @@ -1041,8 +1042,7 @@ void chat_send (register char *s) s1 = clean(s, 0); - if (strlen(s1) > strlen(s) - || strlen(s1) + 1 > sizeof(fail_buffer)) + if (strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long CLR_ABORT string ('%v')", s); old_max = n_aborts; @@ -1053,13 +1053,13 @@ void chat_send (register char *s) pack++; n_aborts--; if (verbose) - msgf("clear abort on (%v)", s); + msgf("clear abort on (%v)", s1); } } free(s1); if (pack) pack_array(abort_string,old_max); - return; + return 0; } if (report_next) { @@ -1070,15 +1070,14 @@ void chat_send (register char *s) fatal(2, "Too many REPORT strings"); s1 = clean(s, 0); - if (strlen(s1) > strlen(s) - || strlen(s1) + 1 > sizeof(fail_buffer)) + if (strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long REPORT string ('%v')", s); report_string[n_reports++] = s1; if (verbose) - msgf("report (%v)", s); - return; + msgf("report (%v)", s1); + return 0; } if (clear_report_next) { @@ -1091,8 +1090,7 @@ void chat_send (register char *s) s1 = clean(s, 0); - if (strlen(s1) > strlen(s) - || strlen(s1) + 1 > sizeof(fail_buffer)) + if (strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long REPORT string ('%v')", s); old_max = n_reports; @@ -1103,14 +1101,14 @@ void chat_send (register char *s) pack++; n_reports--; if (verbose) - msgf("clear report (%v)", s); + msgf("clear report (%v)", s1); } } free(s1); if (pack) pack_array(report_string,old_max); - return; + return 0; } if (timeout_next) { @@ -1124,7 +1122,7 @@ void chat_send (register char *s) if (verbose) msgf("timeout set to %d seconds", timeout); - return; + return 0; } /* @@ -1171,6 +1169,8 @@ void chat_send (register char *s) if (!put_string(s)) fatal(1, "Failed"); + + return 0; } int get_char(void) @@ -1296,10 +1296,11 @@ int put_string(register char *s) * When called with -1, a '\n' character is generated when * the cursor is not at the beginning of a line. */ -void echo_stderr(int n) +int echo_stderr(int n) { static int need_lf; char *s; + int len, ret = 0; switch (n) { case '\r': /* ignore '\r' */ @@ -1309,15 +1310,17 @@ void echo_stderr(int n) break; /* fall through */ case '\n': - write(2, "\n", 1); + ret = write(2, "\n", 1) != 1; need_lf = 0; break; default: s = character(n); - write(2, s, strlen(s)); + len = strlen(s); + ret = write(2, s, len) != len; need_lf = 1; break; } + return ret; } /* @@ -1356,8 +1359,11 @@ int get_string(register char *string) while ( ! alarmed && (c = get_char()) >= 0) { int n, abort_len, report_len; - if (echo) - echo_stderr(c); + if (echo) { + if (echo_stderr(c) != 0) { + fatal(2, "Could not write to stderr, %m"); + } + } if (verbose && c == '\n') { if (s == logged) msgf(""); /* blank line */ diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 0000000..27169d5 --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,6 @@ +EXTRA_ZLIB = \ + zlib.c \ + zlib.h + +EXTRA_DIST = \ + $(EXTRA_ZLIB) diff --git a/configure b/configure deleted file mode 100755 index f977663..0000000 --- a/configure +++ /dev/null @@ -1,145 +0,0 @@ -#!/bin/sh -# $Id: configure,v 1.38 2008/06/15 07:08:49 paulus Exp $ - -# Where to install stuff by default -DESTDIR=/usr/local -SYSCONF=/etc - -# Compile defaults -CROSS_COMPILE= -CC=cc -CFLAGS= - -system=`uname -s` -release=`uname -r` -arch=`uname -m` -state="unknown" - -case $system in - Linux) - makext="linux"; - ksrc="linux"; - state="known"; - CFLAGS="-O2 -g -pipe";; - SunOS) - karch=`/usr/bin/isainfo -k` - case $release in - 5.[7-9]*|5.[1-9][0-9]*) state="known"; ksrc="solaris"; makext="sol2"; - case "$karch" in - amd64) archvariant='-64x';; - sparcv9) archvariant='-64';; - *) ;; - esac;; - 5.[1-6]*) state="known"; ksrc="solaris"; makext="sol2";; - esac - if [ "$1" = gcc ]; then - shift - usegcc=gcc - fi - if [ "$1" = 32 ]; then - shift - archvariant= - fi - if [ -x /opt/SUNWspro/bin/cc -a "$usegcc" != gcc ] && - /opt/SUNWspro/bin/cc -flags >/dev/null 2>&1; then - if [ "$archvariant" = "-64x" ]; then - ( cd /tmp; echo "int x;" > ppp$$.c - /opt/SUNWspro/bin/cc -c -errwarn -xchip=opteron -m64 ppp$$.c >/dev/null 2>&1 || ( - echo "WorkShop C is unable to make 64 bit modules, and your $karch system needs" - echo "them. Consider upgrading cc on this machine." - rm -f ppp$$.c - exit 1 - ) || exit 1 - rm -f ppp$$.c ppp$$.o - ) || exit 1 - fi - elif gcc --version >/dev/null 2>&1; then - archvariant=gcc$archvariant - compiletype=.gcc - if [ "$archvariant" = "gcc-64" -o"$archvariant" = "gcc-64x" ]; then - ( cd /tmp; touch ppp$$.c - gcc -c -m64 ppp$$.c >/dev/null 2>&1 || ( - echo "gcc is unable to make 64 bit modules, and your $karch system needs them." - echo "Consider upgrading gcc on this machine, or switching to Sun WorkShop." - rm -f ppp$$.c - exit 1 - ) || exit 1 - rm -f ppp$$.c ppp$$.o - ) || exit 1 - fi - else - echo "C compiler not found; hoping for the best." - fi;; - NetBSD|FreeBSD|ULTRIX|OSF1|NeXTStep|SINIX-?|UNIX_SV|UNIX_System_V) - state="notincluded";; -esac - -if [ -d "$ksrc" ]; then :; else - state="notincluded" - unset ksrc -fi - -case $state in - unknown) - echo "This software has not been ported to $system. Sorry.";; - notincluded) - echo "Support for $system has not been included" - echo "in this distribution. Sorry.";; - known) - echo "Configuring for $system";; -esac - -# Parse arguments -while [ $# -gt 0 ]; do - arg=$1 - val= - shift - case $arg in - *=*) - val=`expr "x$arg" : 'x[^=]*=\(.*\)'` - arg=`expr "x$arg" : 'x\([^=]*\)=.*'` - ;; - --prefix|--sysconf) - if [ $# -eq 0 ]; then - echo "error: the $arg argument requires a value" 1>&2 - exit 1 - fi - val=$1 - shift - ;; - esac - case $arg in - --prefix) DESTDIR=$val ;; - --sysconfdir) SYSCONF=$val ;; - --cross_compile) CROSS_COMPILE=$val ;; - --cc) CC=$val ;; - --cflags) CFLAGS=$val ;; - esac -done - -mkmkf() { - rm -f $2 - if [ -f $1 ]; then - echo " $2 <= $1" - sed -e "s,@DESTDIR@,$DESTDIR,g" -e "s,@SYSCONF@,$SYSCONF,g" \ - -e "s,@CROSS_COMPILE@,$CROSS_COMPILE,g" -e "s,@CC@,$CC,g" \ - -e "s,@CFLAGS@,$CFLAGS,g" $1 >$2 - fi -} - -if [ -d "$ksrc" ]; then - echo "Creating Makefiles." - mkmkf $ksrc/Makefile.top Makefile - mkmkf $ksrc/Makedefs$compiletype Makedefs.com - for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/pppoe \ - pppd/plugins/radius pppd/plugins/pppoatm \ - pppd/plugins/pppol2tp; do - mkmkf $dir/Makefile.$makext $dir/Makefile - done - if [ -f $ksrc/Makefile.$makext$archvariant ]; then - mkmkf $ksrc/Makefile.$makext$archvariant $ksrc/Makefile - fi -else - echo "Unable to locate kernel source $ksrc" - exit 1 -fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..283b666 --- /dev/null +++ b/configure.ac @@ -0,0 +1,426 @@ +AC_PREREQ([2.69]) +AC_INIT([ppp], + [2.4.10-dev], + [https://github.com/ppp-project/ppp]) + +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE +AM_MAINTAINER_MODE([enable]) + +AC_LANG(C) +AC_CONFIG_SRCDIR([pppd/main.c]) +AC_CONFIG_HEADERS([pppd/config.h pppd/pppdconf.h]) + +# Checks for programs. +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_INSTALL +AC_PROG_LIBTOOL +AC_PROG_LN_S + +PKG_PROG_PKG_CONFIG + +AC_CANONICAL_HOST +build_linux=no +build_sunos=no + +case "${host_os}" in + linux*) + build_linux=yes + ;; + solaris2*) + build_sunos=yes + ;; + *) + AC_MSG_ERROR(["OS ${host_os} not supported"]) + ;; +esac + +AM_CONDITIONAL([LINUX], [test "${build_linux}" = "yes" ]) +AM_CONDITIONAL([SUNOS], [test "${build_sunos}" = "yes" ]) +AM_COND_IF([SUNOS], + CFLAGS="$CFLAGS -DSOL2 -DSRV4") + +# +# Checks for header files, these will set the HAVE_[FILE]_H macros in config.h +AC_HEADER_STDBOOL +AC_CHECK_HEADERS([ \ + asm/types.h \ + crypt.h \ + paths.h \ + shadow.h \ + sys/dlpi.h \ + sys/ioctl.h \ + sys/socket.h \ + sys/time.h \ + sys/uio.h \ + time.h \ + unistd.h \ + utmp.h]) + +# +# Check for linux specific headers, required by pppoe, or pppol2tp +AM_COND_IF([LINUX], [ + AC_CHECK_HEADERS([ \ + net/bpf.h \ + net/if.h \ + net/if_types.h \ + net/if_arp.h \ + linux/if.h \ + linux/if_ether.h \ + linux/if_packet.h \ + netinet/if_ether.h \ + netpacket/packet.h])]) + +AC_CHECK_SIZEOF(unsigned int) +AC_CHECK_SIZEOF(unsigned long) +AC_CHECK_SIZEOF(unsigned short) + +# Checks for library functions. +AC_CHECK_FUNCS([ \ + mmap \ + logwtmp \ + strerror]) + +# +# If libc doesn't provide logwtmp, check if libutil provides logwtmp(), and if so link to it. +AS_IF([test "x${ac_cv_func_logwtmp}" != "xyes"], [ + AC_CHECK_LIB([util], [logwtmp], [ + AC_DEFINE(HAVE_LOGWTMP, 1, ["System provides the logwtmp() function"]) + AC_SUBST([UTIL_LIBS], ["-lutil"]) + ]) +]) + +# +# Check if libcrypt have crypt() function +AC_CHECK_LIB([crypt], [crypt], + AC_SUBST([CRYPT_LIBS], ["-lcrypt"])) + +# +# Should pppd link with -lsystemd (Linux only) +AC_ARG_ENABLE([systemd], + AS_HELP_STRING([--enable-systemd], [Enable support for systemd notification])) +AM_CONDITIONAL(WITH_SYSTEMD, test "x${enable_systemd}" = "xyes") +AM_COND_IF([WITH_SYSTEMD], + AC_DEFINE([SYSTEMD], 1, [Enable support for systemd notifications])) + +# +# Enable Callback Protocol Support, disabled by default +AC_ARG_ENABLE([cbcp], + AS_HELP_STRING([--enable-cbcp], [Enable Callback Protocol])) +AM_CONDITIONAL(WITH_CBCP, test "x${enable_cbcp}" = "xyes") +AM_COND_IF([WITH_CBCP], + AC_DEFINE([CBCP_SUPPORT], 1, [Have Callback Protocol support])) + +# +# Disable support for IPX control protocol +AC_ARG_ENABLE([ipxcp], + AS_HELP_STRING([--enable-ipxcp], [Enable IPX Control Protocol support])) +AM_CONDITIONAL(WITH_IPXCP, test "x${enable_ipxcp}" = "xyes") +AM_COND_IF(WITH_IPXCP, + AC_DEFINE([IPX_CHANGE], 1, ["Have IPX Control Protocol"])) +AS_IF([test "x${build_sunos}" = "xyes" && test "x${enable_ipxcp}" = "xyes"], + [AC_MSG_ERROR([IPXCP is not supported on SunOS, disable using --disable-ipxcp])]) + +# +# Disable support for limiting session duration by maximum octets +AC_ARG_ENABLE([maxoctets], + AS_HELP_STRING([--disable-maxoctets], [Disable support for limiting session by maximum octets])) +AS_IF([test "x$enable_maxoctets" != "xno"], + AC_DEFINE([MAXOCTETS], 1, ["Limit sessions by maximum number of octets"])) + +# +# Disable Microsoft extensions will remove CHAP and MPPE support +AC_ARG_ENABLE([microsoft-extensions], + AS_HELP_STRING([--disable-microsoft-extensions], [Disable Microsoft CHAP / MPPE extensions])) + +AM_CONDITIONAL(WITH_CHAPMS, test "x${enable_microsoft_extensions}" != "xno") +AM_COND_IF([WITH_CHAPMS], + AC_DEFINE([CHAPMS], 1, ["Have Microsoft CHAP support"])) + +AM_CONDITIONAL(WITH_MPPE, test "x${enable_microsoft_extensions}" != "xno") +AM_COND_IF([WITH_MPPE], + AC_DEFINE([MPPE], 1, ["Have Microsoft MPPE support"])) + +# +# Enable Microsoft LAN Manager support, depends on Microsoft Extensions +AC_ARG_ENABLE([mslanman], + AS_HELP_STRING([--enable-mslanman], [Enable Microsoft LAN Manager support])) +AS_IF([test "x${enable_mslanman}" = "xyes" && test "x${enable_microsoft_extensions}" != "xno"], + AC_DEFINE([MSLANMAN], 1, ["Have Microsoft LAN Manager support"])) + +# +# Disable IPv6 support +AC_ARG_ENABLE([ipv6-support], + AS_HELP_STRING([--disable-ipv6-support], [Disable IPv6 support])) +AM_CONDITIONAL(WITH_INET6, test "x${enable_ipv6_support}" != "xno") +AM_COND_IF([WITH_INET6], + AC_DEFINE(INET6, 1, ["Have IPv6 support"])) + +# +# Disable Multilink support +AC_ARG_ENABLE([multilink], + AS_HELP_STRING([--enable-multilink], [Enable multilink support])) +AM_CONDITIONAL(WITH_MULTILINK, test "x${enable_multilink}" = "xyes") +AM_COND_IF([WITH_MULTILINK], + AC_DEFINE([HAVE_MULTILINK], 1, ["Have multilink support"])) +AS_IF([test "x${build_sunos}" = "xyes" && test "x${enable_multilink}" = "xyes"], + [AC_MSG_ERROR([Multilink is not supported on SunOS])]) + +# +# Multilink require Trivial Database Support +AM_CONDITIONAL(WITH_TDB, test "x${enable_multilink}" = "xyes") +AM_COND_IF([WITH_TDB], + AC_DEFINE([USE_TDB], 1, ["Include TDB support"])) + +# +# Enable support for loadable plugins +AC_ARG_ENABLE([plugins], + AS_HELP_STRING([--disable-plugins], [Disable support for loadable plugins])) +AS_IF([test "x$enable_plugins" != "xno"], + AC_DEFINE([PLUGIN], 1, ["Have support for loadable plugins"])) +AM_CONDITIONAL(WITH_PLUGINS, test "${enable_plugins}" != "no") + +# +# Disable EAP-TLS support +AC_ARG_ENABLE([eaptls], + AS_HELP_STRING([--disable-eaptls], [Disable EAP-TLS authentication support])) +AS_IF([test "x$enable_eaptls" != "xno"], + AC_DEFINE([USE_EAPTLS], 1, ["Have EAP-TLS authentication support"])) +AM_CONDITIONAL(WITH_EAPTLS, test "x${enable_eaptls}" != "xno") + +# +# Disable PEAP support +AC_ARG_ENABLE([peap], + AS_HELP_STRING([--disable-peap], [Disable PEAP authentication support])) +AS_IF([test "x${enable_peap}" != "xno"], + AC_DEFINE([USE_PEAP], 1, ["Have PEAP authentication support"])) +AM_CONDITIONAL([WITH_PEAP], test "x${enable_peap}" != "xno") + +# +# Disable OpenSSL engine support +AC_ARG_ENABLE([openssl-engine], + AS_HELP_STRING([--disable-openssl-engine], [Disable OpenSSL engine support])) +AS_IF([test "x$enable_openssl_engine" != "xno"], [], + AC_DEFINE([OPENSSL_NO_ENGINE], 1, ["OpenSSL engine support"])) + +# +# Specify runtime directory +AC_ARG_WITH([plugin-dir], + AC_HELP_STRING([--with-plugin-dir=DIR], [Specify the plugin directory for pppd])) +AS_IF([test -n "$with_plugin_dir"], + [PPPD_PLUGIN_DIR="$with_plugin_dir"], + [PPPD_PLUGIN_DIR="${libdir}/pppd/$VERSION"]) +AC_SUBST(PPPD_PLUGIN_DIR, "$PPPD_PLUGIN_DIR", [The pppd plugin directory]) + +# +# Specify runtime directory +AC_ARG_WITH([runtime-dir], + AC_HELP_STRING([--with-runtime-dir=DIR], [Specify the runtime directory for pppd])) +AS_IF([test -n "$with_runtime_dir"], + [PPPD_RUNTIME_DIR="$with_runtime_dir"], + [PPPD_RUNTIME_DIR="${localstatedir}/run/pppd"]) +AC_SUBST(PPPD_RUNTIME_DIR) + +# +# Specify runtime directory +AC_ARG_WITH([logfile-dir], + AC_HELP_STRING([--with-logfile-dir=DIR], [Specify the log directory for pppd])) +AS_IF([test -n "$with_logfile_dir"], + [PPPD_LOGFILE_DIR="$with_logfile_dir"], + [PPPD_LOGFILE_DIR="${localstatedir}/log/pppd"]) +AC_SUBST(PPPD_LOGFILE_DIR) + +# +# Check for OpenSSL +AX_CHECK_OPENSSL +AM_CONDITIONAL(WITH_OPENSSL, test "${with_openssl}" != "no") + +# +# Check if OpenSSL has compiled in support for various ciphers +AS_IF([test "x${with_openssl}" != "xno" ], [ + AX_CHECK_OPENSSL_DEFINE([OPENSSL_NO_MD4], [md4]) + AX_CHECK_OPENSSL_DEFINE([OPENSSL_NO_MD5], [md5]) + AX_CHECK_OPENSSL_DEFINE([OPENSSL_NO_DES], [des]) + AX_CHECK_OPENSSL_DEFINE([OPENSSL_NO_SHA], [sha]) +], [ + AS_IF([test "x${enable_eaptls}" != "xno" || test "x${enable_peap}" != "xno"], + [AC_MSG_ERROR([OpenSSL not found, and if this is your intention then run configure --disable-eaptls and --disable-peap])]) +]) + +AM_CONDITIONAL([OPENSSL_HAVE_MD4], test "x${ac_cv_openssl_md4}" = "xyes") +AM_COND_IF([OPENSSL_HAVE_MD4],, + AC_DEFINE([USE_MD4], 1, [Use included md4 included with pppd])) + +AM_CONDITIONAL([OPENSSL_HAVE_MD5], test "x${ac_cv_openssl_md5}" = "xyes") +AM_COND_IF([OPENSSL_HAVE_MD5],, + AC_DEFINE([USE_MD5], 1, [Use included md5 included with pppd])) + +AM_CONDITIONAL([OPENSSL_HAVE_SHA], test "x${ac_cv_openssl_sha}" = "xyes") +AM_COND_IF([OPENSSL_HAVE_SHA],, + AC_DEFINE([USE_SHA], 1, [Use included sha included with pppd])) + +AM_CONDITIONAL([OPENSSL_HAVE_DES], test "x${ac_cv_openssl_des}" = "xyes") +AM_COND_IF([OPENSSL_HAVE_DES],, + AC_DEFINE([USE_CRYPT], 1, [Use included des included with pppd])) + +# +# If OpenSSL doesn't support DES, then use the one from libcrypt (glibc dropped support for this in 2.27). +AS_IF([test "${ac_cv_openssl_des}" = "no" ], [ + AC_CHECK_LIB([crypt], [encrypt], + [LIBS="$LIBS -lcrypt"], + [AC_MSG_ERROR([OpenSSL not found or does not support DES, and libcrypt also doesn't support encrypt])] + ) +]) + +# +# With libsrp support +AX_CHECK_SRP + +# +# With libatm support +AX_CHECK_ATM + +# +# With libpam support +AX_CHECK_PAM(AC_DEFINE([USE_PAM], 1, ["Support for Pluggable Authentication Modules"])) +AM_CONDITIONAL(WITH_PAM, test "x${with_pam}" = "xyes") + +# +# With libpcap support, activate pppd on network activity +AX_CHECK_PCAP + +# +# SunOS provides a version of libpcap that would work, but SunOS has no support for activity filter +AM_CONDITIONAL([WITH_FILTER], [ test "x${with_pcap}" = "xyes" && test "x${build_sunos}" != "xyes" ]) +AM_COND_IF([WITH_FILTER], [ + AC_DEFINE([PPP_FILTER], 1, ["Have packet activity filter support"])], [ + AS_IF([test "x${build_sunos}" = "xyes"], [ + AC_MSG_WARN([Packet activity filter not supported on SunOS]) + with_pcap="no" + ]) + ]) + +# +# Some contributions require GTK/GLIB +AC_ARG_WITH([gtk], AS_HELP_STRING([--with-gtk], [Build contributions with the GTK+ interface])) +if test "x${with_gtk}" = "xyes"; then + PKG_CHECK_MODULES([GTK], [gtk+-2.0]) + PKG_CHECK_MODULES([GLIB], [glib-2.0]) +fi +AM_CONDITIONAL([WITH_GTK], test "x${with_gtk}" = "xyes") + + +AC_CONFIG_FILES([ + Makefile + chat/Makefile + contrib/Makefile + contrib/pppgetpass/Makefile + common/Makefile + include/Makefile + modules/Makefile + pppd/Makefile + pppd/pppd.pc + pppd/plugins/Makefile + pppd/plugins/pppoe/Makefile + pppd/plugins/pppoatm/Makefile + pppd/plugins/pppol2tp/Makefile + pppd/plugins/radius/Makefile + pppdump/Makefile + pppstats/Makefile + scripts/Makefile + ]) +AC_OUTPUT + + +AS_IF([test "x${build_sunos}" = "xyes" ], [[ + echo " +Setting up SunOS kernel module(s)" + mkmkf() { + rm -f $2 + if [ -f $1 ]; then + echo " $2 <= $1" + sed -e "s,@DESTDIR@,$prefix,g" \ + -e "s,@SYSCONF@,$sysconfdir,g" \ + -e "s,@CC@,$CC,g" \ + -e "s|@CFLAGS@|$CFLAGS|g" $1 > $2 + fi + } + + release=`uname -r` + karch=`/usr/bin/isainfo -k` + makext="sol2" + archvariant= + + case "$karch" in + amd64) + archvariant='-64x' + ;; + sparcv9) + archvariant='-64' + ;; + *) + ;; + esac + + usegcc=$CC + if [ -x /opt/SUNWspro/bin/cc -a "$usegcc" != gcc ] && + /opt/SUNWspro/bin/cc -flags >/dev/null 2>&1; then + if [ "$archvariant" = "-64x" ]; then + ( cd /tmp; echo "int x;" > ppp$$.c + /opt/SUNWspro/bin/cc -c -errwarn -xchip=opteron -m64 ppp$$.c >/dev/null 2>&1 || ( + echo "WorkShop C is unable to make 64 bit modules, and your $karch system needs" + echo "them. Consider upgrading cc on this machine." + rm -f ppp$$.c + exit 1 + ) || exit 1 + rm -f ppp$$.c ppp$$.o + ) || exit 1 + fi + elif gcc --version >/dev/null 2>&1; then + archvariant=gcc$archvariant + compiletype=.gcc + if [ "$archvariant" = "gcc-64" -o"$archvariant" = "gcc-64x" ]; then + ( cd /tmp; touch ppp$$.c + gcc -c -m64 ppp$$.c >/dev/null 2>&1 || ( + echo "gcc is unable to make 64 bit modules, and your $karch system needs them." + echo "Consider upgrading gcc on this machine, or switching to Sun WorkShop." + rm -f ppp$$.c + exit 1 + ) || exit 1 + rm -f ppp$$.c ppp$$.o + ) || exit 1 + fi + else + echo "C compiler not found; hoping for the best." + fi + + mkmkf solaris/Makedefs$compiletype Makedefs.com + mkmkf solaris/Makefile.sol2$archvariant solaris/Makefile +]]) + +echo " +$PACKAGE_NAME version $PACKAGE_VERSION + Prefix...............: $prefix + Runtime Dir..........: $PPPD_RUNTIME_DIR + Logfile Dir..........: $PPPD_LOGFILE_DIR + Plugin Dir...........: $PPPD_PLUGIN_DIR + With OpenSSL.........: ${with_openssl:-yes} + With libatm..........: ${with_atm:-no} + With libpam..........: ${with_pam:-no} + With libpcap.........: ${with_pcap:-no} + With libsrp..........: ${with_srp:-no} + C Compiler...........: $CC $CFLAGS + Linker...............: $LD $LDFLAGS $LIBS + +Features enabled + Microsoft Extensions.: ${enable_microsoft_extensions:-yes} + Multilink............: ${enable_multilink:-no} + Plugins..............: ${enable_plugins:-yes} + CBCP.................: ${enable_cbcp:-no} + IPXCP................: ${enable_ipxcp:-no} + EAP-TLS..............: ${enable_eaptls:-yes} + PEAP.................: ${enable_peap:-yes} +" diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 0000000..fb9a390 --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = pppgetpass diff --git a/contrib/pppgetpass/.gitignore b/contrib/pppgetpass/.gitignore new file mode 100644 index 0000000..1b8a1c8 --- /dev/null +++ b/contrib/pppgetpass/.gitignore @@ -0,0 +1,2 @@ +pppgetpass.vt +pppgetpass.gtk diff --git a/contrib/pppgetpass/Makefile.am b/contrib/pppgetpass/Makefile.am new file mode 100644 index 0000000..530e82f --- /dev/null +++ b/contrib/pppgetpass/Makefile.am @@ -0,0 +1,17 @@ +noinst_PROGRAMS = pppgetpass.vt +noinst_man8_MANS = pppgetpass.8 + +pppgetpass_vt_SOURCES = pppgetpass.vt.c +pppgetpass_vt_CPPFLAGS = -Wno-unused-result + +if WITH_GTK +noinst_PROGRAMS += pppgetpass.gtk + +pppgetpass_gtk_SOURCES = pppgetpass.gtk.c +pppgetpass_gtk_CPPFLAGS = -Wno-deprecated-declarations -Wno-discarded-qualifiers +pppgetpass_gtk_CPPFLAGS += $(GLIB_CFLAGS) $(GTK_CFLAGS) +pppgetpass_gtk_LDADD = $(GLIB_LIBS) $(GTK_LIBS) +endif + +EXTRA_DIST = \ + pppgetpass.sh diff --git a/contrib/pppgetpass/Makefile.linux b/contrib/pppgetpass/Makefile.linux deleted file mode 100644 index eb16f5b..0000000 --- a/contrib/pppgetpass/Makefile.linux +++ /dev/null @@ -1,16 +0,0 @@ -all: pppgetpass.vt pppgetpass.gtk - -pppgetpass.vt: pppgetpass.vt.o - -pppgetpass.gtk: pppgetpass.gtk.o - $(CC) $(LDFLAGS) pppgetpass.gtk.o -o pppgetpass.gtk `pkg-config --libs glib-2.0 gtk+-2.0` -pppgetpass.gtk.o: pppgetpass.gtk.c - $(CC) $(CFLAGS) -c pppgetpass.gtk.c `pkg-config --cflags glib-2.0 gtk+-2.0` - -install: all - install -m 755 pppgetpass.sh /usr/bin/pppgetpass - install -m 4755 -o root -g root pppgetpass.vt /usr/bin/ - install -m 755 -o root -g root pppgetpass.gtk /usr/X11/bin/ - -clean: - rm -f *.o pppgetpass.gtk pppgetpass.vt core diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..2a576c1 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_HEADERS = \ + linux/if_ppp.h \ + linux/ppp-comp.h \ + linux/ppp_defs.h \ + net/if_ppp.h \ + net/ppp-comp.h \ + net/ppp_defs.h \ + net/pppio.h \ + net/slcompress.h \ + net/vjcompress.h + +EXTRA_DIST = \ + $(EXTRA_HEADERS) diff --git a/linux/Makefile.top b/linux/Makefile.top deleted file mode 100644 index 894f8f3..0000000 --- a/linux/Makefile.top +++ /dev/null @@ -1,70 +0,0 @@ -# PPP top-level Makefile for Linux. - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -INCDIR = $(DESTDIR)/include -MANDIR = $(DESTDIR)/share/man -ETCDIR = $(INSTROOT)@SYSCONF@/ppp - -# uid 0 = root -INSTALL= install - -all: - cd chat; $(MAKE) $(MFLAGS) all - cd pppd/plugins; $(MAKE) $(MFLAGS) all - cd pppd; $(MAKE) $(MFLAGS) all - cd pppstats; $(MAKE) $(MFLAGS) all - cd pppdump; $(MAKE) $(MFLAGS) all - -install: $(BINDIR) $(MANDIR)/man8 install-progs install-devel - -install-progs: - cd chat; $(MAKE) $(MFLAGS) install - cd pppd/plugins; $(MAKE) $(MFLAGS) install - cd pppd; $(MAKE) $(MFLAGS) install - cd pppstats; $(MAKE) $(MFLAGS) install - cd pppdump; $(MAKE) $(MFLAGS) install - -install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \ - $(ETCDIR)/chap-secrets $(ETCDIR)/eaptls-server $(ETCDIR)/eaptls-client - -install-devel: - cd pppd; $(MAKE) $(MFLAGS) install-devel - -$(ETCDIR)/options: - $(INSTALL) -c -m 644 etc.ppp/options $@ -$(ETCDIR)/pap-secrets: - $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@ -$(ETCDIR)/chap-secrets: - $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@ -$(ETCDIR)/eaptls-server: - $(INSTALL) -c -m 600 etc.ppp/eaptls-server $@ -$(ETCDIR)/eaptls-client: - $(INSTALL) -c -m 600 etc.ppp/eaptls-client $@ - -$(BINDIR): - $(INSTALL) -d -m 755 $@ -$(MANDIR)/man8: - $(INSTALL) -d -m 755 $@ -$(ETCDIR): - $(INSTALL) -d -m 755 $@ - -clean: - rm -f `find . -name '*.[oas]' -print` - rm -f `find . -name 'core' -print` - rm -f `find . -name '*~' -print` - cd chat; $(MAKE) clean - cd pppd/plugins; $(MAKE) clean - cd pppd; $(MAKE) clean - cd pppstats; $(MAKE) clean - cd pppdump; $(MAKE) clean - -dist-clean: clean - rm -f Makefile `find . -name Makefile -print` - -#kernel: -# cd linux; ./kinstall.sh - -# no tests yet, one day... -installcheck: - true diff --git a/m4/ax_check_atm.m4 b/m4/ax_check_atm.m4 new file mode 100644 index 0000000..004fe9f --- /dev/null +++ b/m4/ax_check_atm.m4 @@ -0,0 +1,93 @@ +# SYNOPSIS +# +# AX_CHECK_ATM([action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Look for libatm in a number of default locations, or in a provided location +# (via --with-atm=). Sets +# ATM_CFLAGS +# ATM_LDFLAGS +# ATM_LIBS +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# LICENSE +# +# Copyright (c) 2021 Eivind Naess +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_CHECK_ATM], [ + AC_ARG_WITH([atm], + [AS_HELP_STRING([--with-atm=DIR], + [With libatm support, see http://linux-atm.sourceforge.net])], + [ + case "$withval" in + "" | y | ye | yes) + atmdirs="/usr/local /usr/lib /usr" + ;; + n | no) + with_atm="no" + ;; + *) + atmdirs="$withval" + ;; + esac + ]) + + if [ test "x${with_atm}" != "xno" ] ; then + ATM_LIBS="-latm" + for atmdir in $atmdirs; do + AC_MSG_CHECKING([for atm.h in $atmdir]) + if test -f "$atmdir/include/atm.h"; then + ATM_CFLAGS="-I$atmdir/include" + ATM_LDFLAGS="-L$atmdir/lib" + AC_MSG_RESULT([yes]) + break + else + AC_MSG_RESULT([no]) + fi + done + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([if compiling and linking against libatm works]) + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS $ATM_LDFLAGS" + LIBS="$ATM_LIBS $LIBS" + CPPFLAGS="$ATM_CFLAGS $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include + #include ], + [text2atm(NULL,NULL,0,0);])], + [ + AC_MSG_RESULT([yes]) + with_atm=yes + $1 + ], [ + AC_MSG_RESULT([no]) + with_atm="" + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([ATM_CFLAGS]) + AC_SUBST([ATM_LIBS]) + AC_SUBST([ATM_LDFLAGS]) + fi + AM_CONDITIONAL(WITH_LIBATM, test -n "${with_atm}") +]) + diff --git a/m4/ax_check_openssl.m4 b/m4/ax_check_openssl.m4 new file mode 100644 index 0000000..8ae39ca --- /dev/null +++ b/m4/ax_check_openssl.m4 @@ -0,0 +1,119 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Look for OpenSSL in a number of default spots, or in a user-selected +# spot (via --with-openssl). Sets +# +# OPENSSL_INCLUDES to the include directives required +# OPENSSL_LIBS to the -l directives required +# OPENSSL_LDFLAGS to the -L or -R flags required +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# This macro sets OPENSSL_INCLUDES such that source files should use the +# openssl/ directory in include directives: +# +# #include +# +# LICENSE +# +# Copyright (c) 2009,2010 Zmanda Inc. +# Copyright (c) 2009,2010 Dustin J. Mitchell +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 9 + +AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) +AC_DEFUN([AX_CHECK_OPENSSL], [ + found=false + AC_ARG_WITH([openssl], + [AS_HELP_STRING([--with-openssl=DIR], + [With openssl support, see http://www.openssl.org])], + [ + case "$withval" in + "" | y | ye | yes ) + ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" + ;; + n | no ) + ;; + *) ssldirs="$withval" + ;; + esac + ], [ + ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" + ]) + + AS_IF([test "${with_openssl}" != "no"], [ + OPENSSL_INCLUDES= + for ssldir in $ssldirs; do + AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) + AS_IF([ test -f "$ssldir/include/openssl/ssl.h" ], [ + OPENSSL_INCLUDES="-I$ssldir/include" + OPENSSL_LDFLAGS="-L$ssldir/lib" + OPENSSL_LIBS="-lssl -lcrypto" + found=true + AC_MSG_RESULT([yes]) + break + ], [ + AC_MSG_RESULT([no]) + ]) + done]) + + AS_IF([test "${with_openssl}" != "no" && test ! ${found}], [ + # if pkg-config is installed and openssl has installed a .pc file, + # then use that information and don't search ssldirs + AC_PATH_PROG([PKG_CONFIG], [pkg-config]) + if test x"$PKG_CONFIG" != x""; then + OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` + if test $? = 0; then + OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` + OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` + found=true + fi + fi + ]) + + AS_IF([test "${with_openssl}" != "no" && test ${found}], [ + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) + echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ + "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" + LIBS="$OPENSSL_LIBS $LIBS" + CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], + [ + AC_MSG_RESULT([yes]) + $1 + ], [ + AC_MSG_RESULT([no]) + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([OPENSSL_INCLUDES]) + AC_SUBST([OPENSSL_LIBS]) + AC_SUBST([OPENSSL_LDFLAGS]) + ], [ $2 ]) +]) diff --git a/m4/ax_check_openssl_func.m4 b/m4/ax_check_openssl_func.m4 new file mode 100644 index 0000000..d269af8 --- /dev/null +++ b/m4/ax_check_openssl_func.m4 @@ -0,0 +1,44 @@ +# SYNOPSIS +# +# AX_CHECK_OPENSSL_DEFINE([DEFINE], [VAR][, action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Check if OpenSSL has a define set in it's features provided, i.e. OPENSSL_NO_MD4. +# If so, the var argument ac_cv_openssl_[VAR] is set to yes, and action-is-found is +# run, else action-if-not-found is executed. +# +# This module require AX_CHECK_OPENSSL +# +# LICENSE +# +# Copyright (c) 2021 Eivind Naess +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_CHECK_OPENSSL_DEFINE], [ + AC_REQUIRE([AX_CHECK_OPENSSL]) + AC_MSG_CHECKING([for $2 support in openssl]) + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" + AC_PREPROC_IFELSE([ + AC_LANG_PROGRAM( + [[@%:@include ]], + [[#ifdef $1 + #error "No support for $1" + #endif]])], + AC_MSG_RESULT([yes]) + [ac_cv_openssl_$2=yes] + $3, + AC_MSG_RESULT([no]) + [ac_cv_openssl_$2=no] + $4 + ) + CPPFLAGS="$save_CPPFLAGS" +]) + diff --git a/m4/ax_check_pam.m4 b/m4/ax_check_pam.m4 new file mode 100644 index 0000000..edb30e3 --- /dev/null +++ b/m4/ax_check_pam.m4 @@ -0,0 +1,93 @@ +# SYNOPSIS +# +# AX_CHECK_PAM([action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Look for libpam in a number of default locations, or in a provided location +# (via --with-pam=). Sets +# PAM_CFLAGS +# PAM_LDFLAGS +# PAM_LIBS +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# LICENSE +# +# Copyright (c) 2021 Eivind Naess +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_CHECK_PAM], [ + AC_ARG_WITH([pam], + [AS_HELP_STRING([--with-pam=DIR], + [With libpam support, see ftp.redhat.com:/pub/pam])], + [ + case "$withval" in + "" | y | ye | yes) + pamdirs="/usr/local /usr/lib /usr" + ;; + n | no) + with_pam="no" + ;; + *) + pamdirs="$withval" + ;; + esac + ]) + + if [ test "x${with_pam}" != "xno" ] ; then + PAM_LIBS="-lpam" + for pamdir in $pamdirs; do + AC_MSG_CHECKING([for pam_appl.h in $pamdir]) + if test -f "$pamdir/include/security/pam_appl.h"; then + PAM_CFLAGS="-I$pamdir/include" + PAM_LDFLAGS="-L$pamdir/lib" + AC_MSG_RESULT([yes]) + break + else + AC_MSG_RESULT([no]) + fi + done + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([if compiling and linking against libpam works]) + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS $PAM_LDFLAGS" + LIBS="$PAM_LIBS $LIBS" + CPPFLAGS="$PAM_CFLAGS $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include + #include ], + [pam_authenticate(NULL, 0);])], + [ + AC_MSG_RESULT([yes]) + with_pam=yes + $1 + ], [ + AC_MSG_RESULT([no]) + with_pam="" + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([PAM_CFLAGS]) + AC_SUBST([PAM_LIBS]) + AC_SUBST([PAM_LDFLAGS]) + fi + AM_CONDITIONAL(WITH_LIBPAM, test -n "${with_pam}") +]) + diff --git a/m4/ax_check_pcap.m4 b/m4/ax_check_pcap.m4 new file mode 100644 index 0000000..6d70ec1 --- /dev/null +++ b/m4/ax_check_pcap.m4 @@ -0,0 +1,93 @@ +# SYNOPSIS +# +# AX_CHECK_PCAP([action-if-found[, action-if-not-found]] +# +# DESCRIPTION +# +# Look for libpcap in a number of default locations, or in a provided location +# (via --with-pcap=). Sets +# PCAP_CFLAGS +# PCAP_LDFLAGS +# PCAP_LIBS +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# LICENSE +# +# Copyright (c) 2021 Eivind Naess +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_CHECK_PCAP], [ + AC_ARG_WITH([pcap], + [AS_HELP_STRING([--with-pcap=DIR], + [With libpcap support, see https://www.tcpdump.org])], + [ + case "$withval" in + "" | y | ye | yes) + pcapdirs="/usr/local /usr/lib /usr" + ;; + n | no) + with_pcap="no" + ;; + *) + pcapdirs="$withval" + ;; + esac + ]) + + if [ test "x${with_pcap}" != "xno" ] ; then + PCAP_LIBS="-lpcap" + for pcapdir in $pcapdirs; do + AC_MSG_CHECKING([for pcap.h in $pcapdir]) + if test -f "$pcapdir/include/pcap.h"; then + PCAP_CFLAGS="-I$pcapdir/include" + PCAP_LDFLAGS="-L$pcapdir/lib" + AC_MSG_RESULT([yes]) + break + else + AC_MSG_RESULT([no]) + fi + done + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([if compiling and linking against libpcap works]) + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$PCAP_LDFLAGS $LDFLAGS" + LIBS="$PCAP_LIBS $LIBS" + CPPFLAGS="$PCAP_CFLAGS $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [@%:@include ], + [pcap_create(0,0);])], + [ + AC_MSG_RESULT([yes]) + with_pcap=yes + $1 + ], [ + AC_MSG_RESULT([no]) + with_pcap="" + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([PCAP_CFLAGS]) + AC_SUBST([PCAP_LIBS]) + AC_SUBST([PCAP_LDFLAGS]) + fi + + AM_CONDITIONAL(WITH_PCAP, test -n "${with_pcap}") +]) + diff --git a/m4/ax_check_srp.m4 b/m4/ax_check_srp.m4 new file mode 100644 index 0000000..631341d --- /dev/null +++ b/m4/ax_check_srp.m4 @@ -0,0 +1,94 @@ +# SYNOPSIS +# +# AX_CHECK_SRP([action-if-found[, action-if-not-found]]) +# +# DESCRIPTION +# +# Look for libsrp in a number of default locations, or in a provided location +# (via --with-srp=). Sets +# SRP_CFLAGS +# SRP_LDFLAGS +# SRP_LIBS +# +# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately +# +# LICENSE +# +# Copyright (c) 2021 Eivind Naess +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_CHECK_SRP], [ + AC_ARG_WITH([srp], + [AS_HELP_STRING([--with-srp=DIR], + [With libsrp support, see http://srp.stanford.edu])], + [ + case "$withval" in + "" | y | ye | yes) + srpdirs="/usr/local /usr/lib /usr" + ;; + n | no) + with_srp="no" + ;; + *) + srpdirs="$withval" + ;; + esac + ]) + + if [ test "x${with_srp}" != "xno" ] ; then + SRP_LIBS="-lsrp" + for srpdir in $srpdirs; do + AC_MSG_CHECKING([for srp.h in $srpdir]) + if test -f "$srpdir/include/srp.h"; then + SRP_CFLAGS="-I$srpdir/include" + SRP_LDFLAGS="-L$srpdir/lib" + AC_MSG_RESULT([yes]) + break + else + AC_MSG_RESULT([no]) + fi + done + + # try the preprocessor and linker with our new flags, + # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS + + AC_MSG_CHECKING([if compiling and linking against libsrp works]) + + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" + save_CPPFLAGS="$CPPFLAGS" + LDFLAGS="$SRP_LDFLAGS $OPENSSL_LDFLAGS $LDFLAGS" + LIBS="$SRP_LIBS $OPENSSL_LIBS $LIBS" + CPPFLAGS="$SRP_CFLAGS $OPENSSL_INCLUDES $CPPFLAGS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include + #include ], + [SRP_use_engine(NULL);])], + [ + AC_MSG_RESULT([yes]) + with_srp=yes + $1 + ], [ + AC_MSG_RESULT([no]) + with_srp="" + $2 + ]) + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + + AC_SUBST([SRP_CFLAGS]) + AC_SUBST([SRP_LIBS]) + AC_SUBST([SRP_LDFLAGS]) + fi + + AM_CONDITIONAL(WITH_SRP, test -n "${with_srp}") +]) + diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 0000000..13a8890 --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,275 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR diff --git a/modules/Makefile.am b/modules/Makefile.am new file mode 100644 index 0000000..ddd53bc --- /dev/null +++ b/modules/Makefile.am @@ -0,0 +1,12 @@ +EXTRA_MODULE = \ + bsd-comp.c \ + deflate.c \ + if_ppp.c \ + ppp_ahdlc.c \ + ppp.c \ + ppp_comp.c \ + ppp_mod.h \ + vjcompress.c + +EXTRA_DIST = \ + $(EXTRA_MODULE) diff --git a/pppd/Makefile.am b/pppd/Makefile.am new file mode 100644 index 0000000..e6aaac0 --- /dev/null +++ b/pppd/Makefile.am @@ -0,0 +1,197 @@ +sbin_PROGRAMS = pppd +dist_man8_MANS = pppd.8 +check_PROGRAMS = + +utest_chap_SOURCES = chap_ms.c pppcrypt.c utils.c +utest_chap_CPPFLAGS = -DUNIT_TEST +utest_chap_LDFLAGS = + +utest_peap_SOURCES = peap.c utils.c mppe.c +utest_peap_CPPFLAGS = -DUNIT_TEST -I${top_srcdir}/include +utest_peap_LDFLAGS = + +if WITH_SRP +sbin_PROGRAMS += srp-entry +dist_man8_MANS += srp-entry.8 +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = pppd.pc + +pppd_includedir = $(includedir)/pppd +pppd_include_HEADERS = \ + cbcp.h \ + ccp.h \ + chap-md5.h \ + chap_ms.h \ + chap-new.h \ + eap.h \ + eap-tls.h \ + ecp.h \ + eui64.h \ + fsm.h \ + ipcp.h \ + ipv6cp.h \ + ipxcp.h \ + lcp.h \ + magic.h \ + md4.h \ + md5.h \ + mppe.h \ + patchlevel.h \ + pathnames.h \ + peap.h \ + pppcrypt.h \ + pppd.h \ + pppdconf.h \ + session.h \ + sha1.h \ + spinlock.h \ + tls.h \ + tdb.h \ + upap.h + +pppd_SOURCES = \ + auth.c \ + ccp.c \ + chap-md5.c \ + chap-new.c \ + demand.c \ + eap.c \ + ecp.c \ + fsm.c \ + ipcp.c \ + lcp.c \ + magic.c \ + main.c \ + options.c \ + session.c \ + tty.c \ + upap.c \ + utils.c + +pppd_CPPFLAGS = -I${top_srcdir}/include -DPPPD_RUNTIME_DIR='"@PPPD_RUNTIME_DIR@"' -DPPPD_LOGFILE_DIR='"@PPPD_LOGFILE_DIR@"' +pppd_LDFLAGS = +pppd_LIBS = + +if LINUX +pppd_SOURCES += sys-linux.c termios_linux.h +pppd_LIBS += $(CRYPT_LIBS) $(UTIL_LIBS) +endif + +if SUNOS +pppd_SOURCES += sys-solaris.c +pppd_LIBS += -lsocket -lnsl +endif + +if WITH_CHAPMS +pppd_SOURCES += chap_ms.c +pppd_SOURCES += pppcrypt.c +check_PROGRAMS += utest_chap +else +if WITH_SRP +pppd_SOURCES += pppcrypt.c +endif +endif + +if WITH_CBCP +pppd_SOURCES += cbcp.c +endif + +if WITH_IPXCP +pppd_SOURCES += ipxcp.c +endif + +if WITH_MPPE +pppd_SOURCES += mppe.c +endif + +if WITH_FILTER +pppd_CPPFLAGS += $(PCAP_CFLAGS) +pppd_LDFLAGS += $(PCAP_LDFLAGS) +pppd_LIBS += $(PCAP_LIBS) +endif + +if WITH_PLUGINS +pppd_CPPFLAGS += -DPPPD_PLUGIN_DIR='"@PPPD_PLUGIN_DIR@"' +pppd_LIBS += -ldl +if LINUX +pppd_LDFLAGS += -Wl,-E +endif +endif + +if WITH_MULTILINK +pppd_SOURCES += multilink.c +endif + +if WITH_TDB +pppd_SOURCES += tdb.c spinlock.c +endif + +if WITH_INET6 +pppd_SOURCES += ipv6cp.c eui64.c +endif + +if WITH_PAM +pppd_LIBS += -lpam -ldl +endif + +if WITH_EAPTLS +pppd_SOURCES += eap-tls.c tls.c +else +if WITH_PEAP +pppd_SOURCES += tls.c +endif +endif + +if WITH_PEAP +pppd_SOURCES += peap.c +check_PROGRAMS += utest_peap +endif + +noinst_LTLIBRARIES = libppp_crypt.la +libppp_crypt_la_SOURCES= + +if !WITH_OPENSSL +libppp_crypt_la_SOURCES += md4.c md5.c sha1.c +else +libppp_crypt_la_CPPFLAGS=$(OPENSSL_INCLUDES) +libppp_crypt_la_LDFLAGS=$(OPENSSL_LDFLAGS) +libppp_crypt_la_LIBADD=$(OPENSSL_LIBS) +if !OPENSSL_HAVE_SHA +libppp_crypt_la_SOURCES += sha1.c +endif +if !OPENSSL_HAVE_MD5 +libppp_crypt_la_SOURCES += md5.c +endif +if !OPENSSL_HAVE_MD4 +libppp_crypt_la_SOURCES += md4.c +endif +endif + +utest_peap_LDADD = libppp_crypt.la +utest_chap_LDADD = libppp_crypt.la +pppd_LIBS += libppp_crypt.la + +if WITH_SYSTEMD +pppd_LIBS += -lsystemd +endif + +if WITH_SRP +srp_entry_SOURCES = srp-entry.c +srp_entry_CPPFLAGS = $(OPENSSL_INCLUDES) $(SRP_CFLAGS) +srp_entry_LDADD = $(SRP_LIBS) $(OPENSSL_LIBS) +srp_entry_LDFLAGS = $(OPENSSL_LDFLAGS) $(SRP_LDFLAGS) + +pppd_CPPFLAGS += $(SRP_CFLAGS) +pppd_LDFLAGS += $(SRP_LDFLAGS) +pppd_LIBS += $(SRP_LIBS) +endif + +pppd_LDADD = $(pppd_LIBS) + +EXTRA_DIST = \ + ppp.pam + +TESTS = $(check_PROGRAMS) + diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux deleted file mode 100644 index 22837c5..0000000 --- a/pppd/Makefile.linux +++ /dev/null @@ -1,261 +0,0 @@ -# -# pppd makefile for Linux -# Processed by configure to produce pppd/Makefile -# - -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -# Default installation locations -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -MANDIR = $(DESTDIR)/share/man/man8 -INCDIR = $(DESTDIR)/include - -TARGETS = pppd - -PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap-new.c md5.c ccp.c \ - ecp.c ipxcp.c auth.c options.c sys-linux.c md4.c chap_ms.c \ - demand.c utils.c tty.c eap.c chap-md5.c session.c - -HEADERS = ccp.h session.h chap-new.h ecp.h fsm.h ipcp.h \ - ipxcp.h lcp.h magic.h md5.h patchlevel.h pathnames.h pppd.h \ - upap.h eap.h - -MANPAGES = pppd.8 -PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o md5.o ccp.o \ - ecp.o auth.o options.o demand.o utils.o sys-linux.o ipxcp.o tty.o \ - eap.o chap-md5.o session.o - -# -# include dependencies if present -ifeq (.depend,$(wildcard .depend)) -include .depend -endif - -LIBS = -lrt - -# Uncomment the next line to include support for Microsoft's -# MS-CHAP authentication protocol. Also, edit plugins/radius/Makefile.linux. -CHAPMS=y -#USE_CRYPT=y -# Don't use MSLANMAN unless you really know what you're doing. -#MSLANMAN=y -# Uncomment the next line to include support for MPPE. CHAPMS (above) must -# also be enabled. Also, edit plugins/radius/Makefile.linux. -MPPE=y - -# Uncomment the next line to include support for PPP packet filtering. -# This requires that the libpcap library and headers be installed -# and that the kernel driver support PPP packet filtering. -FILTER=y - -# Uncomment the next line to enable multilink PPP (enabled by default) -# Linux distributions: Please leave multilink ENABLED in your builds -# of pppd! -HAVE_MULTILINK=y - -# Uncomment the next line to enable the TDB database (enabled by default.) -# If you enable multilink, then TDB is automatically enabled also. -# Linux distributions: Please leave TDB ENABLED in your builds. -USE_TDB=y - -# Uncomment the next line to enable Type=notify services in systemd -# If enabled, and the user sets the up_sdnotify option, then -# pppd will not detach and will notify systemd when up. -#SYSTEMD=y - -HAS_SHADOW=y -#USE_PAM=y -HAVE_INET6=y - -# Enable plugins -PLUGIN=y - -# Enable Microsoft proprietary Callback Control Protocol -#CBCP=y - -# Enable EAP SRP-SHA1 authentication (requires libsrp) -#USE_SRP=y - -# Use libutil; test if logwtmp is declared in to detect -ifeq ($(shell echo '\#include ' | $(CC) -E - 2>/dev/null | grep -q logwtmp && echo yes),yes) -USE_LIBUTIL=y -endif - -# Enable EAP-TLS authentication (requires MPPE support, libssl and libcrypto) -USE_EAPTLS=y - -MAXOCTETS=y - -INCLUDE_DIRS= -I../include - -COMPILE_FLAGS= -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MMAP -pipe - -CFLAGS= $(COPTS) $(COMPILE_FLAGS) $(INCLUDE_DIRS) '-DDESTDIR="@DESTDIR@"' - -ifdef CHAPMS -CFLAGS += -DCHAPMS=1 -NEEDDES=y -PPPDOBJS += md4.o chap_ms.o -HEADERS += md4.h chap_ms.h -ifdef MSLANMAN -CFLAGS += -DMSLANMAN=1 -endif -ifdef MPPE -CFLAGS += -DMPPE=1 -HEADERS += mppe.h -endif -endif - -# EAP SRP-SHA1 -ifdef USE_SRP -CFLAGS += -DUSE_SRP -DOPENSSL -I/usr/local/ssl/include -LIBS += -lsrp -L/usr/local/ssl/lib -NEEDCRYPTOLIB = y -TARGETS += srp-entry -EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry -MANPAGES += srp-entry.8 -EXTRACLEAN += srp-entry.o -NEEDDES=y -else -# OpenSSL has an integrated version of SHA-1, and its implementation -# is incompatible with this local SHA-1 implementation. We must use -# one or the other, not both. -PPPDSRCS += sha1.c -HEADERS += sha1.h -PPPDOBJS += sha1.o -endif - -# EAP-TLS -ifdef USE_EAPTLS -CFLAGS += -DUSE_EAPTLS=1 -LIBS += -lssl -NEEDCRYPTOLIB = y -PPPDSRC += eap-tls.c -HEADERS += eap-tls.h -PPPDOBJS += eap-tls.o -endif - -ifdef HAS_SHADOW -CFLAGS += -DHAS_SHADOW -#LIBS += -lshadow $(LIBS) -endif - -ifeq ($(shell echo '\#include ' | $(CC) -E - >/dev/null 2>&1 && echo yes),yes) -CFLAGS += -DHAVE_CRYPT_H=1 -LIBS += -lcrypt -endif - -ifdef USE_LIBUTIL -CFLAGS += -DHAVE_LOGWTMP=1 -LIBS += -lutil -endif - -ifdef NEEDDES -ifndef USE_CRYPT -CFLAGS += -I$(shell $(CC) --print-sysroot)/usr/include/openssl -NEEDCRYPTOLIB = y -else -CFLAGS += -DUSE_CRYPT=1 -endif -PPPDOBJS += pppcrypt.o -HEADERS += pppcrypt.h -endif - -ifdef NEEDCRYPTOLIB -LIBS += -lcrypto -endif - -# For "Pluggable Authentication Modules", see ftp.redhat.com:/pub/pam/. -ifdef USE_PAM -CFLAGS += -DUSE_PAM -LIBS += -lpam -ldl -endif - -# Multi-linnk -ifdef HAVE_MULTILINK - # Multilink implies the use of TDB - USE_TDB=y - - CFLAGS += -DHAVE_MULTILINK - PPPDSRCS += multilink.c - PPPDOBJS += multilink.o -endif - -# TDB -ifdef USE_TDB - CFLAGS += -DUSE_TDB=1 - PPPDSRCS += tdb.c spinlock.c - PPPDOBJS += tdb.o spinlock.o - HEADERS += tdb.h spinlock.h -endif - -# Lock library binary for Linux is included in 'linux' subdirectory. -ifdef LOCKLIB -LIBS += -llock -CFLAGS += -DLOCKLIB=1 -endif - -ifdef SYSTEMD -LIBS += -lsystemd -CFLAGS += -DSYSTEMD=1 -endif - -ifdef PLUGIN -CFLAGS += -DPLUGIN -LDFLAGS_PLUGIN += -Wl,-E -LIBS += -ldl -endif - -ifdef FILTER -LIBS += -lpcap -CFLAGS += -DPPP_FILTER -endif - -ifdef HAVE_INET6 - PPPDSRCS += ipv6cp.c eui64.c - HEADERS += ipv6cp.h eui64.h - PPPDOBJS += ipv6cp.o eui64.o - CFLAGS += -DINET6=1 -endif - -ifdef CBCP - PPPDSRCS += cbcp.c - PPPDOBJS += cbcp.o - CFLAGS += -DCBCP_SUPPORT - HEADERS += cbcp.h -endif - -ifdef MAXOCTETS - CFLAGS += -DMAXOCTETS -endif - -INSTALL= install - -all: $(TARGETS) - -install: pppd - mkdir -p $(BINDIR) $(MANDIR) - $(EXTRAINSTALL) - $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd - if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \ - chmod o-rx,u+s $(BINDIR)/pppd; fi - $(INSTALL) -c -m 444 pppd.8 $(MANDIR) - -pppd: $(PPPDOBJS) - $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_PLUGIN) -o pppd $(PPPDOBJS) $(LIBS) - -srp-entry: srp-entry.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ srp-entry.c $(LIBS) - -install-devel: - mkdir -p $(INCDIR)/pppd - $(INSTALL) -c -m 644 $(HEADERS) $(INCDIR)/pppd - -clean: - rm -f $(PPPDOBJS) $(EXTRACLEAN) $(TARGETS) *~ #* core - -depend: - $(CPP) -M $(CFLAGS) $(PPPDSRCS) >.depend diff --git a/pppd/Makefile.sol2 b/pppd/Makefile.sol2 deleted file mode 100644 index 809cb4b..0000000 --- a/pppd/Makefile.sol2 +++ /dev/null @@ -1,71 +0,0 @@ -# -# Makefile for pppd under Solaris 2. -# $Id: Makefile.sol2,v 1.30 2008/01/30 14:26:52 carlsonj Exp $ -# - -include ../Makedefs.com - -CFLAGS = -I../include -DSVR4 -DSOL2 $(COPTS) '-DDESTDIR="@DESTDIR@"' -LIBS = -lsocket -lnsl - -OBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap-new.o eap.o md5.o \ - tty.o ccp.o ecp.o auth.o options.o demand.o utils.o sys-solaris.o \ - chap-md5.o session.o - -# Solaris uses shadow passwords -CFLAGS += -DHAS_SHADOW - -# -# Comment the following out to disable plugins -# -CFLAGS += -DPLUGIN -LIBS += -ldl - -# -# Solaris 8 and above accomodates /var/run, so uncomment the -# following to place pppd process IDs on that location -# -#CFLAGS += -D_PATH_VARRUN='"/var/run/"' - -# -# uncomment the following to enable IPv6 -# -# Solaris 8 and on includes support for IPv6 -# -CFLAGS += -DINET6 -OBJS += ipv6cp.o eui64.o - -# Uncomment to enable MS-CHAP -CFLAGS += -DUSE_CRYPT -DCHAPMS -DMSLANMAN -DHAVE_CRYPT_H -OBJS += chap_ms.o pppcrypt.o md4.o sha1.o - -# Uncomment to enable MPPE (in both CHAP and EAP-TLS) -CFLAGS += -DMPPE - -# Uncomment to enable EAP-TLS -CFLAGS += -DUSE_EAPTLS -LIBS += -lcrypto -lssl -OBJS += eap-tls.o - -# Uncomment for CBCP -#CFLAGS += -DCBCP_SUPPORT -#OBJS += cbcp.o - -# Uncomment for PAM -#CFLAGS += -DUSE_PAM -#LIBS += -lpam - -# -# Make targets -# -all: pppd - -pppd: $(OBJS) - $(CC) -o pppd $(OBJS) $(LIBS) - -install: - $(INSTALL) -f $(BINDIR) -m 4755 -u root pppd - $(INSTALL) -f $(MANDIR)/man8 -m 444 pppd.8 - -clean: - rm -f $(OBJS) pppd *~ core y.tab.c y.tab.h diff --git a/pppd/auth.c b/pppd/auth.c index b1271c4..01ece57 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -70,6 +70,10 @@ #define RCSID "$Id: auth.c,v 1.117 2008/07/01 12:27:56 paulus Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -93,7 +97,7 @@ #include -#ifdef HAS_SHADOW +#ifdef HAVE_SHADOW_H #include #ifndef PW_PPP #define PW_PPP PW_LOGIN @@ -101,6 +105,10 @@ #endif #include +#ifdef HAVE_CRYPT_H +#include +#endif + #ifdef SYSTEMD #include #endif @@ -250,20 +258,25 @@ bool explicit_remote = 0; /* User specified explicit remote name */ bool explicit_user = 0; /* Set if "user" option supplied */ bool explicit_passwd = 0; /* Set if "password" option supplied */ char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -#ifdef USE_EAPTLS -char *cacert_file = NULL; /* CA certificate file (pem format) */ -char *ca_path = NULL; /* directory with CA certificates */ -char *cert_file = NULL; /* client certificate file (pem format) */ -char *privkey_file = NULL; /* client private key file (pem format) */ -char *crl_dir = NULL; /* directory containing CRL files */ -char *crl_file = NULL; /* Certificate Revocation List (CRL) file (pem format) */ -char *max_tls_version = NULL; /* Maximum TLS protocol version (default=1.2) */ -bool need_peer_eap = 0; /* Require peer to authenticate us */ + +#if defined(USE_EAPTLS) || defined(USE_PEAP) +char *cacert_file = NULL; /* CA certificate file (pem format) */ +char *ca_path = NULL; /* Directory with CA certificates */ +char *crl_dir = NULL; /* Directory containing CRL files */ +char *crl_file = NULL; /* Certificate Revocation List (CRL) file (pem format) */ +char *max_tls_version = NULL; /* Maximum TLS protocol version (default=1.2) */ +char *tls_verify_method = NULL; /* Verify certificate method */ +bool tls_verify_key_usage = 0; /* Verify peer certificate key usage */ #endif -static char *uafname; /* name of most recent +ua file */ +#if defined(USE_EAPTLS) +char *cert_file = NULL; /* Client certificate file (pem format) */ +char *privkey_file = NULL; /* Client private key file (pem format) */ +char *pkcs12_file = NULL; /* Client private key envelope file (pkcs12 format) */ +bool need_peer_eap = 0; /* Require peer to authenticate us */ +#endif -extern char *crypt (const char *, const char *); +static char *uafname; /* name of most recent +ua file */ /* Prototypes for procedures local to this file. */ @@ -436,18 +449,26 @@ option_t auth_options[] = { "Set telephone number(s) which are allowed to connect", OPT_PRIV | OPT_A2LIST }, -#ifdef USE_EAPTLS - { "ca", o_string, &cacert_file, "EAP-TLS CA certificate in PEM format" }, - { "capath", o_string, &ca_path, "EAP-TLS CA certificate directory" }, - { "cert", o_string, &cert_file, "EAP-TLS client certificate in PEM format" }, - { "key", o_string, &privkey_file, "EAP-TLS client private key in PEM format" }, - { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" }, - { "crl", o_string, &crl_file, "Use specific CRL file" }, +#if defined(USE_EAPTLS) || defined(USE_PEAP) + { "ca", o_string, &cacert_file, "CA certificate in PEM format" }, + { "capath", o_string, &ca_path, "TLS CA certificate directory" }, + { "crl-dir", o_string, &crl_dir, "Use CRLs in directory" }, + { "crl", o_string, &crl_file, "Use specific CRL file" }, { "max-tls-version", o_string, &max_tls_version, "Maximum TLS version (1.0/1.1/1.2 (default)/1.3)" }, + { "tls-verify-key-usage", o_bool, &tls_verify_key_usage, + "Verify certificate type and extended key usage" }, + { "tls-verify-method", o_string, &tls_verify_method, + "Verify peer by method (none|subject|name|suffix)" }, +#endif + +#if defined(USE_EAPTLS) + { "cert", o_string, &cert_file, "client certificate in PEM format" }, + { "key", o_string, &privkey_file, "client private key in PEM format" }, + { "pkcs12", o_string, &pkcs12_file, "EAP-TLS client credentials in PKCS12 format" }, { "need-peer-eap", o_bool, &need_peer_eap, "Require the peer to authenticate us", 1 }, -#endif /* USE_EAPTLS */ +#endif { NULL } }; @@ -1509,8 +1530,10 @@ check_passwd(int unit, if (secret[0] != 0 && !login_secret) { /* password given in pap-secrets - must match */ if (cryptpap || strcmp(passwd, secret) != 0) { +#ifdef HAVE_CRYPT_H char *cbuf = crypt(passwd, secret); if (!cbuf || strcmp(cbuf, secret) != 0) +#endif ret = UPAP_AUTHNAK; } } @@ -2458,6 +2481,8 @@ have_eaptls_secret_client(char *client, char *server) if ((cacert_file || ca_path) && cert_file && privkey_file) return 1; + if (pkcs12_file) + return 1; filename = _PATH_EAPTLSCLIFILE; f = fopen(filename, "r"); @@ -2641,7 +2666,7 @@ scan_authfile_eaptls(FILE *f, char *client, char *server, int get_eaptls_secret(int unit, char *client, char *server, char *clicertfile, char *servcertfile, char *cacertfile, - char *capath, char *pkfile, int am_server) + char *capath, char *pkfile, char *pkcs12, int am_server) { FILE *fp; int ret; @@ -2655,6 +2680,7 @@ get_eaptls_secret(int unit, char *client, char *server, bzero(cacertfile, MAXWORDLEN); bzero(capath, MAXWORDLEN); bzero(pkfile, MAXWORDLEN); + bzero(pkcs12, MAXWORDLEN); /* the ca+cert+privkey can also be specified as options */ if (!am_server && (cacert_file || ca_path) && cert_file && privkey_file ) @@ -2666,6 +2692,14 @@ get_eaptls_secret(int unit, char *client, char *server, strlcpy( capath, ca_path, MAXWORDLEN ); strlcpy( pkfile, privkey_file, MAXWORDLEN ); } + else if (!am_server && pkcs12_file) + { + strlcpy( pkcs12, pkcs12_file, MAXWORDLEN ); + if (cacert_file) + strlcpy( cacertfile, cacert_file, MAXWORDLEN ); + if (ca_path) + strlcpy( capath, ca_path, MAXWORDLEN ); + } else { filename = (am_server ? _PATH_EAPTLSSERVFILE : _PATH_EAPTLSCLIFILE); diff --git a/pppd/cbcp.c b/pppd/cbcp.c index e356633..87bf9c0 100644 --- a/pppd/cbcp.c +++ b/pppd/cbcp.c @@ -32,6 +32,9 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include diff --git a/pppd/cbcp.h b/pppd/cbcp.h index c2ab3f6..c74b5f8 100644 --- a/pppd/cbcp.h +++ b/pppd/cbcp.h @@ -1,6 +1,8 @@ #ifndef CBCP_H #define CBCP_H +#include "pppdconf.h" + typedef struct cbcp_state { int us_unit; /* Interface unit number */ u_char us_id; /* Current id */ diff --git a/pppd/ccp.c b/pppd/ccp.c index 052c4c6..644a9d1 100644 --- a/pppd/ccp.c +++ b/pppd/ccp.c @@ -28,6 +28,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define RCSID "$Id: ccp.c,v 1.50 2005/06/26 19:34:41 carlsonj Exp $" #include @@ -38,10 +42,9 @@ #include "ccp.h" #include -#ifdef MPPE -#include "chap_ms.h" /* mppe_xxxx_key, mppe_keys_set */ +#include "chap_ms.h" +#include "mppe.h" #include "lcp.h" /* lcp_close(), lcp_fsm */ -#endif /* @@ -574,7 +577,7 @@ ccp_resetci(fsm *f) } /* A plugin (eg radius) may not have obtained key material. */ - if (!mppe_keys_set) { + if (!mppe_keys_isset()) { error("MPPE required, but keys are not available. " "Possible plugin problem?"); lcp_close(f->unit, "MPPE required but not available"); @@ -705,7 +708,7 @@ static void p[1] = opt_buf[1] = CILEN_MPPE; MPPE_OPTS_TO_CI(go->mppe, &p[2]); MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); - BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN); + mppe_get_recv_key(&opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN); res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0); if (res > 0) p += CILEN_MPPE; @@ -1156,8 +1159,7 @@ ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) int mtu; BCOPY(p, opt_buf, CILEN_MPPE); - BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE], - MPPE_MAX_KEY_LEN); + mppe_get_send_key(&opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN); if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) { /* This shouldn't happen, we've already tested it! */ @@ -1426,8 +1428,7 @@ ccp_up(fsm *f) notice("%s transmit compression enabled", method_name(ho, NULL)); #ifdef MPPE if (go->mppe) { - BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN); - BZERO(mppe_send_key, MPPE_MAX_KEY_LEN); + mppe_clear_keys(); continue_networks(f->unit); /* Bring up IP et al */ } #endif diff --git a/pppd/ccp.h b/pppd/ccp.h index 76446db..35961b9 100644 --- a/pppd/ccp.h +++ b/pppd/ccp.h @@ -29,6 +29,7 @@ * * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ */ +#include "pppdconf.h" typedef struct ccp_options { bool bsd_compress; /* do BSD Compress? */ diff --git a/pppd/chap-md5.c b/pppd/chap-md5.c index 77dd4ec..000f880 100644 --- a/pppd/chap-md5.c +++ b/pppd/chap-md5.c @@ -30,6 +30,10 @@ #define RCSID "$Id: chap-md5.c,v 1.4 2004/11/09 22:39:25 paulus Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include "pppd.h" diff --git a/pppd/chap-md5.h b/pppd/chap-md5.h index 30d0658..4dbbfd1 100644 --- a/pppd/chap-md5.h +++ b/pppd/chap-md5.h @@ -27,5 +27,6 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" extern void chap_md5_init(void); diff --git a/pppd/chap-new.c b/pppd/chap-new.c index ad2f5eb..ab4302b 100644 --- a/pppd/chap-new.c +++ b/pppd/chap-new.c @@ -30,6 +30,10 @@ #define RCSID "$Id: chap-new.c,v 1.9 2007/06/19 02:08:35 carlsonj Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include "pppd.h" @@ -171,11 +175,11 @@ chap_register_digest(struct chap_digest_type *dp) */ struct chap_digest_type * chap_find_digest(int digest_code) { - struct chap_digest_type *dp = NULL; + struct chap_digest_type *dp = NULL; for (dp = chap_digests; dp != NULL; dp = dp->next) if (dp->code == digest_code) break; - return dp; + return dp; } /* @@ -222,9 +226,8 @@ chap_auth_peer(int unit, char *our_name, int digest_code) error("CHAP: peer authentication already started!"); return; } - for (dp = chap_digests; dp != NULL; dp = dp->next) - if (dp->code == digest_code) - break; + + dp = chap_find_digest(digest_code); if (dp == NULL) fatal("CHAP digest 0x%x requested but not available", digest_code); diff --git a/pppd/chap-new.h b/pppd/chap-new.h index e5330da..b4b0ee2 100644 --- a/pppd/chap-new.h +++ b/pppd/chap-new.h @@ -28,6 +28,8 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" + /* * CHAP packets begin with a standard header with code, id, len (2 bytes). */ diff --git a/pppd/chap_ms.c b/pppd/chap_ms.c index e6b84f2..c6e4b34 100644 --- a/pppd/chap_ms.c +++ b/pppd/chap_ms.c @@ -76,6 +76,10 @@ #define RCSID "$Id: chap_ms.c,v 1.38 2007/12/01 20:10:51 carlsonj Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef CHAPMS #include @@ -93,8 +97,11 @@ #include "sha1.h" #include "pppcrypt.h" #include "magic.h" +#include "mppe.h" - +#ifdef UNIT_TEST +#undef MPPE +#endif static void ascii2unicode (char[], int, u_char[]); static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); @@ -109,21 +116,12 @@ static void GenerateAuthenticatorResponsePlain static void ChapMS_LANMan (u_char *, char *, int, u_char *); #endif -#ifdef MPPE -static void Set_Start_Key (u_char *, char *, int); -static void SetMasterKeys (char *, int, u_char[24], int); -#endif - #ifdef MSLANMAN bool ms_lanman = 0; /* Use LanMan password instead of NT */ /* Has meaning only with MS-CHAP challenges */ #endif #ifdef MPPE -u_char mppe_send_key[MPPE_MAX_KEY_LEN]; -u_char mppe_recv_key[MPPE_MAX_KEY_LEN]; -int mppe_keys_set = 0; /* Have the MPPE keys been set? */ - #ifdef DEBUGMPPEKEY /* For MPPE debug */ /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ @@ -575,7 +573,7 @@ ascii2unicode(char ascii[], int ascii_len, u_char unicode[]) static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { -#ifdef __NetBSD__ +#if defined(__NetBSD__) || !defined(USE_MD4) /* NetBSD uses the libc md4 routines which take bytes instead of bits */ int mdlen = secret_len; #else @@ -584,12 +582,14 @@ NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) MD4_CTX md4Context; MD4Init(&md4Context); - /* MD4Update can take at most 64 bytes at a time */ +#if !defined(USE_MD4) + /* Internal MD4Update can take at most 64 bytes at a time */ while (mdlen > 512) { MD4Update(&md4Context, secret, 512); secret += 64; mdlen -= 512; } +#endif MD4Update(&md4Context, secret, mdlen); MD4Final(hash, &md4Context); @@ -719,28 +719,6 @@ GenerateAuthenticatorResponsePlain #ifdef MPPE -/* - * Set mppe_xxxx_key from the NTPasswordHashHash. - * RFC 2548 (RADIUS support) requires us to export this function (ugh). - */ -void -mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]) -{ - SHA1_CTX sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, rchallenge, 8); - SHA1_Final(Digest, &sha1Context); - - /* Same key in both directions. */ - BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key)); - BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key)); - - mppe_keys_set = 1; -} /* * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) @@ -757,104 +735,7 @@ Set_Start_Key(u_char *rchallenge, char *secret, int secret_len) NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - mppe_set_keys(rchallenge, PasswordHashHash); -} - -/* - * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) - * - * This helper function used in the Winbind module, which gets the - * NTHashHash from the server. - */ -void -mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], int IsServer) -{ - SHA1_CTX sha1Context; - u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - - u_char SHApad1[40] = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - u_char SHApad2[40] = - { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; - - /* "This is the MPPE Master Key" */ - u_char Magic1[27] = - { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; - /* "On the client side, this is the send key; " - "on the server side, it is the receive key." */ - u_char Magic2[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, - 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - /* "On the client side, this is the receive key; " - "on the server side, it is the send key." */ - u_char Magic3[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - u_char *s; - - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - SHA1_Update(&sha1Context, NTResponse, 24); - SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); - SHA1_Final(MasterKey, &sha1Context); - - /* - * generate send key - */ - if (IsServer) - s = Magic3; - else - s = Magic2; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, MasterKey, 16); - SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); - SHA1_Update(&sha1Context, s, 84); - SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); - SHA1_Final(Digest, &sha1Context); - - BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key)); - - /* - * generate recv key - */ - if (IsServer) - s = Magic2; - else - s = Magic3; - SHA1_Init(&sha1Context); - SHA1_Update(&sha1Context, MasterKey, 16); - SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); - SHA1_Update(&sha1Context, s, 84); - SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); - SHA1_Final(Digest, &sha1Context); - - BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key)); - - mppe_keys_set = 1; + mppe_set_chapv1(rchallenge, PasswordHashHash); } /* @@ -870,7 +751,7 @@ SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer) ascii2unicode(secret, secret_len, unicodePassword); NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - mppe_set_keys2(PasswordHashHash, NTResponse, IsServer); + mppe_set_chapv2(PasswordHashHash, NTResponse, IsServer); } #endif /* MPPE */ @@ -945,38 +826,6 @@ ChapMS2(u_char *rchallenge, u_char *PeerChallenge, #endif } -#ifdef MPPE -/* - * Set MPPE options from plugins. - */ -void -set_mppe_enc_types(int policy, int types) -{ - /* Early exit for unknown policies. */ - if (policy != MPPE_ENC_POL_ENC_ALLOWED || - policy != MPPE_ENC_POL_ENC_REQUIRED) - return; - - /* Don't modify MPPE if it's optional and wasn't already configured. */ - if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) - return; - - /* - * Disable undesirable encryption types. Note that we don't ENABLE - * any encryption types, to avoid overriding manual configuration. - */ - switch(types) { - case MPPE_ENC_TYPES_RC4_40: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ - break; - case MPPE_ENC_TYPES_RC4_128: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ - break; - default: - break; - } -} -#endif /* MPPE */ static struct chap_digest_type chapms_digest = { CHAP_MICROSOFT, /* code */ @@ -996,6 +845,7 @@ static struct chap_digest_type chapms2_digest = { chapms_handle_failure, }; +#ifndef UNIT_TEST void chapms_init(void) { @@ -1003,5 +853,96 @@ chapms_init(void) chap_register_digest(&chapms2_digest); add_options(chapms_option_list); } +#else + +#include + +int debug = 1; +int error_count = 0; +int unsuccess = 0; + +void random_bytes(unsigned char *bytes, int len) +{ + int i = 0; + srand(time(NULL)); + while (i < len) { + bytes[i++] = (unsigned char) rand(); + } +} + + +int test_chap_v1(void) { + char *secret = "TestPassword"; + + unsigned char challenge[8] = { + 0x6c, 0x8d, 0x4b, 0xa1, 0x2b, 0x5c, 0x13, 0xc3 + }; + unsigned char response[MS_CHAP_RESPONSE_LEN] = { + }; + unsigned char result[MS_CHAP_RESPONSE_LEN] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x91, 0x09, 0x61, 0x5a, 0x0c, 0xac, 0xac, 0x55, + 0x1f, 0x60, 0xe2, 0x9c, 0x00, 0xac, 0x24, 0xda, + 0x6e, 0xa5, 0x7b, 0xdb, 0x1d, 0x6a, 0x17, 0xc5, + 0x01 + }; + + ChapMS(challenge, secret, strlen(secret), response); + return memcmp(response, result, MS_CHAP_RESPONSE_LEN); +} + +int test_chap_v2(void) { + char *secret = "clientPass"; + char *name = "User"; + + char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + char *saresult = "407A5589115FD0D6209F510FE9C04566932CDA56"; + + unsigned char authenticator[16] = { + 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E, + 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28 + }; + unsigned char peerchallenge[16] = { + 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, + 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E + }; + unsigned char result[MS_CHAP_NTRESP_LEN] = { + 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, + 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, + 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF + }; + + unsigned char response[MS_CHAP2_RESPONSE_LEN] = { + }; + + ChapMS2(authenticator, peerchallenge, name, + secret, strlen(secret), response, + (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); + + return memcmp(&response[MS_CHAP2_NTRESP], result, MS_CHAP2_NTRESP_LEN) || + strncmp(saresponse, saresult, MS_AUTH_RESPONSE_LENGTH); +} + +int main(int argc, char *argv[]) { + + if (test_chap_v1()) { + printf("CHAPv1 failed\n"); + return -1; + } + + if (test_chap_v2()) { + printf("CHAPv2 failed\n"); + return -1; + } + + printf("Success\n"); + return 0; +} + +#endif /* UNIT_TEST */ + #endif /* CHAPMS */ diff --git a/pppd/chap_ms.h b/pppd/chap_ms.h index 005eb63..c1c5ed8 100644 --- a/pppd/chap_ms.h +++ b/pppd/chap_ms.h @@ -30,6 +30,8 @@ * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ */ +#include "pppdconf.h" + #ifndef __CHAPMS_INCLUDE__ #define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ @@ -38,6 +40,7 @@ #define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ #define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ #define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ +#define MS_AUTH_NTRESP_LEN 24 /* Length of NT-response field */ /* as ASCII */ /* E=eeeeeeeeee error codes for MS-CHAP failure messages. */ @@ -67,22 +70,6 @@ #define MS_CHAP2_NTRESP_LEN 24 #define MS_CHAP2_FLAGS 48 -#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; - -/* These values are the RADIUS attribute values--see RFC 2548. */ -#define MPPE_ENC_POL_ENC_ALLOWED 1 -#define MPPE_ENC_POL_ENC_REQUIRED 2 -#define MPPE_ENC_TYPES_RC4_40 2 -#define MPPE_ENC_TYPES_RC4_128 4 - -/* used by plugins (using above values) */ -extern void set_mppe_enc_types(int, int); -#endif - /* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ #define MS_CHAP2_AUTHENTICATEE 0 #define MS_CHAP2_AUTHENTICATOR 1 @@ -90,11 +77,6 @@ extern void set_mppe_enc_types(int, int); void ChapMS (u_char *, char *, int, u_char *); void ChapMS2 (u_char *, u_char *, char *, char *, int, u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); -#ifdef MPPE -void mppe_set_keys (u_char *, u_char[MD4_SIGNATURE_SIZE]); -void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], int IsServer); -#endif void ChallengeHash (u_char[16], u_char *, char *, u_char[8]); diff --git a/pppd/demand.c b/pppd/demand.c index 289c9f8..0943e8a 100644 --- a/pppd/demand.c +++ b/pppd/demand.c @@ -30,6 +30,10 @@ #define RCSID "$Id: demand.c,v 1.20 2005/08/25 12:14:18 paulus Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/eap-tls.c b/pppd/eap-tls.c index 5740f30..b9bab84 100644 --- a/pppd/eap-tls.c +++ b/pppd/eap-tls.c @@ -29,6 +29,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -37,87 +41,53 @@ #include #include +#ifndef OPENSSL_NO_ENGINE #include +#endif +#include #include #include #include #include +#include #include "pppd.h" +#include "tls.h" #include "eap.h" #include "eap-tls.h" #include "fsm.h" #include "lcp.h" +#include "chap_ms.h" +#include "mppe.h" #include "pathnames.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define SSL3_RT_HEADER 0x100 +#endif + typedef struct pw_cb_data { const void *password; const char *prompt_info; } PW_CB_DATA; +#ifndef OPENSSL_NO_ENGINE /* 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; +#endif /* TLSv1.3 do we have a session ticket ? */ static int have_session_ticket = 0; -int ssl_verify_callback(int, X509_STORE_CTX *); void ssl_msg_callback(int write_p, int version, int ct, const void *buf, size_t len, SSL * ssl, void *arg); int ssl_new_session_cb(SSL *s, SSL_SESSION *sess); -X509 *get_X509_from_file(char *filename); -int ssl_cmp_certs(char *filename, X509 * a); - #ifdef MPPE - #define EAPTLS_MPPE_KEY_LEN 32 -/* - * OpenSSL 1.1+ introduced a generic TLS_method() - * For older releases we substitute the appropriate method - */ - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - -#define TLS_method SSLv23_method - -#define SSL3_RT_HEADER 0x100 - -#ifndef SSL_CTX_set_max_proto_version -/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ -static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max) -{ - long sslopt = 0; - - if (tls_ver_max < TLS1_VERSION) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 - if (tls_ver_max < TLS1_1_VERSION) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 - if (tls_ver_max < TLS1_2_VERSION) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } -#endif - SSL_CTX_set_options(ctx, sslopt); - - return 1; -} -#endif /* SSL_CTX_set_max_proto_version */ - -#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ - - /* * Generate keys according to RFC 2716 and add to reply */ @@ -159,37 +129,16 @@ void eaptls_gen_mppe_keys(struct eaptls_session *ets, int client) */ 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) ); + mppe_set_keys(out, out + EAPTLS_MPPE_KEY_LEN, EAPTLS_MPPE_KEY_LEN); } 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_set_keys(out + EAPTLS_MPPE_KEY_LEN, out, EAPTLS_MPPE_KEY_LEN); } - - mppe_keys_set = 1; } #endif /* MPPE */ -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) @@ -219,20 +168,23 @@ CONF *eaptls_ssl_load_config( void ) } dbglog( "Loading OpenSSL built-ins" ); +#ifndef OPENSSL_NO_ENGINE ENGINE_load_builtin_engines(); +#endif 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(); + tls_log_sslerr(); config = NULL; } return config; } +#ifndef OPENSSL_NO_ENGINE ENGINE *eaptls_ssl_load_engine( char *engine_name ) { ENGINE *e = NULL; @@ -252,7 +204,7 @@ ENGINE *eaptls_ssl_load_engine( char *engine_name ) || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { warn( "EAP-TLS: Error loading dynamic engine '%s'", engine_name ); - log_ssl_errors(); + tls_log_sslerr(); ENGINE_free(e); e = NULL; } @@ -269,7 +221,7 @@ ENGINE *eaptls_ssl_load_engine( char *engine_name ) if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { warn( "EAP-TLS: Cannot use that engine" ); - log_ssl_errors(); + tls_log_sslerr(); ENGINE_free(e); e = NULL; } @@ -277,90 +229,103 @@ ENGINE *eaptls_ssl_load_engine( char *engine_name ) return e; } +#endif + + +#ifndef OPENSSL_NO_ENGINE +static int eaptls_UI_writer(UI *ui, UI_STRING *uis) +{ + PW_CB_DATA* cb_data = (PW_CB_DATA*)UI_get0_user_data(ui); + UI_set_result(ui, uis, cb_data->password); + return 1; +} +static int eaptls_UI_stub(UI* ui) { + return 1; +} +static int eaptls_UI_reader(UI *ui, UI_STRING *uis) { + return 1; +} +#endif /* * 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 *capath, - char *certfile, char *peer_certfile, char *privkeyfile) + char *certfile, char *privkeyfile, char *pkcs12) { +#ifndef OPENSSL_NO_ENGINE char *cert_engine_name = NULL; - char *cert_identifier = NULL; char *pkey_engine_name = NULL; - char *pkey_identifier = NULL; + char *idx; +#endif SSL_CTX *ctx; SSL *ssl; - X509_STORE *certstore; - X509_LOOKUP *lookup; X509 *tmp; + X509 *cert = NULL; + PKCS12 *p12 = NULL; + EVP_PKEY *pkey = NULL; + STACK_OF(X509) *chain = NULL; + BIO *input; int ret; -#if defined(TLS1_2_VERSION) - long tls_version = TLS1_2_VERSION; -#elif defined(TLS1_1_VERSION) - long tls_version = TLS1_1_VERSION; -#else - long tls_version = TLS1_VERSION; -#endif + int reason; /* * Without these can't continue */ - if (!(cacertfile[0] || capath[0])) + if (!pkcs12[0]) { - error("EAP-TLS: CA certificate file or path missing"); - return NULL; - } + if (!(cacertfile[0] || capath[0])) + { + error("EAP-TLS: CA certificate file or path missing"); + return NULL; + } - if (!certfile[0]) - { - error("EAP-TLS: Certificate missing"); - return NULL; - } + if (!certfile[0]) + { + error("EAP-TLS: Certificate missing"); + return NULL; + } - if (!privkeyfile[0]) - { - error("EAP-TLS: Private key missing"); - return NULL; + if (!privkeyfile[0]) + { + error("EAP-TLS: Private key missing"); + return NULL; + } } - SSL_library_init(); - SSL_load_error_strings(); + tls_init(); +#ifndef OPENSSL_NO_ENGINE /* load the openssl config file only once and load it before triggering the loading of a global openssl config file via SSL_CTX_new() */ if (!ssl_config) ssl_config = eaptls_ssl_load_config(); +#endif - ctx = SSL_CTX_new(TLS_method()); - + ctx = SSL_CTX_new(tls_method()); if (!ctx) { error("EAP-TLS: Cannot initialize SSL CTX context"); goto fail; } +#ifndef OPENSSL_NO_ENGINE /* 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 ) + if ( (idx = index( certfile, ':' )) != NULL ) { - cert_identifier = index( certfile, ':' ); - - if (cert_identifier) - { - cert_engine_name = certfile; - *cert_identifier = '\0'; - cert_identifier++; + cert_engine_name = strdup( certfile ); + cert_engine_name[idx - certfile] = 0; - dbglog( "Found certificate engine '%s'", cert_engine_name ); - dbglog( "Found certificate identifier '%s'", cert_identifier ); - } + dbglog( "Using engine '%s' for certificate, URI: '%s'", + cert_engine_name, certfile ); } /* if the privatekey filename is of the form engine:id. e.g. @@ -369,39 +334,33 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, 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 ) + if ( (idx = index( privkeyfile, ':' )) != NULL ) { - pkey_identifier = index( privkeyfile, ':' ); - - if (pkey_identifier) - { - pkey_engine_name = privkeyfile; - *pkey_identifier = '\0'; - pkey_identifier++; + pkey_engine_name = strdup( privkeyfile ); + pkey_engine_name[idx - privkeyfile] = 0; - dbglog( "Found privatekey engine '%s'", pkey_engine_name ); - dbglog( "Found privatekey identifier '%s'", pkey_identifier ); - } + dbglog( "Using engine '%s' for private key, URI: '%s'", + pkey_engine_name, privkeyfile ); } - if (cert_identifier && pkey_identifier) + if (cert_engine_name && pkey_engine_name) { - if (strlen( cert_identifier ) == 0) + if (strlen( certfile ) - strlen( cert_engine_name ) == 1) { - if (strlen( pkey_identifier ) == 0) + if (strlen( privkeyfile ) - strlen( pkey_engine_name ) == 1) error( "EAP-TLS: both the certificate and privatekey identifiers are missing!" ); else { dbglog( "Substituting privatekey identifier for certificate identifier" ); - cert_identifier = pkey_identifier; + certfile = privkeyfile; } } else { - if (strlen( pkey_identifier ) == 0) + if (strlen( privkeyfile ) - strlen( pkey_engine_name ) == 1) { dbglog( "Substituting certificate identifier for privatekey identifier" ); - pkey_identifier = cert_identifier; + privkeyfile = certfile; } } } @@ -418,22 +377,24 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, pkey_engine = eaptls_ssl_load_engine( pkey_engine_name ); } - SSL_CTX_set_default_passwd_cb (ctx, password_callback); + if (cert_engine_name) + free(cert_engine_name); - if (strlen(cacertfile) == 0) cacertfile = NULL; - if (strlen(capath) == 0) capath = NULL; + if (pkey_engine_name) + free(pkey_engine_name); - if (!SSL_CTX_load_verify_locations(ctx, cacertfile, capath)) - { - error("EAP-TLS: Cannot load verify locations"); - if (cacertfile) dbglog("CA certificate file = [%s]", cacertfile); - if (capath) dbglog("CA certificate path = [%s]", capath); +#endif + + SSL_CTX_set_default_passwd_cb (ctx, password_callback); + + if (tls_set_ca(ctx, capath, cacertfile) != 0) { goto fail; } if (init_server) SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(cacertfile)); +#ifndef OPENSSL_NO_ENGINE if (cert_engine) { struct @@ -442,40 +403,87 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, X509 *cert; } cert_info; - cert_info.s_slot_cert_id = cert_identifier; + cert_info.s_slot_cert_id = certfile; 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 ); + error( "EAP-TLS: Error loading certificate with URI '%s' from engine", certfile ); goto fail; } if (cert_info.cert) { - dbglog( "Got the certificate, adding it to SSL context" ); + dbglog( "Got the certificate" ); 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) + cert = cert_info.cert; + } + else + { + warn("EAP-TLS: Cannot load key with URI: '%s'", certfile ); + tls_log_sslerr(); + } + } + else +#endif + { + if (pkcs12[0]) + { + input = BIO_new_file(pkcs12, "r"); + if (input == NULL) + { + error("EAP-TLS: Cannot open `%s' PKCS12 for input", pkcs12); + goto fail; + } + + p12 = d2i_PKCS12_bio(input, NULL); + BIO_free(input); + if (!p12) + { + error("EAP-TLS: Cannot load PKCS12 certificate"); + goto fail; + } + + if (PKCS12_parse(p12, passwd, &pkey, &cert, &chain) != 1) { - error("EAP-TLS: Cannot use PKCS11 certificate %s", cert_identifier); + error("EAP-TLS: Cannot parse PKCS12 certificate, invalid password"); + PKCS12_free(p12); goto fail; } + + PKCS12_free(p12); } - else + else { - warn("EAP-TLS: Cannot load PKCS11 key %s", cert_identifier); - log_ssl_errors(); + if (!SSL_CTX_use_certificate_chain_file(ctx, certfile)) + { + error( "EAP-TLS: Cannot load certificate %s", certfile ); + goto fail; + } } } - else + + if (cert) { - if (!SSL_CTX_use_certificate_chain_file(ctx, certfile)) + if (!SSL_CTX_use_certificate(ctx, cert)) { - error( "EAP-TLS: Cannot use public certificate %s", certfile ); + error("EAP-TLS: Cannot use load certificate"); goto fail; } - } + if (chain) + { + int i; + for (i = 0; i < sk_X509_num(chain); i++) + { + if (!SSL_CTX_add_extra_chain_cert(ctx, sk_X509_value(chain, i))) + { + error("EAP-TLS: Cannot add extra chain certificate"); + goto fail; + } + } + } + } /* * Check the Before and After dates of the certificate @@ -504,86 +512,70 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, } SSL_free(ssl); +#ifndef OPENSSL_NO_ENGINE if (pkey_engine) { - EVP_PKEY *pkey = NULL; PW_CB_DATA cb_data; cb_data.password = passwd; - cb_data.prompt_info = pkey_identifier; + cb_data.prompt_info = privkeyfile; if (passwd[0] != 0) { UI_METHOD* transfer_pin = UI_create_method("transfer_pin"); - int writer (UI *ui, UI_STRING *uis) - { - PW_CB_DATA* cb_data = (PW_CB_DATA*)UI_get0_user_data(ui); - UI_set_result(ui, uis, cb_data->password); - return 1; - }; - int stub (UI* ui) {return 1;}; - int stub_reader (UI *ui, UI_STRING *uis) {return 1;}; - - UI_method_set_writer(transfer_pin, writer); - UI_method_set_opener(transfer_pin, stub); - UI_method_set_closer(transfer_pin, stub); - UI_method_set_flusher(transfer_pin, stub); - UI_method_set_reader(transfer_pin, stub_reader); - - dbglog( "Using our private key '%s' in engine", pkey_identifier ); - pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, transfer_pin, &cb_data); + UI_method_set_writer(transfer_pin, eaptls_UI_writer); + UI_method_set_opener(transfer_pin, eaptls_UI_stub); + UI_method_set_closer(transfer_pin, eaptls_UI_stub); + UI_method_set_flusher(transfer_pin, eaptls_UI_stub); + UI_method_set_reader(transfer_pin, eaptls_UI_reader); + + dbglog( "Using our private key URI: '%s' in engine", privkeyfile ); + pkey = ENGINE_load_private_key(pkey_engine, privkeyfile, transfer_pin, &cb_data); if (transfer_pin) UI_destroy_method(transfer_pin); } else { - dbglog( "Loading private key '%s' from engine", pkey_identifier ); - pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, NULL, NULL); + dbglog( "Loading private key URI: '%s' from engine", privkeyfile ); + pkey = ENGINE_load_private_key(pkey_engine, privkeyfile, NULL, NULL); } - if (pkey) + } + else +#endif + { + if (!pkey) { - dbglog( "Got the private key, adding it to SSL context" ); - if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) + input = BIO_new_file(privkeyfile, "r"); + if (!input) { - error("EAP-TLS: Cannot use PKCS11 key %s", pkey_identifier); + error("EAP-TLS: Could not open private key, %s", privkeyfile); + goto fail; + } + + pkey = PEM_read_bio_PrivateKey(input, NULL, password_callback, NULL); + BIO_free(input); + if (!pkey) + { + error("EAP-TLS: Cannot load private key, %s", privkeyfile); goto fail; } - } - else - { - warn("EAP-TLS: Cannot load PKCS11 key %s", pkey_identifier); - log_ssl_errors(); } } - else + + if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) { - if (!SSL_CTX_use_PrivateKey_file(ctx, privkeyfile, SSL_FILETYPE_PEM)) - { - error("EAP-TLS: Cannot use private key %s", privkeyfile); - goto fail; - } + error("EAP-TLS: Cannot use private key"); + goto fail; } - if (SSL_CTX_check_private_key(ctx) != 1) { - error("EAP-TLS: Private key %s fails security check", privkeyfile); + if (SSL_CTX_check_private_key(ctx) != 1) + { + error("EAP-TLS: Private key fails security check"); goto fail; } - /* Explicitly set the NO_TICKETS flag to support Win7/Win8 clients */ - SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 -#ifdef SSL_OP_NO_TICKET - | SSL_OP_NO_TICKET -#endif - ); - - /* OpenSSL 1.1.1+ does not include RC4 ciphers by default. - * This causes totally obsolete WinXP clients to fail. If you really - * need ppp+EAP-TLS+openssl 1.1.1+WinXP then enable RC4 cipers and - * make sure that you use an OpenSSL that supports them - - SSL_CTX_set_cipher_list(ctx, "RC4"); - */ - + /* Configure the default options */ + tls_set_opts(ctx); /* Set up a SSL Session cache with a callback. This is needed for TLSv1.3+. * During the initial handshake the server signals to the client early on @@ -595,100 +587,33 @@ SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE); SSL_CTX_sess_set_new_cb(ctx, ssl_new_session_cb); - /* As EAP-TLS+TLSv1.3 is highly experimental we offer the user a chance to override */ - if (max_tls_version) - { - if (strncmp(max_tls_version, "1.0", 3) == 0) - tls_version = TLS1_VERSION; - else if (strncmp(max_tls_version, "1.1", 3) == 0) - tls_version = TLS1_1_VERSION; - else if (strncmp(max_tls_version, "1.2", 3) == 0) -#ifdef TLS1_2_VERSION - tls_version = TLS1_2_VERSION; -#else - { - warn("TLSv1.2 not available. Defaulting to TLSv1.1"); - tls_version = TLS_1_1_VERSION; - } -#endif - else if (strncmp(max_tls_version, "1.3", 3) == 0) -#ifdef TLS1_3_VERSION - tls_version = TLS1_3_VERSION; -#else - warn("TLSv1.3 not available."); -#endif - } - - dbglog("EAP-TLS: Setting max protocol version to 0x%X", tls_version); - SSL_CTX_set_max_proto_version(ctx, tls_version); - - 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"); + /* Configure the maximum SSL version */ + tls_set_version(ctx, max_tls_version); - goto fail; - } - - X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); - X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); + /* Configure the callback */ + if (tls_set_verify(ctx, 5)) { + goto fail; } - if (crl_file) { - FILE *fp = NULL; - X509_CRL *crl = NULL; - - fp = fopen(crl_file, "r"); - if (!fp) { - error("EAP-TLS: Cannot open CRL file '%s'", crl_file); - goto fail; - } + /* Configure CRL check (if any) */ + if (tls_set_crl(ctx, crl_dir, crl_file)) { + goto fail; + } - crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL); - if (!crl) { - error("EAP-TLS: Cannot read CRL file '%s'", crl_file); - goto fail; - } + return ctx; - if (!(certstore = SSL_CTX_get_cert_store(ctx))) { - error("EAP-TLS: Failed to get certificate store"); - goto fail; - } - if (!X509_STORE_add_crl(certstore, crl)) { - error("EAP-TLS: Cannot add CRL to certificate store"); - goto fail; - } - X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); +fail: - } + if (cert) + X509_free(cert); - /* - * 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); - } + if (pkey) + EVP_PKEY_free(pkey); - return ctx; + if (chain) + sk_X509_pop_free(chain, X509_free); -fail: - log_ssl_errors(); + tls_log_sslerr(); SSL_CTX_free(ctx); return NULL; } @@ -726,6 +651,8 @@ int eaptls_init_ssl_server(eap_state * esp) char cacertfile[MAXWORDLEN]; char capath[MAXWORDLEN]; char pkfile[MAXWORDLEN]; + char pkcs12[MAXWORDLEN]; + /* * Allocate new eaptls session */ @@ -739,12 +666,10 @@ int eaptls_init_ssl_server(eap_state * esp) return 0; } - strlcpy(ets->peer, esp->es_server.ea_peer, MAXWORDLEN-1); - dbglog( "getting eaptls secret" ); if (!get_eaptls_secret(esp->es_unit, esp->es_server.ea_peer, esp->es_server.ea_name, clicertfile, - servcertfile, cacertfile, capath, pkfile, 1)) { + servcertfile, cacertfile, capath, pkfile, pkcs12, 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; @@ -752,13 +677,17 @@ int eaptls_init_ssl_server(eap_state * esp) ets->mtu = eaptls_get_mtu(esp->es_unit); - ets->ctx = eaptls_init_ssl(1, cacertfile, capath, servcertfile, clicertfile, pkfile); + ets->ctx = eaptls_init_ssl(1, cacertfile, capath, servcertfile, pkfile, pkcs12); if (!ets->ctx) goto fail; if (!(ets->ssl = SSL_new(ets->ctx))) goto fail; + if (tls_set_verify_info(ets->ssl, esp->es_server.ea_peer, + clicertfile, 0, &ets->info)) + goto fail; + /* * Set auto-retry to avoid timeouts on BIO_read */ @@ -774,12 +703,6 @@ int eaptls_init_ssl_server(eap_state * esp) 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->tls_v13 = 0; @@ -788,16 +711,6 @@ int eaptls_init_ssl_server(eap_state * esp) 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]) - strlcpy(&ets->peercertfile[0], clicertfile, MAXWORDLEN); - else - ets->peercertfile[0] = 0; - return 1; fail: @@ -816,6 +729,7 @@ int eaptls_init_ssl_client(eap_state * esp) char cacertfile[MAXWORDLEN]; char capath[MAXWORDLEN]; char pkfile[MAXWORDLEN]; + char pkcs12[MAXWORDLEN]; /* * Allocate new eaptls session @@ -824,37 +738,30 @@ int eaptls_init_ssl_client(eap_state * esp) 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) - strlcpy(ets->peer, esp->es_client.ea_peer, MAXWORDLEN-1); - else - ets->peer[0] = 0; - ets->mtu = eaptls_get_mtu(esp->es_unit); dbglog( "calling get_eaptls_secret" ); if (!get_eaptls_secret(esp->es_unit, esp->es_client.ea_name, - ets->peer, clicertfile, - servcertfile, cacertfile, capath, pkfile, 0)) { + esp->es_client.ea_peer, clicertfile, + servcertfile, cacertfile, capath, pkfile, pkcs12, 0)) { error( "EAP-TLS: Cannot get secret/password for client \"%s\", server \"%s\"", - esp->es_client.ea_name, ets->peer ); + esp->es_client.ea_name, esp->es_client.ea_peer); return 0; } dbglog( "calling eaptls_init_ssl" ); - ets->ctx = eaptls_init_ssl(0, cacertfile, capath, clicertfile, servcertfile, pkfile); + ets->ctx = eaptls_init_ssl(0, cacertfile, capath, clicertfile, pkfile, pkcs12); if (!ets->ctx) goto fail; ets->ssl = SSL_new(ets->ctx); - if (!ets->ssl) goto fail; + if (tls_set_verify_info(ets->ssl, esp->es_client.ea_peer, + servcertfile, 0, &ets->info)) + goto fail; + /* * Initialize the BIOs we use to read/write to ssl engine */ @@ -865,13 +772,6 @@ int eaptls_init_ssl_client(eap_state * esp) 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->tls_v13 = 0; @@ -880,17 +780,6 @@ int eaptls_init_ssl_client(eap_state * esp) 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]) - strlcpy(ets->peercertfile, servcertfile, MAXWORDLEN); - else - ets->peercertfile[0] = 0; - return 1; fail: @@ -908,6 +797,9 @@ void eaptls_free_session(struct eaptls_session *ets) if (ets->ctx) SSL_CTX_free(ets->ctx); + if (ets->info) + tls_free_verify_info(&ets->info); + free(ets); } @@ -1017,7 +909,7 @@ int eaptls_receive(struct eaptls_session *ets, u_char * inp, int len) } if (BIO_write(ets->into_ssl, ets->data, ets->datalen) == -1) - log_ssl_errors(); + tls_log_sslerr(); SSL_read(ets->ssl, dummy, 65536); @@ -1132,133 +1024,6 @@ void eaptls_retransmit(struct eaptls_session *ets, u_char ** outp) 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 ok, X509_STORE_CTX * ctx) -{ - char subject[256]; - char cn_str[256]; - X509 *peer_cert; - int err, depth; - 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 ok; - } - - /* - * 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 ok; -} - -/* - * 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 diff --git a/pppd/eap-tls.h b/pppd/eap-tls.h index cdbc9e4..9c56687 100644 --- a/pppd/eap-tls.h +++ b/pppd/eap-tls.h @@ -30,6 +30,8 @@ * */ +#include "pppdconf.h" + #ifndef __EAP_TLS_H__ #define __EAP_TLS_H__ @@ -44,6 +46,8 @@ #define EAP_TLS_MAX_LEN 65536 /* max eap tls packet size */ +struct tls_info; + struct eaptls_session { u_char *data; /* buffered data */ @@ -56,7 +60,6 @@ struct eaptls_session 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; @@ -65,11 +68,12 @@ struct eaptls_session char rtx[EAP_TLS_MAX_LEN]; /* retransmission buffer */ int rtx_len; int mtu; /* unit mtu */ + struct tls_info *info; }; SSL_CTX *eaptls_init_ssl(int init_server, char *cacertfile, char *capath, - char *certfile, char *peer_certfile, char *privkeyfile); + char *certfile, char *privkeyfile, char *pkcs12); int eaptls_init_ssl_server(eap_state * esp); int eaptls_init_ssl_client(eap_state * esp); void eaptls_free_session(struct eaptls_session *ets); @@ -82,14 +86,9 @@ 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 *capath, char *pkfile, int am_server); + char *capath, char *pkfile, char *pkcs12, 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, int client); #endif diff --git a/pppd/eap.c b/pppd/eap.c index 7914655..54c3d42 100644 --- a/pppd/eap.c +++ b/pppd/eap.c @@ -48,6 +48,10 @@ * Implemented EAP-TLS authentication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -63,12 +67,14 @@ #include "pathnames.h" #include "md5.h" #include "eap.h" - -#ifdef CHAPMS -#include "chap_ms.h" -#endif +#ifdef USE_PEAP +#include "peap.h" +#endif /* USE_PEAP */ #ifdef USE_SRP +#ifdef HAVE_TIME_H +#include +#endif #include #include #include @@ -82,10 +88,12 @@ #ifdef USE_EAPTLS #include "eap-tls.h" #endif /* USE_EAPTLS */ + #ifdef CHAPMS -#include "magic.h" #include "chap_ms.h" #include "chap-new.h" + +extern int chapms_strip_domain; #endif /* CHAPMS */ eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */ @@ -223,7 +231,8 @@ eap_init(int unit) esp->es_client.ea_using_eaptls = 0; #endif /* USE_EAPTLS */ #ifdef CHAPMS - esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2); + esp->es_client.digest = chap_find_digest(CHAP_MICROSOFT_V2); + esp->es_server.digest = chap_find_digest(CHAP_MICROSOFT_V2); #endif } @@ -553,7 +562,7 @@ eap_figure_next_state(eap_state *esp, int status) tpw.pebuf.name = esp->es_server.ea_peer; tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, cp); - tpw.pebuf.password.data = tpw.pwbuf; + tpw.pebuf.password.data = (char*) tpw.pwbuf; tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, cp2); tpw.pebuf.salt.data = tpw.saltbuf; @@ -719,92 +728,6 @@ eap_figure_next_state(eap_state *esp, int status) } #if CHAPMS -static int -eap_chapms2_verify_response(int id, char *name, - unsigned char *secret, int secret_len, - unsigned char *challenge, unsigned char *response, - char *message, int message_space) -{ - unsigned char md[MS_CHAP2_RESPONSE_LEN]; - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; - int challenge_len, response_len; - - challenge_len = *challenge++; /* skip length, is 16 */ - response_len = *response++; - if (response_len != MS_CHAP2_RESPONSE_LEN) - goto bad; /* not even the right length */ - - /* Generate the expected response and our mutual auth. */ - ChapMS2(challenge, &response[MS_CHAP2_PEER_CHALLENGE], name, - (char *)secret, secret_len, md, - (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); - - /* compare MDs and send the appropriate status */ - /* - * Per RFC 2759, success message must be formatted as - * "S= M=" - * where - * is the Authenticator Response (mutual auth) - * is a text message - * - * However, some versions of Windows (win98 tested) do not know - * about the M= part (required per RFC 2759) and flag - * it as an error (reported incorrectly as an encryption error - * to the user). Since the RFC requires it, and it can be - * useful information, we supply it if the peer is a conforming - * system. Luckily (?), win98 sets the Flags field to 0x04 - * (contrary to RFC requirements) so we can use that to - * distinguish between conforming and non-conforming systems. - * - * Special thanks to Alex Swiridov for - * help debugging this. - */ - if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], - MS_CHAP2_NTRESP_LEN) == 0) { - if (response[MS_CHAP2_FLAGS]) - slprintf(message, message_space, "S=%s", saresponse); - else - slprintf(message, message_space, "S=%s M=%s", - saresponse, "Access granted"); - return 1; - } - - bad: - /* - * Failure message must be formatted as - * "E=e R=r C=c V=v M=m" - * where - * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) - * r = retry (we use 1, ok to retry) - * c = challenge to use for next response, we reuse previous - * v = Change Password version supported, we use 0 - * m = text message - * - * The M=m part is only for MS-CHAPv2. Neither win2k nor - * win98 (others untested) display the message to the user anyway. - * They also both ignore the E=e code. - * - * Note that it's safe to reuse the same challenge as we don't - * actually accept another response based on the error message - * (and no clients try to resend a response anyway). - * - * Basically, this whole bit is useless code, even the small - * implementation here is only because of overspecification. - */ - slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", - challenge_len, challenge, "Access denied"); - return 0; -} - -static struct chap_digest_type eap_chapms2_digest = { - CHAP_MICROSOFT_V2, /* code */ - NULL, /* chapms2_generate_challenge, */ - eap_chapms2_verify_response, - NULL, /* chapms2_make_response, */ - NULL, /* chapms2_check_success, */ - NULL, /* chapms_handle_failure, */ -}; - /* * eap_chap_verify_response - check whether the peer's response matches * what we think it should be. Returns 1 if it does (authentication @@ -961,10 +884,9 @@ eap_send_request(eap_state *esp) #ifdef CHAPMS case eapMSCHAPv2Chall: - challen = 0x10; + esp->es_server.digest->generate_challenge(esp->es_challenge); + challen = esp->es_challenge[0]; esp->es_challen = challen; - esp->es_challenge[0] = challen; - random_bytes(&esp->es_challenge[1], challen); PUTCHAR(EAPT_MSCHAPV2, outp); PUTCHAR(CHAP_CHALLENGE, outp); @@ -2297,6 +2219,28 @@ eap_request(eap_state *esp, u_char *inp, int id, int len) break; #endif /* CHAPMS */ +#ifdef USE_PEAP + case EAPT_PEAP: + + /* Initialize the PEAP context (if not already initialized) */ + if (!esp->ea_peap) { + rhostname[0] = '\0'; + if (explicit_remote || (remote_name[0] != '\0')) { + strlcpy(rhostname, remote_name, sizeof (rhostname)); + } + if (peap_init(&esp->ea_peap, rhostname)) { + eap_send_nak(esp, id, EAPT_TLS); + break; + } + } + + /* Process the PEAP packet */ + if (peap_process(esp, id, inp, len)) { + eap_send_nak(esp, id, EAPT_TLS); + } + + break; +#endif /* USE_PEAP */ default: info("EAP: unknown authentication type %d; Naking", typenum); @@ -2341,8 +2285,6 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) struct t_num A; SHA1_CTX ctxt; u_char dig[SHA_DIGESTSIZE]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; #endif /* USE_SRP */ #ifdef USE_EAPTLS @@ -2500,6 +2442,12 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) #ifdef CHAPMS case EAPT_MSCHAPV2: info("EAP: peer proposes MSCHAPv2"); + /* If MSCHAPv2 digest was not found, NAK the packet */ + if (!esp->es_server.digest) { + error("EAP MSCHAPv2 not supported"); + eap_send_nak(esp, id, EAPT_SRP); + break; + } esp->es_server.ea_state = eapMSCHAPv2Chall; break; #endif /* CHAPMS */ @@ -2629,6 +2577,14 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) (remote_name[0] != '\0' && vallen == len)) strlcpy(rhostname, remote_name, sizeof (rhostname)); + /* strip the MS domain name */ + if (chapms_strip_domain && strrchr(rhostname, '\\')) { + char tmp[MAXNAMELEN+1]; + + strcpy(tmp, strrchr(rhostname, '\\') + 1); + strcpy(rhostname, tmp); + } + if (chap_verify_hook) chap_verifier = chap_verify_hook; else @@ -2638,7 +2594,7 @@ eap_response(eap_state *esp, u_char *inp, int id, int len) if ((*chap_verifier)(rhostname, esp->es_server.ea_name, id, - &eap_chapms2_digest, + esp->es_server.digest, esp->es_challenge, inp - 1, response_message, @@ -2838,6 +2794,10 @@ eap_success(eap_state *esp, u_char *inp, int id, int len) PRINTMSG(inp, len); } +#ifdef USE_PEAP + peap_finish(&esp->ea_peap); +#endif + esp->es_client.ea_state = eapOpen; auth_withpeer_success(esp->es_unit, PPP_EAP, 0); } @@ -2872,6 +2832,11 @@ eap_failure(eap_state *esp, u_char *inp, int id, int len) esp->es_client.ea_state = eapBadAuth; error("EAP: peer reports authentication failure"); + +#ifdef USE_PEAP + peap_finish(&esp->ea_peap); +#endif + auth_withpeer_fail(esp->es_unit, PPP_EAP); } @@ -3095,6 +3060,7 @@ eap_printpkt(u_char *inp, int inlen, break; #endif /* USE_EAPTLS */ +#ifdef USE_SRP case EAPT_SRP: if (len < 3) goto truncated; @@ -3182,6 +3148,7 @@ eap_printpkt(u_char *inp, int inlen, break; } break; +#endif /* USE_SRP */ } break; @@ -3307,6 +3274,7 @@ eap_printpkt(u_char *inp, int inlen, break; #endif /* CHAPMS */ +#ifdef USE_SRP case EAPT_SRP: if (len < 1) goto truncated; @@ -3351,6 +3319,7 @@ eap_printpkt(u_char *inp, int inlen, break; } break; +#endif /* USE_SRP */ } break; diff --git a/pppd/eap.h b/pppd/eap.h index 046eb1c..5d582bc 100644 --- a/pppd/eap.h +++ b/pppd/eap.h @@ -20,6 +20,8 @@ * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ */ +#include "pppdconf.h" + #ifndef PPP_EAP_H #define PPP_EAP_H @@ -167,6 +169,9 @@ typedef struct eap_state { int es_unit; /* Interface unit number */ struct eap_auth es_client; /* Client (authenticatee) data */ struct eap_auth es_server; /* Server (authenticator) data */ +#ifdef USE_PEAP + struct peap_state *ea_peap; /* Client PEAP (authenticator) data */ +#endif int es_savedtime; /* Saved timeout */ int es_rechallenge; /* EAP rechallenge interval */ int es_lwrechallenge; /* SRP lightweight rechallenge inter */ diff --git a/pppd/ecp.c b/pppd/ecp.c index 1ecd7be..9570f38 100644 --- a/pppd/ecp.c +++ b/pppd/ecp.c @@ -57,6 +57,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "pppd.h" diff --git a/pppd/ecp.h b/pppd/ecp.h index df6e3ca..162dace 100644 --- a/pppd/ecp.h +++ b/pppd/ecp.h @@ -30,6 +30,7 @@ * * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ */ +#include "pppdconf.h" typedef struct ecp_options { bool required; /* Is ECP required? */ diff --git a/pppd/eui64.c b/pppd/eui64.c index 98caf94..7978c06 100644 --- a/pppd/eui64.c +++ b/pppd/eui64.c @@ -34,6 +34,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "pppd.h" diff --git a/pppd/eui64.h b/pppd/eui64.h index c48d689..aa83e1a 100644 --- a/pppd/eui64.h +++ b/pppd/eui64.h @@ -34,6 +34,8 @@ * */ +#include "pppdconf.h" + #ifndef __EUI64_H__ #define __EUI64_H__ diff --git a/pppd/fsm.c b/pppd/fsm.c index 96d20e8..17cb76f 100644 --- a/pppd/fsm.c +++ b/pppd/fsm.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* * TODO: * Randomize fsm id on link/init. diff --git a/pppd/fsm.h b/pppd/fsm.h index 75a36d5..d23725c 100644 --- a/pppd/fsm.h +++ b/pppd/fsm.h @@ -42,6 +42,8 @@ * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ */ +#include "pppdconf.h" + /* * Packet header = Code, id, length. */ diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 302ca40..0dc251e 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* * TODO: */ @@ -89,6 +93,7 @@ struct notifier *ip_down_notifier = NULL; static int default_route_set[NUM_PPP]; /* Have set up a default route */ static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ static bool usepeerdns; /* Ask peer for DNS addrs */ +static bool usepeerwins; /* Ask peer for WINS addrs */ static int ipcp_is_up; /* have called np_up() */ static int ipcp_is_open; /* haven't called np_finished() */ static bool ask_for_local; /* request our address from peer */ @@ -217,6 +222,9 @@ static option_t ipcp_option_list[] = { { "usepeerdns", o_bool, &usepeerdns, "Ask peer for DNS address(es)", 1 }, + { "usepeerwins", o_bool, &usepeerwins, + "Ask peer for WINS address(es)", 1 }, + { "netmask", o_special, (void *)setnetmask, "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, @@ -678,14 +686,17 @@ ipcp_resetci(fsm *f) ipcp_options *go = &ipcp_gotoptions[f->unit]; ipcp_options *ao = &ipcp_allowoptions[f->unit]; - wo->req_addr = (wo->neg_addr || wo->old_addrs) && - (ao->neg_addr || ao->old_addrs); + wo->req_addr = ((wo->neg_addr || wo->old_addrs) && + (ao->neg_addr || ao->old_addrs)) || + (wo->hisaddr && !wo->accept_remote); if (wo->ouraddr == 0) wo->accept_local = 1; if (wo->hisaddr == 0) wo->accept_remote = 1; wo->req_dns1 = usepeerdns; /* Request DNS addresses from the peer */ wo->req_dns2 = usepeerdns; + wo->req_wins1 = usepeerwins; /* Request WINS addresses from the peer */ + wo->req_wins2 = usepeerwins; *go = *wo; if (!ask_for_local) go->ouraddr = 0; @@ -737,8 +748,8 @@ ipcp_cilen(fsm *f) LENCIADDR(go->neg_addr) + LENCIDNS(go->req_dns1) + LENCIDNS(go->req_dns2) + - LENCIWINS(go->winsaddr[0]) + - LENCIWINS(go->winsaddr[1])) ; + LENCIWINS(go->req_wins1) + + LENCIWINS(go->req_wins2)) ; } @@ -809,8 +820,8 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp) neg = 0; \ } -#define ADDCIWINS(opt, addr) \ - if (addr) { \ +#define ADDCIWINS(opt, neg, addr) \ + if (neg) { \ if (len >= CILEN_ADDR) { \ u_int32_t l; \ PUTCHAR(opt, ucp); \ @@ -819,7 +830,7 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp) PUTLONG(l, ucp); \ len -= CILEN_ADDR; \ } else \ - addr = 0; \ + neg = 0; \ } ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, @@ -834,9 +845,9 @@ ipcp_addci(fsm *f, u_char *ucp, int *lenp) ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); - ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); + ADDCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]); - ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); + ADDCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]); *lenp -= len; } @@ -938,8 +949,8 @@ ipcp_ackci(fsm *f, u_char *p, int len) goto bad; \ } -#define ACKCIWINS(opt, addr) \ - if (addr) { \ +#define ACKCIWINS(opt, neg, addr) \ + if (neg) { \ u_int32_t l; \ if ((len -= CILEN_ADDR) < 0) \ goto bad; \ @@ -965,9 +976,9 @@ ipcp_ackci(fsm *f, u_char *p, int len) ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); - ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); + ACKCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]); - ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); + ACKCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]); /* * If there are any remaining CIs, then this packet is bad. @@ -994,11 +1005,12 @@ bad: static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { + ipcp_options *wo = &ipcp_wantoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; u_short cishort; - u_int32_t ciaddr1, ciaddr2, l, cidnsaddr; + u_int32_t ciaddr1, ciaddr2, l, cidnsaddr, ciwinsaddr; ipcp_options no; /* options we've seen Naks for */ ipcp_options try; /* options to request next time */ @@ -1063,6 +1075,19 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) code \ } +#define NAKCIWINS(opt, neg, code) \ + if (go->neg && \ + ((cilen = p[1]) == CILEN_ADDR) && \ + len >= cilen && \ + p[0] == opt) { \ + len -= cilen; \ + INCPTR(2, p); \ + GETLONG(l, p); \ + ciwinsaddr = htonl(l); \ + no.neg = 1; \ + code \ + } + /* * Accept the peer's idea of {our,his} address, if different * from our idea, only if the accept_{local,remote} flag is set. @@ -1139,6 +1164,22 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) } ); + NAKCIWINS(CI_MS_WINS1, req_wins1, + if (treat_as_reject) { + try.req_wins1 = 0; + } else { + try.winsaddr[0] = ciwinsaddr; + } + ); + + NAKCIWINS(CI_MS_WINS2, req_wins2, + if (treat_as_reject) { + try.req_wins2 = 0; + } else { + try.winsaddr[1] = ciwinsaddr; + } + ); + /* * There may be remaining CIs, if the peer is requesting negotiation * on an option that we didn't include in our request packet. @@ -1169,7 +1210,7 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) GETLONG(l, p); ciaddr1 = htonl(l); if (ciaddr1 && go->accept_local) - try.ouraddr = ciaddr1; + try.ouraddr = wo->old_addrs ? ciaddr1 : 0; GETLONG(l, p); ciaddr2 = htonl(l); if (ciaddr2 && go->accept_remote) @@ -1184,7 +1225,7 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) ciaddr1 = htonl(l); if (ciaddr1 && go->accept_local) try.ouraddr = ciaddr1; - if (try.ouraddr != 0) + if (try.ouraddr != 0 && wo->neg_addr) try.neg_addr = 1; no.neg_addr = 1; break; @@ -1205,13 +1246,20 @@ ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) no.req_dns2 = 1; break; case CI_MS_WINS1: + if (go->req_wins1 || no.req_wins1 || cilen != CILEN_ADDR) + goto bad; + GETLONG(l, p); + try.winsaddr[0] = htonl(l); + try.req_wins1 = 1; + no.req_wins1 = 1; + break; case CI_MS_WINS2: - if (cilen != CILEN_ADDR) + if (go->req_wins2 || no.req_wins2 || cilen != CILEN_ADDR) goto bad; GETLONG(l, p); - ciaddr1 = htonl(l); - if (ciaddr1) - try.winsaddr[citype == CI_MS_WINS2] = ciaddr1; + try.winsaddr[1] = htonl(l); + try.req_wins2 = 1; + no.req_wins2 = 1; break; } p = next; @@ -1231,7 +1279,6 @@ bad: return 0; } - /* * ipcp_rejci - Reject some of our CIs. * Callback from fsm_rconfnakrej. @@ -1326,8 +1373,8 @@ ipcp_rejci(fsm *f, u_char *p, int len) try.neg = 0; \ } -#define REJCIWINS(opt, addr) \ - if (addr && \ +#define REJCIWINS(opt, neg, addr) \ + if (go->neg && \ ((cilen = p[1]) == CILEN_ADDR) && \ len >= cilen && \ p[0] == opt) { \ @@ -1339,7 +1386,7 @@ ipcp_rejci(fsm *f, u_char *p, int len) /* Check rejected value. */ \ if (cilong != addr) \ goto bad; \ - try.winsaddr[opt == CI_MS_WINS2] = 0; \ + try.neg = 0; \ } REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, @@ -1354,9 +1401,9 @@ ipcp_rejci(fsm *f, u_char *p, int len) REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); - REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); + REJCIWINS(CI_MS_WINS1, req_wins1, go->winsaddr[0]); - REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); + REJCIWINS(CI_MS_WINS2, req_wins2, go->winsaddr[1]); /* * If there are any remaining CIs, then this packet is bad. @@ -1470,7 +1517,7 @@ ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) if (ciaddr2 != wo->ouraddr) { if (ciaddr2 == 0 || !wo->accept_local) { orc = CONFNAK; - if (!reject_if_disagree) { + if (!reject_if_disagree && wo->old_addrs) { DECPTR(sizeof(u_int32_t), p); tl = ntohl(wo->ouraddr); PUTLONG(tl, p); @@ -1546,7 +1593,7 @@ ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) /* Microsoft primary or secondary WINS request */ d = citype == CI_MS_WINS2; - /* If we do not have a DNS address then we cannot send it */ + /* If we do not have a WINS address then we cannot send it */ if (ao->winsaddr[d] == 0 || cilen != CILEN_ADDR) { /* Check CI length */ orc = CONFREJ; /* Reject CI */ @@ -1647,7 +1694,8 @@ endswitch: * option safely. */ if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && - wo->req_addr && !reject_if_disagree && !noremoteip) { + wo->req_addr && !reject_if_disagree && + ((wo->hisaddr && !wo->accept_remote) || !noremoteip)) { if (rc == CONFACK) { rc = CONFNAK; ucp = inp; /* reset pointer */ @@ -1759,6 +1807,12 @@ ipcp_up(fsm *f) /* * We must have a non-zero IP address for both ends of the link. */ + + if (wo->hisaddr && !wo->accept_remote && (!(ho->neg_addr || ho->old_addrs) || ho->hisaddr != wo->hisaddr)) { + error("Peer refused to agree to his IP address"); + ipcp_close(f->unit, "Refused his IP address"); + return; + } if (!ho->neg_addr && !ho->old_addrs) ho->hisaddr = wo->hisaddr; @@ -1795,6 +1849,13 @@ ipcp_up(fsm *f) create_resolv(go->dnsaddr[0], go->dnsaddr[1]); } + if (go->winsaddr[0]) + script_setenv("WINS1", ip_ntoa(go->winsaddr[0]), 0); + if (go->winsaddr[1]) + script_setenv("WINS2", ip_ntoa(go->winsaddr[1]), 0); + if (usepeerwins && (go->winsaddr[0] || go->winsaddr[1])) + script_setenv("USEPEERWINS", "1", 0); + /* * Check that the peer is allowed to use the IP address it wants. */ @@ -1822,9 +1883,10 @@ ipcp_up(fsm *f) wo->ouraddr = go->ouraddr; } else script_unsetenv("OLDIPLOCAL"); - if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { + if (ho->hisaddr != wo->hisaddr) { warn("Remote IP address changed to %I", ho->hisaddr); - script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); + if (wo->hisaddr != 0) + script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); wo->hisaddr = ho->hisaddr; } else script_unsetenv("OLDIPREMOTE"); diff --git a/pppd/ipcp.h b/pppd/ipcp.h index 9c4f68d..90336c4 100644 --- a/pppd/ipcp.h +++ b/pppd/ipcp.h @@ -39,6 +39,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" /* * Options. @@ -76,6 +77,8 @@ typedef struct ipcp_options { bool accept_remote; /* accept peer's value for hisaddr */ bool req_dns1; /* Ask peer to send primary DNS address? */ bool req_dns2; /* Ask peer to send secondary DNS address? */ + bool req_wins1; /* Ask peer to send primary WINS address? */ + bool req_wins2; /* Ask peer to send secondary WINS address? */ int vj_protocol; /* protocol value to use in VJ option */ int maxslotindex; /* values for RFC1332 VJ compression neg. */ bool cflag; diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index 431cb62..cef1e38 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -146,6 +146,10 @@ * since SVR4 && (SNI || __USLC__) didn't work properly) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -239,9 +243,9 @@ static option_t ipv6cp_option_list[] = { { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, - { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, + { "ipv6cp-accept-local", o_bool, &ipv6cp_wantoptions[0].accept_local, "Accept peer's interface identifier for us", 1 }, - { "ipv6cp-accept-remote", o_bool, &ipv6cp_allowoptions[0].accept_remote, + { "ipv6cp-accept-remote", o_bool, &ipv6cp_wantoptions[0].accept_remote, "Accept peer's interface identifier for itself", 1 }, { "defaultroute6", o_bool, &ipv6cp_wantoptions[0].default_route, @@ -528,7 +532,8 @@ ipv6cp_resetci(fsm *f) if (!wo->opt_local) { wo->accept_local = 1; - eui64_magic_nz(wo->ourid); + if (!demand) + eui64_magic_nz(wo->ourid); } if (!wo->opt_remote) wo->accept_remote = 1; @@ -719,7 +724,9 @@ ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) NAKCIIFACEID(CI_IFACEID, neg_ifaceid, if (treat_as_reject) { try.neg_ifaceid = 0; - } else if (go->accept_local) { + } else if (go->accept_local && !eui64_iszero(ifaceid) && !eui64_equals(ifaceid, go->hisid)) { + try.ourid = ifaceid; + } else if (eui64_iszero(ifaceid) && !go->opt_local) { while (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->hisid)) /* bad luck */ eui64_magic(ifaceid); @@ -771,11 +778,15 @@ ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) goto bad; try.neg_ifaceid = 1; eui64_get(ifaceid, p); - if (go->accept_local) { + if (go->accept_local && !eui64_iszero(ifaceid) && !eui64_equals(ifaceid, go->hisid)) { + try.ourid = ifaceid; + } else if (eui64_iszero(ifaceid) && !go->opt_local) { while (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->hisid)) /* bad luck */ eui64_magic(ifaceid); try.ourid = ifaceid; + } else { + try.neg_ifaceid = 0; } no.neg_ifaceid = 1; break; @@ -942,8 +953,7 @@ ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) break; } if (!eui64_iszero(wo->hisid) && !wo->accept_remote && - !eui64_equals(ifaceid, wo->hisid) && - eui64_iszero(go->hisid)) { + !eui64_equals(ifaceid, wo->hisid)) { orc = CONFNAK; ifaceid = wo->hisid; @@ -955,9 +965,17 @@ ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) orc = CONFNAK; if (eui64_iszero(go->hisid)) /* first time, try option */ ifaceid = wo->hisid; - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->ourid)) /* bad luck */ - eui64_magic(ifaceid); + if (eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_zero(ifaceid); + if (eui64_iszero(ifaceid)) { + if (wo->opt_remote) + ifaceid = wo->hisid; + else { + while (eui64_iszero(ifaceid) || + eui64_equals(ifaceid, go->ourid)) /* bad luck */ + eui64_magic(ifaceid); + } + } go->hisid = ifaceid; DECPTR(sizeof(ifaceid), p); eui64_put(ifaceid, p); @@ -1069,7 +1087,7 @@ ether_to_eui64(eui64_t *p_eui64) { u_char addr[6]; - if (get_if_hwaddr(addr, devnam) < 0 || get_first_ether_hwaddr(addr) < 0) { + if (get_if_hwaddr(addr, devnam) < 0 && get_first_ether_hwaddr(addr) < 0) { error("ipv6cp: no persistent id can be found"); return 0; } @@ -1106,7 +1124,7 @@ ipv6_check_options(void) * Persistent link-local id is only used when user has not explicitly * configure/hard-code the id */ - if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { + if ((wo->use_persistent) && (!wo->opt_local)) { /* * On systems where there are no Ethernet interfaces used, there @@ -1140,11 +1158,6 @@ ipv6_check_options(void) wo->opt_remote = 1; } } - - if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { - option_error("local/remote LL address required for demand-dialling\n"); - exit(EXIT_OPTION_ERROR); - } } @@ -1157,6 +1170,15 @@ ipv6_demand_conf(int u) { ipv6cp_options *wo = &ipv6cp_wantoptions[u]; + if (eui64_iszero(wo->hisid)) { + /* make up an arbitrary identifier for the peer */ + eui64_magic_nz(wo->hisid); + } + if (eui64_iszero(wo->ourid)) { + /* make up an arbitrary identifier for us */ + eui64_magic_nz(wo->ourid); + } + if (!sif6up(u)) return 0; if (!sif6addr(u, wo->ourid, wo->hisid)) @@ -1171,7 +1193,6 @@ ipv6_demand_conf(int u) if (sif6defaultroute(u, wo->ourid, wo->hisid)) default_route_set[u] = 1; - notice("ipv6_demand_conf"); notice("local LL address %s", llv6_ntoa(wo->ourid)); notice("remote LL address %s", llv6_ntoa(wo->hisid)); @@ -1196,6 +1217,12 @@ ipv6cp_up(fsm *f) /* * We must have a non-zero LL address for both ends of the link. */ + + if (!eui64_iszero(wo->hisid) && !wo->accept_remote && (!ho->neg_ifaceid || !eui64_equals(ho->hisid, wo->hisid))) { + error("Peer refused to agree to his interface identifier"); + ipv6cp_close(f->unit, "Refused his interface identifier"); + return; + } if (!ho->neg_ifaceid) ho->hisid = wo->hisid; @@ -1238,7 +1265,7 @@ ipv6cp_up(fsm *f) if (! eui64_equals(ho->hisid, wo->hisid)) warn("Remote LL address changed to %s", llv6_ntoa(ho->hisid)); - ipv6cp_clear_addrs(f->unit, go->ourid, ho->hisid); + ipv6cp_clear_addrs(f->unit, wo->ourid, wo->hisid); /* Set the interface to the new addresses */ if (!sif6addr(f->unit, go->ourid, ho->hisid)) { @@ -1295,7 +1322,7 @@ ipv6cp_up(fsm *f) */ if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); + ipv6cp_script(path_ipv6up); } } @@ -1346,7 +1373,7 @@ ipv6cp_down(fsm *f) /* Execute the ipv6-down script */ if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); + ipv6cp_script(path_ipv6down); } } @@ -1384,13 +1411,13 @@ ipv6cp_script_done(void *arg) case s_up: if (ipv6cp_fsm[0].state != OPENED) { ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); + ipv6cp_script(path_ipv6down); } break; case s_down: if (ipv6cp_fsm[0].state == OPENED) { ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); + ipv6cp_script(path_ipv6up); } break; } diff --git a/pppd/ipv6cp.h b/pppd/ipv6cp.h index 19bc013..5e1db6b 100644 --- a/pppd/ipv6cp.h +++ b/pppd/ipv6cp.h @@ -33,6 +33,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ +#include "pppdconf.h" /* Original version, based on RFC2023 : diff --git a/pppd/ipxcp.c b/pppd/ipxcp.c index d39b14c..000608d 100644 --- a/pppd/ipxcp.c +++ b/pppd/ipxcp.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef IPX_CHANGE /* diff --git a/pppd/ipxcp.h b/pppd/ipxcp.h index 8a69232..6112e75 100644 --- a/pppd/ipxcp.h +++ b/pppd/ipxcp.h @@ -39,6 +39,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" /* * Options. diff --git a/pppd/lcp.c b/pppd/lcp.c index ac5d5ce..8a18e95 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/lcp.h b/pppd/lcp.h index 984f868..768442d 100644 --- a/pppd/lcp.h +++ b/pppd/lcp.h @@ -39,6 +39,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" /* * Options. diff --git a/pppd/magic.c b/pppd/magic.c index 8e08e47..6a5a7eb 100644 --- a/pppd/magic.c +++ b/pppd/magic.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/magic.h b/pppd/magic.h index d6094db..b864b7b 100644 --- a/pppd/magic.h +++ b/pppd/magic.h @@ -39,6 +39,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" void magic_init (void); /* Initialize the magic number generator */ u_int32_t magic (void); /* Returns the next magic number */ diff --git a/pppd/main.c b/pppd/main.c index 87a5d29..bdc6faa 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -66,6 +66,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -120,7 +124,7 @@ /* interface vars */ -char ifname[MAXIFNAMELEN]; /* Interface name */ +char ifname[IFNAMSIZ]; /* Interface name */ int ifunit; /* Interface unit number */ struct channel *the_channel; @@ -296,6 +300,10 @@ main(int argc, char *argv[]) strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup)); strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown)); +#ifdef INET6 + strlcpy(path_ipv6up, _PATH_IPV6UP, sizeof(path_ipv6up)); + strlcpy(path_ipv6down, _PATH_IPV6DOWN, sizeof(path_ipv6down)); +#endif link_stats_valid = 0; new_phase(PHASE_INITIALIZE); @@ -749,6 +757,7 @@ void detach(void) { int pid; + int ret; char numbuf[16]; int pipefd[2]; @@ -770,7 +779,10 @@ detach(void) exit(0); /* parent dies */ } setsid(); - chdir("/"); + ret = chdir("/"); + if (ret != 0) { + fatal("Could not change directory to '/', %m"); + } dup2(fd_devnull, 0); dup2(fd_devnull, 1); dup2(fd_devnull, 2); @@ -1409,8 +1421,12 @@ hup(int sig) /* Send the signal to the [dis]connector process(es) also */ kill_my_pg(sig); notify(sigreceived, sig); - if (waiting) + if (waiting) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" write(sigpipe[1], &sig, sizeof(sig)); +#pragma GCC diagnostic pop + } } @@ -1429,8 +1445,12 @@ term(int sig) /* Send the signal to the [dis]connector process(es) also */ kill_my_pg(sig); notify(sigreceived, sig); - if (waiting) + if (waiting) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" write(sigpipe[1], &sig, sizeof(sig)); +#pragma GCC diagnostic pop + } } @@ -1442,8 +1462,12 @@ static void chld(int sig) { got_sigchld = 1; - if (waiting) + if (waiting) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" write(sigpipe[1], &sig, sizeof(sig)); +#pragma GCC diagnostic pop + } } @@ -1475,8 +1499,12 @@ static void open_ccp(int sig) { got_sigusr2 = 1; - if (waiting) + if (waiting) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" write(sigpipe[1], &sig, sizeof(sig)); +#pragma GCC diagnostic pop + } } @@ -1638,6 +1666,7 @@ device_script(char *program, int in, int out, int dont_wait) int pid; int status = -1; int errfd; + int ret; if (log_to_fd >= 0) errfd = log_to_fd; @@ -1672,12 +1701,15 @@ device_script(char *program, int in, int out, int dont_wait) } /* here we are executing in the child */ - - setgid(getgid()); - setuid(uid); - if (getuid() != uid) { - fprintf(stderr, "pppd: setuid failed\n"); - exit(1); + ret = setgid(getgid()); + if (ret != 0) { + perror("pppd: setgid failed\n"); + exit(1); + } + ret = setuid(uid); + if (ret != 0 || getuid() != uid) { + perror("pppd: setuid failed\n"); + exit(1); } update_system_environment(); execl("/bin/sh", "sh", "-c", program, (char *)0); @@ -1738,7 +1770,7 @@ update_script_environment(void) pid_t run_program(char *prog, char **args, int must_exist, void (*done)(void *), void *arg, int wait) { - int pid, status; + int pid, status, ret; struct stat sbuf; /* @@ -1778,9 +1810,18 @@ run_program(char *prog, char **args, int must_exist, void (*done)(void *), void /* Leave the current location */ (void) setsid(); /* No controlling tty. */ (void) umask (S_IRWXG|S_IRWXO); - (void) chdir ("/"); /* no current directory. */ - setuid(0); /* set real UID = root */ - setgid(getegid()); + ret = chdir ("/"); /* no current directory. */ + if (ret != 0) { + fatal("Failed to change directory to '/', %m"); + } + ret = setuid(0); /* set real UID = root */ + if (ret != 0) { + fatal("Failed to set uid, %m"); + } + ret = setgid(getegid()); + if (ret != 0) { + fatal("failed to set gid, %m"); + } #ifdef BSD /* Force the priority back to zero if pppd is running higher. */ diff --git a/pppd/md4.c b/pppd/md4.c index 42a9b2e..88f3413 100644 --- a/pppd/md4.c +++ b/pppd/md4.c @@ -30,6 +30,9 @@ /* Implementation notes: ** This implementation assumes that ints are 32-bit quantities. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #define TRUE 1 #define FALSE 0 diff --git a/pppd/md4.h b/pppd/md4.h index b6fc3f5..d67daeb 100644 --- a/pppd/md4.h +++ b/pppd/md4.h @@ -7,6 +7,16 @@ ** (C) 1990 RSA Data Security, Inc. ** ** ******************************************************************** */ +#include "pppdconf.h" + +#ifndef __MD4_INCLUDE__ +#define __MD4_INCLUDE__ +#ifndef USE_MD4 +#include +#define MD4Init MD4_Init +#define MD4Update MD4_Update +#define MD4Final MD4_Final +#else /* MDstruct is the data structure for a message digest computation. */ @@ -53,3 +63,5 @@ extern void MD4Final(unsigned char *, MD4_CTX *); /* ** End of md4.h ****************************(cut)***********************************/ +#endif /* USE_MD4 */ +#endif /* __MD4_INCLUDE__ */ diff --git a/pppd/md5.c b/pppd/md5.c index f7988e6..9fb3397 100644 --- a/pppd/md5.c +++ b/pppd/md5.c @@ -33,6 +33,10 @@ *********************************************************************** */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "md5.h" diff --git a/pppd/md5.h b/pppd/md5.h index 71e8b00..662eb41 100644 --- a/pppd/md5.h +++ b/pppd/md5.h @@ -36,8 +36,13 @@ ** documentation and/or software. ** *********************************************************************** */ +#include "pppdconf.h" #ifndef __MD5_INCLUDE__ +#define __MD5_INCLUDE__ +#ifndef USE_MD5 +#include +#else /* typedef a 32-bit type */ #ifdef _LP64 @@ -61,5 +66,5 @@ void MD5_Init (MD5_CTX *mdContext); void MD5_Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); void MD5_Final (unsigned char hash[], MD5_CTX *mdContext); -#define __MD5_INCLUDE__ +#endif /* USE_MD5 */ #endif /* __MD5_INCLUDE__ */ diff --git a/pppd/mppe.c b/pppd/mppe.c new file mode 100644 index 0000000..f1b7abf --- /dev/null +++ b/pppd/mppe.c @@ -0,0 +1,256 @@ +/* * mppe.c - MPPE key implementation + * + * Copyright (c) 2020 Eivind Naess. All rights reserved. + * Copyright (c) 2008 Paul Mackerras. 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +#include "pppd.h" +#include "fsm.h" +#include "md4.h" +#include "sha1.h" +#include "ccp.h" +#include "chap_ms.h" +#include "mppe.h" + +u_char mppe_send_key[MPPE_MAX_KEY_SIZE]; +u_char mppe_recv_key[MPPE_MAX_KEY_SIZE]; +int mppe_keys_set = 0; + +void +mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen) +{ + int length = keylen; + if (length > MPPE_MAX_KEY_SIZE) + length = MPPE_MAX_KEY_SIZE; + + if (send_key) { + BCOPY(send_key, mppe_send_key, length); + BZERO(send_key, keylen); + } + + if (recv_key) { + BCOPY(recv_key, mppe_recv_key, length); + BZERO(recv_key, keylen); + } + + mppe_keys_set = length; +} + +bool +mppe_keys_isset() +{ + return !!mppe_keys_set; +} + +int +mppe_get_recv_key(u_char *recv_key, int length) +{ + if (mppe_keys_isset()) { + if (length > mppe_keys_set) + length = mppe_keys_set; + BCOPY(mppe_recv_key, recv_key, length); + return length; + } + return 0; +} + +int +mppe_get_send_key(u_char *send_key, int length) +{ + if (mppe_keys_isset()) { + if (length > mppe_keys_set) + length = mppe_keys_set; + BCOPY(mppe_send_key, send_key, length); + return length; + } + return 0; +} + +void +mppe_clear_keys(void) +{ + mppe_keys_set = 0; + BZERO(mppe_send_key, sizeof(mppe_send_key)); + BZERO(mppe_recv_key, sizeof(mppe_recv_key)); +} + +/* + * Set mppe_xxxx_key from the NTPasswordHashHash. + * RFC 2548 (RADIUS support) requires us to export this function (ugh). + */ +void +mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]) +{ + SHA1_CTX sha1Context; + u_char Digest[SHA1_SIGNATURE_SIZE]; + + SHA1_Init(&sha1Context); + SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + SHA1_Update(&sha1Context, rchallenge, 8); + SHA1_Final(Digest, &sha1Context); + + /* Same key in both directions. */ + mppe_set_keys(Digest, Digest, sizeof(Digest)); +} + +/* + * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) + * + * This helper function used in the Winbind module, which gets the + * NTHashHash from the server. + */ +void +mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer) +{ + SHA1_CTX sha1Context; + u_char MasterKey[SHA1_SIGNATURE_SIZE]; + u_char SendKey[SHA1_SIGNATURE_SIZE]; + u_char RecvKey[SHA1_SIGNATURE_SIZE]; + + u_char SHApad1[40] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u_char SHApad2[40] = + { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; + + /* "This is the MPPE Master Key" */ + u_char Magic1[27] = + { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; + /* "On the client side, this is the send key; " + "on the server side, it is the receive key." */ + u_char Magic2[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, + 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, + 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + /* "On the client side, this is the receive key; " + "on the server side, it is the send key." */ + u_char Magic3[84] = + { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, + 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, + 0x6b, 0x65, 0x79, 0x2e }; + u_char *s; + + SHA1_Init(&sha1Context); + SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); + SHA1_Update(&sha1Context, NTResponse, 24); + SHA1_Update(&sha1Context, Magic1, sizeof(Magic1)); + SHA1_Final(MasterKey, &sha1Context); + + /* + * generate send key + */ + if (IsServer) + s = Magic3; + else + s = Magic2; + SHA1_Init(&sha1Context); + SHA1_Update(&sha1Context, MasterKey, 16); + SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); + SHA1_Update(&sha1Context, s, 84); + SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); + SHA1_Final(SendKey, &sha1Context); + + /* + * generate recv key + */ + if (IsServer) + s = Magic2; + else + s = Magic3; + SHA1_Init(&sha1Context); + SHA1_Update(&sha1Context, MasterKey, 16); + SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1)); + SHA1_Update(&sha1Context, s, 84); + SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2)); + SHA1_Final(RecvKey, &sha1Context); + + mppe_set_keys(SendKey, RecvKey, SHA1_SIGNATURE_SIZE); +} + +#ifndef UNIT_TEST + +/* + * Set MPPE options from plugins. + */ +void +mppe_set_enc_types(int policy, int types) +{ + /* Early exit for unknown policies. */ + if (policy != MPPE_ENC_POL_ENC_ALLOWED && + policy != MPPE_ENC_POL_ENC_REQUIRED) + return; + + /* Don't modify MPPE if it's optional and wasn't already configured. */ + if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) + return; + + /* + * Disable undesirable encryption types. Note that we don't ENABLE + * any encryption types, to avoid overriding manual configuration. + */ + switch(types) { + case MPPE_ENC_TYPES_RC4_40: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ + break; + case MPPE_ENC_TYPES_RC4_128: + ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ + break; + default: + break; + } +} + +#endif diff --git a/pppd/mppe.h b/pppd/mppe.h index 5eb3b37..2684a7f 100644 --- a/pppd/mppe.h +++ b/pppd/mppe.h @@ -32,9 +32,14 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" + +#ifndef __MPPE_H__ +#define __MPPE_H__ #define MPPE_PAD 4 /* MPPE growth per frame */ -#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ +#define MPPE_MAX_KEY_SIZE 32 /* Largest key length */ +#define MPPE_MAX_KEY_LEN 16 /* Largest key size accepted by the kernel */ /* option bits for ccp_options.mppe */ #define MPPE_OPT_40 0x01 /* 40 bit */ @@ -119,3 +124,68 @@ if (ptr[3] & ~MPPE_ALL_BITS) \ opts |= MPPE_OPT_UNKNOWN; \ } while (/* CONSTCOND */ 0) + + +#if MPPE + +/* + * NOTE: + * Access to these variables directly is discuraged. Please + * change your code to use below accessor functions. + */ + +/* The key material generated which is used for MPPE send key */ +extern u_char mppe_send_key[MPPE_MAX_KEY_SIZE]; +/* The key material generated which is used for MPPE recv key */ +extern u_char mppe_recv_key[MPPE_MAX_KEY_SIZE]; +/* Keys are set if value is non-zero */ +extern int mppe_keys_set; + +/* These values are the RADIUS attribute values--see RFC 2548. */ +#define MPPE_ENC_POL_ENC_ALLOWED 1 +#define MPPE_ENC_POL_ENC_REQUIRED 2 +#define MPPE_ENC_TYPES_RC4_40 2 +#define MPPE_ENC_TYPES_RC4_128 4 + +/* used by plugins (using above values) */ +void mppe_set_enc_types (int policy, int types); + +/* + * Set the MPPE send and recv keys. NULL values for keys are ignored + * and input values are cleared to avoid leaving them on the stack + */ +void mppe_set_keys(u_char *send_key, u_char *recv_key, int keylen); + +/* + * Get the MPPE recv key + */ +int mppe_get_recv_key(u_char *recv_key, int length); + +/* + * Get the MPPE send key + */ +int mppe_get_send_key(u_char *send_key, int length); + +/* + * Clear the MPPE keys + */ +void mppe_clear_keys(void); + +/* + * Check if the MPPE keys are set + */ +bool mppe_keys_isset(void); + +/* + * Set mppe_xxxx_key from NT Password Hash Hash (MSCHAPv1), see RFC3079 + */ +void mppe_set_chapv1(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]); + +/* + * Set the mppe_xxxx_key from MS-CHAP-v2 credentials, see RFC3079 + */ +void mppe_set_chapv2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE], + u_char NTResponse[MS_AUTH_NTRESP_LEN], int IsServer); + +#endif // #ifdef MPPE +#endif // #ifdef __MPPE_H__ diff --git a/pppd/multilink.c b/pppd/multilink.c index ddd848c..6f17cf8 100644 --- a/pppd/multilink.c +++ b/pppd/multilink.c @@ -27,6 +27,11 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/options.c b/pppd/options.c index f8d6c00..c959283 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -117,7 +121,7 @@ int connect_delay = 1000; /* wait this many ms after connect script */ int req_unit = -1; /* requested interface unit */ char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */ char path_ipdown[MAXPATHLEN];/* pathname of ip-down script */ -char req_ifname[MAXIFNAMELEN]; /* requested interface name */ +char req_ifname[IFNAMSIZ]; /* requested interface name */ bool multilink = 0; /* Enable multilink operation */ char *bundle_name = NULL; /* bundle name for multilink */ bool dump_options; /* print out option values */ @@ -127,6 +131,11 @@ int child_wait = 5; /* # seconds to wait for children at exit */ struct userenv *userenv_list; /* user environment variables */ int dfl_route_metric = -1; /* metric of the default route to set over the PPP link */ +#ifdef INET6 +char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */ +char path_ipv6down[MAXPATHLEN]; /* pathname of ipv6-down script */ +#endif + #ifdef MAXOCTETS unsigned int maxoctets = 0; /* default - no limit */ int maxoctets_dir = 0; /* default - sum of traffic */ @@ -295,7 +304,7 @@ option_t general_options[] = { { "ifname", o_string, req_ifname, "Set PPP interface name", - OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXIFNAMELEN }, + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, IFNAMSIZ }, { "dump", o_bool, &dump_options, "Print out option values after parsing all options", 1 }, @@ -324,6 +333,15 @@ option_t general_options[] = { "Set pathname of ip-down script", OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, +#ifdef INET6 + { "ipv6-up-script", o_string, path_ipv6up, + "Set pathname of ipv6-up script", + OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, + { "ipv6-down-script", o_string, path_ipv6down, + "Set pathname of ipv6-down script", + OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, +#endif + #ifdef HAVE_MULTILINK { "multilink", o_bool, &multilink, "Enable multilink operation", OPT_PRIO | 1 }, diff --git a/pppd/patchlevel.h b/pppd/patchlevel.h index 30df079..1ecdb82 100644 --- a/pppd/patchlevel.h +++ b/pppd/patchlevel.h @@ -1,2 +1 @@ -#define VERSION "2.4.9" #define DATE "5 January 2021" diff --git a/pppd/pathnames.h b/pppd/pathnames.h index 524d608..e68d91a 100644 --- a/pppd/pathnames.h +++ b/pppd/pathnames.h @@ -1,16 +1,35 @@ /* * define path names */ +#include "pppdconf.h" #ifdef HAVE_PATHS_H #include +#endif /* HAVE_PATHS_H */ -#else /* HAVE_PATHS_H */ -#ifndef _PATH_VARRUN -#define _PATH_VARRUN "/etc/ppp/" -#endif +#ifndef _PATH_DEVNULL #define _PATH_DEVNULL "/dev/null" -#endif /* HAVE_PATHS_H */ +#endif + +#ifdef PPPD_RUNTIME_DIR +#undef _PATH_VARRUN +#define _PATH_VARRUN PPPD_RUNTIME_DIR "/" +#endif + +#ifdef PPPD_LOGFILE_DIR +#undef _PATH_VARLOG +#define _PATH_VARLOG PPPD_LOGFILE_DIR +#endif + +#ifdef PPPD_PLUGIN_DIR +#define _PATH_PLUGIN PPPD_PLUGIN_DIR +#else +#ifdef __STDC__ +#define _PATH_PLUGIN DESTDIR "/lib/pppd/" VERSION +#else /* __STDC__ */ +#define _PATH_PLUGIN "/usr/lib/pppd" +#endif /* __STDC__ */ +#endif /* PPPD_PLUGIN_DIR */ #ifndef _ROOT_PATH #define _ROOT_PATH @@ -33,7 +52,7 @@ #define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up" #define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down" #define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options." -#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors" +#define _PATH_CONNERRS _ROOT_PATH _PATH_VARLOG "/connect-errors" #define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/" #define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf" @@ -53,18 +72,6 @@ #ifdef __STDC__ #define _PATH_PPPDB _ROOT_PATH _PATH_VARRUN "pppd2.tdb" #else /* __STDC__ */ -#ifdef HAVE_PATHS_H -#define _PATH_PPPDB "/var/run/pppd2.tdb" -#else -#define _PATH_PPPDB "/etc/ppp/pppd2.tdb" -#endif -#endif /* __STDC__ */ - -#ifdef PLUGIN -#ifdef __STDC__ -#define _PATH_PLUGIN DESTDIR "/lib/pppd/" VERSION -#else /* __STDC__ */ -#define _PATH_PLUGIN "/usr/lib/pppd" +#define _PATH_PPPDB _PPP_VARRUN "pppd2.tdb" #endif /* __STDC__ */ -#endif /* PLUGIN */ diff --git a/pppd/peap.c b/pppd/peap.c new file mode 100644 index 0000000..fb9af3e --- /dev/null +++ b/pppd/peap.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2011 Rustam Kovhaev. All rights reserved. + * Copyright (c) 2021 Eivind Næss. 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. + * + * NOTES: + * + * PEAP has 2 phases, + * 1 - Outer EAP, where TLS session gets established + * 2 - Inner EAP, where inside TLS session with EAP MSCHAPV2 auth, or any other auth + * + * And so protocols encapsulation looks like this: + * Outer EAP -> TLS -> Inner EAP -> MSCHAPV2 + * PEAP can compress an inner EAP packet prior to encapsulating it within + * the Data field of a PEAP packet by removing its Code, Identifier, + * and Length fields, and Microsoft PEAP server/client always does that + * + * Current implementation does not support: + * a) Fast reconnect + * b) Inner EAP fragmentation + * c) Any other auth other than MSCHAPV2 + * + * For details on the PEAP protocol, look to Microsoft: + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-peap + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pppd.h" +#include "eap.h" +#include "tls.h" +#include "chap-new.h" +#include "chap_ms.h" +#include "mppe.h" +#include "peap.h" + +#ifdef UNIT_TEST +#define novm(x) +#endif + +struct peap_state { + SSL_CTX *ctx; + SSL *ssl; + BIO *in_bio; + BIO *out_bio; + + int phase; + int written, read; + u_char *in_buf; + u_char *out_buf; + + u_char ipmk[PEAP_TLV_IPMK_LEN]; + u_char tk[PEAP_TLV_TK_LEN]; + u_char nonce[PEAP_TLV_NONCE_LEN]; + struct tls_info *info; +#ifdef CHAPMS + struct chap_digest_type *chap; +#endif +}; + +/* + * K = Key, S = Seed, LEN = output length + * PRF+(K, S, LEN) = T1 | T2 | ... |Tn + * Where: + * T1 = HMAC-SHA1 (K, S | 0x01 | 0x00 | 0x00) + * T2 = HMAC-SHA1 (K, T1 | S | 0x02 | 0x00 | 0x00) + * ... + * Tn = HMAC-SHA1 (K, Tn-1 | S | n | 0x00 | 0x00) + * As shown, PRF+ is computed in iterations. The number of iterations (n) + * depends on the output length (LEN). + */ +static void peap_prfplus(u_char *seed, size_t seed_len, u_char *key, size_t key_len, u_char *out_buf, size_t pfr_len) +{ + int pos; + u_char *buf, *hash; + size_t max_iter, i, j, k; + u_int len; + + max_iter = (pfr_len + SHA_DIGEST_LENGTH - 1) / SHA_DIGEST_LENGTH; + buf = malloc(seed_len + max_iter * SHA_DIGEST_LENGTH); + if (!buf) + novm("pfr buffer"); + hash = malloc(pfr_len + SHA_DIGEST_LENGTH); + if (!hash) + novm("hash buffer"); + + for (i = 0; i < max_iter; i++) { + j = 0; + k = 0; + + if (i > 0) + j = SHA_DIGEST_LENGTH; + for (k = 0; k < seed_len; k++) + buf[j + k] = seed[k]; + pos = j + k; + buf[pos] = i + 1; + pos++; + buf[pos] = 0x00; + pos++; + buf[pos] = 0x00; + pos++; + if (!HMAC(EVP_sha1(), key, key_len, buf, pos, (hash + i * SHA_DIGEST_LENGTH), &len)) + fatal("HMAC() failed"); + for (j = 0; j < SHA_DIGEST_LENGTH; j++) + buf[j] = hash[i * SHA_DIGEST_LENGTH + j]; + } + BCOPY(hash, out_buf, pfr_len); + free(hash); + free(buf); +} + +static void generate_cmk(u_char *ipmk, u_char *tempkey, u_char *nonce, u_char *tlv_response_out, int client) +{ + const char *label = PEAP_TLV_IPMK_SEED_LABEL; + u_char data_tlv[PEAP_TLV_DATA_LEN] = {0}; + u_char isk[PEAP_TLV_ISK_LEN] = {0}; + u_char ipmkseed[PEAP_TLV_IPMKSEED_LEN] = {0}; + u_char cmk[PEAP_TLV_CMK_LEN] = {0}; + u_char buf[PEAP_TLV_CMK_LEN + PEAP_TLV_IPMK_LEN] = {0}; + u_char compound_mac[PEAP_TLV_COMP_MAC_LEN] = {0}; + u_int len; + + /* format outgoing CB TLV response packet */ + data_tlv[1] = PEAP_TLV_TYPE; + data_tlv[3] = PEAP_TLV_LENGTH_FIELD; + if (client) + data_tlv[7] = PEAP_TLV_SUBTYPE_RESPONSE; + else + data_tlv[7] = PEAP_TLV_SUBTYPE_REQUEST; + BCOPY(nonce, (data_tlv + PEAP_TLV_HEADERLEN), PEAP_TLV_NONCE_LEN); + data_tlv[60] = EAPT_PEAP; + +#ifdef MPPE + mppe_get_send_key(isk, MPPE_MAX_KEY_LEN); + mppe_get_recv_key(isk + MPPE_MAX_KEY_LEN, MPPE_MAX_KEY_LEN); +#endif + + BCOPY(label, ipmkseed, strlen(label)); + BCOPY(isk, ipmkseed + strlen(label), PEAP_TLV_ISK_LEN); + peap_prfplus(ipmkseed, PEAP_TLV_IPMKSEED_LEN, + tempkey, PEAP_TLV_TEMPKEY_LEN, buf, PEAP_TLV_CMK_LEN + PEAP_TLV_IPMK_LEN); + + BCOPY(buf, ipmk, PEAP_TLV_IPMK_LEN); + BCOPY(buf + PEAP_TLV_IPMK_LEN, cmk, PEAP_TLV_CMK_LEN); + if (!HMAC(EVP_sha1(), cmk, PEAP_TLV_CMK_LEN, data_tlv, PEAP_TLV_DATA_LEN, compound_mac, &len)) + fatal("HMAC() failed"); + BCOPY(compound_mac, data_tlv + PEAP_TLV_HEADERLEN + PEAP_TLV_NONCE_LEN, PEAP_TLV_COMP_MAC_LEN); + /* do not copy last byte to response packet */ + BCOPY(data_tlv, tlv_response_out, PEAP_TLV_DATA_LEN - 1); +} + +static void verify_compound_mac(struct peap_state *psm, u_char *in_buf) +{ + u_char nonce[PEAP_TLV_NONCE_LEN] = {0}; + u_char out_buf[PEAP_TLV_LEN] = {0}; + + BCOPY(in_buf, nonce, PEAP_TLV_NONCE_LEN); + generate_cmk(psm->ipmk, psm->tk, nonce, out_buf, 0); + if (memcmp((in_buf + PEAP_TLV_NONCE_LEN), (out_buf + PEAP_TLV_HEADERLEN + PEAP_TLV_NONCE_LEN), PEAP_TLV_CMK_LEN)) + fatal("server's CMK does not match client's CMK, potential MiTM"); +} + +#ifdef MPPE +#define PEAP_MPPE_KEY_LEN 32 + +static void generate_mppe_keys(u_char *ipmk, int client) +{ + const char *label = PEAP_TLV_CSK_SEED_LABEL; + u_char csk[PEAP_TLV_CSK_LEN] = {0}; + size_t len; + + dbglog("PEAP CB: generate mppe keys"); + len = strlen(label); + len++; /* CSK requires NULL byte in seed */ + peap_prfplus((u_char *)label, len, ipmk, PEAP_TLV_IPMK_LEN, csk, PEAP_TLV_CSK_LEN); + + /* + * The first 64 bytes of the CSK are split into two MPPE keys, as follows. + * + * +-----------------------+------------------------+ + * | First 32 bytes of CSK | Second 32 bytes of CSK | + * +-----------------------+------------------------+ + * | MS-MPPE-Send-Key | MS-MPPE-Recv-Key | + * +-----------------------+------------------------+ + */ + if (client) { + mppe_set_keys(csk, csk + PEAP_MPPE_KEY_LEN, PEAP_MPPE_KEY_LEN); + } else { + mppe_set_keys(csk + PEAP_MPPE_KEY_LEN, csk, PEAP_MPPE_KEY_LEN); + } +} + +#endif + +#ifndef UNIT_TEST + +static void peap_ack(eap_state *esp, u_char id) +{ + u_char *outp; + + outp = outpacket_buf; + MAKEHEADER(outp, PPP_EAP); + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + esp->es_client.ea_id = id; + PUTSHORT(PEAP_HEADERLEN, outp); + PUTCHAR(EAPT_PEAP, outp); + PUTCHAR(PEAP_FLAGS_ACK, outp); + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + PEAP_HEADERLEN); +} + +static void peap_response(eap_state *esp, u_char id, u_char *buf, int len) +{ + struct peap_state *psm = esp->ea_peap; + u_char *outp; + int peap_len; + + outp = outpacket_buf; + MAKEHEADER(outp, PPP_EAP); + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + esp->es_client.ea_id = id; + + if (psm->phase == PEAP_PHASE_1) + peap_len = PEAP_HEADERLEN + PEAP_FRAGMENT_LENGTH_FIELD + len; + else + peap_len = PEAP_HEADERLEN + len; + + PUTSHORT(peap_len, outp); + PUTCHAR(EAPT_PEAP, outp); + + if (psm->phase == PEAP_PHASE_1) { + PUTCHAR(PEAP_L_FLAG_SET, outp); + PUTLONG(len, outp); + } else + PUTCHAR(PEAP_NO_FLAGS, outp); + + BCOPY(buf, outp, len); + output(esp->es_unit, outpacket_buf, PPP_HDRLEN + peap_len); +} + +void peap_do_inner_eap(u_char *in_buf, int in_len, eap_state *esp, int id, + u_char *out_buf, int *out_len) +{ + struct peap_state *psm = esp->ea_peap; + int used = 0; + int typenum; + int secret_len; + char secret[MAXSECRETLEN + 1]; + char rhostname[MAXWORDLEN]; + u_char *outp = out_buf; + + dbglog("PEAP: EAP (in): %.*B", in_len, in_buf); + + if (*(in_buf + EAP_HEADERLEN) == PEAP_CAPABILITIES_TYPE && + in_len == (EAP_HEADERLEN + PEAP_CAPABILITIES_LEN)) { + /* use original packet as template for response */ + BCOPY(in_buf, outp, EAP_HEADERLEN + PEAP_CAPABILITIES_LEN); + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + /* change last byte to 0 to disable fragmentation */ + *(outp + PEAP_CAPABILITIES_LEN + 1) = 0x00; + used = EAP_HEADERLEN + PEAP_CAPABILITIES_LEN; + goto done; + } + if (*(in_buf + EAP_HEADERLEN + PEAP_TLV_HEADERLEN) == PEAP_TLV_TYPE && + in_len == PEAP_TLV_LEN) { + /* PEAP TLV message, do cryptobinding */ + SSL_export_keying_material(psm->ssl, psm->tk, PEAP_TLV_TK_LEN, + PEAP_TLV_TK_SEED_LABEL, strlen(PEAP_TLV_TK_SEED_LABEL), NULL, 0, 0); + /* verify server's CMK */ + verify_compound_mac(psm, in_buf + EAP_HEADERLEN + PEAP_TLV_RESULT_LEN + PEAP_TLV_HEADERLEN); + /* generate client's CMK with new nonce */ + PUTCHAR(EAP_RESPONSE, outp); + PUTCHAR(id, outp); + PUTSHORT(PEAP_TLV_LEN, outp); + BCOPY(in_buf + EAP_HEADERLEN, outp, PEAP_TLV_RESULT_LEN); + outp = outp + PEAP_TLV_RESULT_LEN; + RAND_bytes(psm->nonce, PEAP_TLV_NONCE_LEN); + generate_cmk(psm->ipmk, psm->tk, psm->nonce, outp, 1); +#ifdef MPPE + /* set mppe keys */ + generate_mppe_keys(psm->ipmk, 1); +#endif + used = PEAP_TLV_LEN; + goto done; + } + + GETCHAR(typenum, in_buf); + in_len--; + + switch (typenum) { + case EAPT_IDENTITY: + /* Respond with our identity to the peer */ + PUTCHAR(EAPT_IDENTITY, outp); + BCOPY(esp->es_client.ea_name, outp, + esp->es_client.ea_namelen); + used += (esp->es_client.ea_namelen + 1); + break; + + case EAPT_TLS: + /* Send NAK to EAP_TLS request */ + PUTCHAR(EAPT_NAK, outp); + PUTCHAR(EAPT_MSCHAPV2, outp); + used += 2; + break; + +#if CHAPMS + case EAPT_MSCHAPV2: { + + // Must have at least 4 more bytes to process CHAP header + if (in_len < 4) { + error("PEAP: received invalid MSCHAPv2 packet, too short"); + break; + } + + u_char opcode; + GETCHAR(opcode, in_buf); + + u_char chap_id; + GETCHAR(chap_id, in_buf); + + short mssize; + GETSHORT(mssize, in_buf); + + // Validate the CHAP packet (including header) + if (in_len != mssize) { + error("PEAP: received invalid MSCHAPv2 packet, invalid length"); + break; + } + in_len -= 4; + + switch (opcode) { + case CHAP_CHALLENGE: { + + u_char *challenge = in_buf; // VLEN + VALUE + u_char vsize; + + GETCHAR(vsize, in_buf); + in_len -= 1; + + if (vsize != MS_CHAP2_PEER_CHAL_LEN || in_len < MS_CHAP2_PEER_CHAL_LEN) { + error("PEAP: received invalid MSCHAPv2 packet, invalid value-length: %d", vsize); + goto done; + } + + INCPTR(MS_CHAP2_PEER_CHAL_LEN, in_buf); + in_len -= MS_CHAP2_PEER_CHAL_LEN; + + // Copy the provided remote host name + rhostname[0] = '\0'; + if (in_len > 0) { + if (in_len >= sizeof(rhostname)) { + dbglog("PEAP: trimming really long peer name down"); + in_len = sizeof(rhostname) - 1; + } + BCOPY(in_buf, rhostname, in_len); + rhostname[in_len] = '\0'; + } + + // In case the remote doesn't give us his name, or user explictly specified remotename is config + if (explicit_remote || (remote_name[0] != '\0' && in_len == 0)) + strlcpy(rhostname, remote_name, sizeof(rhostname)); + + // Get the scrert for authenticating ourselves with the specified host + if (get_secret(esp->es_unit, esp->es_client.ea_name, + rhostname, secret, &secret_len, 0)) { + + u_char response[MS_CHAP2_RESPONSE_LEN+1]; + u_char user_len = esp->es_client.ea_namelen; + char *user = esp->es_client.ea_name; + + psm->chap->make_response(response, chap_id, user, + challenge, secret, secret_len, NULL); + + PUTCHAR(EAPT_MSCHAPV2, outp); + PUTCHAR(CHAP_RESPONSE, outp); + PUTCHAR(chap_id, outp); + PUTCHAR(0, outp); + PUTCHAR(5 + user_len + MS_CHAP2_RESPONSE_LEN, outp); + BCOPY(response, outp, MS_CHAP2_RESPONSE_LEN+1); // VLEN + VALUE + INCPTR(MS_CHAP2_RESPONSE_LEN+1, outp); + BCOPY(user, outp, user_len); + used = 5 + user_len + MS_CHAP2_RESPONSE_LEN + 1; + + } else { + dbglog("PEAP: no CHAP secret for auth to %q", rhostname); + PUTCHAR(EAPT_NAK, outp); + ++used; + } + break; + } + case CHAP_SUCCESS: { + + u_char status = CHAP_FAILURE; + if (psm->chap->check_success(chap_id, in_buf, in_len)) { + info("Chap authentication succeeded! %.*v", in_len, in_buf); + status = CHAP_SUCCESS; + } + + PUTCHAR(EAPT_MSCHAPV2, outp); + PUTCHAR(status, outp); + used += 2; + break; + } + case CHAP_FAILURE: { + + psm->chap->handle_failure(in_buf, in_len); + PUTCHAR(EAPT_MSCHAPV2, outp); + PUTCHAR(status, outp); + used += 2; + break; + } + default: + break; + } + break; + } // EAPT_MSCHAPv2 +#endif + default: + + /* send compressed EAP NAK for any unknown packet */ + PUTCHAR(EAPT_NAK, outp); + ++used; + } + +done: + + dbglog("PEAP: EAP (out): %.*B", used, psm->out_buf); + *out_len = used; +} + +int peap_init(struct peap_state **ctx, const char *rhostname) +{ + const SSL_METHOD *method; + + if (!ctx) + return -1; + + tls_init(); + + struct peap_state *psm = malloc(sizeof(*psm)); + if (!psm) + novm("peap psm struct"); + psm->in_buf = malloc(TLS_RECORD_MAX_SIZE); + if (!psm->in_buf) + novm("peap tls buffer"); + psm->out_buf = malloc(TLS_RECORD_MAX_SIZE); + if (!psm->out_buf) + novm("peap tls buffer"); + method = tls_method(); + if (!method) + novm("TLS_method() failed"); + psm->ctx = SSL_CTX_new(method); + if (!psm->ctx) + novm("SSL_CTX_new() failed"); + + /* Configure the default options */ + tls_set_opts(psm->ctx); + + /* Configure the max TLS version */ + tls_set_version(psm->ctx, max_tls_version); + + /* Configure the peer certificate callback */ + tls_set_verify(psm->ctx, 5); + + /* Configure CA locations */ + if (tls_set_ca(psm->ctx, ca_path, cacert_file)) { + fatal("Could not set CA verify locations"); + } + + /* Configure CRL check (if any) */ + if (tls_set_crl(psm->ctx, crl_dir, crl_file)) { + fatal("Could not set CRL verify locations"); + } + + psm->out_bio = BIO_new(BIO_s_mem()); + psm->in_bio = BIO_new(BIO_s_mem()); + BIO_set_mem_eof_return(psm->out_bio, -1); + BIO_set_mem_eof_return(psm->in_bio, -1); + psm->ssl = SSL_new(psm->ctx); + SSL_set_bio(psm->ssl, psm->in_bio, psm->out_bio); + SSL_set_connect_state(psm->ssl); + psm->phase = PEAP_PHASE_1; + tls_set_verify_info(psm->ssl, explicit_remote ? rhostname : NULL, NULL, 1, &psm->info); + psm->chap = chap_find_digest(CHAP_MICROSOFT_V2); + *ctx = psm; + return 0; +} + +void peap_finish(struct peap_state **psm) { + + if (psm && *psm) { + struct peap_state *tmp = *psm; + + if (tmp->ssl) + SSL_free(tmp->ssl); + + if (tmp->ctx) + SSL_CTX_free(tmp->ctx); + + if (tmp->info) + tls_free_verify_info(&tmp->info); + + // NOTE: BIO and memory is freed as a part of SSL_free() + + free(*psm); + *psm = NULL; + } +} + +int peap_process(eap_state *esp, u_char id, u_char *inp, int len) +{ + int ret; + int out_len; + + struct peap_state *psm = esp->ea_peap; + + if (esp->es_client.ea_id == id) { + info("PEAP: retransmits are not supported.."); + return -1; + } + + switch (*inp) { + case PEAP_S_FLAG_SET: + dbglog("PEAP: S bit is set, starting PEAP phase 1"); + ret = SSL_do_handshake(psm->ssl); + if (ret != 1) { + ret = SSL_get_error(psm->ssl, ret); + if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) + fatal("SSL_do_handshake(): %s", ERR_error_string(ret, NULL)); + + } + psm->read = BIO_read(psm->out_bio, psm->out_buf, TLS_RECORD_MAX_SIZE); + peap_response(esp, id, psm->out_buf, psm->read); + break; + + case PEAP_LM_FLAG_SET: + dbglog("PEAP TLS: LM bits are set, need to get more TLS fragments"); + inp = inp + PEAP_FRAGMENT_LENGTH_FIELD + PEAP_FLAGS_FIELD; + psm->written = BIO_write(psm->in_bio, inp, len - PEAP_FRAGMENT_LENGTH_FIELD - PEAP_FLAGS_FIELD); + peap_ack(esp, id); + break; + + case PEAP_M_FLAG_SET: + dbglog("PEAP TLS: M bit is set, need to get more TLS fragments"); + inp = inp + PEAP_FLAGS_FIELD; + psm->written = BIO_write(psm->in_bio, inp, len - PEAP_FLAGS_FIELD); + peap_ack(esp, id); + break; + + case PEAP_L_FLAG_SET: + case PEAP_NO_FLAGS: + if (*inp == PEAP_L_FLAG_SET) { + dbglog("PEAP TLS: L bit is set"); + inp = inp + PEAP_FRAGMENT_LENGTH_FIELD + PEAP_FLAGS_FIELD; + psm->written = BIO_write(psm->in_bio, inp, len - PEAP_FRAGMENT_LENGTH_FIELD - PEAP_FLAGS_FIELD); + } else { + dbglog("PEAP TLS: all bits are off"); + inp = inp + PEAP_FLAGS_FIELD; + psm->written = BIO_write(psm->in_bio, inp, len - PEAP_FLAGS_FIELD); + } + + if (psm->phase == PEAP_PHASE_1) { + dbglog("PEAP TLS: continue handshake"); + ret = SSL_do_handshake(psm->ssl); + if (ret != 1) { + ret = SSL_get_error(psm->ssl, ret); + if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) + fatal("SSL_do_handshake(): %s", ERR_error_string(ret, NULL)); + } + if (SSL_is_init_finished(psm->ssl)) + psm->phase = PEAP_PHASE_2; + if (BIO_ctrl_pending(psm->out_bio) == 0) { + peap_ack(esp, id); + break; + } + psm->read = 0; + psm->read = BIO_read(psm->out_bio, psm->out_buf, + TLS_RECORD_MAX_SIZE); + peap_response(esp, id, psm->out_buf, psm->read); + break; + } + psm->read = SSL_read(psm->ssl, psm->in_buf, + TLS_RECORD_MAX_SIZE); + out_len = TLS_RECORD_MAX_SIZE; + peap_do_inner_eap(psm->in_buf, psm->read, esp, id, + psm->out_buf, &out_len); + if (out_len > 0) { + psm->written = SSL_write(psm->ssl, psm->out_buf, out_len); + psm->read = BIO_read(psm->out_bio, psm->out_buf, + TLS_RECORD_MAX_SIZE); + peap_response(esp, id, psm->out_buf, psm->read); + } + break; + } + return 0; +} + +#else + +u_char outpacket_buf[255]; +int debug = 1; +int error_count = 0; +int unsuccess = 0; + +/** + * Using the example in MS-PEAP, section 4.4.1. + * see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-peap/5308642b-90c9-4cc4-beec-fb367325c0f9 + */ +int test_cmk(u_char *ipmk) { + u_char nonce[PEAP_TLV_NONCE_LEN] = { + 0x6C, 0x6B, 0xA3, 0x87, 0x84, 0x23, 0x74, 0x57, + 0xCC, 0xC9, 0x0B, 0x1A, 0x90, 0x8C, 0xBD, 0xF4, + 0x71, 0x1B, 0x69, 0x99, 0x4D, 0x0C, 0xFE, 0x8D, + 0x3D, 0xB4, 0x4E, 0xCB, 0xCD, 0xAD, 0x37, 0xE9 + }; + + u_char tmpkey[PEAP_TLV_TEMPKEY_LEN] = { + 0x73, 0x8B, 0xB5, 0xF4, 0x62, 0xD5, 0x8E, 0x7E, + 0xD8, 0x44, 0xE1, 0xF0, 0x0D, 0x0E, 0xBE, 0x50, + 0xC5, 0x0A, 0x20, 0x50, 0xDE, 0x11, 0x99, 0x77, + 0x10, 0xD6, 0x5F, 0x45, 0xFB, 0x5F, 0xBA, 0xB7, + 0xE3, 0x18, 0x1E, 0x92, 0x4F, 0x42, 0x97, 0x38, + // 0xDE, 0x40, 0xC8, 0x46, 0xCD, 0xF5, 0x0B, 0xCB, + // 0xF9, 0xCE, 0xDB, 0x1E, 0x85, 0x1D, 0x22, 0x52, + // 0x45, 0x3B, 0xDF, 0x63 + }; + + u_char expected[60] = { + 0x00, 0x0C, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, + 0x6C, 0x6B, 0xA3, 0x87, 0x84, 0x23, 0x74, 0x57, + 0xCC, 0xC9, 0x0B, 0x1A, 0x90, 0x8C, 0xBD, 0xF4, + 0x71, 0x1B, 0x69, 0x99, 0x4D, 0x0C, 0xFE, 0x8D, + 0x3D, 0xB4, 0x4E, 0xCB, 0xCD, 0xAD, 0x37, 0xE9, + 0x42, 0xE0, 0x86, 0x07, 0x1D, 0x1C, 0x8B, 0x8C, + 0x8E, 0x45, 0x8F, 0x70, 0x21, 0xF0, 0x6A, 0x6E, + 0xAB, 0x16, 0xB6, 0x46 + }; + + u_char inner_mppe_keys[32] = { + 0x67, 0x3E, 0x96, 0x14, 0x01, 0xBE, 0xFB, 0xA5, + 0x60, 0x71, 0x7B, 0x3B, 0x5D, 0xDD, 0x40, 0x38, + 0x65, 0x67, 0xF9, 0xF4, 0x16, 0xFD, 0x3E, 0x9D, + 0xFC, 0x71, 0x16, 0x3B, 0xDF, 0xF2, 0xFA, 0x95 + }; + + u_char response[60] = {}; + + // Set the inner MPPE keys (e.g. from CHAPv2) + mppe_set_keys(inner_mppe_keys, inner_mppe_keys + 16, 16); + + // Generate and compare the response + generate_cmk(ipmk, tmpkey, nonce, response, 1); + if (memcmp(expected, response, sizeof(response)) != 0) { + dbglog("Failed CMK key generation\n"); + dbglog("%.*B", sizeof(response), response); + dbglog("%.*B", sizeof(expected), expected); + return -1; + } + + return 0; +} + +int test_mppe(u_char *ipmk) { + u_char outer_mppe_send_key[MPPE_MAX_KEY_SIZE] = { + 0x6A, 0x02, 0xD7, 0x82, 0x20, 0x1B, 0xC7, 0x13, + 0x8B, 0xF8, 0xEF, 0xF7, 0x33, 0xB4, 0x96, 0x97, + 0x0D, 0x7C, 0xAB, 0x30, 0x0A, 0xC9, 0x57, 0x72, + 0x78, 0xE1, 0xDD, 0xD5, 0xAE, 0xF7, 0x66, 0x97 + }; + + u_char outer_mppe_recv_key[MPPE_MAX_KEY_SIZE] = { + 0x17, 0x52, 0xD4, 0xE5, 0x84, 0xA1, 0xC8, 0x95, + 0x03, 0x9B, 0x4D, 0x05, 0xE3, 0xBC, 0x9A, 0x84, + 0x84, 0xDD, 0xC2, 0xAA, 0x6E, 0x2C, 0xE1, 0x62, + 0x76, 0x5C, 0x40, 0x68, 0xBF, 0xF6, 0x5A, 0x45 + }; + + u_char result[MPPE_MAX_KEY_SIZE]; + int len; + + mppe_clear_keys(); + + generate_mppe_keys(ipmk, 1); + + len = mppe_get_recv_key(result, sizeof(result)); + if (len != sizeof(result)) { + dbglog("Invalid length of resulting MPPE recv key"); + return -1; + } + + if (memcmp(result, outer_mppe_recv_key, len) != 0) { + dbglog("Invalid result for outer mppe recv key"); + return -1; + } + + len = mppe_get_send_key(result, sizeof(result)); + if (len != sizeof(result)) { + dbglog("Invalid length of resulting MPPE send key"); + return -1; + } + + if (memcmp(result, outer_mppe_send_key, len) != 0) { + dbglog("Invalid result for outer mppe send key"); + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + u_char ipmk[PEAP_TLV_IPMK_LEN] = { + 0x3A, 0x91, 0x1C, 0x25, 0x54, 0x73, 0xE8, 0x3E, + 0x9A, 0x0C, 0xC3, 0x33, 0xAE, 0x1F, 0x8A, 0x35, + 0xCD, 0xC7, 0x41, 0x63, 0xE7, 0xF6, 0x0F, 0x6C, + 0x65, 0xEF, 0x71, 0xC2, 0x64, 0x42, 0xAA, 0xAC, + 0xA2, 0xB6, 0xF1, 0xEB, 0x4F, 0x25, 0xEC, 0xA3, + }; + int ret = -1; + + ret = test_cmk(ipmk); + if (ret != 0) { + return -1; + } + + ret = test_mppe(ipmk); + if (ret != 0) { + return -1; + } + + return 0; +} + +#endif diff --git a/pppd/peap.h b/pppd/peap.h new file mode 100644 index 0000000..49e28e8 --- /dev/null +++ b/pppd/peap.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011 Rustam Kovhaev. All rights reserved. + * Copyright (c) 2021 Eivind Næss. 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 PPP_PEAP_H +#define PPP_PEAP_H + +#define PEAP_PHASE_1 1 +#define PEAP_PHASE_2 2 + +#define PEAP_HEADERLEN 6 +#define PEAP_FRAGMENT_LENGTH_FIELD 4 +#define PEAP_FLAGS_FIELD 1 +#define PEAP_FLAGS_ACK 0 + +#define PEAP_CAPABILITIES_TYPE 254 +#define PEAP_CAPABILITIES_LEN 12 + +#define PEAP_TLV_TYPE 12 +#define PEAP_TLV_LENGTH_FIELD 56 +#define PEAP_TLV_SUBTYPE_REQUEST 0 +#define PEAP_TLV_SUBTYPE_RESPONSE 1 +#define PEAP_TLV_HEADERLEN 8 +#define PEAP_TLV_RESULT_LEN 7 +#define PEAP_TLV_LEN 71 + +/* + * Microsoft PEAP client/server never exchange + * outer TLVs during PEAP authentication + */ +#define PEAP_TLV_DATA_LEN 61 + +#define PEAP_TLV_TK_LEN 60 +#define PEAP_TLV_ISK_LEN 32 +#define PEAP_TLV_IPMKSEED_LEN 59 +#define PEAP_TLV_TEMPKEY_LEN 40 +#define PEAP_TLV_IPMK_LEN 40 +#define PEAP_TLV_CMK_LEN 20 +#define PEAP_TLV_NONCE_LEN 32 +#define PEAP_TLV_COMP_MAC_LEN 20 +#define PEAP_TLV_CSK_LEN 128 +#define PEAP_TLV_TK_SEED_LABEL "client EAP encryption" +#define PEAP_TLV_IPMK_SEED_LABEL "Inner Methods Compound Keys" +#define PEAP_TLV_CSK_SEED_LABEL "Session Key Generating Function" + +#define PEAP_S_FLAG_SET 0x20 +#define PEAP_L_FLAG_SET 0x80 +#define PEAP_LM_FLAG_SET 0xC0 +#define PEAP_M_FLAG_SET 0x40 +#define PEAP_NO_FLAGS 0x00 + +#define EAP_TLS_KEY_LEN 0x40 +#define TLS_RECORD_MAX_SIZE 0x4000 + +struct peap_state; + +/** + * Initialize the PEAP structure + */ +int peap_init(struct peap_state** psm, const char *remote_name); + +/** + * Process a PEAP packet + */ +int peap_process(eap_state *esp, u_char id, u_char *inp, int len); + +/** + * Clean up the PEAP structure + */ +void peap_finish(struct peap_state **psm); + +#endif /* PPP_PEAP_H */ diff --git a/pppd/plugins/Makefile.am b/pppd/plugins/Makefile.am new file mode 100644 index 0000000..cfc9164 --- /dev/null +++ b/pppd/plugins/Makefile.am @@ -0,0 +1,25 @@ +pppd_plugin_LTLIBRARIES = minconn.la passprompt.la passwordfd.la winbind.la +pppd_plugindir = $(PPPD_PLUGIN_DIR) + +PLUGIN_CPPFLAGS = -I${top_srcdir}/include -I${top_srcdir}/pppd +PLUGIN_LDFLAGS = -module -avoid-version + +minconn_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) +minconn_la_LDFLAGS = $(PLUGIN_LDFLAGS) +minconn_la_SOURCES = minconn.c + +passprompt_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) +passprompt_la_LDFLAGS = $(PLUGIN_LDFLAGS) +passprompt_la_SOURCES = passprompt.c + +passwordfd_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) +passwordfd_la_LDFLAGS = $(PLUGIN_LDFLAGS) +passwordfd_la_SOURCES = passwordfd.c + +winbind_la_CPPFLAGS = $(PLUGIN_CPPFLAGS) +winbind_la_LDFLAGS = $(PLUGIN_LDFLAGS) +winbind_la_SOURCES = winbind.c + +if !SUNOS +SUBDIRS = pppoe pppoatm pppol2tp radius +endif diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux deleted file mode 100644 index 6403e3d..0000000 --- a/pppd/plugins/Makefile.linux +++ /dev/null @@ -1,53 +0,0 @@ -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -MANDIR = $(DESTDIR)/share/man/man8 -LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) - -CFLAGS = $(COPTS) -I.. -I../../include -fPIC -LDFLAGS_SHARED = -shared -INSTALL = install - -# EAP-TLS -CFLAGS += -DUSE_EAPTLS=1 - -SUBDIRS := pppoe pppoatm pppol2tp -# Uncomment the next line to include the radius authentication plugin -SUBDIRS += radius -PLUGINS := minconn.so passprompt.so passwordfd.so winbind.so - -# This setting should match the one in ../Makefile.linux -MPPE=y - -ifdef MPPE -CFLAGS += -DMPPE=1 -endif - -# include dependencies if present -ifeq (.depend,$(wildcard .depend)) -include .depend -endif - -all: $(PLUGINS) - for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d all || exit $$?; done - -%.so: %.c - $(CC) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) $(CFLAGS) $^ - -VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../patchlevel.h) - -install: $(PLUGINS) - $(INSTALL) -d $(LIBDIR) - $(INSTALL) $? $(LIBDIR) - for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d install || exit $$?; done - -clean: - rm -f *.o *.so *.a - for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d clean || exit $$?; done - -depend: - $(CPP) -M $(CFLAGS) *.c >.depend - for d in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$d depend || exit $$?; done diff --git a/pppd/plugins/Makefile.sol2 b/pppd/plugins/Makefile.sol2 deleted file mode 100644 index bc7d85d..0000000 --- a/pppd/plugins/Makefile.sol2 +++ /dev/null @@ -1,27 +0,0 @@ -# -# Makefile for plugins on Solaris 2 -# -# $Id: Makefile.sol2,v 1.3 2002/09/07 05:15:25 carlsonj Exp $ -# - -include ../../Makedefs.com - -CFLAGS = -c -O -I.. -I../../include $(COPTS) -LDFLAGS = -G - -all: minconn.so - -minconn.so: minconn.o - ld -o $@ $(LDFLAGS) -h $@ minconn.o - -minconn.o: minconn.c - $(CC) $(CFLAGS) -c $? - -passprompt.so: passprompt.o - ld -o $@ $(LDFLAGS) -h $@ passprompt.o - -passprompt.o: passprompt.c - $(CC) $(CFLAGS) -c $? - -clean: - rm -f *.o *.so diff --git a/pppd/plugins/minconn.c b/pppd/plugins/minconn.c index c12216a..40855ee 100644 --- a/pppd/plugins/minconn.c +++ b/pppd/plugins/minconn.c @@ -32,6 +32,10 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include "pppd.h" diff --git a/pppd/plugins/passprompt.c b/pppd/plugins/passprompt.c index ab9f390..743c087 100644 --- a/pppd/plugins/passprompt.c +++ b/pppd/plugins/passprompt.c @@ -8,6 +8,11 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -30,7 +35,7 @@ static int promptpass(char *user, char *passwd) { int p[2]; pid_t kid; - int readgood, wstat; + int readgood, wstat, ret; ssize_t red; if (promptprog_refused || promptprog[0] == 0 || access(promptprog, X_OK) < 0) @@ -55,8 +60,14 @@ static int promptpass(char *user, char *passwd) sys_close(); closelog(); close(p[0]); - seteuid(getuid()); - setegid(getgid()); + ret = seteuid(getuid()); + if (ret != 0) { + warn("Couldn't set effective user id"); + } + ret = setegid(getgid()); + if (ret != 0) { + warn("Couldn't set effective user id"); + } argv[0] = promptprog; argv[1] = user; argv[2] = remote_name; diff --git a/pppd/plugins/passwordfd.c b/pppd/plugins/passwordfd.c index c3f9793..84fd72e 100644 --- a/pppd/plugins/passwordfd.c +++ b/pppd/plugins/passwordfd.c @@ -7,6 +7,10 @@ * with pap- and chap-secrets files. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/plugins/pppoatm/Makefile.am b/pppd/plugins/pppoatm/Makefile.am new file mode 100644 index 0000000..66119c9 --- /dev/null +++ b/pppd/plugins/pppoatm/Makefile.am @@ -0,0 +1,18 @@ +pppd_plugin_LTLIBRARIES = pppoatm.la +pppd_plugindir = $(PPPD_PLUGIN_DIR) + +noinst_HEADERS = \ + atm.h \ + atmres.h \ + atmsap.h + +pppoatm_la_CPPFLAGS = -I${top_srcdir}/include -I${top_srcdir}/pppd +pppoatm_la_LDFLAGS = -module -avoid-version +pppoatm_la_SOURCES = pppoatm.c + +if WITH_LIBATM +pppoatm_la_LIBADD = -latm +else +pppoatm_la_SOURCES += text2qos.c text2atm.c misc.c ans.c +pppoatm_la_LIBADD = -lresolv +endif diff --git a/pppd/plugins/pppoatm/Makefile.linux b/pppd/plugins/pppoatm/Makefile.linux deleted file mode 100644 index d3a8086..0000000 --- a/pppd/plugins/pppoatm/Makefile.linux +++ /dev/null @@ -1,47 +0,0 @@ -#*********************************************************************** -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) - -VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) - -CFLAGS = $(COPTS) -I../.. -I../../../include -fPIC -LDFLAGS_SHARED = -shared -INSTALL = install - -PLUGIN := pppoatm.so -PLUGIN_OBJS := pppoatm.o - -#******* -# Do we have the ATM libraries installed? Set HAVE_LIBATM to use them, -# or leave it unset to build the few routines we actually _use_ into -# the plugin directly. -# -#HAVE_LIBATM=yes - -ifdef HAVE_LIBATM -LIBS := -latm -else -CFLAGS += -I. -PLUGIN_OBJS += text2qos.o text2atm.o misc.o ans.o -LIBS := -lresolv -endif - -#********* -all: $(PLUGIN) - -$(PLUGIN): $(PLUGIN_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LDFLAGS_SHARED) $^ $(LIBS) - -install: all - $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -c -m 4550 $(PLUGIN) $(LIBDIR) - -clean: - rm -f *.o *.so - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/pppd/plugins/pppoatm/pppoatm.c b/pppd/plugins/pppoatm/pppoatm.c index 5a3ecd6..09cd0b8 100644 --- a/pppd/plugins/pppoatm/pppoatm.c +++ b/pppd/plugins/pppoatm/pppoatm.c @@ -13,6 +13,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -183,15 +187,15 @@ void plugin_init(void) } struct channel pppoa_channel = { - options: pppoa_options, - process_extra_options: NULL, - check_options: NULL, - connect: &connect_pppoatm, - disconnect: &disconnect_pppoatm, - establish_ppp: &generic_establish_ppp, - disestablish_ppp: &generic_disestablish_ppp, - send_config: NULL, - recv_config: NULL, - close: NULL, - cleanup: NULL + .options = pppoa_options, + .process_extra_options = NULL, + .check_options = NULL, + .connect = &connect_pppoatm, + .disconnect = &disconnect_pppoatm, + .establish_ppp = &generic_establish_ppp, + .disestablish_ppp = &generic_disestablish_ppp, + .send_config = NULL, + .recv_config = NULL, + .close = NULL, + .cleanup = NULL }; diff --git a/pppd/plugins/pppoe/Makefile.am b/pppd/plugins/pppoe/Makefile.am new file mode 100644 index 0000000..0d70380 --- /dev/null +++ b/pppd/plugins/pppoe/Makefile.am @@ -0,0 +1,14 @@ +pppd_plugin_LTLIBRARIES = pppoe.la +pppd_plugindir = $(PPPD_PLUGIN_DIR) +sbin_PROGRAMS = pppoe-discovery +dist_man8_MANS = pppoe-discovery.8 + +noinst_HEADERS = \ + pppoe.h + +pppoe_la_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include +pppoe_la_LDFLAGS = -module -avoid-version +pppoe_la_SOURCES = plugin.c discovery.c if.c common.c + +pppoe_discovery_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include +pppoe_discovery_SOURCES = pppoe-discovery.c discovery.c if.c common.c diff --git a/pppd/plugins/pppoe/Makefile.linux b/pppd/plugins/pppoe/Makefile.linux deleted file mode 100644 index 0dd46ec..0000000 --- a/pppd/plugins/pppoe/Makefile.linux +++ /dev/null @@ -1,62 +0,0 @@ -#*********************************************************************** -# -# Makefile -# -# Makefile for Roaring Penguin's Linux PPPoE plugin. -# Modified for integration with pppd sources by Paul Mackerras. -# -# Copyright (C) 2001 Roaring Penguin Software Inc. -# -# This program may be distributed according to the terms of the GNU -# General Public License, version 2 or (at your option) any later version. -# -#*********************************************************************** - -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -LIBDIR = $(DESTDIR)/lib/pppd/$(PPPDVERSION) - -PPPDVERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) - -INSTALL = install -LN_S = ln -sf - -CFLAGS=$(COPTS) -I../../../include -all: pppoe.so pppoe-discovery - -pppoe-discovery: pppoe-discovery.o discovery.o if.o common.o - $(CC) $(LDFLAGS) -o pppoe-discovery pppoe-discovery.o discovery.o if.o common.o - -pppoe-discovery.o: pppoe-discovery.c - $(CC) $(CFLAGS) -I../../.. -c -o pppoe-discovery.o pppoe-discovery.c - -pppoe.so: plugin.o discovery.o if.o common.o - $(CC) $(LDFLAGS) -o pppoe.so -shared plugin.o discovery.o if.o common.o - -install: all - $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -c -m 4550 pppoe.so $(LIBDIR) - # Symlink for backward compatibility - $(LN_S) pppoe.so $(LIBDIR)/rp-pppoe.so - $(INSTALL) -d -m 755 $(BINDIR) - $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR) - -clean: - rm -f *.o *.so pppoe-discovery - -plugin.o: plugin.c - $(CC) $(CFLAGS) -I../../.. -c -o plugin.o -fPIC plugin.c - -discovery.o: discovery.c - $(CC) $(CFLAGS) -I../../.. -c -o discovery.o -fPIC discovery.c - -if.o: if.c - $(CC) $(CFLAGS) -I../../.. -c -o if.o -fPIC if.c - -common.o: common.c - $(CC) $(CFLAGS) -I../../.. -c -o common.o -fPIC common.c - diff --git a/pppd/plugins/pppoe/common.c b/pppd/plugins/pppoe/common.c index f57d9de..8b0e636 100644 --- a/pppd/plugins/pppoe/common.c +++ b/pppd/plugins/pppoe/common.c @@ -16,6 +16,10 @@ static char const RCSID[] = "$Id: common.c,v 1.3 2008/06/09 08:34:23 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" @@ -132,7 +136,7 @@ sendPADT(PPPoEConnection *conn, char const *msg) size_t elen = strlen(msg); err.type = htons(TAG_GENERIC_ERROR); err.length = htons(elen); - strcpy(err.payload, msg); + strcpy((char*) err.payload, msg); memcpy(cursor, &err, elen + TAG_HDR_SIZE); cursor += elen + TAG_HDR_SIZE; plen += elen + TAG_HDR_SIZE; diff --git a/pppd/plugins/pppoe/config.h b/pppd/plugins/pppoe/config.h deleted file mode 100644 index a708859..0000000 --- a/pppd/plugins/pppoe/config.h +++ /dev/null @@ -1,129 +0,0 @@ -/* config.h. Generated automatically by configure. */ -/* config.h.in. Generated automatically from configure.in by autoheader. */ - -/* Define to empty if the keyword does not work. */ -/* #undef const */ - -/* Define if you have that is POSIX.1 compatible. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define to `int' if doesn't define. */ -/* #undef pid_t */ - -/* Define as the return type of signal handlers (int or void). */ -#define RETSIGTYPE void - -/* Define if the setvbuf function takes the buffering type as its second - argument and the buffer pointer as the third, as on System V - before release 3. */ -/* #undef SETVBUF_REVERSED */ - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define if your declares struct tm. */ -/* #undef TM_IN_SYS_TIME */ - -#define HAVE_STRUCT_SOCKADDR_LL 1 - -/* The number of bytes in a unsigned int. */ -#define SIZEOF_UNSIGNED_INT 4 - -/* The number of bytes in a unsigned long. */ -#define SIZEOF_UNSIGNED_LONG 4 - -/* The number of bytes in a unsigned short. */ -#define SIZEOF_UNSIGNED_SHORT 2 - -/* Define if you have the select function. */ -#define HAVE_SELECT 1 - -/* Define if you have the socket function. */ -#define HAVE_SOCKET 1 - -/* Define if you have the strerror function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the strtol function. */ -#define HAVE_STRTOL 1 - -/* Define if you have the header file. */ -#define HAVE_ASM_TYPES_H 1 - -/* Define if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define if you have the header file. */ -#define HAVE_GETOPT_H 1 - -/* Define if you have the header file. */ -#define HAVE_LINUX_IF_ETHER_H 1 - -/* Define if you have kernel-mode PPPoE in Linux file. */ -#define HAVE_LINUX_KERNEL_PPPOE 1 - -/* Define if you have the header file. */ -#define HAVE_LINUX_IF_PACKET_H 1 - -/* Define if you have the header file. */ -#define HAVE_LINUX_IF_PPPOX_H 1 - -/* Define if you have the header file. */ -#define HAVE_NET_BPF_H 1 - -/* Define if you have the header file. */ -#define HAVE_NET_IF_ARP_H 1 - -/* Define if you have the header file. */ -#define HAVE_NET_ETHERNET_H 1 - -/* Define if you have the header file. */ -#define HAVE_NET_IF_H 1 - -/* Define if you have the header file. */ -#define HAVE_LINUX_IF_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_NET_IF_DL_H */ - -/* Define if you have the header file. */ -/* #undef HAVE_NET_IF_ETHER_H */ - -/* Define if you have the header file. */ -/* #undef HAVE_NET_IF_TYPES_H */ - -/* Define if you have the header file. */ -#define HAVE_NETINET_IF_ETHER_H 1 - -/* Define if you have the header file. */ -#define HAVE_NETPACKET_PACKET_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_DLPI_H */ - -/* Define if you have the header file. */ -#define HAVE_SYS_IOCTL_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_UIO_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYSLOG_H 1 - -/* Define if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define if you have the N_HDLC line discipline in linux/termios.h */ -#define HAVE_N_HDLC 1 diff --git a/pppd/plugins/pppoe/discovery.c b/pppd/plugins/pppoe/discovery.c index 86ea207..b32b0c8 100644 --- a/pppd/plugins/pppoe/discovery.c +++ b/pppd/plugins/pppoe/discovery.c @@ -11,6 +11,10 @@ static char const RCSID[] = "$Id: discovery.c,v 1.6 2008/06/15 04:35:50 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" diff --git a/pppd/plugins/pppoe/if.c b/pppd/plugins/pppoe/if.c index 225dd56..3dfea8c 100644 --- a/pppd/plugins/pppoe/if.c +++ b/pppd/plugins/pppoe/if.c @@ -16,6 +16,10 @@ static char const RCSID[] = "$Id: if.c,v 1.2 2008/06/09 08:34:23 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" diff --git a/pppd/plugins/pppoe/plugin.c b/pppd/plugins/pppoe/plugin.c index e9353eb..c534507 100644 --- a/pppd/plugins/pppoe/plugin.c +++ b/pppd/plugins/pppoe/plugin.c @@ -25,6 +25,10 @@ static char const RCSID[] = "$Id: plugin.c,v 1.17 2008/06/15 04:35:50 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #define _GNU_SOURCE 1 #include "pppoe.h" diff --git a/pppd/plugins/pppoe/pppoe-discovery.8 b/pppd/plugins/pppoe/pppoe-discovery.8 new file mode 100644 index 0000000..d0a93db --- /dev/null +++ b/pppd/plugins/pppoe/pppoe-discovery.8 @@ -0,0 +1,86 @@ +.\" pppoe-discovery.8 written by +.\" Ben Hutchings , based on pppoe.8. +.\" Licenced under the GPL version 2 or later. +.TH PPPOE-DISCOVERY 8 +.SH NAME +pppoe\-discovery \- perform PPPoE discovery +.SH SYNOPSIS +.B pppoe\-discovery +[ +.I options +] +.br +.BR pppoe\-discovery " { " \-V " | " \-h " }" +.SH DESCRIPTION +.LP +\fBpppoe\-discovery\fR performs the same discovery process as +\fBpppoe\fR, but does not initiate a session. +It sends a PADI packet and then prints the names of access +concentrators in each PADO packet it receives. +.SH OPTIONS +.TP +.BI \-I " interface" +.RS +The \fB\-I\fR option specifies the Ethernet interface to use. +Under Linux, it is typically eth0 or eth1. +The interface should be \(lqup\(rq before you start +\fBpppoe\-discovery\fR, but should \fInot\fR be configured to have an +IP address. +The default interface is eth0. +.RE +.TP +.BI \-D " file_name" +.RS +The \fB\-D\fR option causes every packet to be dumped to the specified +\fIfile_name\fR. +This is intended for debugging only. +.RE +.TP +.B \-U +.RS +Causes \fBpppoe\-discovery\fR to use the Host-Uniq tag in its discovery +packets. +This lets you run multiple instances of \fBpppoe\-discovery\fR and/or +\fBpppoe\fR without having their discovery packets interfere with one +another. +You must supply this option to \fIall\fR instances that you intend to +run simultaneously. +.RE +.TP +.BI \-S " service_name" +.RS +Specifies the desired service name. +\fBpppoe\-discovery\fR will only accept access concentrators which can +provide the specified service. +In most cases, you should \fInot\fR specify this option. +Use it only if you know that there are multiple access concentrators +or know that you need a specific service name. +.RE +.TP +.BI \-C " ac_name" +.RS +Specifies the desired access concentrator name. +\fBpppoe\-discovery\fR will only accept the specified access +concentrator. +In most cases, you should \fInot\fR specify this option. +Use it only if you know that there are multiple access concentrators. +If both the \fB\-S\fR and \fB\-C\fR options are specified, they must +\fIboth\fR match. +.RE +.TP +.B \-A +.RS +This option is accepted for compatibility with \fBpppoe\fR, but has no +effect. +.RE +.TP +.BR \-V " | " \-h +.RS +Either of these options causes \fBpppoe\-discovery\fR to print its +version number and usage information, then exit. +.RE +.SH AUTHORS +\fBpppoe\-discovery\fR was written by Marco d'Itri , +based on \fBpppoe\fR by David F. Skoll . +.SH SEE ALSO +pppoe(8), pppoe-sniff(8) diff --git a/pppd/plugins/pppoe/pppoe-discovery.c b/pppd/plugins/pppoe/pppoe-discovery.c index 2557b38..1fe999d 100644 --- a/pppd/plugins/pppoe/pppoe-discovery.c +++ b/pppd/plugins/pppoe/pppoe-discovery.c @@ -9,6 +9,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/pppd/plugins/pppoe/pppoe.h b/pppd/plugins/pppoe/pppoe.h index 9c5073b..26e14f5 100644 --- a/pppd/plugins/pppoe/pppoe.h +++ b/pppd/plugins/pppoe/pppoe.h @@ -13,8 +13,6 @@ * ***********************************************************************/ -#include "config.h" - #include /* For FILE */ #include /* For pid_t */ #include diff --git a/pppd/plugins/pppol2tp/Makefile.am b/pppd/plugins/pppol2tp/Makefile.am new file mode 100644 index 0000000..999f35b --- /dev/null +++ b/pppd/plugins/pppol2tp/Makefile.am @@ -0,0 +1,13 @@ +pppd_plugin_LTLIBRARIES = pppol2tp.la openl2tp.la +pppd_plugindir = $(PPPD_PLUGIN_DIR) + +noinst_HEADERS = \ + l2tp_event.h + +pppol2tp_la_CPPFLAGS = -I${top_srcdir}/include -I${top_srcdir}/pppd +pppol2tp_la_LDFLAGS = -module -avoid-version +pppol2tp_la_SOURCES = pppol2tp.c + +openl2tp_la_CPPFLAGS = -I${top_srcdir}/include -I${top_srcdir}/pppd +openl2tp_la_LDFLAGS = -module -avoid-version +openl2tp_la_SOURCES = openl2tp.c diff --git a/pppd/plugins/pppol2tp/Makefile.linux b/pppd/plugins/pppol2tp/Makefile.linux deleted file mode 100644 index 1aa1c0b..0000000 --- a/pppd/plugins/pppol2tp/Makefile.linux +++ /dev/null @@ -1,30 +0,0 @@ -#*********************************************************************** -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)/@DESTDIR@ -LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) - -VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) - -CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC -LDFLAGS_SHARED = -shared -INSTALL = install - -PLUGINS := pppol2tp.so openl2tp.so - -all: $(PLUGINS) - -%.so: %.o - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(LDFLAGS_SHARED) $^ $(LIBS) - -install: all - $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -c -m 755 $(PLUGINS) $(LIBDIR) - -clean: - rm -f *.o *.so - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/pppd/plugins/pppol2tp/openl2tp.c b/pppd/plugins/pppol2tp/openl2tp.c index 85ff0b5..0f9db6d 100644 --- a/pppd/plugins/pppol2tp/openl2tp.c +++ b/pppd/plugins/pppol2tp/openl2tp.c @@ -19,6 +19,10 @@ /* pppd plugin for interfacing to openl2tpd */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include diff --git a/pppd/plugins/pppol2tp/pppol2tp.c b/pppd/plugins/pppol2tp/pppol2tp.c index 1be0ad2..c9902af 100644 --- a/pppd/plugins/pppol2tp/pppol2tp.c +++ b/pppd/plugins/pppol2tp/pppol2tp.c @@ -20,6 +20,10 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -121,10 +125,10 @@ static int setdevname_pppol2tp(char **argv) char buffer[128]; struct sockaddr pppol2tp; } s; - int len = sizeof(s); + socklen_t len = sizeof(s); char **a; int tmp; - int tmp_len = sizeof(tmp); + socklen_t tmp_len = sizeof(tmp); if (device_got_set) return 0; @@ -203,8 +207,8 @@ static void send_config_pppol2tp(int mtu, int on = 1; int fd; char reorderto[16]; - char tid[8]; - char sid[8]; + char tid[12]; + char sid[12]; if (pppol2tp_ifname[0]) { struct ifreq ifr; @@ -237,10 +241,10 @@ static void send_config_pppol2tp(int mtu, sprintf(&reorderto[0], "%d ", pppol2tp_reorder_timeout); tid[0] = '\0'; if (pppol2tp_tunnel_id > 0) - sprintf(&tid[0], "%hu ", pppol2tp_tunnel_id); + sprintf(&tid[0], "%u ", pppol2tp_tunnel_id); sid[0] = '\0'; if (pppol2tp_session_id > 0) - sprintf(&sid[0], "%hu ", pppol2tp_session_id); + sprintf(&sid[0], "%u ", pppol2tp_session_id); dbglog("PPPoL2TP options: %s%s%s%s%s%s%s%s%sdebugmask %d", pppol2tp_recv_seq ? "recvseq " : "", @@ -505,20 +509,22 @@ void plugin_init(void) */ add_notifier(&ip_up_notifier, pppol2tp_ip_up, NULL); add_notifier(&ip_down_notifier, pppol2tp_ip_down, NULL); +#ifdef INET6 add_notifier(&ipv6_up_notifier, pppol2tp_ip_up, NULL); add_notifier(&ipv6_down_notifier, pppol2tp_ip_down, NULL); +#endif } struct channel pppol2tp_channel = { - options: pppol2tp_options, - process_extra_options: NULL, - check_options: &pppol2tp_check_options, - connect: &connect_pppol2tp, - disconnect: &disconnect_pppol2tp, - establish_ppp: &generic_establish_ppp, - disestablish_ppp: &generic_disestablish_ppp, - send_config: &send_config_pppol2tp, - recv_config: &recv_config_pppol2tp, - close: NULL, - cleanup: NULL + .options = pppol2tp_options, + .process_extra_options = NULL, + .check_options = &pppol2tp_check_options, + .connect = &connect_pppol2tp, + .disconnect = &disconnect_pppol2tp, + .establish_ppp = &generic_establish_ppp, + .disestablish_ppp = &generic_disestablish_ppp, + .send_config = &send_config_pppol2tp, + .recv_config = &recv_config_pppol2tp, + .close = NULL, + .cleanup = NULL }; diff --git a/pppd/plugins/radius/Makefile.am b/pppd/plugins/radius/Makefile.am new file mode 100644 index 0000000..c3cff23 --- /dev/null +++ b/pppd/plugins/radius/Makefile.am @@ -0,0 +1,64 @@ +pppd_plugin_LTLIBRARIES = radius.la radattr.la radrealms.la +pppd_plugindir = $(PPPD_PLUGIN_DIR) + +noinst_LTLIBRARIES = libradiusclient.la +dist_man8_MANS = pppd-radius.8 pppd-radattr.8 +noinst_HEADERS = \ + includes.h \ + options.h \ + pathnames.h \ + radiusclient.h + +EXTRA_FILES = \ + COPYRIGHT + +EXTRA_ETC = \ + etc/dictionary \ + etc/dictionary.ascend \ + etc/dictionary.compat \ + etc/dictionary.merit \ + etc/dictionary.microsoft \ + etc/issue \ + etc/port-id-map \ + etc/radiusclient.conf \ + etc/radiusclient.conf.in \ + etc/realms \ + etc/servers + +RADIUS_CPPFLAGS = -I${top_srcdir}/include -I${top_srcdir}/pppd -DRC_LOG_FACILITY=LOG_DAEMON +RADIUS_LDFLAGS = -module -avoid-version $(LDFLAGS) + +radius_la_CPPFLAGS = $(RADIUS_CPPFLAGS) +radius_la_LDFLAGS = $(RADIUS_LDFLAGS) +radius_la_SOURCES = radius.c +radius_la_LIBADD = libradiusclient.la +if WITH_OPENSSL +radius_la_LIBADD += $(OPENSSL_LIBS) +endif + +radattr_la_CPPFLAGS = $(RADIUS_CPPFLAGS) +radattr_la_LDFLAGS = $(RADIUS_LDFLAGS) +radattr_la_SOURCES = radattr.c + +radrealms_la_CPPFLAGS = $(RADIUS_CPPFLAGS) +radrealms_la_LDFLAGS = $(RADIUS_LDFLAGS) +radrealms_la_SOURCES = radrealms.c + +libradiusclient_la_SOURCES = \ + avpair.c buildreq.c config.c dict.c ip_util.c \ + clientid.c sendserver.c lock.c util.c +libradiusclient_la_CPPFLAGS = $(RADIUS_CPPFLAGS) + +if !WITH_OPENSSL +libradiusclient_la_SOURCES += md5.c +else +if OPENSSL_HAVE_MD5 +libradiusclient_la_SOURCES += md5.c +else +libradiusclient_la_CPPFLAGS += $(OPENSSL_INCLUDES) +endif +endif + +EXTRA_DIST = \ + $(EXTRA_FILES) \ + $(EXTRA_ETC) diff --git a/pppd/plugins/radius/Makefile.linux b/pppd/plugins/radius/Makefile.linux deleted file mode 100644 index 489aef2..0000000 --- a/pppd/plugins/radius/Makefile.linux +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for RADIUS plugin -# -# Copyright 2002 Roaring Penguin Software Inc. -# - -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -MANDIR = $(DESTDIR)/share/man/man8 -LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) - -VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../../patchlevel.h) - -INSTALL = install - -PLUGIN=radius.so radattr.so radrealms.so -CFLAGS = $(COPTS) -I. -I../.. -I../../../include -fPIC -DRC_LOG_FACILITY=LOG_DAEMON - -# Uncomment the next line to include support for Microsoft's -# MS-CHAP authentication protocol. -CHAPMS=y -# Uncomment the next line to include support for MPPE. -MPPE=y -# Uncomment the next lint to include support for traffic limiting -MAXOCTETS=y - -ifdef CHAPMS -CFLAGS += -DCHAPMS=1 -ifdef MPPE -CFLAGS += -DMPPE=1 -endif -endif -ifdef MAXOCTETS -CFLAGS += -DMAXOCTETS=1 -endif - -all: $(PLUGIN) - -install: all - $(INSTALL) -d -m 755 $(LIBDIR) - $(INSTALL) -c -m 755 radius.so $(LIBDIR) - $(INSTALL) -c -m 755 radattr.so $(LIBDIR) - $(INSTALL) -c -m 755 radrealms.so $(LIBDIR) - $(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR) - $(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR) - -radius.so: radius.o libradiusclient.a - $(CC) $(LDFLAGS) -o radius.so -shared radius.o libradiusclient.a - -radattr.so: radattr.o - $(CC) $(LDFLAGS) -o radattr.so -shared radattr.o - -radrealms.so: radrealms.o - $(CC) $(LDFLAGS) -o radrealms.so -shared radrealms.o - -CLIENTOBJS = avpair.o buildreq.o config.o dict.o ip_util.o \ - clientid.o sendserver.o lock.o util.o md5.o -libradiusclient.a: $(CLIENTOBJS) - $(AR) rv $@ $? - -clean: - rm -f *.o *.so *.a - -distclean: - rm -f *.o *.so *.a - -dist-clean: distclean diff --git a/pppd/plugins/radius/avpair.c b/pppd/plugins/radius/avpair.c index d548b47..0dc9a85 100644 --- a/pppd/plugins/radius/avpair.c +++ b/pppd/plugins/radius/avpair.c @@ -76,7 +76,7 @@ int rc_avpair_assign (VALUE_PAIR *vp, void *pval, int len) vp->strvalue[len] = '\0'; vp->lvalue = len; } else { - strncpy (vp->strvalue, (char *) pval, AUTH_STRING_LEN); + strncpy ((char*) vp->strvalue, (char *) pval, AUTH_STRING_LEN); vp->lvalue = strlen((char *) pval); } @@ -161,7 +161,7 @@ VALUE_PAIR *rc_avpair_gen (AUTH_HDR *auth) DICT_ATTR *attr; VALUE_PAIR *vp; VALUE_PAIR *pair; - unsigned char hex[3]; /* For hex string conversion. */ + char hex[3]; /* For hex string conversion. */ char buffer[512]; /* @@ -600,7 +600,7 @@ int rc_avpair_parse (char *buffer, VALUE_PAIR **first_pair) { case PW_TYPE_STRING: - strcpy (pair->strvalue, valstr); + strcpy ((char*) pair->strvalue, valstr); pair->lvalue = strlen(valstr); break; @@ -725,7 +725,7 @@ int rc_avpair_tostr (VALUE_PAIR *pair, char *name, int ln, char *value, int lv) } else { - strncat(value, ptr, 1); + strncat(value, (char*) ptr, 1); lv--; if (lv < 0) break; } diff --git a/pppd/plugins/radius/buildreq.c b/pppd/plugins/radius/buildreq.c index 3edd5ea..562790a 100644 --- a/pppd/plugins/radius/buildreq.c +++ b/pppd/plugins/radius/buildreq.c @@ -94,7 +94,7 @@ unsigned char rc_get_seqnbr(void) { FILE *sf; int tries = 1; - int seq_nbr, pos; + int seq_nbr, pos, ret; char *seqfile = rc_conf_str("seqfile"); if ((sf = fopen(seqfile, "a+")) == NULL) @@ -135,7 +135,10 @@ unsigned char rc_get_seqnbr(void) } rewind(sf); - ftruncate(fileno(sf),0); + ret = ftruncate(fileno(sf),0); + if (ret != 0) { + error("rc_get_seqnbr: couldn't truncate sequence file, %m"); + } fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX); fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */ diff --git a/pppd/plugins/radius/config.c b/pppd/plugins/radius/config.c index 871cea0..47c172c 100644 --- a/pppd/plugins/radius/config.c +++ b/pppd/plugins/radius/config.c @@ -525,7 +525,6 @@ int rc_find_server (char *server_name, UINT4 *ip_addr, char *secret) if (result == 0) { memset (buffer, '\0', sizeof (buffer)); - memset (secret, '\0', sizeof (secret)); error("rc_find_server: couldn't find RADIUS server %s in %s", server_name, rc_conf_str("servers")); return (-1); diff --git a/pppd/plugins/radius/dict.c b/pppd/plugins/radius/dict.c index 3b2add2..6f2657d 100644 --- a/pppd/plugins/radius/dict.c +++ b/pppd/plugins/radius/dict.c @@ -150,7 +150,7 @@ int rc_read_dictionary (char *filename) { type = PW_TYPE_INTEGER; } - else if (strcmp (typestr, "ipaddr") == 0) + else if (strcmp (typestr, "ipaddr") == 0 || strcmp (typestr, "ipv4addr") == 0) { type = PW_TYPE_IPADDR; } diff --git a/pppd/plugins/radius/radattr.c b/pppd/plugins/radius/radattr.c index 1fe7daa..f6a7874 100644 --- a/pppd/plugins/radius/radattr.c +++ b/pppd/plugins/radius/radattr.c @@ -17,9 +17,15 @@ static char const RCSID[] = "$Id: radattr.c,v 1.2 2004/10/28 00:24:40 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #include "pppd.h" #include "radiusclient.h" #include +#include +#include extern void (*radius_attributes_hook)(VALUE_PAIR *); static void print_attributes(VALUE_PAIR *); @@ -71,9 +77,12 @@ print_attributes(VALUE_PAIR *vp) char name[2048]; char value[2048]; int cnt = 0; + mode_t old_umask; slprintf(fname, sizeof(fname), "/var/run/radattr.%s", ifname); + old_umask = umask(077); fp = fopen(fname, "w"); + umask(old_umask); if (!fp) { warn("radattr plugin: Could not open %s for writing: %m", fname); return; diff --git a/pppd/plugins/radius/radius.c b/pppd/plugins/radius/radius.c index c579831..254ed90 100644 --- a/pppd/plugins/radius/radius.c +++ b/pppd/plugins/radius/radius.c @@ -26,11 +26,16 @@ static char const RCSID[] = "$Id: radius.c,v 1.32 2008/05/26 09:18:08 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #include "pppd.h" #include "chap-new.h" #ifdef CHAPMS #include "chap_ms.h" #ifdef MPPE +#include "mppe.h" #include "md5.h" #endif #endif @@ -107,7 +112,6 @@ static int radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info); #endif struct radius_state { - int accounting_started; int initialized; int client_port; int choose_ip; @@ -202,7 +206,7 @@ add_avp(char **argv) * 1 -- we are ALWAYS willing to supply a secret. :-) * %DESCRIPTION: * Tells pppd that we will try to authenticate the peer, and not to -* worry about looking in /etc/ppp/*-secrets +* worry about looking in *-secrets file(s) ***********************************************************************/ static int radius_secret_check(void) @@ -593,11 +597,11 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, break; case PW_FILTER_ID: /* packet filter, will be handled via ip-(up|down) script */ - script_setenv("RADIUS_FILTER_ID", vp->strvalue, 1); + script_setenv("RADIUS_FILTER_ID", (char*) vp->strvalue, 1); break; case PW_FRAMED_ROUTE: /* route, will be handled via ip-(up|down) script */ - script_setenv("RADIUS_FRAMED_ROUTE", vp->strvalue, 1); + script_setenv("RADIUS_FRAMED_ROUTE", (char*) vp->strvalue, 1); break; case PW_IDLE_TIMEOUT: /* idle parameter */ @@ -661,12 +665,12 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, #ifdef CHAPMS switch (vp->attribute) { case PW_MS_CHAP2_SUCCESS: - if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) { + if ((vp->lvalue != 43) || strncmp((char*) vp->strvalue + 1, "S=", 2)) { slprintf(msg,BUF_LEN,"RADIUS: bad MS-CHAP2-Success packet"); return -1; } if (message != NULL) - strlcpy(message, vp->strvalue + 1, message_space); + strlcpy(message, (char*) vp->strvalue + 1, message_space); ms_chap2_success = 1; break; @@ -743,11 +747,12 @@ radius_setparams(VALUE_PAIR *vp, char *msg, REQUEST_INFO *req_info, * Note that if the policy value was '0' we don't set the key! */ if (mppe_enc_policy && mppe_enc_keys) { - mppe_keys_set = 1; /* Set/modify allowed encryption types. */ if (mppe_enc_types) - set_mppe_enc_types(mppe_enc_policy, mppe_enc_types); + mppe_set_enc_types(mppe_enc_policy, mppe_enc_types); + return 0; } + mppe_clear_keys(); #endif return 0; @@ -803,7 +808,7 @@ radius_setmppekeys(VALUE_PAIR *vp, REQUEST_INFO *req_info, * the NAS (us) doesn't need; we only need the start key. So we have * to generate the start key, sigh. NB: We do not support the LM-Key. */ - mppe_set_keys(challenge, &plain[8]); + mppe_set_chapv1(challenge, &plain[8]); return 0; } @@ -855,7 +860,7 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) for (i = 0; i < 16; i++) plain[i] ^= buf[i]; - if (plain[0] != sizeof(mppe_send_key) /* 16 */) { + if (plain[0] != 16) { error("RADIUS: Incorrect key length (%d) for MS-MPPE-%s-Key attribute", (int) plain[0], type); return -1; @@ -869,9 +874,9 @@ radius_setmppekeys2(VALUE_PAIR *vp, REQUEST_INFO *req_info) plain[16] ^= buf[0]; /* only need the first byte */ if (vp->attribute == PW_MS_MPPE_SEND_KEY) - memcpy(mppe_send_key, plain + 1, 16); + mppe_set_keys(plain + 1, NULL, 16); else - memcpy(mppe_recv_key, plain + 1, 16); + mppe_set_keys(NULL, plain + 1, 16); return 0; } @@ -955,12 +960,11 @@ radius_acct_start(void) /* RADIUS server could be down so make this a warning */ syslog(LOG_WARNING, "Accounting START failed for %s", rstate.user); - } else { - rstate.accounting_started = 1; - /* Kick off periodic accounting reports */ - if (rstate.acct_interim_interval) { - TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); - } + } + + /* Kick off periodic accounting reports */ + if (rstate.acct_interim_interval) { + TIMEOUT(radius_acct_interim, NULL, rstate.acct_interim_interval); } } @@ -986,14 +990,9 @@ radius_acct_stop(void) return; } - if (!rstate.accounting_started) { - return; - } - if (rstate.acct_interim_interval) UNTIMEOUT(radius_acct_interim, NULL); - rstate.accounting_started = 0; rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 0, VENDOR_NONE); @@ -1138,10 +1137,6 @@ radius_acct_interim(void *ignored) return; } - if (!rstate.accounting_started) { - return; - } - rc_avpair_add(&send, PW_ACCT_SESSION_ID, rstate.session_id, 0, VENDOR_NONE); diff --git a/pppd/plugins/radius/radrealms.c b/pppd/plugins/radius/radrealms.c index cd006fd..a3b9a51 100644 --- a/pppd/plugins/radius/radrealms.c +++ b/pppd/plugins/radius/radrealms.c @@ -17,6 +17,10 @@ static char const RCSID[] = "$Id: radrealms.c,v 1.2 2004/11/14 07:26:26 paulus Exp $"; +#ifdef HAVE_CONFIG_H +#include +#endif + #include "pppd.h" #include "radiusclient.h" #include diff --git a/pppd/plugins/radius/sendserver.c b/pppd/plugins/radius/sendserver.c index 0c0ef30..f601286 100644 --- a/pppd/plugins/radius/sendserver.c +++ b/pppd/plugins/radius/sendserver.c @@ -104,7 +104,7 @@ static int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth) memcpy ((char *) passbuf, vp->strvalue, (size_t) length); secretlen = strlen (secret); - vector = (char *)auth->vector; + vector = auth->vector; for(i = 0; i < padded_length; i += AUTH_VECTOR_LEN) { /* Calculate the MD5 digest*/ strcpy ((char *) md5buf, secret); @@ -200,10 +200,10 @@ int rc_send_server (SEND_DATA *data, char *msg, REQUEST_INFO *info) AUTH_HDR *auth, *recv_auth; UINT4 auth_ipaddr; char *server_name; /* Name of server to query */ - int salen; + socklen_t salen; int result; int total_length; - int length; + socklen_t length; int retry_max; int secretlen; char secret[MAX_SECRET_LENGTH + 1]; @@ -228,6 +228,7 @@ int rc_send_server (SEND_DATA *data, char *msg, REQUEST_INFO *info) { if (rc_find_server (server_name, &auth_ipaddr, secret) != 0) { + memset (secret, '\0', sizeof (secret)); return (ERROR_RC); } } @@ -272,7 +273,7 @@ int rc_send_server (SEND_DATA *data, char *msg, REQUEST_INFO *info) memset((char *) auth->vector, 0, AUTH_VECTOR_LEN); secretlen = strlen (secret); memcpy ((char *) auth + total_length, secret, secretlen); - rc_md5_calc (vector, (char *) auth, total_length + secretlen); + rc_md5_calc (vector, (unsigned char *) auth, total_length + secretlen); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); } else @@ -362,7 +363,7 @@ int rc_send_server (SEND_DATA *data, char *msg, REQUEST_INFO *info) { if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE))) { - strcat(msg, vp->strvalue); + strcat(msg, (char*) vp->strvalue); strcat(msg, "\n"); vp = vp->next; } @@ -428,7 +429,7 @@ static int rc_check_reply (AUTH_HDR *auth, int bufferlen, char *secret, memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN); memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN); memcpy ((char *) auth + totallen, secret, secretlen); - rc_md5_calc (calc_digest, (char *) auth, totallen + secretlen); + rc_md5_calc (calc_digest, (unsigned char *) auth, totallen + secretlen); #ifdef DIGEST_DEBUG { diff --git a/pppd/plugins/radius/util.c b/pppd/plugins/radius/util.c index 740131e..4065724 100644 --- a/pppd/plugins/radius/util.c +++ b/pppd/plugins/radius/util.c @@ -75,10 +75,10 @@ rc_mksid (void) { static char buf[32]; static unsigned short int cnt = 0; - slprintf(buf, sizeof(buf), "%08lX%04X%02hX", + snprintf(buf, sizeof(buf), "%08lX%04X%02hX", (unsigned long int) time (NULL), (unsigned int) getpid (), - cnt & 0xFF); + (unsigned short) (cnt & 0xFF)); cnt++; return buf; } diff --git a/pppd/plugins/winbind.c b/pppd/plugins/winbind.c index 0c395c3..76db234 100644 --- a/pppd/plugins/winbind.c +++ b/pppd/plugins/winbind.c @@ -34,14 +34,16 @@ * ***********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "pppd.h" #include "chap-new.h" #include "chap_ms.h" -#ifdef MPPE -#include "md5.h" -#endif #include "fsm.h" #include "ipcp.h" +#include "mppe.h" #include #include #include @@ -165,7 +167,7 @@ plugin_init(void) Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -size_t strhex_to_str(char *p, size_t len, const char *strhex) +size_t strhex_to_str(unsigned char *p, size_t len, const char *strhex) { size_t i; size_t num_chars = 0; @@ -297,15 +299,20 @@ unsigned int run_ntlm_auth(const char *username, if (forkret == 0) { /* child process */ uid_t uid; + gid_t gid; close(child_out[0]); close(child_in[1]); /* run winbind as the user that invoked pppd */ - setgid(getgid()); + gid = getgid(); + if (setgid(gid) == -1 || getgid() != gid) { + fatal("pppd/winbind: could not setgid to %d: %m", gid); + } uid = getuid(); - if (setuid(uid) == -1 || getuid() != uid) + if (setuid(uid) == -1 || getuid() != uid) { fatal("pppd/winbind: could not setuid to %d: %m", uid); + } execl("/bin/sh", "sh", "-c", ntlm_auth, NULL); fatal("pppd/winbind: could not exec /bin/sh: %m"); } @@ -520,7 +527,7 @@ winbind_chap_verify(char *user, char *ourname, int id, char *domain; char *username; char *p; - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; + unsigned char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; /* The first byte of each of these strings contains their length */ challenge_len = *challenge++; @@ -583,7 +590,9 @@ winbind_chap_verify(char *user, char *ourname, int id, nt_response, nt_response_size, session_key, &error_string) == AUTHENTICATED) { - mppe_set_keys(challenge, session_key); +#ifdef MPPE + mppe_set_chapv1(challenge, session_key); +#endif slprintf(message, message_space, "Access granted"); return AUTHENTICATED; @@ -628,8 +637,10 @@ winbind_chap_verify(char *user, char *ourname, int id, &response[MS_CHAP2_NTRESP], &response[MS_CHAP2_PEER_CHALLENGE], challenge, user, saresponse); - mppe_set_keys2(session_key, &response[MS_CHAP2_NTRESP], +#ifdef MPPE + mppe_set_chapv2(session_key, &response[MS_CHAP2_NTRESP], MS_CHAP2_AUTHENTICATOR); +#endif if (response[MS_CHAP2_FLAGS]) { slprintf(message, message_space, "S=%s", saresponse); } else { diff --git a/pppd/pppcrypt.c b/pppd/pppcrypt.c index 193f8fd..a954d62 100644 --- a/pppd/pppcrypt.c +++ b/pppd/pppcrypt.c @@ -30,7 +30,12 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include + #include "pppd.h" #include "pppcrypt.h" diff --git a/pppd/pppcrypt.h b/pppd/pppcrypt.h index 364940e..79676ca 100644 --- a/pppd/pppcrypt.h +++ b/pppd/pppcrypt.h @@ -29,6 +29,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" #ifndef PPPCRYPT_H #define PPPCRYPT_H @@ -38,7 +39,7 @@ #endif #ifndef USE_CRYPT -#include +#include #endif extern bool DesSetkey(u_char *); diff --git a/pppd/pppd.8 b/pppd/pppd.8 index cbbcb45..b31594a 100644 --- a/pppd/pppd.8 +++ b/pppd/pppd.8 @@ -55,8 +55,8 @@ non-privileged user. .I speed An option that is a decimal number is taken as the desired baud rate for the serial device. On systems such as -4.4BSD and NetBSD, any speed can be specified. Other systems -(e.g. Linux, SunOS) only support the commonly-used baud rates. +Linux, 4.4BSD and NetBSD, any speed can be specified. Other systems +(e.g. SunOS) only support the commonly-used baud rates. .TP .B asyncmap \fImap This option sets the Async-Control-Character-Map (ACCM) for this end @@ -127,12 +127,6 @@ is no other default route with the same metric. With the default value of -1, the route is only added if there is no default route at all. .TP -.B defaultroute6 -Add a default IPv6 route to the system routing tables, using the peer as -the gateway, when IPv6CP negotiation is successfully completed. -This entry is removed when the PPP connection is broken. This option -is privileged if the \fInodefaultroute6\fR option has been specified. -.TP .B replacedefaultroute This option is a flag to the defaultroute option. If defaultroute is set and this flag is also set, pppd replaces an existing default route @@ -266,10 +260,16 @@ compression in the corresponding direction. Use \fInobsdcomp\fR or \fIbsdcomp 0\fR to disable BSD-Compress compression entirely. .TP .B ca \fIca-file -(EAP-TLS) Use the file \fIca-file\fR as the X.509 Certificate Authority +(EAP-TLS, or PEAP) Use the file \fIca-file\fR as the X.509 Certificate Authority (CA) file (in PEM format), needed for setting up an EAP-TLS connection. This option is used on the client-side in conjunction with the \fBcert\fR -and \fBkey\fR options. +and \fBkey\fR options. Either \fIca\fR, or \fIcapath\fR options are required +for PEAP. EAP-TLS may also use the entry in eaptls-client or eaptls-server +for a CA certificate associated with a particular peer. +.TP +.B capath \fIpath +(EAP-TLS, or PEAP) Specify a location that contains public CA certificates. +Either \fIca\fR, or \fIcapath\fR options are required for PEAP. .TP .B cdtrcts Use a non-standard hardware flow control (i.e. DTR/CTS) to control @@ -326,15 +326,15 @@ negotiation by sending its first LCP packet. The default value is or \fBpty\fR option is used. .TP .B crl \fIfilename -(EAP-TLS) Use the file \fIfilename\fR as the Certificate Revocation List +(EAP-TLS, or PEAP) Use the file \fIfilename\fR as the Certificate Revocation List to check for the validity of the peer's certificate. This option is not -mandatory for setting up an EAP-TLS connection. Also see the \fBcrl-dir\fR +mandatory for setting up a TLS connection. Also see the \fBcrl-dir\fR option. .TP .B crl-dir \fIdirectory -(EAP-TLS) Use the directory \fIdirectory\fR to scan for CRL files in +(EAP-TLS, or PEAP) Use the directory \fIdirectory\fR to scan for CRL files in has format ($hash.r0) to check for the validity of the peer's certificate. -This option is not mandatory for setting up an EAP-TLS connection. +This option is not mandatory for setting up a TLS connection. Also see the \fBcrl\fR option. .TP .B debug @@ -354,6 +354,17 @@ Disable MRU [Maximum Receive Unit] negotiation. With this option, pppd will use the default MRU value of 1500 bytes for both the transmit and receive direction. .TP +.B defaultroute6 +Add a default IPv6 route to the system routing tables, using the peer as +the gateway, when IPv6CP negotiation is successfully completed. +This entry is removed when the PPP connection is broken. This option +is privileged if the \fInodefaultroute6\fR option has been specified. +\fBWARNING: Do not enable this option by default\fR. IPv6 routing tables +are managed by kernel (as apposite to IPv4) and IPv6 default route is +configured by kernel automatically too based on ICMPv6 Router Advertisement +packets. This option may conflict with kernel IPv6 route setup and should +be used only for broken IPv6 networks. +.TP .B deflate \fInr,nt Request that the peer compress packets that it sends, using the Deflate scheme, with a maximum window size of \fI2**nr\fR bytes, and @@ -493,6 +504,18 @@ to send configure-Rejects instead to \fIn\fR (default 10). Set the maximum number of IPCP terminate-request transmissions to \fIn\fR (default 3). .TP +.B ipcp\-no\-address +Disable negotiation of addresses via IP-Address IPCP option. +.TP +.B ipcp\-no\-addresses +Disable negotiation of addresses via old-style deprecated IP-Addresses +IPCP option. pppd by default try to use new-style IP-Address IPCP option. +If new-style is not supported by peer or is disabled by \fBipcp\-no\-address\fR +option then pppd fallbacks to old-style deprecated IP-Addresses IPCP option. +When both new-style and old-style are disabled by both \fBipcp\-no\-address\fR +and \fBipcp\-no\-addresses\fR options then negotiation of IP addresses +is completely disabled. +.TP .B ipcp\-restart \fIn Set the IPCP restart interval (retransmission timeout) to \fIn\fR seconds (default 3). @@ -707,6 +730,11 @@ network control protocol comes up). Terminate after \fIn\fR consecutive failed connection attempts. A value of 0 means no limit. The default value is 10. .TP +.B max-tls-version \fIstring +(EAP-TLS, or PEAP) Configures the max allowed TLS version used during +negotiation with a peer. The default value for this is \fI1.2\fR. Values +allowed for this option is \fI1.0.\fR, \fI1.1\fR, \fI1.2\fR, \fI1.3\fR. +.TP .B modem Use the modem control lines. This option is the default. With this option, pppd will wait for the CD (Carrier Detect) signal from the @@ -924,6 +952,9 @@ situation, the ppp interface can be used for routing by creating device routes, but the peer itself cannot be addressed directly for IP traffic. .TP +.B nosendip +Don't send our local IP address to peer during IP address negotiation. +.TP .B notty Normally, pppd requires a terminal device. With this option, pppd will allocate itself a pseudo-tty master/slave pair and use the slave @@ -1153,6 +1184,16 @@ The device used by pppd with this option must have sync support. Currently supports Microgate SyncLink adapters under Linux and FreeBSD 2.2.8 and later. .TP +.B tls-verify-method \fIstring +(EAP-TLS, or PEAP) Match the value specified for \fIremotename\fR to that that +of the X509 certificates subject name, common name, or suffix of the common +name. Respective values allowed for this option is: \fInone\fR, \fIsubject\fR, +\fIname\fR, or \fIsuffix\fR. The default value for this option is \fIname\fR. +.TP +.B tls-verify-key-usage +(EAP-TLS, or PEAP) Enables examination of peer certificate's purpose, and +extended key usage attributes. +.TP .B unit \fInum Sets the ppp unit number (for a ppp0 or ppp1 etc interface name) for outbound connections. If the unit is already in use a dynamically allocated number will @@ -1199,6 +1240,16 @@ USEPEERDNS will be set to 1. In addition, pppd will create an /etc/ppp/resolv.conf file containing one or two nameserver lines with the address(es) supplied by the peer. .TP +.B usepeerwins +Ask the peer for up to 2 WINS server addresses. The addresses supplied +by the peer (if any) are passed to the /etc/ppp/ip\-up script in the +environment variables WINS1 and WINS2, and the environment variable +USEPEERWINS will be set to 1. +.LP +Please note that some modems (like the Huawei E220) requires this option in +order to avoid a race condition that results in the incorrect DNS servers +being assigned. +.TP .B user \fIname Sets the name used for authenticating the local system to the peer to \fIname\fR. @@ -1751,6 +1802,14 @@ IPCP has come up. The IP address for the remote end of the link. This is only set when IPCP has come up. .TP +.B LLLOCAL +The Link-Local IPv6 address for the local end of the link. This is only +set when IPV6CP has come up. +.TP +.B LLREMOTE +The Link-Local IPv6 address for the remote end of the link. This is only +set when IPV6CP has come up. +.TP .B PEERNAME The authenticated name of the peer. This is only set if the peer authenticates itself. @@ -1794,6 +1853,15 @@ option was given). If the peer supplies DNS server addresses, this variable is set to the second DNS server address supplied (whether or not the usepeerdns option was given). +.TP +.B WINS1 +If the peer supplies WINS server addresses, this variable is set to the +first WINS server address supplied. +.TP +.B WINS2 +If the peer supplies WINS server addresses, this variable is set to the +second WINS server address supplied. +.P .P Pppd invokes the following scripts, if they exist. It is not an error if they don't exist. diff --git a/pppd/pppd.h b/pppd/pppd.h index 612902f..ce43a28 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -42,6 +42,8 @@ * $Id: pppd.h,v 1.96 2008/06/23 11:47:18 paulus Exp $ */ +#include "pppdconf.h" + /* * TODO: */ @@ -58,6 +60,7 @@ #include /* for u_int32_t, if defined */ #include /* for struct timeval */ #include +#include #include "patchlevel.h" #ifdef INET6 @@ -73,8 +76,6 @@ #define MAXARGS 1 /* max # args to a command */ #define MAXNAMELEN 256 /* max length of hostname or name for auth */ #define MAXSECRETLEN 256 /* max length of password or secret */ -#define MAXIFNAMELEN 32 /* max length of interface name; or use IFNAMSIZ, can we - always include net/if.h? */ /* * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name. @@ -327,7 +328,7 @@ extern int max_data_rate; /* max bytes/sec through charshunt */ extern int req_unit; /* interface unit number to use */ extern char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */ extern char path_ipdown[MAXPATHLEN]; /* pathname of ip-down script */ -extern char req_ifname[MAXIFNAMELEN]; /* interface name to use */ +extern char req_ifname[IFNAMSIZ]; /* interface name to use */ extern bool multilink; /* enable multilink operation */ extern bool noendpoint; /* don't send or accept endpt. discrim. */ extern char *bundle_name; /* bundle name for multilink */ @@ -335,10 +336,30 @@ extern bool dump_options; /* print out option values */ extern bool dryrun; /* check everything, print options, exit */ extern int child_wait; /* # seconds to wait for children at end */ -#ifdef USE_EAPTLS -extern char *crl_dir; -extern char *crl_file; +#ifdef INET6 +extern char path_ipv6up[MAXPATHLEN]; /* pathname of ipv6-up script */ +extern char path_ipv6down[MAXPATHLEN]; /* pathname of ipv6-down script */ +#endif + +#if defined(USE_EAPTLS) || defined(USE_PEAP) + +#define TLS_VERIFY_NONE "none" +#define TLS_VERIFY_NAME "name" +#define TLS_VERIFY_SUBJECT "subject" +#define TLS_VERIFY_SUFFIX "suffix" + +extern char *crl_dir; +extern char *crl_file; +extern char *ca_path; +extern char *cacert_file; + extern char *max_tls_version; +extern bool tls_verify_key_usage; +extern char *tls_verify_method; +#endif /* USE_EAPTLS || USE_PEAP */ + +#ifdef USE_EAPTLS +extern char *pkcs12_file; #endif /* USE_EAPTLS */ #ifdef MAXOCTETS diff --git a/pppd/pppd.pc.in b/pppd/pppd.pc.in new file mode 100644 index 0000000..20ef104 --- /dev/null +++ b/pppd/pppd.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +plugindir=@PPPD_PLUGIN_DIR@ + +Name: pppd +Description: Point-to-Point Protocol (PPP) daemon +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} diff --git a/pppd/pppdconf.h.in b/pppd/pppdconf.h.in new file mode 100644 index 0000000..a1eea0e --- /dev/null +++ b/pppd/pppdconf.h.in @@ -0,0 +1,61 @@ +/* + * This file is generated by configure and sets the features enabled + * in pppd when configured. + */ + +/* "Have Microsoft CHAP support" */ +#undef CHAPMS + +/* "Have Microsoft MPPE support" */ +#undef MPPE + +/* "Have multilink support" */ +#undef HAVE_MULTILINK + +/* "Have IPX Control Protocol" */ +#undef IPX_CHANGE + +/* "Have packet activity filter support" */ +#undef PPP_FILTER + +/* "Have support for loadable plugins" */ +#undef PLUGIN + +/* "Limit sessions by maximum number of octets" */ +#undef MAXOCTETS + +/* Have Microsoft Callback Protocol support */ +#undef CBCP_SUPPORT + +/* "Include Trivial Database support" */ +#undef USE_TDB + +/* "Have IPv6 support" */ +#undef INET6 + +/* "Support for Pluggable Authentication Modules" */ +#undef USE_PAM + +/* "Have EAP-SRP authentication support" */ +#undef USE_SRP + +/* "Have EAP-TLS authentication support" */ +#undef USE_EAPTLS + +/* "Have PEAP authentication support" */ +#undef USE_PEAP + +/* Use included des included with pppd */ +#undef USE_CRYPT + +/* Use included md4 included with pppd */ +#undef USE_MD4 + +/* Use included md5 included with pppd */ +#undef USE_MD5 + +/* Use included sha included with pppd */ +#undef USE_SHA + +/* Version number of package */ +#undef VERSION diff --git a/pppd/session.c b/pppd/session.c index 2f1c83e..3d1fb6d 100644 --- a/pppd/session.c +++ b/pppd/session.c @@ -68,14 +68,23 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include #include + +#ifdef HAVE_CRYPT_H #include -#ifdef HAS_SHADOW +#endif + +#ifdef HAVE_SHADOW_H #include #endif + #include #include #include @@ -171,11 +180,11 @@ session_start(const int flags, const char *user, const char *passwd, const char #else /* #ifdef USE_PAM */ struct passwd *pw; char *cbuf; -#ifdef HAS_SHADOW +#ifdef HAVE_SHADOW_H struct spwd *spwd; struct spwd *getspnam(); long now = 0; -#endif /* #ifdef HAS_SHADOW */ +#endif /* #ifdef HAVE_SHADOW_H */ #endif /* #ifdef USE_PAM */ SET_MSG(msg, SUCCESS_MSG); @@ -305,7 +314,7 @@ session_start(const int flags, const char *user, const char *passwd, const char if (pw == NULL) return SESSION_FAILED; -#ifdef HAS_SHADOW +#ifdef HAVE_SHADOW_H spwd = getspnam(user); endspent(); @@ -336,15 +345,17 @@ session_start(const int flags, const char *user, const char *passwd, const char /* We have a valid shadow entry, keep the password */ pw->pw_passwd = spwd->sp_pwdp; -#endif /* #ifdef HAS_SHADOW */ +#endif /* #ifdef HAVE_SHADOW_H */ /* * If no passwd, don't let them login if we're authenticating. */ if (pw->pw_passwd == NULL || strlen(pw->pw_passwd) < 2) return SESSION_FAILED; +#ifdef HAVE_CRYPT_H cbuf = crypt(passwd, pw->pw_passwd); if (!cbuf || strcmp(cbuf, pw->pw_passwd) != 0) +#endif return SESSION_FAILED; } diff --git a/pppd/session.h b/pppd/session.h index bee8c41..0047db6 100644 --- a/pppd/session.h +++ b/pppd/session.h @@ -27,6 +27,7 @@ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "pppdconf.h" #ifndef __SESSION_H #define __SESSION_H diff --git a/pppd/sha1.c b/pppd/sha1.c index 4e51cee..efb37be 100644 --- a/pppd/sha1.c +++ b/pppd/sha1.c @@ -14,6 +14,10 @@ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define SHA1HANDSOFF * Copies data before messing with it. */ #include diff --git a/pppd/sha1.h b/pppd/sha1.h index 83f64df..e7e5573 100644 --- a/pppd/sha1.h +++ b/pppd/sha1.h @@ -1,12 +1,17 @@ /* sha1.h */ -/* If OpenSSL is in use, then use that version of SHA-1 */ -#ifdef OPENSSL -#include -#define __SHA1_INCLUDE_ -#endif +#include "pppdconf.h" #ifndef __SHA1_INCLUDE_ +#define __SHA1_INCLUDE_ + +#ifndef USE_SHA +#include + +#define SHA1_CTX SHA_CTX +#define SHA1_SIGNATURE_SIZE SHA_DIGEST_LENGTH + +#else #ifndef SHA1_SIGNATURE_SIZE #ifdef SHA_DIGESTSIZE @@ -26,6 +31,5 @@ extern void SHA1_Init(SHA1_CTX *); extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int); extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *); -#define __SHA1_INCLUDE_ +#endif /* USE_SHA */ #endif /* __SHA1_INCLUDE_ */ - diff --git a/pppd/spinlock.c b/pppd/spinlock.c index 4df7e47..56abae4 100644 --- a/pppd/spinlock.c +++ b/pppd/spinlock.c @@ -23,6 +23,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/spinlock.h b/pppd/spinlock.h index 967fe37..38e7bcc 100644 --- a/pppd/spinlock.h +++ b/pppd/spinlock.h @@ -1,10 +1,8 @@ +#include "pppdconf.h" + #ifndef __SPINLOCK_H__ #define __SPINLOCK_H__ -#ifdef HAVE_CONFIG_H -#include -#endif - #include "tdb.h" #ifdef USE_SPINLOCKS diff --git a/pppd/srp-entry.c b/pppd/srp-entry.c index 8c0e297..d59c1d3 100644 --- a/pppd/srp-entry.c +++ b/pppd/srp-entry.c @@ -29,6 +29,10 @@ * The default modulus/generator can be requested as index 0. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index 85033d9..1e00366 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -69,6 +69,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -85,12 +89,13 @@ #include #include #include +#ifdef HAVE_UTMP_H #include +#endif #include #include #include #include -#include #include /* This is in netdevice.h. However, this compile will fail miserably if @@ -125,6 +130,14 @@ #include #include #include +/* glibc versions prior to 2.24 do not define SOL_NETLINK */ +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif +/* linux kernel versions prior to 4.3 do not define/support NETLINK_CAP_ACK */ +#ifndef NETLINK_CAP_ACK +#define NETLINK_CAP_ACK 10 +#endif #endif #include "pppd.h" @@ -150,6 +163,12 @@ #include #endif +/* + * Instead of system header file use local "termios_linux.h" header + * file as it provides additional support for arbitrary baud rates via BOTHER. + */ +#include "termios_linux.h" + #ifdef INET6 #ifndef _LINUX_IN6_H /* @@ -164,9 +183,9 @@ struct in6_ifreq { #endif #define IN6_LLADDR_FROM_EUI64(sin6, eui64) do { \ - memset(&sin6.s6_addr, 0, sizeof(struct in6_addr)); \ - sin6.s6_addr16[0] = htons(0xfe80); \ - eui64_copy(eui64, sin6.s6_addr32[2]); \ + memset(&(sin6).s6_addr, 0, sizeof(struct in6_addr)); \ + (sin6).s6_addr16[0] = htons(0xfe80); \ + eui64_copy(eui64, (sin6).s6_addr32[2]); \ } while (0) static const eui64_t nulleui64; @@ -668,11 +687,11 @@ static int make_ppp_unit(void) if (x == 0 && req_ifname[0] != '\0') { struct ifreq ifr; - char t[MAXIFNAMELEN]; + char t[IFNAMSIZ]; memset(&ifr, 0, sizeof(struct ifreq)); slprintf(t, sizeof(t), "%s%d", PPP_DRV_NAME, ifunit); - strlcpy(ifr.ifr_name, t, IF_NAMESIZE); - strlcpy(ifr.ifr_newname, req_ifname, IF_NAMESIZE); + strlcpy(ifr.ifr_name, t, IFNAMSIZ); + strlcpy(ifr.ifr_newname, req_ifname, IFNAMSIZ); x = ioctl(sock_fd, SIOCSIFNAME, &ifr); if (x < 0) error("Couldn't rename interface %s to %s: %m", t, req_ifname); @@ -890,6 +909,12 @@ struct speed { #ifdef B460800 { 460800, B460800 }, #endif +#ifdef B500000 + { 500000, B500000 }, +#endif +#ifdef B576000 + { 576000, B576000 }, +#endif #ifdef B921600 { 921600, B921600 }, #endif @@ -934,7 +959,6 @@ static int translate_speed (int bps) if (bps == speedp->speed_int) return speedp->speed_val; } - warn("speed %d not supported", bps); } return 0; } @@ -1013,26 +1037,53 @@ void set_up_tty(int tty_fd, int local) if (stop_bits >= 2) tios.c_cflag |= CSTOPB; - speed = translate_speed(inspeed); - if (speed) { - cfsetospeed (&tios, speed); - cfsetispeed (&tios, speed); + if (inspeed) { + speed = translate_speed(inspeed); + if (speed) { + cfsetospeed (&tios, speed); + cfsetispeed (&tios, speed); + speed = cfgetospeed(&tios); + baud_rate = baud_rate_of(speed); + } else { +#ifdef BOTHER + tios.c_cflag &= ~CBAUD; + tios.c_cflag |= BOTHER; + tios.c_ospeed = inspeed; +#ifdef IBSHIFT + /* B0 sets input baudrate to the output baudrate */ + tios.c_cflag &= ~(CBAUD << IBSHIFT); + tios.c_cflag |= B0 << IBSHIFT; + tios.c_ispeed = inspeed; +#endif + baud_rate = inspeed; +#else + baud_rate = 0; +#endif + } + } + else { + speed = cfgetospeed(&tios); + baud_rate = baud_rate_of(speed); +#ifdef BOTHER + if (!baud_rate) + baud_rate = tios.c_ospeed; +#endif } + /* - * We can't proceed if the serial port speed is B0, + * We can't proceed if the serial port baud rate is unknown, * since that implies that the serial port is disabled. */ - else { - speed = cfgetospeed(&tios); - if (speed == B0) + if (!baud_rate) { + if (inspeed) + fatal("speed %d not supported", inspeed); + else fatal("Baud rate for %s is 0; need explicit baud rate", devnam); } while (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0 && !ok_error(errno)) if (errno != EINTR) fatal("tcsetattr: %m (line %d)", __LINE__); - - baud_rate = baud_rate_of(speed); restore_term = 1; } @@ -2824,133 +2875,143 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr) } #ifdef INET6 -static int append_peer_ipv6_address(unsigned int iface, struct in6_addr *local_addr, struct in6_addr *remote_addr) -{ - struct msghdr msg; - struct sockaddr_nl sa; +/******************************************************************** + * + * sif6addr_rtnetlink - Config the interface with both IPv6 link-local addresses via rtnetlink + */ +static int sif6addr_rtnetlink(unsigned int iface, eui64_t our_eui64, eui64_t his_eui64) +{ + struct { + struct nlmsghdr nlh; + struct ifaddrmsg ifa; + struct { + struct rtattr rta; + struct in6_addr addr; + } addrs[2]; + } nlreq; + struct { + struct nlmsghdr nlh; + struct nlmsgerr nlerr; + } nlresp; + struct sockaddr_nl nladdr; struct iovec iov; - struct nlmsghdr *nlmsg; - struct ifaddrmsg *ifa; - struct rtattr *local_rta; - struct rtattr *remote_rta; - char buf[NLMSG_LENGTH(sizeof(*ifa) + RTA_LENGTH(sizeof(*local_addr)) + RTA_LENGTH(sizeof(*remote_addr)))]; - ssize_t nlmsg_len; - struct nlmsgerr *errmsg; + struct msghdr msg; + ssize_t nlresplen; int one; int fd; fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (fd < 0) + if (fd < 0) { + error("sif6addr_rtnetlink: socket(NETLINK_ROUTE): %m (line %d)", __LINE__); return 0; + } - /* do not ask for error message content */ + /* + * Tell kernel to not send to us payload of acknowledgment error message. + * NETLINK_CAP_ACK option is supported since Linux kernel version 4.3 and + * older kernel versions always send full payload in acknowledgment netlink + * message. We ignore payload of this message as we need only error code, + * to check if our set remote peer address request succeeded or failed. + * So ignore return value from the following setsockopt() call as setting + * option NETLINK_CAP_ACK means for us just a kernel hint / optimization. + */ one = 1; setsockopt(fd, SOL_NETLINK, NETLINK_CAP_ACK, &one, sizeof(one)); - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - sa.nl_pid = 0; - sa.nl_groups = 0; + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; - if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + if (bind(fd, (struct sockaddr *)&nladdr, sizeof(nladdr)) < 0) { + error("sif6addr_rtnetlink: bind(AF_NETLINK): %m (line %d)", __LINE__); close(fd); return 0; } - memset(buf, 0, sizeof(buf)); - - nlmsg = (struct nlmsghdr *)buf; - nlmsg->nlmsg_len = NLMSG_LENGTH(sizeof(*ifa) + RTA_LENGTH(sizeof(*local_addr)) + RTA_LENGTH(sizeof(*remote_addr))); - nlmsg->nlmsg_type = RTM_NEWADDR; - nlmsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; - nlmsg->nlmsg_seq = 1; - nlmsg->nlmsg_pid = 0; - - ifa = NLMSG_DATA(nlmsg); - ifa->ifa_family = AF_INET6; - ifa->ifa_prefixlen = 128; - ifa->ifa_flags = 0; - ifa->ifa_scope = RT_SCOPE_UNIVERSE; - ifa->ifa_index = iface; - - local_rta = IFA_RTA(ifa); - local_rta->rta_len = RTA_LENGTH(sizeof(*local_addr)); - local_rta->rta_type = IFA_LOCAL; - memcpy(RTA_DATA(local_rta), local_addr, sizeof(*local_addr)); - - remote_rta = (struct rtattr *)((char *)local_rta + local_rta->rta_len); - remote_rta->rta_len = RTA_LENGTH(sizeof(*remote_addr)); - remote_rta->rta_type = IFA_ADDRESS; - memcpy(RTA_DATA(remote_rta), remote_addr, sizeof(*remote_addr)); - - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - sa.nl_pid = 0; - sa.nl_groups = 0; + memset(&nlreq, 0, sizeof(nlreq)); + nlreq.nlh.nlmsg_len = sizeof(nlreq); + nlreq.nlh.nlmsg_type = RTM_NEWADDR; + nlreq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE; + nlreq.ifa.ifa_family = AF_INET6; + nlreq.ifa.ifa_prefixlen = 128; + nlreq.ifa.ifa_flags = IFA_F_NODAD | IFA_F_PERMANENT; + nlreq.ifa.ifa_scope = RT_SCOPE_LINK; + nlreq.ifa.ifa_index = iface; + nlreq.addrs[0].rta.rta_len = sizeof(nlreq.addrs[0]); + nlreq.addrs[0].rta.rta_type = IFA_LOCAL; + IN6_LLADDR_FROM_EUI64(nlreq.addrs[0].addr, our_eui64); + nlreq.addrs[1].rta.rta_len = sizeof(nlreq.addrs[1]); + nlreq.addrs[1].rta.rta_type = IFA_ADDRESS; + IN6_LLADDR_FROM_EUI64(nlreq.addrs[1].addr, his_eui64); + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; memset(&iov, 0, sizeof(iov)); - iov.iov_base = nlmsg; - iov.iov_len = nlmsg->nlmsg_len; + iov.iov_base = &nlreq; + iov.iov_len = sizeof(nlreq); memset(&msg, 0, sizeof(msg)); - msg.msg_name = &sa; - msg.msg_namelen = sizeof(sa); + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; if (sendmsg(fd, &msg, 0) < 0) { + error("sif6addr_rtnetlink: sendmsg(RTM_NEWADDR/NLM_F_CREATE): %m (line %d)", __LINE__); close(fd); return 0; } memset(&iov, 0, sizeof(iov)); - iov.iov_base = buf; - iov.iov_len = sizeof(buf); + iov.iov_base = &nlresp; + iov.iov_len = sizeof(nlresp); memset(&msg, 0, sizeof(msg)); - msg.msg_name = NULL; - msg.msg_namelen = 0; + msg.msg_name = &nladdr; + msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - nlmsg_len = recvmsg(fd, &msg, 0); - close(fd); + nlresplen = recvmsg(fd, &msg, 0); - if (nlmsg_len < 0) + if (nlresplen < 0) { + error("sif6addr_rtnetlink: recvmsg(NLM_F_ACK): %m (line %d)", __LINE__); + close(fd); return 0; + } - if ((size_t)nlmsg_len < sizeof(*nlmsg)) { - errno = EINVAL; + close(fd); + + if (nladdr.nl_family != AF_NETLINK) { + error("sif6addr_rtnetlink: recvmsg(NLM_F_ACK): Not a netlink packet (line %d)", __LINE__); return 0; } - nlmsg = (struct nlmsghdr *)buf; + if ((size_t)nlresplen != sizeof(nlresp) || nlresp.nlh.nlmsg_len < sizeof(nlresp)) { + error("sif6addr_rtnetlink: recvmsg(NLM_F_ACK): Acknowledgment netlink packet too short (line %d)", __LINE__); + return 0; + } /* acknowledgment packet for NLM_F_ACK is NLMSG_ERROR */ - if (nlmsg->nlmsg_type != NLMSG_ERROR) { - errno = EINVAL; + if (nlresp.nlh.nlmsg_type != NLMSG_ERROR) { + error("sif6addr_rtnetlink: recvmsg(NLM_F_ACK): Not an acknowledgment netlink packet (line %d)", __LINE__); return 0; } - if ((size_t)nlmsg_len < NLMSG_LENGTH(sizeof(*errmsg))) { - errno = EINVAL; + /* error == 0 indicates success, negative value is errno code */ + if (nlresp.nlerr.error != 0) { + /* + * Linux kernel versions prior 3.11 do not support setting IPv6 peer + * addresses and error response is expected. On older kernel versions + * do not show this error message. On error pppd tries to fallback to + * the old IOCTL method. + */ + if (kernel_version >= KVERSION(3,11,0)) + error("sif6addr_rtnetlink: %s (line %d)", strerror(-nlresp.nlerr.error), __LINE__); return 0; } - errmsg = NLMSG_DATA(nlmsg); - - /* error == 0 indicates success */ - if (errmsg->error == 0) - return 1; - - errno = -errmsg->error; - return 0; + return 1; } /******************************************************************** @@ -2962,7 +3023,7 @@ int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) struct in6_ifreq ifr6; struct ifreq ifr; struct in6_rtmsg rt6; - struct in6_addr remote_addr; + int ret; if (sock6_fd < 0) { errno = -sock6_fd; @@ -2976,27 +3037,34 @@ int sif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) return 0; } - /* Local interface */ - memset(&ifr6, 0, sizeof(ifr6)); - IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64); - ifr6.ifr6_ifindex = ifr.ifr_ifindex; - ifr6.ifr6_prefixlen = 128; - - if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) { - error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__); - return 0; + if (kernel_version >= KVERSION(2,1,16)) { + /* Set both local address and remote peer address (with route for it) via rtnetlink */ + ret = sif6addr_rtnetlink(ifr.ifr_ifindex, our_eui64, his_eui64); + } else { + ret = 0; } - if (kernel_version >= KVERSION(2,1,16)) { - /* Set remote peer address (and route for it) */ - IN6_LLADDR_FROM_EUI64(remote_addr, his_eui64); - if (!append_peer_ipv6_address(ifr.ifr_ifindex, &ifr6.ifr6_addr, &remote_addr)) { - error("sif6addr: setting remote peer address failed: %m"); + /* + * Linux kernel versions prior 3.11 do not support setting IPv6 peer address + * via rtnetlink. So if sif6addr_rtnetlink() fails then try old IOCTL method. + */ + if (!ret) { + /* Local interface */ + memset(&ifr6, 0, sizeof(ifr6)); + IN6_LLADDR_FROM_EUI64(ifr6.ifr6_addr, our_eui64); + ifr6.ifr6_ifindex = ifr.ifr_ifindex; + ifr6.ifr6_prefixlen = 128; + + if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6) < 0) { + error("sif6addr: ioctl(SIOCSIFADDR): %m (line %d)", __LINE__); return 0; } - } - if (kernel_version < KVERSION(2,1,16)) { + /* + * Linux kernel does not provide AF_INET6 ioctl SIOCSIFDSTADDR for + * setting remote peer host address, so set only route to remote host. + */ + /* Route to remote host */ memset(&rt6, 0, sizeof(rt6)); IN6_LLADDR_FROM_EUI64(rt6.rtmsg_dst, his_eui64); @@ -3062,7 +3130,7 @@ int cif6addr (int unit, eui64_t our_eui64, eui64_t his_eui64) int get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid) { - int i, mfd, sfd = -1; + int i, mfd, ret, sfd = -1; char pty_name[16]; struct termios tios; @@ -3100,8 +3168,14 @@ get_pty(int *master_fdp, int *slave_fdp, char *slave_name, int uid) pty_name[5] = 't'; sfd = open(pty_name, O_RDWR | O_NOCTTY, 0); if (sfd >= 0) { - fchown(sfd, uid, -1); - fchmod(sfd, S_IRUSR | S_IWUSR); + ret = fchown(sfd, uid, -1); + if (ret != 0) { + warn("Couldn't change ownership of %s, %m", pty_name); + } + ret = fchmod(sfd, S_IRUSR | S_IWUSR); + if (ret != 0) { + warn("Couldn't change permissions of %s, %m", pty_name); + } break; } close(mfd); diff --git a/pppd/sys-solaris.c b/pppd/sys-solaris.c index 58ad21a..809b506 100644 --- a/pppd/sys-solaris.c +++ b/pppd/sys-solaris.c @@ -85,6 +85,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -127,6 +131,10 @@ #include #endif +#ifdef PPP_FILTER +#include +#endif + #include "pppd.h" #include "fsm.h" #include "lcp.h" @@ -1636,33 +1644,6 @@ get_ppp_stats(int u, struct pppd_stats *stats) return 1; } -#if 0 -/* - * set_filters - transfer the pass and active filters to the kernel. - */ -int -set_filters(struct bpf_program *pass, struct bpf_program *active) -{ - int ret = 1; - - if (pass->bf_len > 0) { - if (strioctl(pppfd, PPPIO_PASSFILT, pass, - sizeof(struct bpf_program), 0) < 0) { - error("Couldn't set pass-filter in kernel: %m"); - ret = 0; - } - } - if (active->bf_len > 0) { - if (strioctl(pppfd, PPPIO_ACTIVEFILT, active, - sizeof(struct bpf_program), 0) < 0) { - error("Couldn't set active-filter in kernel: %m"); - ret = 0; - } - } - return ret; -} -#endif - /* * ccp_fatal_error - returns 1 if decompression was disabled as a * result of an error detected after decompression of a packet, diff --git a/pppd/tdb.c b/pppd/tdb.c index bdc5828..8a563f8 100644 --- a/pppd/tdb.c +++ b/pppd/tdb.c @@ -46,6 +46,10 @@ * right time. Probably too hard -- the process just doesn't know. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/pppd/tdb.h b/pppd/tdb.h index 153b6e9..418bd8d 100644 --- a/pppd/tdb.h +++ b/pppd/tdb.h @@ -1,3 +1,5 @@ +#include "pppdconf.h" + #ifndef __TDB_H__ #define __TDB_H__ diff --git a/pppd/termios_linux.h b/pppd/termios_linux.h new file mode 100644 index 0000000..9c79d16 --- /dev/null +++ b/pppd/termios_linux.h @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-4-Clause OR BSD-3-Clause OR BSD-2-Clause */ +/* + * termios fuctions to support arbitrary baudrates (on Linux) + * + * Copyright (c) 2021 Pali Rohár + * Copyright (c) 2021 Marek Behún + */ + +#ifndef _TERMIOS_LINUX_H_ +#define _TERMIOS_LINUX_H_ + +/* + * We need to use raw TCGETS2/TCSETS2 or TCGETS/TCSETS ioctls with the BOTHER + * flag in struct termios2/termios, defined in Linux headers + * and . Since these headers conflict with glibc's header file + * , it is not possible to use libc's termios functions and we need + * to reimplement them via ioctl() calls. + * + * An arbitrary baudrate is supported when the macro BOTHER is defined. The + * baudrate value itself is then stored into the c_ospeed and c_ispeed members. + * If ioctls TCGETS2/TCSETS2 are defined and supported then these fields are + * present in struct termios2, otherwise these fields are present in struct + * termios. + * + * Note that the Bnnn constants from need not be compatible with + * Bnnn constants from . + */ + +#include +#include +#include +#include +#include + +#if defined(BOTHER) && defined(TCGETS2) +#define termios termios2 +#endif + +static inline int tcgetattr(int fd, struct termios *t) +{ +#if defined(BOTHER) && defined(TCGETS2) + return ioctl(fd, TCGETS2, t); +#else + return ioctl(fd, TCGETS, t); +#endif +} + +static inline int tcsetattr(int fd, int a, const struct termios *t) +{ + int cmd; + + switch (a) { +#if defined(BOTHER) && defined(TCGETS2) + case TCSANOW: + cmd = TCSETS2; + break; + case TCSADRAIN: + cmd = TCSETSW2; + break; + case TCSAFLUSH: + cmd = TCSETSF2; + break; +#else + case TCSANOW: + cmd = TCSETS; + break; + case TCSADRAIN: + cmd = TCSETSW; + break; + case TCSAFLUSH: + cmd = TCSETSF; + break; +#endif + default: + errno = EINVAL; + return -1; + } + + return ioctl(fd, cmd, t); +} + +static inline int tcdrain(int fd) +{ + return ioctl(fd, TCSBRK, 1); +} + +static inline int tcflush(int fd, int q) +{ + return ioctl(fd, TCFLSH, q); +} + +static inline int tcsendbreak(int fd, int d) +{ +#ifdef TCSBRKP + return ioctl(fd, TCSBRKP, d); +#else + return ioctl(fd, TCSBRK, 0); +#endif +} + +static inline int tcflow(int fd, int a) +{ + return ioctl(fd, TCXONC, a); +} + +static inline pid_t tcgetsid(int fd) +{ + pid_t sid; + + if (ioctl(fd, TIOCGSID, &sid) < 0) + return (pid_t)-1; + + return sid; +} + +static inline speed_t cfgetospeed(const struct termios *t) +{ + return t->c_cflag & CBAUD; +} + +static inline int cfsetospeed(struct termios *t, speed_t s) +{ + if (s & ~CBAUD) { + errno = EINVAL; + return -1; + } + + t->c_cflag &= ~CBAUD; + t->c_cflag |= s; + + return 0; +} + +#ifdef IBSHIFT +static inline speed_t cfgetispeed(const struct termios *t) +{ + speed_t s = (t->c_cflag >> IBSHIFT) & CBAUD; + + if (s == B0) + return cfgetospeed(t); + else + return s; +} + +static inline int cfsetispeed(struct termios *t, speed_t s) +{ + if (s == 0) + s = B0; + + if (s & ~CBAUD) { + errno = EINVAL; + return -1; + } + + t->c_cflag &= ~(CBAUD << IBSHIFT); + t->c_cflag |= s << IBSHIFT; + + return 0; +} +#else /* !IBSHIFT */ +static inline speed_t cfgetispeed(const struct termios *t) +{ + return cfgetospeed(t); +} + +static inline int cfsetispeed(struct termios *t, speed_t s) +{ + return cfsetospeed(t, s); +} +#endif /* !IBSHIFT */ + +static inline int cfsetspeed(struct termios *t, speed_t s) +{ + if (cfsetospeed(t, s)) + return -1; +#ifdef IBSHIFT + if (cfsetispeed(t, s)) + return -1; +#endif + + return 0; +} + +static void cfmakeraw(struct termios *t) +{ + t->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | + ICRNL | IXON); + t->c_oflag &= ~OPOST; + t->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + t->c_cflag &= ~(CSIZE | PARENB); + t->c_cflag |= CS8; +} + +#endif /* _TERMIOS_LINUX_H_ */ diff --git a/pppd/tls.c b/pppd/tls.c new file mode 100644 index 0000000..28c2e57 --- /dev/null +++ b/pppd/tls.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2021 Eivind Næss. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "pppd.h" +#include "tls.h" + +/** + * Structure used in verifying the peer certificate + */ +struct tls_info +{ + char *peer_name; + X509 *peer_cert; + bool client; +}; + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +/* + * OpenSSL 1.1+ introduced a generic TLS_method() + * For older releases we substitute the appropriate method + */ +#define TLS_method SSLv23_method + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, long tls_ver_max) +{ + long sslopt = 0; + + if (tls_ver_max < TLS1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_ver_max < TLS1_1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_ver_max < TLS1_2_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_set_options(ctx, sslopt); + + return 1; +} +#endif /* SSL_CTX_set_max_proto_version */ + +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + + +/* + * 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. + */ +static int tls_verify_callback(int ok, X509_STORE_CTX *ctx) +{ + char subject[256]; + char cn_str[256]; + X509 *peer_cert; + int err, depth; + SSL *ssl; + struct tls_info *inf; + char *ptr1 = NULL, *ptr2 = NULL; + + 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()); + + inf = (struct tls_info*) SSL_get_ex_data(ssl, 0); + if (inf == NULL) { + error("Error: SSL_get_ex_data returned NULL"); + return 0; + } + + tls_log_sslerr(); + + if (!depth) + { + /* Verify certificate based on certificate type and extended key usage */ + if (tls_verify_key_usage) { + int purpose = inf->client ? X509_PURPOSE_SSL_SERVER : X509_PURPOSE_SSL_CLIENT ; + if (X509_check_purpose(peer_cert, purpose, 0) == 0) { + error("Certificate verification error: nsCertType mismatch"); + return 0; + } + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + int flags = inf->client ? XKU_SSL_SERVER : XKU_SSL_CLIENT; + if (!(X509_get_extended_key_usage(peer_cert) & flags)) { + error("Certificate verification error: invalid extended key usage"); + return 0; + } +#endif + info("Certificate key usage: OK"); + } + + /* + * If acting as client and the name of the server wasn't specified + * explicitely, we can't verify the server authenticity + */ + if (!tls_verify_method) + tls_verify_method = TLS_VERIFY_NONE; + + if (!inf->peer_name || !strcmp(TLS_VERIFY_NONE, tls_verify_method)) { + warn("Certificate verication disabled or no peer name was specified"); + return ok; + } + + /* 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); + + /* Verify based on subject name */ + ptr1 = inf->peer_name; + if (!strcmp(TLS_VERIFY_SUBJECT, tls_verify_method)) { + ptr2 = subject; + } + + /* Verify based on common name (default) */ + if (strlen(tls_verify_method) == 0 || + !strcmp(TLS_VERIFY_NAME, tls_verify_method)) { + ptr2 = cn_str; + } + + /* Match the suffix of common name */ + if (!strcmp(TLS_VERIFY_SUFFIX, tls_verify_method)) { + int len = strlen(ptr1); + int off = strlen(cn_str) - len; + ptr2 = cn_str; + if (off > 0) { + ptr2 = cn_str + off; + } + } + + if (strcmp(ptr1, ptr2)) { + error("Certificate verification error: CN (%s) != %s", ptr1, ptr2); + return 0; + } + + if (inf->peer_cert) { + if (X509_cmp(inf->peer_cert, peer_cert) != 0) { + error("Peer certificate doesn't match stored certificate"); + return 0; + } + } + + info("Certificate CN: %s, peer name %s", cn_str, inf->peer_name); + } + + return ok; +} + +int tls_init() +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + SSL_library_init(); + SSL_load_error_strings(); +#endif + return 0; +} + +int tls_set_verify(SSL_CTX *ctx, int depth) +{ + SSL_CTX_set_verify_depth(ctx, depth); + SSL_CTX_set_verify(ctx, + SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + &tls_verify_callback); + return 0; +} + +int tls_set_verify_info(SSL *ssl, const char *peer_name, const char *peer_cert, + bool client, struct tls_info **out) +{ + if (out != NULL) { + struct tls_info *tmp = calloc(sizeof(struct tls_info), 1); + if (!tmp) { + fatal("Allocation error"); + } + + tmp->client = client; + if (peer_name) { + tmp->peer_name = strdup(peer_name); + } + + if (peer_cert && strlen(peer_cert) > 0) { + FILE *fp = fopen(peer_cert, "r"); + if (fp) { + tmp->peer_cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + } + + if (!tmp->peer_cert) { + error("EAP-TLS: Error loading client certificate from file %s", + peer_cert); + tls_free_verify_info(&tmp); + return -1; + } + } + + SSL_set_ex_data(ssl, 0, tmp); + *out = tmp; + return 0; + } + + return -1; +} + +void tls_free_verify_info(struct tls_info **in) { + if (in && *in) { + struct tls_info *tmp = *in; + if (tmp->peer_name) { + free(tmp->peer_name); + } + if (tmp->peer_cert) { + X509_free(tmp->peer_cert); + } + free(tmp); + *in = NULL; + } +} + +const SSL_METHOD* tls_method() { + return TLS_method(); +} + +int tls_set_version(SSL_CTX *ctx, const char *max_version) +{ +#if defined(TLS1_2_VERSION) + long tls_version = TLS1_2_VERSION; +#elif defined(TLS1_1_VERSION) + long tls_version = TLS1_1_VERSION; +#else + long tls_version = TLS1_VERSION; +#endif + + /* As EAP-TLS+TLSv1.3 is highly experimental we offer the user a chance to override */ + if (max_version) { + if (strncmp(max_version, "1.0", 3) == 0) { + tls_version = TLS1_VERSION; + } + else if (strncmp(max_version, "1.1", 3) == 0) { + tls_version = TLS1_1_VERSION; + } + else if (strncmp(max_version, "1.2", 3) == 0) { +#ifdef TLS1_2_VERSION + tls_version = TLS1_2_VERSION; +#else + warn("TLSv1.2 not available. Defaulting to TLSv1.1"); + tls_version = TLS_1_1_VERSION; +#endif + } + else if (strncmp(max_version, "1.3", 3) == 0) { +#ifdef TLS1_3_VERSION + tls_version = TLS1_3_VERSION; +#else + warn("TLSv1.3 not available."); +#endif + } + } + + dbglog("Setting max protocol version to 0x%X", tls_version); + if (!SSL_CTX_set_max_proto_version(ctx, tls_version)) { + error("Could not set max protocol version"); + return -1; + } + + return 0; +} + +int tls_set_opts(SSL_CTX *ctx) { + + /* Explicitly set the NO_TICKETS flag to support Win7/Win8 clients */ + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 +#ifdef SSL_OP_NO_TICKET + | SSL_OP_NO_TICKET +#endif + | SSL_OP_NO_COMPRESSION + ); + + /* OpenSSL 1.1.1+ does not include RC4 ciphers by default. + * This causes totally obsolete WinXP clients to fail. If you really + * need ppp+EAP-TLS+openssl 1.1.1+WinXP then enable RC4 cipers and + * make sure that you use an OpenSSL that supports them + + SSL_CTX_set_cipher_list(ctx, "RC4"); + */ + return 0; +} + +int tls_set_crl(SSL_CTX *ctx, const char *crl_dir, const char *crl_file) +{ + X509_STORE *certstore = NULL; + X509_LOOKUP *lookup = NULL; + FILE *fp = NULL; + int status = -1; + + if (crl_dir) { + if (!(certstore = SSL_CTX_get_cert_store(ctx))) { + error("Failed to get certificate store"); + goto done; + } + + if (!(lookup = + X509_STORE_add_lookup(certstore, X509_LOOKUP_hash_dir()))) { + error("Store lookup for CRL failed"); + goto done; + } + + X509_LOOKUP_add_dir(lookup, crl_dir, X509_FILETYPE_PEM); + X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); + } + + if (crl_file) { + X509_CRL *crl = NULL; + + fp = fopen(crl_file, "r"); + if (!fp) { + error("Cannot open CRL file '%s'", crl_file); + goto done; + } + + crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL); + if (!crl) { + error("Cannot read CRL file '%s'", crl_file); + goto done; + } + + if (!(certstore = SSL_CTX_get_cert_store(ctx))) { + error("Failed to get certificate store"); + goto done; + } + if (!X509_STORE_add_crl(certstore, crl)) { + error("Cannot add CRL to certificate store"); + goto done; + } + X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK); + } + + status = 0; + +done: + + if (fp != NULL) { + fclose(fp); + } + + return status; +} + +int tls_set_ca(SSL_CTX *ctx, const char *ca_dir, const char *ca_file) +{ + if (ca_file && strlen(ca_file) == 0) { + ca_file = NULL; + } + + if (ca_dir && strlen(ca_dir) == 0) { + ca_dir = NULL; + } + + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) { + + error("Cannot load verify locations"); + if (ca_file) { + dbglog("CA certificate file = [%s]", ca_file); + } + + if (ca_dir) { + dbglog("CA certificate path = [%s]", ca_dir); + } + + return -1; + } + + return 0; +} + +void tls_log_sslerr( 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(); + } +} + diff --git a/pppd/tls.h b/pppd/tls.h new file mode 100644 index 0000000..39fdef7 --- /dev/null +++ b/pppd/tls.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Eivind Næss. 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 TLS_H +#define TLS_H + +/** + * Structure used in verifying the peer certificate + */ +struct tls_info; + +/** + * Initialize the SSL library + */ +int tls_init(); + +/** + * Get the SSL_METHOD + */ +const SSL_METHOD* tls_method(); + +/** + * Configure the SSL options + */ +int tls_set_opts(SSL_CTX *ctx); + +/** + * Configure the SSL context's max TLS version + */ +int tls_set_version(SSL_CTX *ctx, const char *max_version); + +/** + * Configure the SSL context's verify callback + */ +int tls_set_verify(SSL_CTX *ctx, int depth); + +/** + * Configure the SSL verify information + */ +int tls_set_verify_info(SSL *ssl, const char *peer_name, const char *peer_cert_file, + bool client, struct tls_info **out); + +/** + * Free the tls_info structure and it's members + */ +void tls_free_verify_info(struct tls_info **in); + +/** + * Configure the SSL context's CRL details + */ +int tls_set_crl(SSL_CTX *ctx, const char *crl_dir, const char *crl_file); + +/** + * Configure the SSL context's CA verify locations + */ +int tls_set_ca(SSL_CTX *ctx, const char *ca_dir, const char *ca_file); + +/** + * Log all errors from ssl library + */ +void tls_log_sslerr( void ); + +#endif /* TLS_H */ diff --git a/pppd/tty.c b/pppd/tty.c index 852cee7..7e208ba 100644 --- a/pppd/tty.c +++ b/pppd/tty.c @@ -68,6 +68,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -905,7 +909,7 @@ open_socket(char *dest) static int start_charshunt(int ifd, int ofd) { - int cpid; + int cpid, ret; cpid = safe_fork(ifd, ofd, (log_to_fd >= 0? log_to_fd: 2)); if (cpid == -1) { @@ -919,10 +923,14 @@ start_charshunt(int ifd, int ofd) log_to_fd = -1; else if (log_to_fd >= 0) log_to_fd = 2; - setgid(getgid()); - setuid(uid); - if (getuid() != uid) - fatal("setuid failed"); + ret = setgid(getgid()); + if (ret != 0) { + fatal("setgid failed, %m"); + } + ret = setuid(uid); + if (ret != 0 || getuid() != uid) { + fatal("setuid failed, %m"); + } charshunt(0, 1, record_file); exit(0); } diff --git a/pppd/upap.c b/pppd/upap.c index 0ae0288..1fcff09 100644 --- a/pppd/upap.c +++ b/pppd/upap.c @@ -40,6 +40,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* * TODO: */ diff --git a/pppd/upap.h b/pppd/upap.h index 99b007f..709cd62 100644 --- a/pppd/upap.h +++ b/pppd/upap.h @@ -1,3 +1,5 @@ +#include "pppdconf.h" + /* * upap.h - User/Password Authentication Protocol definitions. * diff --git a/pppd/utils.c b/pppd/utils.c index 7228279..e75bb9c 100644 --- a/pppd/utils.c +++ b/pppd/utils.c @@ -28,6 +28,10 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -137,6 +141,7 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args) int c, i, n; int width, prec, fillch; int base, len, neg, quoted; + long lval = 0; unsigned long val = 0; char *str, *f, *buf0; unsigned char *p; @@ -202,11 +207,12 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args) c = *fmt++; switch (c) { case 'd': - val = va_arg(args, long); - if (val < 0) { + lval = va_arg(args, long); + if (lval < 0) { neg = 1; - val = -val; - } + val = -lval; + } else + val = lval; base = 10; break; case 'u': @@ -323,6 +329,7 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args) OUTCHAR(c); } continue; +#ifndef UNIT_TEST case 'P': /* print PPP packet */ bufinfo.ptr = buf; bufinfo.len = buflen + 1; @@ -332,6 +339,7 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args) buf = bufinfo.ptr; buflen = bufinfo.len - 1; continue; +#endif case 'B': p = va_arg(args, unsigned char *); for (n = prec; n > 0; --n) { @@ -426,6 +434,7 @@ log_packet(u_char *p, int len, char *prefix, int level) } #endif /* unused */ +#ifndef UNIT_TEST /* * format_packet - make a readable representation of a packet, * calling `printer(arg, format, ...)' to output it. @@ -471,6 +480,7 @@ format_packet(u_char *p, int len, printer_func printer, void *arg) else printer(arg, "%.*B", len, p); } +#endif /* UNIT_TEST */ /* * init_pr_log, end_pr_log - initialize and finish use of pr_log. @@ -597,6 +607,7 @@ logit(int level, char *fmt, va_list args) log_write(level, buf); } +#ifndef UNIT_TEST static void log_write(int level, char *buf) { @@ -611,6 +622,13 @@ log_write(int level, char *buf) log_to_fd = -1; } } +#else +static void +log_write(int level, char *buf) +{ + printf("<%d>: %s\n", level, buf); +} +#endif /* * fatal - log an error message and die horribly. @@ -625,7 +643,11 @@ fatal(char *fmt, ...) logit(LOG_ERR, fmt, pvar); va_end(pvar); +#ifndef UNIT_TEST die(1); /* as promised */ +#else + exit(-1); +#endif } /* @@ -729,6 +751,8 @@ dump_packet(const char *tag, unsigned char *p, int len) dbglog("%s %P", tag, p, len); } + +#ifndef UNIT_TEST /* * complete_read - read a full `count' bytes from fd, * unless end-of-file or an error other than EINTR is encountered. @@ -754,6 +778,7 @@ complete_read(int fd, void *buf, size_t count) } return done; } +#endif /* Procedures for locking the serial device using a lock file. */ #ifndef LOCK_DIR @@ -794,7 +819,7 @@ lock(char *dev) #else /* LOCKLIB */ char lock_buffer[12]; - int fd, pid, n; + int fd, pid, n, siz; #ifdef SVR4 struct stat sbuf; @@ -881,11 +906,16 @@ lock(char *dev) pid = getpid(); #ifndef LOCK_BINARY + siz = 11; slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); + n = write (fd, lock_buffer, siz); #else - write(fd, &pid, sizeof (pid)); + siz = sizeof (pid); + n = write(fd, &pid, siz); #endif + if (n != siz) { + error("Could not write pid to lock file when locking"); + } close(fd); return 0; @@ -909,7 +939,7 @@ relock(int pid) return -1; #else /* LOCKLIB */ - int fd; + int fd, n, siz; char lock_buffer[12]; if (lock_file[0] == 0) @@ -922,11 +952,16 @@ relock(int pid) } #ifndef LOCK_BINARY + siz = 11; slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); + n = write (fd, lock_buffer, siz); #else - write(fd, &pid, sizeof(pid)); + siz = sizeof(pid); + n = write(fd, &pid, siz); #endif /* LOCK_BINARY */ + if (n != siz) { + error("Could not write pid to lock file when locking"); + } close(fd); return 0; diff --git a/pppdump/Makefile.am b/pppdump/Makefile.am new file mode 100644 index 0000000..2df7e0e --- /dev/null +++ b/pppdump/Makefile.am @@ -0,0 +1,9 @@ +sbin_PROGRAMS = pppdump +dist_man8_MANS = pppdump.8 + +pppdump_SOURCES = pppdump.c bsd-comp.c deflate.c zlib.c +pppdump_CFLAGS = -I${top_srcdir}/include/net + +noinst_HEADERS = \ + ppp-comp.h \ + zlib.h diff --git a/pppdump/Makefile.linux b/pppdump/Makefile.linux deleted file mode 100644 index a94187f..0000000 --- a/pppdump/Makefile.linux +++ /dev/null @@ -1,25 +0,0 @@ -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -MANDIR = $(DESTDIR)/share/man/man8 - -CFLAGS = $(COPTS) -I../include/net -OBJS = pppdump.o bsd-comp.o deflate.o zlib.o - -INSTALL= install - -all: pppdump - -pppdump: $(OBJS) - $(CC) $(LDFLAGS) -o pppdump $(OBJS) - -clean: - rm -f pppdump $(OBJS) *~ - -install: - mkdir -p $(BINDIR) $(MANDIR) - $(INSTALL) -c pppdump $(BINDIR) - $(INSTALL) -c -m 444 pppdump.8 $(MANDIR) diff --git a/pppdump/Makefile.sol2 b/pppdump/Makefile.sol2 deleted file mode 100644 index e9196f6..0000000 --- a/pppdump/Makefile.sol2 +++ /dev/null @@ -1,21 +0,0 @@ -# -# pppdump Makefile for SVR4 systems -# $Id: Makefile.sol2,v 1.4 2002/09/07 05:15:25 carlsonj Exp $ -# - -include ../Makedefs.com - -CFLAGS= $(COPTS) -I../include/net -OBJS = pppdump.o bsd-comp.o deflate.o zlib.o - -all: pppdump - -pppdump: $(OBJS) - $(CC) -o pppdump $(OBJS) - -clean: - rm -f $(OBJS) pppdump *~ - -install: - $(INSTALL) -f $(BINDIR) pppdump - $(INSTALL) -m 444 -f $(MANDIR)/man8 pppdump.8 diff --git a/pppstats/Makefile.am b/pppstats/Makefile.am new file mode 100644 index 0000000..d7d74e0 --- /dev/null +++ b/pppstats/Makefile.am @@ -0,0 +1,14 @@ +sbin_PROGRAMS = pppstats +dist_man8_MANS = pppstats.8 + +pppstats_SOURCES = pppstats.c +pppstats_CFLAGS = +pppstats_CPPFLAGS = + +if LINUX +pppstats_CFLAGS += -I${top_srcdir}/include +endif + +if SUNOS +pppstats_CPPFLAGS += -DSTREAMS +endif diff --git a/pppstats/Makefile.linux b/pppstats/Makefile.linux deleted file mode 100644 index ddfe0cc..0000000 --- a/pppstats/Makefile.linux +++ /dev/null @@ -1,37 +0,0 @@ -# -# pppstats makefile -# -CROSS_COMPILE=@CROSS_COMPILE@ -CC=$(CROSS_COMPILE)@CC@ -COPTS=@CFLAGS@ - -DESTDIR = $(INSTROOT)@DESTDIR@ -BINDIR = $(DESTDIR)/sbin -MANDIR = $(DESTDIR)/share/man/man8 - -PPPSTATSRCS = pppstats.c -PPPSTATOBJS = pppstats.o - -COMPILE_FLAGS = -I../include -LIBS = - -INSTALL= install - -CFLAGS = $(COPTS) $(COMPILE_FLAGS) - -all: pppstats - -install: pppstats - -mkdir -p $(MANDIR) - $(INSTALL) -c pppstats $(BINDIR) - $(INSTALL) -c -m 444 pppstats.8 $(MANDIR) - -pppstats: $(PPPSTATSRCS) - $(CC) $(CFLAGS) $(LDFLAGS) -o pppstats pppstats.c $(LIBS) - -clean: - rm -f pppstats *~ #* core - -depend: - cpp -M $(CFLAGS) $(PPPSTATSRCS) >.depend -# makedepend $(CFLAGS) $(PPPSTATSRCS) diff --git a/pppstats/Makefile.sol2 b/pppstats/Makefile.sol2 deleted file mode 100644 index e0093a5..0000000 --- a/pppstats/Makefile.sol2 +++ /dev/null @@ -1,20 +0,0 @@ -# -# pppstats Makefile for SVR4 systems -# $Id: Makefile.sol2,v 1.10 2002/09/07 05:15:25 carlsonj Exp $ -# - -include ../Makedefs.com - -CFLAGS = -DSTREAMS -I../include $(COPTS) - -all: pppstats - -pppstats: pppstats.c - $(CC) $(CFLAGS) -o pppstats pppstats.c - -install: pppstats - $(INSTALL) -f $(BINDIR) pppstats - $(INSTALL) -m 444 -f $(MANDIR)/man8 pppstats.8 - -clean: - rm -f pppstats *~ core diff --git a/pppstats/pppstats.c b/pppstats/pppstats.c index 92ebc2a..cbea00b 100644 --- a/pppstats/pppstats.c +++ b/pppstats/pppstats.c @@ -235,7 +235,7 @@ strioctl(int fd, int cmd, char *ptr, int ilen, int olen) static void get_ppp_stats(struct ppp_stats *curp) { - if (strioctl(s, PPPIO_GETSTAT, curp, 0, sizeof(*curp)) < 0) { + if (strioctl(s, PPPIO_GETSTAT, (char*) curp, 0, sizeof(*curp)) < 0) { fprintf(stderr, "%s: ", progname); if (errno == EINVAL) fprintf(stderr, "kernel support missing\n"); @@ -248,7 +248,7 @@ get_ppp_stats(struct ppp_stats *curp) static void get_ppp_cstats(struct ppp_comp_stats *csp) { - if (strioctl(s, PPPIO_GETCSTAT, csp, 0, sizeof(*csp)) < 0) { + if (strioctl(s, PPPIO_GETCSTAT, (char*) csp, 0, sizeof(*csp)) < 0) { fprintf(stderr, "%s: ", progname); if (errno == ENOTTY) { fprintf(stderr, "no kernel compression support\n"); @@ -539,7 +539,7 @@ main(int argc, char *argv[]) perror(dev); exit(1); } - if (strioctl(s, PPPIO_ATTACH, &unit, sizeof(int), 0) < 0) { + if (strioctl(s, PPPIO_ATTACH, (char*) &unit, sizeof(int), 0) < 0) { fprintf(stderr, "%s: ppp%d is not available\n", progname, unit); exit(1); } diff --git a/sample/auth-down b/sample/auth-down new file mode 100644 index 0000000..edde65d --- /dev/null +++ b/sample/auth-down @@ -0,0 +1,17 @@ +#!/bin/sh +# +# A program or script which is executed after the remote system +# successfully authenticates itself. It is executed with the parameters +# +# + +# +# The environment is cleared before executing this script +# so the path must be reset +# +PATH=/usr/sbin:/sbin:/usr/bin:/bin +export PATH + +echo auth-down `date +'%y/%m/%d %T'` $* >> /var/log/pppstats + +# last line diff --git a/sample/auth-up b/sample/auth-up new file mode 100644 index 0000000..54722a3 --- /dev/null +++ b/sample/auth-up @@ -0,0 +1,17 @@ +#!/bin/sh +# +# A program or script which is executed after the remote system +# successfully authenticates itself. It is executed with the parameters +# +# + +# +# The environment is cleared before executing this script +# so the path must be reset +# +PATH=/usr/sbin:/sbin:/usr/bin:/bin +export PATH + +echo auth-up `date +'%y/%m/%d %T'` $* >> /var/log/pppstats + +# last line diff --git a/sample/ip-down b/sample/ip-down new file mode 100644 index 0000000..b771fb6 --- /dev/null +++ b/sample/ip-down @@ -0,0 +1,22 @@ +#!/bin/sh +# +# This script is run by the pppd _after_ the link is brought down. +# It should be used to delete routes, unset IP addresses etc. +# +# This script is called with the following arguments: +# Arg Name Example +# $1 Interface name ppp0 +# $2 The tty ttyS1 +# $3 The link speed 38400 +# $4 Local IP number 12.34.56.78 +# $5 Peer IP number 12.34.56.99 +# + +# +# The environment is cleared before executing this script +# so the path must be reset +# +PATH=/usr/sbin:/sbin:/usr/bin:/bin +export PATH + +# last line diff --git a/sample/ip-up b/sample/ip-up new file mode 100644 index 0000000..7ce7c8d --- /dev/null +++ b/sample/ip-up @@ -0,0 +1,23 @@ +#!/bin/sh +# +# This script is run by the pppd after the link is established. +# It should be used to add routes, set IP address, run the mailq +# etc. +# +# This script is called with the following arguments: +# Arg Name Example +# $1 Interface name ppp0 +# $2 The tty ttyS1 +# $3 The link speed 38400 +# $4 Local IP number 12.34.56.78 +# $5 Peer IP number 12.34.56.99 +# + +# +# The environment is cleared before executing this script +# so the path must be reset +# +PATH=/usr/sbin:/sbin:/usr/bin:/bin +export PATH + +# last line diff --git a/sample/options b/sample/options new file mode 100644 index 0000000..35852c5 --- /dev/null +++ b/sample/options @@ -0,0 +1,159 @@ +# /etc/ppp/options + +# The name of this server. Often, the FQDN is used here. +#name + +# Enforce the use of the hostname as the name of the local system for +# authentication purposes (overrides the name option). +usehostname + +# If no local IP address is given, pppd will use the first IP address +# that belongs to the local hostname. If "noipdefault" is given, this +# is disabled and the peer will have to supply an IP address. +noipdefault + +# With this option, pppd will accept the peer's idea of our local IP +# address, even if the local IP address was specified in an option. +#ipcp-accept-local + +# With this option, pppd will accept the peer's idea of its (remote) IP +# address, even if the remote IP address was specified in an option. +#ipcp-accept-remote + +# Specify which DNS Servers the incoming Win95 or WinNT Connection should use +# Two Servers can be remotely configured +#ms-dns 192.168.1.1 +#ms-dns 192.168.1.2 + +# Specify which WINS Servers the incoming connection Win95 or WinNT should use +#wins-addr 192.168.1.50 +#wins-addr 192.168.1.51 + +# enable this on a server that already has a permanent default route +#nodefaultroute + +# Default IPv6 route is automatically configured by kernel based on +# received ICMPv6 Router Advertisement packets. +# pppd should not touch default IPv6 route to prevent breaking IPv6 setup. +# Enabling defaultroute6 is needed only for broken IPv6 setup. +nodefaultroute6 + +# Run the executable or shell command specified after pppd has terminated +# the link. This script could, for example, issue commands to the modem +# to cause it to hang up if hardware modem control signals were not +# available. +# If mgetty is running, it will reset the modem anyway. So there is no need +# to do it here. +#disconnect "chat -- \d+++\d\c OK ath0 OK" + +# Increase debugging level (same as -d). The debug output is written +# to syslog LOG_LOCAL2. +debug + +# Enable debugging code in the kernel-level PPP driver. The argument n +# is a number which is the sum of the following values: 1 to enable +# general debug messages, 2 to request that the contents of received +# packets be printed, and 4 to request that the contents of transmitted +# packets be printed. +#kdebug n + +# Require the peer to authenticate itself before allowing network +# packets to be sent or received. +# Please do not disable this setting. It is expected to be standard in +# future releases of pppd. Use the call option (see manpage) to disable +# authentication for specific peers. +#auth + +# authentication can either be pap or chap. As most people only want to +# use pap, you can also disable chap: +#require-pap +#refuse-chap + +# Use hardware flow control (i.e. RTS/CTS) to control the flow of data +# on the serial port. +crtscts + +# Specifies that pppd should use a UUCP-style lock on the serial device +# to ensure exclusive access to the device. +lock + +# Use the modem control lines. +modem + +# async character map -- 32-bit hex; each bit is a character +# that needs to be escaped for pppd to receive it. 0x00000001 +# represents '\x01', and 0x80000000 represents '\x1f'. +# To allow pppd to work over a rlogin/telnet connection, ou should escape +# XON (^Q), XOFF (^S) and ^]: (The peer should use "escape ff".) +#asyncmap 200a0000 +asyncmap 0 + +# Specifies that certain characters should be escaped on transmission +# (regardless of whether the peer requests them to be escaped with its +# async control character map). The characters to be escaped are +# specified as a list of hex numbers separated by commas. Note that +# almost any character can be specified for the escape option, unlike +# the asyncmap option which only allows control characters to be +# specified. The characters which may not be escaped are those with hex +# values 0x20 - 0x3f or 0x5e. +#escape 11,13,ff + +# Set the MRU [Maximum Receive Unit] value to for negotiation. pppd +# will ask the peer to send packets of no more than bytes. The +# minimum MRU value is 128. The default MRU value is 1500. A value of +# 296 is recommended for slow links (40 bytes for TCP/IP header + 256 +# bytes of data). +#mru 542 + +# Set the MTU [Maximum Transmit Unit] value to . Unless the peer +# requests a smaller value via MRU negotiation, pppd will request that +# the kernel networking code send data packets of no more than n bytes +# through the PPP network interface. +#mtu + +# Set the interface netmask to , a 32 bit netmask in "decimal dot" +# notation (e.g. 255.255.255.0). +#netmask 255.255.255.0 + +# Don't fork to become a background process (otherwise pppd will do so +# if a serial device is specified). +nodetach + +# Set the assumed name of the remote system for authentication purposes +# to . +#remotename + +# Add an entry to this system's ARP [Address Resolution Protocol] +# table with the IP address of the peer and the Ethernet address of this +# system. {proxyarp,noproxyarp} +proxyarp + +# Use the system password database for authenticating the peer using +# PAP. Note: mgetty already provides this option. If this is specified +# then dialin from users using a script under Linux to fire up ppp wont work. +#login + +# If this option is given, pppd will send an LCP echo-request frame to +# the peer every n seconds. Under Linux, the echo-request is sent when +# no packets have been received from the peer for n seconds. Normally +# the peer should respond to the echo-request by sending an echo-reply. +# This option can be used with the lcp-echo-failure option to detect +# that the peer is no longer connected. +lcp-echo-interval 30 + +# If this option is given, pppd will presume the peer to be dead if n +# LCP echo-requests are sent without receiving a valid LCP echo-reply. +# If this happens, pppd will terminate the connection. Use of this +# option requires a non-zero value for the lcp-echo-interval parameter. +# This option can be used to enable pppd to terminate after the physical +# connection has been broken (e.g., the modem has hung up) in +# situations where no hardware modem control lines are available. +lcp-echo-failure 4 + +# Specifies that pppd should disconnect if the link is idle for n seconds. +idle 600 + +# Disable the IPXCP and IPX protocols. +noipx + +# ------ diff --git a/sample/options.ttyXX b/sample/options.ttyXX new file mode 100644 index 0000000..d4202f5 --- /dev/null +++ b/sample/options.ttyXX @@ -0,0 +1,14 @@ +# If you need to set up multiple serial lines then copy this file to +# options. for each tty with a modem on it. +# +# The options.tty file will assign an IP address to each PPP connection +# as it comes up. They must all be distinct! +# +# Example: +# options.ttyS1 for com2 under DOS. +# +# Edit the following line so that the first IP address +# mentioned is the ip address of the serial port while the second +# is the IP address of your host +# +hostname-s1:hostname diff --git a/sample/pap-secrets b/sample/pap-secrets new file mode 100644 index 0000000..098971b --- /dev/null +++ b/sample/pap-secrets @@ -0,0 +1,28 @@ +# Secrets for authentication using PAP +# client server secret IP addresses + +# OUTBOUND CONNECTIONS +# Here you should add your userid password to connect to your providers via +# pap. The * means that the password is to be used for ANY host you connect +# to. Thus you do not have to worry about the foreign machine name. Just +# replace password with your password. +# If you have different providers with different passwords then you better +# remove the following line. +#hostname * password + +# INBOUND CONNECTIONS +#client hostname 192.168.1.1 + +# If you add "auth login -chap +pap" to /etc/mgetty+sendfax/login.config, +# all users in /etc/passwd can use their password for pap-authentication. +# +# Every regular user can use PPP and has to use passwords from /etc/passwd +#* hostname "" +# UserIDs that cannot use PPP at all. Check your /etc/passwd and add any +# other accounts that should not be able to use pppd! Replace hostname +# with your local hostname. +#guest hostname "*" - +#master hostname "*" - +#root hostname "*" - +#support hostname "*" - +#stats hostname "*" - diff --git a/scripts/Makefile.am b/scripts/Makefile.am new file mode 100644 index 0000000..0fadd48 --- /dev/null +++ b/scripts/Makefile.am @@ -0,0 +1,32 @@ +EXTRA_CHATCHAT = \ + chatchat/chatchat.c \ + chatchat/README + +EXTRA_SCRIPTS = \ + autopppd \ + callback \ + chatchat \ + ip-down.local.add \ + ip-up.local.add \ + ipv6-down.sample \ + ipv6-up.sample \ + options-rsh-loc \ + options-rsh-rem \ + options-ssh-loc \ + options-ssh-rem \ + plog \ + poff \ + pon \ + pon.1 \ + ppp-off \ + ppp-on \ + ppp-on-dialer \ + ppp-on-rsh \ + ppp-on-ssh \ + README \ + redialer \ + secure-card + +EXTRA_DIST= \ + $(EXTRA_CHATCHAT) \ + $(EXTRA_SCRIPTS)