Daniel Lenski [Sun, 17 May 2020 02:31:22 +0000 (19:31 -0700)]
add delay_close and use it for clean PPP termination on cancel, pause, or server-sent termination
Whatever delay_close is set to decrements on each mainloop iteration, and
if delay_close == 1, we don't set work_done.
This allows us to set delay_close = 2 for the case where we need to send a termination request
immediately, and then wait briefly for an acknowledgment.
Daniel Lenski [Sat, 16 May 2020 01:03:45 +0000 (18:03 -0700)]
use ACK/NAK request mechanism to request IPv4 address, (IPv4) DNS/NBNS addresses, and IPv6 interface identifiers
The idea is that if we CONFREQ an all-zero value for one of these.
PPP server/peer is supposed to:
- CONFNAK with a value filled in, which we then re-CONFREQ to confirm.
- CONFREJ if it can't supply a value (e.g. NBNS servers because it's
not 1994 and we're not using Windows for Workgroups 3.11).
Tested with F5, by overriding ppp->solicit_peerns=7, ppp->out_peer_addr.s_addr=0,
ppp->out_ipv6_int_ident=0 in openconnect_ppp_new (even though F5 in fact sends these
addresses in the XML config prior to PPP tunnel).
The CONFREQ/CONFNAK/re-CONFREQ exchange is inefficient, requiring three rounds trips
(request and reject, partial re-request and nak, confirming request and ack), but it
works:
Received proto 0x8021/id 1 Configure-Reject from server
Server rejected IPCP request for NBNS[1] server
Server rejected IPCP request for DNS[1] server
Server rejected IPCP request for NBNS[0] server
...
Sending our proto 0x8021/id 2 config request to server
< 0000: f5 00 00 10 80 57 02 01 00 0e 01 0a e0 a7 1c fb |.....W..........|
< 0010: 9e 55 00 00 |.U..|
Sending PPP IPCP Configure-Request packet (id 2, 22 bytes total)
> 0000: f5 00 00 12 80 21 01 02 00 10 03 06 00 00 00 00 |.....!..........|
> 0010: 81 06 00 00 00 00 |......|
No work to do; sleeping for 3000 ms...
< 0000: f5 00 00 12 80 21 03 02 00 10 03 06 0a 00 00 17 |.....!..........|
< 0010: 81 06 5a 9b 5c d1 |..Z.\.|
Received proto 0x8021/id 2 Configure-Nak from server
Server nak-offered IPv4 address: 10.0.0.23
Server nak-offered IPCP request for DNS[0] server: 90.155.92.209
...
Sending our proto 0x8021/id 3 config request to server
Sending PPP IPCP Configure-Request packet (id 3, 16 bytes total)
> 0000: f5 00 00 0c 80 21 01 03 00 0a 03 06 0a 00 00 17 |.....!..........|
No work to do; sleeping for 3000 ms...
< 0000: f5 00 00 0c 80 21 02 03 00 0a 03 06 0a 00 00 17 |.....!..........|
Received proto 0x8021/id 3 Configure-Ack from server
PPP state transition from OPENED to NETWORK
Current PPP state: NETWORK (encap F5):
in: asyncmap=0x00000000, lcp_opts=384, lcp_magic=0x04eb81f9, peer=1.1.1.1
out: asyncmap=0x00000000, lcp_opts=422, lcp_magic=0x70ac508f, peer=10.0.0.23, solicit_peerns=0
The purpose of the IPv6 interface identifier negotiation is unclear, but the F5
server does not accept a zero value, using CONFNAK to offer a new one.
Daniel Lenski [Fri, 15 May 2020 01:48:55 +0000 (18:48 -0700)]
attempted support for concatenated packets
Plus add comments about what each variable points to and when, during packet parsing.
Tested with F5 HDLC and non-HDLC. Doesn't complain about leftover bytes, or short/incomplete packets, but NOT YET
actually tested with concatenated packets.
Daniel Lenski [Wed, 13 May 2020 21:29:41 +0000 (14:29 -0700)]
add test-fortinet-login.py
Often easier to prototype HTTPS-based authentication flows in Python, since
they're so fiddly and arbitary. So I copied `test-f5-login.py` to
`test-fortinet-login.py`. Currently only handles basic
username-and-password auth, no 2FA:
positional arguments:
endpoint Fortinet server (or complete URL, e.g.
https://forti.vpn.com/remote/login)
extra Extra field to pass to include in the login query
string (e.g. "foo=bar")
optional arguments:
-h, --help show this help message and exit
-v, --verbose
--no-verify Ignore invalid server certificate
Login credentials:
-u USERNAME, --username USERNAME
Username (will prompt if unspecified)
-p PASSWORD, --password PASSWORD
Password (will prompt if unspecified)
-r REALM, --realm REALM
Realm (empty if unspecified)
-c CERT, --cert CERT PEM file containing client certificate (and optionally
private key)
--key KEY PEM file containing client private key (if not
included in same file as certificate)
```
David Woodhouse [Tue, 12 May 2020 21:27:24 +0000 (22:27 +0100)]
Handle ConfRej for anything that needs it.
If get a ConfReq with anything we don't want or understand — and that
includes bloody VJ header compression, since I'm not completely batshit
insane — send a ConfRej.
Do this by building up the options to be rejected in an oc_text_buf as
we go, then rejecting that set if it's non-empty once we get to the end.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Daniel Lenski [Tue, 12 May 2020 21:12:25 +0000 (14:12 -0700)]
Fix un-HDLC corner cases
1) The initial 0x7e is optional, the final 0x7e is not (was reversed).
2) Dangling escape can occur even when we haven't run out of buffer. 0x7d 0x7e is an invalid sequence.
While not breaking…
3) 0x7d can be the “target” of an escape (0x7d 0x7d → 0x5d)
4) 0x5d as the “target” of an escape (0x7d 0x5d → 0x7d) doesn't indicate a new escape
Daniel Lenski [Tue, 12 May 2020 06:16:34 +0000 (23:16 -0700)]
simplify PPP header checking
There's no point whatsover to checking if the server is doing ACCOMP/PFCOMP
as negotiated:
- Even if negotiated, they're optional.
- Even if *not* negotiated, they're unambiguous.
- Either way, it's much easier just to ignore the negotiated options.
“Be liberal in what you accept, and conservative in what you send.”
Some day I will acquire a time machine, travel back to 1993, and ask the
designers of PPP not to add meaningless boilerplate bytes to their protocol
in such a uniquely strange-yet-approachable way that compels future implementers to
reinvent clever ways of dealing with them hundreds of times.
David Woodhouse [Mon, 11 May 2020 12:29:28 +0000 (13:29 +0100)]
Drop hdlc and we_go_first args from openconnect_ppp_new()
We should always go first for *our* outbound ConfReqs, not wait for the
server to go first. And HDLC can be inferred from the encap mode, to
which we can add PPP_ENCAP_F5_HDLC.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>