Richard Purdie [Fri, 8 Jan 2021 01:41:42 +0000 (01:41 +0000)]
pppd/Makefile.linux: Fix reproducibility issue with differing make versions (#234)
We were seeing reproducibility issues where one host would use the internal
logwtmp wrapper, another would use the one in libutil. The issue was that in
some cases the "\#include" was making it to CC, in others, "#include". The
issue seems to be related to shell escaping.
Eivind Næss [Mon, 4 Jan 2021 01:34:34 +0000 (17:34 -0800)]
pppd: Add support for EAP-MSCHAPv2 (client side) (#211)
* Adding EAP-MSCHAPv2 support #175
Implementation based on the RFC: draft-kamath-pppext-eap-mschapv2-02.
Adding support for MSCHAPv2 inside extensible authentication protocol (EAP).
Signed-off-by: Thomas Omerzu <thomas@omerzu.de>
* Removing empty "TODO" in comment section
Signed-off-by: Eivind Naess <eivnaes@yahoo.com>
* Add support for EAP-MSCHAPv2 #138
Rewrote the original patch to use the chap-new.c API for caching request/responses. Also incorporate feedback from @paulusmack for input validation and function signatures.
pali [Sun, 3 Jan 2021 23:01:44 +0000 (00:01 +0100)]
pppd: Fix setting IPv6 peer address (#212)
On Linux IPv6 peer address cannot be set via SIOCSIFDSTADDR ioctl like it
is for IPv4 peer address. Linux kernel does not support SIOCSIFDSTADDR for
AF_INET6 PPP interfaces.
The only way how to set IPv6 peer address on Linux is via kernel netlink
interface which is just a little bit complicated compared to one ioctl
call.
Linux kernel for a long time automatically adds IPv6 peer address from
interface into route table so it is not needed to explicitly set routing
for remote peer address. pppd already does not do it for kernel versions
newer than 2.1.16. So the same check is used also for IPv6 peer route
address.
Prior this patch ppp interface was configured as:
$ ip -6 address show dev ppp0
2: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 3
inet6 fe80::2/128 scope link
valid_lft forever preferred_lft forever
$ ip -6 route show dev ppp0
fe80::1 metric 1 pref medium
fe80::2 proto kernel metric 256 pref medium
And after applying this patch as:
$ ip -6 address show dev ppp0
2: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 3
inet6 fe80::2 peer fe80::1/128 scope link
valid_lft forever preferred_lft forever
$ ip -6 route show dev ppp0
fe80::1 proto kernel metric 256 pref medium
fe80::2 proto kernel metric 256 pref medium
As can be seen IPv6 peer address is now correctly set on the interface and
also kernel correctly fill route table for IPv6 peer address.
Please note that old ifconfig utility cannot show nor change IPv6 peer
address. Peer address is supported only for IPv4 addresses as opposite of
the local addresses where both IPv4 and IPv6 are supported. It is because
old ifconfig utility is also using ioctl interface which cannot handle it.
Therefore for any testing it is really required ip utility or other utility
with netlink interface (and not ioctl interface).
Samuel Thibault [Sat, 2 Jan 2021 03:25:48 +0000 (04:25 +0100)]
pppd: Add replacedefaultroute option (#200)
Adds an option to pppd to control whether to replace existing default routes
when using the 'defaultroute' option.
If defaultroute and replacedefaultroute are both set, pppd replaces an existing
default route with the new default route. The old default route is restored when
the connection is taken down.
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Co-authored-by: Chris Boot <bootc@debian.org>
pali [Fri, 1 Jan 2021 08:58:02 +0000 (09:58 +0100)]
pppd: Fix ether_to_eui64() to prefer devnam ether interface (#206)
In case of PPPoE connection, devnam is ethernet interface. So in this case
calculate EUI-64 IPV6CP identifier from the PPPoE ethernet interface
instead from the first ethernet interface in the system.
This would ensure that each PPPoE connection would have unique IPv6 link
local address calculated from the interface MAC address on which is PPPoE
going to be established.
Currently IPv6 link local address is always calculated from the MAC address
of the first ethernet interface and therefore all active PPPoE connections
have by default same (non unique) IPv6 link local address.
These get propagated to the Makefiles in the subdirectories. The
cross-compile prefix is prepended to the CC value, so for example
if you do "./configure --cross_compile=powerpc64le-linux-" then
everything gets compiled and linked using powerpc64le-linux-cc.
Paul Mackerras [Fri, 1 Jan 2021 00:26:48 +0000 (11:26 +1100)]
pppd: Use a run-time test to detect libutil availability on Linux
This tests whether logwtmp is declared in <utmp.h>, and if not we
assume we need to include our own logwtmp implementation. We assume
that if logwtmp is provided by the system then we need -lutil to get
it (as is the case for glibc).
This fixes compilation with musl libc and other libcs that don't
provide logwtmp.
Pali Rohár [Thu, 31 Dec 2020 17:49:27 +0000 (18:49 +0100)]
Make a consistency in pppoe options
Remove 'rp_' prefix from all pppoe options and ensure that pppoe options
have 'pppoe-' prefix. Also change underlines to dashes to be consistent
with other pppd options.
To not break a backward compatibility ensure that old option names still
work via (legacy) aliases.
Now when get_first_ethernet() is implemented for both Linux and Solaris,
implementation of ether_to_eui64() function can use this function
get_first_ethernet() and therefore be system independent.
So change implementation of ether_to_eui64() to use get_first_ethernet()
function and move it from Linux and Solaris files to common ipv6cp.c file
where it is used.
Pali Rohár [Thu, 31 Dec 2020 17:46:01 +0000 (18:46 +0100)]
Rename rp-pppoe.so plugin to pppoe.so
Original out-of-tree rp-pppoe plugin for pppd software is still available
at website https://dianne.skoll.ca/projects/rp-pppoe/ and receives new
releases. The last update is from the June 2020.
Currently it is ambiguous if user is using original out-of-tree rp-pppoe
plugin or in-tree pppd's rp-pppoe plugin. These two plugins are different,
come from different sources but share same name.
Some users want to use original rp-pppoe plugin and not pppd's in-tree
rp-pppoe plugin. Also some distribution want to package both plugins,
pppd's in-tree and original rp-pppoe.
So for this reason and also because all other PPP over <something> plugins
have just pppo prefix, rename in-tree rp-pppoe.so plugin to just pppoe.so.
This will allow to distinguish and make it clear what is the original
rp-pppoe plugin and what is pppd's in-tree pppoe plugin.
When installing pppd create a compatibility symlink from pppoe.so to
rp-pppoe.so so nothing would be broken. This compatibility symlink may be
removed by Linux distribution which do not want to have compatibility with
the old name as before and rather use rp-pppoe.so name for original
rp-pppoe software.
Samuel Thibault [Thu, 31 Dec 2020 05:35:24 +0000 (06:35 +0100)]
pppd: Use a compile test to detect crypt.h (#198)
ppp checks header for existence of crypt.h looking it up in /usr/include.
That's incompatible with non-glibcs or a glibc with multiarch headers
(https://bugs.debian.org/798955). This patch replaces the file existence
test with a compile test.
Reviewed-by: Chris Boot <bootc@debian.org> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Co-authored-by: Helmut Grohne <helmut@subdivi.de>
cc -o pppdump pppdump.o deflate.o bsd-comp.o -lz
/usr/bin/ld: deflate.o: in function `z_incomp':
deflate.c:(.text+0x99): undefined reference to `inflateIncomp'
/usr/bin/ld: deflate.o: in function `z_decomp_alloc':
deflate.c:(.text+0x355): undefined reference to `inflateInit2'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:38: pppdump] Error 1
The copy of zlib here is not the same as the standard upstream zlib;
this version has some extra functions added.
Samuel Thibault [Thu, 31 Dec 2020 04:30:58 +0000 (05:30 +0100)]
pppd: Make sure that the linkpidfile is always created (#185)
From https://bugs.debian.org/284382
When pppd detaches from the parent normally, that is, without nodetach
or updetach set, the linkpidfile is not created even when linkname is
set.
This is because the create_linkpidfile call in detach() is only made
if the linkpidfile is filled in. However, linkpidfile is never filled
in until create_linkpidfile has been called.
IMHO the call should be made uncondtionally in detach() since
create_linkpidfile does its own check on linkname anyway.
Please note that the version of pppd in woody always wrote the
linkpidfile after detaching. It did so in main() however. That
call has now been removed which is why I'm seeing this problem.
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Co-authored-by: Herbert Xu <herbert@gondor.apana.org.au>
Samuel Thibault [Thu, 31 Dec 2020 04:28:19 +0000 (05:28 +0100)]
pppd: Be sure to close /dev/ppp when reconnecting (#184)
From https://bugs.debian.org/306261
When using the kernel PPPoE driver, pppd never
closes /dev/ppp when the link has come down.
It opens superfluous fds to the device each time it re-opens the
connection, with the unclosed ones falsely reported always ready for
data by select().
This makes pppd eat up 100% CPU time after the first persist because of
the always instantly returning select() on the unclosed fds.
The problem also occurs with the upstream version, but does not occur
when a pty/tty device is used for the ppp connection.
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Co-authored-by: Simon Peter <dn.tlp@gmx.net>
This implements EAP-MSCHAPv2 as specified by
draft-kamath-pppext-eap-mschapv2-02 [1] in server mode (as the client
mode is already proposed by Thomas [2]).
The flow is camparable to MD5-Challenge, with some additional steps for
confirmation:
* Client sends an EAP request
* Server answers with MD5-Challenge
* Client Naks and requests MSCHAPv2
* Server answers with MSCHAPv2-Challenge
* Client answers with MSCHAPv2-Response
* Server answers with MSCHAPv2-{Success/Failure}
* Client possibly confirms MSCHAPv2-{Success/Failure}
I reused as much as possible from pppd/chap-new.c and pppd/chap_ms.c,
but most of the implementation is protected by static functions.
Therefore eap_chapms2_verify_response is an exact copy of
chapms2_verify_response, likewise for eap_chap_verify which is an exact
copy of chap_verify_response. This is not optimal and subject for
improvement.
By using a chap_digest_type struct/object with validator
(verify_response), validation is compatible with other (external)
plugins that have a specific CHAP implementation exposed in the
chap_verify_hook (like radius, windbind, ...).
Changes in eap.h are identical to [2], except for the additional
eapMSCHAPv2Chall server state.
Duncan Sands [Wed, 30 Dec 2020 11:22:50 +0000 (12:22 +0100)]
Fix pppoatm plugin for pppd to accept a wildcard argument for an ATM device
From https://bugs.debian.org/376990
This becomes an issue when using a USB ADSL modem (e.g. Alcatel Speedtouch)
and the USB host controller disconnects the modem, then later re-connects it
with a new USB address and consequently a new ATM device number.
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Paul Mackerras [Tue, 29 Dec 2020 05:08:24 +0000 (16:08 +1100)]
Convert to ANSI C
This gets rid of the __P and __V macros that were used so that the
code was in theory compilable by a K&R C compiler, and converts the
function definitions to ANSI C style. In fact there were already
quite a few function definitions in the ANSI C style, so it would not
have been compilable by a K&R C compiler in fact.
The Solaris and BSD kernel code modules have had __P removed but the
function definitions have not been converted.
There are some other minor changes here to remove warnings.
Xing Qingjie [Thu, 26 Nov 2020 11:09:38 +0000 (06:09 -0500)]
Close discovery socket after session completed
After the session is complete, the socket is left unmanaged. When the
interface receives PADIs from other device, the packets is putting
in the socket's Recv-Q, which eat system memory.
[root@test ~]# ss -f link
Netid Recv-Q Send-Q Local Address:Port Peer Address:Port
p_raw 10269952 0 ppp_disc:eth1 *
Simon Tate [Sat, 12 Sep 2020 20:13:26 +0000 (21:13 +0100)]
pppd: Fix blank password usage
If a password has been provided as "", CHAP authentication wouldn't
happen. A user providing a username/password, even if blank, should be
expecting authentication to occur with those set.
Added a check for explicit_passwd property, set on finding the password
argument, to allow CHAP authentication with a blank password.
Pali Rohár [Fri, 7 Aug 2020 07:55:04 +0000 (09:55 +0200)]
Fix setting prefix for IPv6 link-local addresss
PPP IPV6CP protocol exchanges only IPv6 Interface Identifiers which are
used for generating IPv6 link-local addresses. As on PPP link cannot be
more hosts and IPv6 link-local addresses are designed for addressing a
single link, set route prefix for local and remote IPv6 link-local
addresses to /128 which means single IPv6 address.
This ensures that Linux kernel would not try to route other IPv6 link-local
addresses over PPP link.
Routable IPv6 prefix on PPP link is later configured either by ICMPv6
Router Advertisement packets or manually/statically. Routable local IPv6
address is then assigned by SLAAC, DHCPv6 or manual/static configuration.
So this change has no effect for routable IPv6 address or routable IPv6
prefix.
Note that pppd for IPv4 already sets netmask to 255.255.255.255, one single
IPv4 address.
Simon Arlott [Sat, 4 Jul 2015 16:32:18 +0000 (17:32 +0100)]
pppd: Add client CHAP authentication timeout
If CHAP authentication is required with the peer but this is never
completed (either because the server never sends the challenge or
because the client doesn't receive the outcome) then the client
will wait forever, relying on the server to terminate the connection.
There are options for server side retries but a client side timeout
option is required to prevent the client from getting stuck if the
server won't terminate the connection. This is defaulted to 60 seconds.
Marco d'Itri [Sat, 4 Apr 2020 17:10:47 +0000 (19:10 +0200)]
pppd: Add lcp-echo-adaptive option
This adds an option that has been added by Debian and other distros
for a while now.
When adaptive LCP echo is enabled, LCP echo requests are only sent if the
link is idle, avoiding the common situation where a congested PPP link
(e.g. during torrenting) is falsely detected as disconnected because the
LCP replies are not received in time.
gettimeofday() suffers from time jumps due ntp or any manual change,
so duration measurements and scheduling can not be accurate.
let's use monotonic time source instead, if available.
it's known glibc (< 2.3.4) & old uclibc don't provide CLOCK_MONOTONIC
denine, but kernel may have it supported. so, use clock_gettime()
with fallback to gettimeofday() if first call has failed.
several gettimeofday()/time() calls still have to be preserved for
debug, pseudoterminal timestamping and string formatting. all the
rest calls are replaced to new get_time() call.
solaris kept with gettimeofday() as before, corresponding get_time()
system implementation can be updated/added in any future.
Paul Mackerras [Sat, 21 Mar 2020 04:13:42 +0000 (15:13 +1100)]
pppd: Obfuscate password argument string
After processing the argument to the 'password' option, this
overwrites the original argument on the stack with '?' characters,
and for good measure makes the argument pointer point to a constant
string "********" so as not to reveal the length of the password.
This is so that tools such as ps don't show the actual password
when displaying the process arguments. Nevertheless, it is still
better to get the password from a file, since there is inevitably
still a window of time when the password would be visible.
Paul Mackerras [Mon, 3 Feb 2020 05:31:42 +0000 (16:31 +1100)]
pppd: Ignore received EAP messages when not doing EAP
This adds some basic checks to the subroutines of eap_input to check
that we have requested or agreed to doing EAP authentication before
doing any processing on the received packet. The motivation is to
make it harder for a malicious peer to disrupt the operation of pppd
by sending unsolicited EAP packets. Note that eap_success() already
has a check that the EAP client state is reasonable, and does nothing
(apart from possibly printing a debug message) if not.
Paul Mackerras [Mon, 3 Feb 2020 04:53:28 +0000 (15:53 +1100)]
pppd: Fix bounds check in EAP code
Given that we have just checked vallen < len, it can never be the case
that vallen >= len + sizeof(rhostname). This fixes the check so we
actually avoid overflowing the rhostname array.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Paul Mackerras [Sat, 4 Jan 2020 01:01:32 +0000 (12:01 +1100)]
radius: Prevent buffer overflow in rc_mksid()
On some systems getpid() can return a value greater than 65535.
Increase the size of buf[] to allow for this, and use slprintf()
to make sure we never overflow it.
Paul Mackerras [Tue, 31 Dec 2019 00:12:07 +0000 (11:12 +1100)]
pppd: Avoid use of strnlen (and strlen) in vslprintf
Commit b311e98b ("pppd: Limit memory accessed by string formats with
max length specified") added calls to strnlen() in vslprintf().
Unfortunately, strnlen() is not provided in some standard C libraries.
This changes the code to avoid using strnlen(). Using the observation
that the number of characters we can use from the input string is
bounded by buflen, the number of bytes of output buffer available,
we can also avoid doing strlen() on a potentially long string.