summaryrefslogtreecommitdiff
path: root/accel-pppd
AgeCommit message (Collapse)Author
2018-12-08iprange: rework range parsing using u_parse_*() functionsGuillaume Nault
Now that we have primitives for parsing IPv4 ranges, let's use them to simplify parse_iprange(). Try u_parse_ip4cidr() first. In case of failure, try u_parse_ip4range(). If any of them succeeds, verify that there aren't spurious data following the range definition. If everything is valid, either load the range or disable the module (if the range is 0.0.0.0/0). The diff is a bit ugly, but the implementation should be much clearer. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-08utils: add IPv4 string parsing helpersGuillaume Nault
Define the IPv4 counterparts of u_ip6str() and u_parse_ip6cidr(). Also add the special u_parse_ip4range() which will be useful for parsing the [client-ip-range] section of accel-ppp.conf. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-08utils: rework u_parse_ip4addr()Guillaume Nault
Redefine u_parse_ip4addr() to match the behaviour of other u_parse_*() functions: * Drop the err_msg parameter. * Return the number of bytes parsed instead of an error number. * Remove support for fancy IPv4 address notations. There is currently only one user of u_parse_ip4addr() (in iprange.c). Dropping the fancy IPv4 address representations is probably not going to harm anyone (quite the opposite as many users don't realise that leading 0 means octal and that plain integers can be considered IPv4 addresses). Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-08utils: fix typo in description of u_parse_endstr()Guillaume Nault
u_parse_endstr() used to be u_parse_eos() in my internal repository. I forgot to update the documentation when I renamed it. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-04radius: implement Framed-IPv6-Route attributeGuillaume Nault
Framed-IPv6-Route is the IPv6 counterpart of Framed-Route. It's only used for defining routes to be added locally by accel-ppp. Routes that should be announced to the peer using Router Advertisements should be defined in the Route-IPv6-Information attribute (but that's currently not implemented). Framed-IPv6-Route format is: <network in CIDR notation> [<gateway IPv6 address> [<route metric>]] The gateway address and the route metric are optionals, but the metric can only be set if a gateway address is given. One can use the unspecified address '::' to define a route with no gateway and a non-default route metric. When no gateway address is defined, the session's network interface is used directly. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-04utils: add string parsing helpersGuillaume Nault
Define parsers for IPv6 addresses and CIDR notations, unsigned integers, separators (variable number of space characters) and end of strings (variable number of spaces followed by '\0'). All of these functions work on constant string and return the number bytes parsed. If the input string doesn't have the expected format, these functions return 0 (no forward progress). Also implement a convenient wrapper around inet_ntop() that can be used easily in printf-like functions. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-12-04libnetlink: add gateway and priority parameters to ip6route_*()Guillaume Nault
Let callers set a gateway and a priority to IPv6 routes. This is necessary for implementing the RADIUS Framed-IPv6-Route attribute. Also let ip6route_del() configure .rtm_protocol. This is already implemented in ip6route_add(), so we need to add the ip6route_del() counterpart. Otherwise, we couldn't delete routes that were added using a non-zero protocol. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-27ppp: use random LCP (and NCP) identifiersGuillaume Nault
In DSL setups, it's common to have an intermediate equipment, potentially managed by a different operator, between the two PPP endpoints. In such setups, the client establishes a PPPoE or L2TP session with the intermediate equipment. They perform LCP negotiation and eventually get to the authentication phase. Based on the client's username, the intermediate equipment then establishes another L2TP session with the final PPP endpoint (accel-ppp). At this point, the intermediate equipment forwards any PPP frame received on one side to the other side, so that it becomes transparent to PPP frames. Then accel-ppp starts an LCP negotiation again, performs authentication, negotiates NCPs and finally forwards IP packets to and from the client. +--------+ +--------------+ +-----------+ | Client |------------------------| Intermediate |--------------------| accel-ppp | | | | equipment | | | +--------+ +--------------+ +-----------+ <-- First hop PPPoE --> <-- Second hop --> or L2TP session L2TP session <----------------- End to end PPP session -----------------> Therefore, from the client point of view, two LCP negotiations occur. LCP re-negotiation is explicitly handled by RFC 1661 and even non-conforming PPP clients generally cope with this situation well enough (as long as LCP re-negotiation occurs before the authentication phase completes). However, accel-ppp always starts its LCP negotiation with an identifier set to 1. If the previous LCP negotiation also used identifier 1, then some clients (at least MikroTik products) consider that the Configure-Request sent by accel-ppp is part of the previous LCP negotiation and refuse to return to link establishment phase as mandated by section 3.4 of RFC 1661. We can easily work around this problem by using random identifiers. This maximises the chances that accel-ppp picks a different identifier than the intermediate equipment and avoids falling into the MikroTik problem. In case of bad luck and the chosen identifier is the same as the one used for the original LCP negotiation, then PPP establishment fails and the client tries to reconnect until the intermediate equipment and accel-ppp pick up different numbers. So the connection eventually succeeds. The identifier is set in ppp_fsm_init(), so it also affects NCPs. Therefore, IPCP and IPv6CP now also use random identifiers. We need to define 'id' and 'recv_id' in struct ppp_fsm_t as uint8_t, otherwise they could be chosen larger than 255 and comparing their value with the 8-bits values found in received packets would fail (this was generally not a problem when id was initially set to 1 and wouldn't grow much). Also, let's seed random() at startup, so that we don't end up with the same sequences across restarts. This also benefits other users of random(), like LCP magic numbers. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-27auth: remove .recv_conf_req from struct ppp_auth_handler_tGuillaume Nault
This callback isn't used anymore. Let's remove it from all authentication backends. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-27lcp: reject Authentication-Protocol option in Configure-Request packetsGuillaume Nault
If we receive a Configure-Request packet, that means the peer wants us to authenticate to him. However, none of our authentication backends (PAP, CHAP and MSCHAP v1/v2) supports authenticating ourself to the peer. Therefore, the LCP negotiation completes, but we hang in the authentication phase because accel-ppp never sends any credential. We should reject the Authentication-Protocol option found in Configure-Request packets sent by the peer. This way, the peer knows that we won't authenticate to him. Then it's up to him to keep connecting without authentication from our side or to drop the connection. This doesn't change the way we request the peer to authenticate to us. That part of the negotiation is handled by Configure-Request packets that are sent by us (not those sent by the peer). In practice some PPP clients wouldn't connect with the previous behaviour, but are perfectly happy with their Authentication-Protocol option being rejected. They just resend their Configure-Request without requesting authentication from our side. Also, since the peer_auth field of struct auth_option_t is never set anymore, we can remove the conditionals in auth_recv_conf_nak() and auth_recv_conf_rej(). Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-16Remove redundant openssl includeGuillaume Nault
The openssl/ssl.h header file is already included at the beginning of this file. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-16Add --no-sigsegv option to accel-pppdGuillaume Nault
It's often useful to let a program crash on SIGSEGV and let an external daemon, like monit or systemd, restart it when needed. This allows to generate core dumps and do post-mortem analysis based on the collected traces. This patch add the new '--no-sigsegv' option to disable accel-ppp's SIGSEGV handler and use the system's core(5) mechanism instead. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-16Don't wait for non-blocked signalsGuillaume Nault
SIGSEGV, SIGILL, SIGFPE and SIGBUS aren't blocked, but they're added to the set of signals passed to sigwait(). This is confusing (should these signals be consumed by sigwait() or by their respective signal handler?) and is undefined according to the POSIX man page (http://man7.org/linux/man-pages/man3/sigwait.3p.html). In practice, sigwait() was only triggered when manually sending the signals to accel-pppd ("pkill -FPE accel-pppd"). On normal circumstances though, these signals are triggered by invalid operations run by the program. In these cases the signal handler was run and sigwait() wasn't woken up. So let's remove SIGSEGV, SIGILL, SIGFPE and SIGBUS from the set passed to sigwait(). This simplifies the code, avoids undefined behaviour and doesn't change accel-ppp behaviour for real-world use cases. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-12ipcp: reject *-NBNS-Address if we have no value to proposeGuillaume Nault
If wins_opt->addr is NULL, then we have no address to propose (none defined in accel-ppp.conf and none provided by RADIUS). Currently, in that case, accel-ppp accepts and acks the address found in the peer's configuration request. But the peer would normally use the undefined IP address, so if we ack it, we explicitely tell the peer that 0.0.0.0 is the primary/secondary NBNS server. If the peer already knows a NBNS server IP address, it doesn't have to negociate it with accel-ppp. It can just use it directly, after it retrieved its own IP address. Therefore there is no need for accel-ppp to blindly accept addresses proposed by the peer. This patch rejects *-NBNS-Address if accel-ppp has no NBNS server to propose, making it explicit to the peer that its request can't be satisfied. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-12ipcp: fix uninitialised memory access when negociating *-NBNS-AddressGuillaume Nault
When handling the EV_WINS event, IPCP assumes that the ->wins1 and ->wins2 fields of the event structure are properly set. But that may not be the case. If only one of the MS-Primary-NBNS-Server or MS-Secondary-NBNS-Server RADIUS attributes was received, then only ->wins1 or ->wins2 is set, while the other keeps a non initialised value. This uninitialised value is then copied by ev_wins() and proposed to the peer when negociating the Primary-NBNS-Address or Secondary-NBNS-Address IPCP options. That leaks four bytes of the stack to the network and prevents using the values found in the [wins] section of accel-ppp.conf as fallback. Fix this by initialising the whole event structure in rad_proc_attrs(). Then, in ev_wins(), we can check if ->wins1 or ->wins2 is properly set before copying them. That allows to propery fallback to accel-ppp.conf values when one of the values was not provided by RADIUS. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-12ipcp: reject *-DNS-Address if we have no value to proposeGuillaume Nault
If dns_opt->addr is NULL, then we have no address to propose (none defined in accel-ppp.conf and none provided by RADIUS). Currently, in that case, accel-ppp accepts and acks the address found in the peer's configuration request. But the peer would normally use the undefined IP address, so if we ack it, we explicitely tell the peer that 0.0.0.0 is the primary/secondary DNS server. If the peer already knows a DNS server IP address, it doesn't have to negociate it with accel-ppp. It can just use it directly, after it retrieved its own IP address. Therefore there is no need for accel-ppp to blindly accept addresses proposed by the peer. This patch rejects *-DNS-Address if accel-ppp has no DNS server to propose, making it explicit to the peer that its request can't be satisfied. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-12ipcp: fix uninitialised memory access when negociating *-DNS-AddressGuillaume Nault
When handling the EV_DNS event, IPCP assumes that the ->dns1 and ->dns2 fields of the event structure are properly set. But that may not be the case. If only one of the MS-Primary-DNS-Server or MS-Secondary-DNS-Server RADIUS attributes was received, then only ->dns1 or ->dns2 is set, while the other keeps a non initialised value. This uninitialised value is then copied by ev_dns() and proposed to the peer when negociating the Primary-DNS-Address or Secondary-DNS-Address IPCP options. That leaks four bytes of the stack to the network and prevents using the values found in the [dns] section of accel-ppp.conf as fallback. Fix this by initialising the whole event structure in rad_proc_attrs(). Then, in ev_dns(), we can check if ->dns1 or ->dns2 is properly set before copying them. That allows to propery fallback to accel-ppp.conf values when one of the values was not provided by RADIUS. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-03pppd_compat: fix handling of fork() failuresGuillaume Nault
When accel-ppp is under stress (for example because of massive disconnections) it may enter a state where no session could be created or destroyed anymore. This happens when at least one of the pppd_compat fork() fail. In this case, the error code path doesn't unlock the sigchld handler, which prevents it from running the completion callbacks of running scripts. If the "fork-limit" option is used, failure to call the completion callback will prevent other scripts from running. This will block setting up and tearing down sessions, as those will wait indefinitely for their pppd_compat scripts to run. Therefore, we have to unlock the sigchld handler when fork() fails. We also need to call fork_queue_wakeup(), because the previous check_fork_limit() call already took one reference in the fork limit. Finally, ev_ses_pre_up() is a bit special because it has to tear the session down if the ip-pre-up script failed. Therefore it also has to call ap_session_terminate() upon fork() failures. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-11-03triton: fix context schedule/wakeup raceGuillaume Nault
Allow triton_context_wakeup() to run before triton_context_schedule(). When that happens, triton_context_schedule() now lets the context running instead of putting it in sleep mode. Note that, even though triton now allows triton_context_wakeup() to happen before triton_context_schedule(), these two functions still need to be paired and not nested. That is, in a sequence like the following, triton_context_wakeup() triton_context_wakeup() triton_context_schedule() triton_context_schedule() the second triton_context_schedule() would put the context in sleep mode. No matter how many triton_context_wakeup() have been called, the first triton_context_schedule() "consumes" them all. Being immune to schedule/wakeup inversion allows to fix the pppd_compat module. This module needs to fork() to execute external programs. The parent then waits for completion of its child using triton_context_schedule(). When child terminates, the sigchld module runs a callback that has to call triton_context_wakeup() to resume execution of the parent. The problem is that there is no synchronisation between the parent and its child. When under stress, the child may execute faster than its parent and the sigchld callback might run triton_context_wakeup() before the parent had time to call triton_context_schedule(). Then accel-ppp might crash because the triton thread might have reset ctx->thread to NULL, making triton_context_wakeup() write to invalid memory when trying to insert the context in ctx->thread->wakeup_list[]. Synchronising the parent and its child completion's callback would require cooperation from triton_context_schedule(). Otherwise we would still have a time frame between the moment we let the callback waking up the context and the moment we put the context in sleep mode. Allowing schedule/wakeup call inversion in triton looks simpler since it avoids modifying the current API. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-29Merge pull request #57 from themiron/sstpxebd
sstp: fix build w/o openssl & with 1.1.0-1.1.0g
2018-10-26sstp: fix build w/o opensslVladislav Grishenko
2018-10-26sstp: fix build with openssl 1.1.0-1.1.0gVladislav Grishenko
2018-10-26Merge branch 'master' of https://github.com/xebd/accel-pppDmitry Kozlov
2018-10-26cli: fix include directive for list.hGuillaume Nault
list.h is an accel-ppp internal file. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26vlan_mon: make vlan_mon.h self-containedGuillaume Nault
We need to include <stdint.h> to define 'uint16_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26triton: make mempool.h self-contained even when MEMDEBUG is definedGuillaume Nault
If MEMDEBUG is defined, then we need to include "memdebug.h" to define 'md_free'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26radius: make radius.h self-containedGuillaume Nault
We need to include "list.h" to define 'struct list_head' and <netinet/in.h> for 'in_addr_t' and 'struct in6_addr'. Also, let's include "ap_session.h" so that we don't need a forward declaration for 'struct ap_session'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26ppp: make ppp_fsm.h self-containedGuillaume Nault
We need to include <stdint.h> to define 'uint16_t' and "triton.h" for 'struct triton_timer_t'. Also, let's include "ppp.h" so that we don't need a forward declaration for 'struct ppp_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26ppp: make ppp_auth.h self-containedGuillaume Nault
We need to include <stdint.h> to define 'uint8_t' and "ppp.h" for 'struct ppp_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26ppp: make ppp_lcp.h self-containedGuillaume Nault
We need to include "ppp.h" to define 'struct ppp_layer_data_t' and 'struct ppp_handler_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26memdebug: make memdebug.h self-contained even when MEMDEBUG isn't definedGuillaume Nault
We need to include <stdio.h> to define 'asprintf', <stdlib.h> for 'malloc', 'realloc' and 'free' and <string.h> for 'strdup' and 'strndup'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26lua: make luasupp.h self-containedGuillaume Nault
We need to include "ap_session.h" to define 'struct ap_session'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26libnetlink: make libnetlink.h self-containedGuillaume Nault
We need to include <sys/types.h> to define 'pid_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26libnetlink: make ipset.h self-containedGuillaume Nault
We need to include <netinet/in.h> to define 'in_addr_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26iputils: make iputils.h self-containedGuillaume Nault
We need to include <stdint.h> to define 'uint32_t' and <netinet/in.h> for 'in_addr_t' and 'struct in6_addr'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26core: make ap_net.h self-containedGuillaume Nault
We need to include <sys/socket.h> to define 'socklen_t', <sys/types.h> for 'ssize_t' and "list.h" for 'struct list_head'. Also, let's include "libnetlink.h" so that we don't need a forward declaration for 'struct rtnl_handle'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26connlimit: make connlimit.h self-containedGuillaume Nault
We need to include <stdint.h> to define 'uint*_t' and <string.h> for 'memcpy'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26backup: make backup.h self-containedGuillaume Nault
We need to include <sys/types.h> to define 'size_t'. Also, let's include "ap_session.h" so that we don't need a forward declaration for 'struct ap_session'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26backup: make ap_session_backup.h self-containedGuillaume Nault
We need to include <netinet/in.h> to define 'struct in6_addr' and <stdint.h> for 'uint8_t'. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-26Merge pull request #56 from themiron/addr-setup-fixxebd
fix gateway address setup fail due memory corruption
2018-10-25fix gateway address setup fail due memory corruptionVladislav Grishenko
log: libnetlink: RTNETLINK answers: Invalid argument ppp0: f7bb00a79ef667d2: failed to set IPv4 address: Invalid argument ipaddr_add_peer() called only with mask equeal 0 or 32, but w/o zero-allocated structs it contans garbage in some cases. so, instead ipaddr_add() was called with wrong mask value. also, init chap-secrets mask for the same reason.
2018-10-25sstp: disable ciphers renegotiation (CVE-2009-3555)Vladislav Grishenko
2018-10-25sstp: improve openssl 1.1.x compatibilityVladislav Grishenko
2018-10-23cli: add network namespace column in "show sessions"Guillaume Nault
Define a new column, called "netns", that prints the network namespace in which sessions are set. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-10-23ipv6: fix IPv6 processing of sessions that only have only a link-local addressGuillaume Nault
Several modules assume that if ses->ipv6 is set, then ses->ipv6->addr_list contains at least one element. But this is not true if ipv6 was allocated by the pseudo ipdb backend of ipv6cp (ipv6cp_opt_intfid.c). That is, if the PPP session only has an automatic link-local address. This leads modules like pppd-compat and dhcpv6 to access invalid memory when trying to retrieve the IPv6 address of a PPP session. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-08-24load ipoe and vlan_mon module on startDmitry Kozlov
2018-07-31Merge branch 'master' of ssh://git.code.sf.net/p/accel-ppp/codeDmitry Kozlov
2018-07-31Merge branch 'master' of github.com:xebd/accel-pppDmitry Kozlov
2018-06-24pppd_compat: fix indentation in ev_radius_coa()Guillaume Nault
Missing tab was misleading. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
2018-06-24pppd_compat: run scripts in the PPP device netnsGuillaume Nault
If the PPP device is set up into a specific network namespace, all the configuration that goes with it belongs to this same netns. Therefore, we need to run the up/down scripts in that namespace too. Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>