summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Grishenko <themiron@mail.ru>2020-06-29 02:32:13 +0500
committerVladislav Grishenko <themiron@mail.ru>2020-06-29 04:38:42 +0500
commit0f2c18df473d131ff4c696078923e622e1bb4682 (patch)
tree523efa084b8d985783f72c08cb949862f822bc95
parent7dd9766a72d9ad26f4db09c8a52067d1dd4e777c (diff)
downloadaccel-ppp-xebd-0f2c18df473d131ff4c696078923e622e1bb4682.tar.gz
accel-ppp-xebd-0f2c18df473d131ff4c696078923e622e1bb4682.zip
sstp: fix MITM w/o SSTP_MSG_CALL_CONNECTED is being sent
3.3.2.1 Negotiation Timer When establishing the SSTP connection, the SSTP server starts the negotiation timer. 2. After sending the Call Connect Acknowledge message, if the server does not receive a Call Connected message before the Negotiation timer expires then it MUST send a Call Abort message and start the process of bringing down (disconnecting) the connection. The server MAY implement different timer values for the Call Connected message and the Call Connect Request message. 3.3.7.1 Server-Side Interface with PPP When the server receives a PPP data frame from the PPP layer, the server MUST perform the following steps: * If CurrentState is set to Server_Call_Connected: Generate an SSTP data packet (section 2.2.3) with the PPP frame as the higher-layer payload and send the packet to the HTTPS layer. * Else, drop the PPP frame. sstp-client is known to be broken, it doesn't send SSTP_MSG_CALL_CONNECTED with PAP and CHAP-MD5 auth, no network data flow and disconnect by negotiation timer is expected.
-rw-r--r--accel-pppd/ctrl/sstp/sstp.c30
-rw-r--r--accel-pppd/ifcfg.c4
-rw-r--r--accel-pppd/include/ap_session.h1
3 files changed, 29 insertions, 6 deletions
diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c
index a90ab95..7f60e6d 100644
--- a/accel-pppd/ctrl/sstp/sstp.c
+++ b/accel-pppd/ctrl/sstp/sstp.c
@@ -1483,10 +1483,6 @@ static int sstp_recv_msg_call_connect_request(struct sstp_conn_t *conn, struct s
conn->ppp_state = STATE_FINISHED;
goto error;
}
-
- if (conn->timeout_timer.tpd)
- triton_timer_del(&conn->timeout_timer);
-
return 0;
error:
@@ -1504,6 +1500,7 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct
} __attribute__((packed)) *msg = (void *)hdr;
uint8_t hash;
unsigned int len;
+ struct npioctl np;
#ifdef CRYPTO_OPENSSL
typeof(*msg) buf;
uint8_t md[EVP_MAX_MD_SIZE], *ptr;
@@ -1602,8 +1599,28 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct
#endif
}
+ if (conn->timeout_timer.tpd)
+ triton_timer_del(&conn->timeout_timer);
conn->sstp_state = STATE_SERVER_CALL_CONNECTED;
+ conn->ctrl.ppp_npmode = NPMODE_PASS;
+ switch (conn->ppp_state) {
+ case STATE_STARTED:
+ if (conn->ppp.ses.ipv4) {
+ np.protocol = PPP_IP;
+ np.mode = conn->ctrl.ppp_npmode;
+ if (net->ppp_ioctl(conn->ppp.unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("failed to set NP (IPv4) mode: %s\n", strerror(errno));
+ }
+ if (conn->ppp.ses.ipv6) {
+ np.protocol = PPP_IPV6;
+ np.mode = conn->ctrl.ppp_npmode;
+ if (net->ppp_ioctl(conn->ppp.unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("failed to set NP (IPv6) mode: %s\n", strerror(errno));
+ }
+ break;
+ }
+
_free(conn->nonce);
conn->nonce = NULL;
_free(conn->hlak_key);
@@ -2088,6 +2105,10 @@ static void sstp_timeout(struct triton_timer_t *t)
case STATE_CALL_DISCONNECT_ACK_PENDING:
triton_context_call(&conn->ctx, (triton_event_func)sstp_disconnect, conn);
break;
+ case STATE_SERVER_CONNECT_REQUEST_PENDING:
+ case STATE_SERVER_CALL_CONNECTED_PENDING:
+ log_ppp_warn("sstp: negotiation timeout\n");
+ /* fall through */
default:
sstp_abort(conn, 0);
break;
@@ -2333,6 +2354,7 @@ static int sstp_connect(struct triton_md_handler_t *h)
conn->ctrl.max_mtu = conf_ppp_max_mtu;
conn->ctrl.type = CTRL_TYPE_SSTP;
conn->ctrl.ppp = 1;
+ conn->ctrl.ppp_npmode = NPMODE_DROP;
conn->ctrl.name = "sstp";
conn->ctrl.ifname = "";
conn->ctrl.mppe = MPPE_DENY;
diff --git a/accel-pppd/ifcfg.c b/accel-pppd/ifcfg.c
index d939547..6ab5505 100644
--- a/accel-pppd/ifcfg.c
+++ b/accel-pppd/ifcfg.c
@@ -158,7 +158,7 @@ void __export ap_session_accounting_started(struct ap_session *ses)
ppp = container_of(ses, typeof(*ppp), ses);
if (ses->ipv4) {
np.protocol = PPP_IP;
- np.mode = NPMODE_PASS;
+ np.mode = ses->ctrl->ppp_npmode ? : NPMODE_PASS;
if (net->ppp_ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
log_ppp_error("failed to set NP (IPv4) mode: %s\n", strerror(errno));
@@ -166,7 +166,7 @@ void __export ap_session_accounting_started(struct ap_session *ses)
if (ses->ipv6) {
np.protocol = PPP_IPV6;
- np.mode = NPMODE_PASS;
+ np.mode = ses->ctrl->ppp_npmode ? : NPMODE_PASS;
if (net->ppp_ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
log_ppp_error("failed to set NP (IPv6) mode: %s\n", strerror(errno));
diff --git a/accel-pppd/include/ap_session.h b/accel-pppd/include/ap_session.h
index 8c79d31..2af2f04 100644
--- a/accel-pppd/include/ap_session.h
+++ b/accel-pppd/include/ap_session.h
@@ -53,6 +53,7 @@ struct ap_ctrl {
char *called_station_id;
int dont_ifcfg:1;
int ppp:1;
+ int ppp_npmode:2;
void (*started)(struct ap_session*);
void (*finished)(struct ap_session *);
int (*terminate)(struct ap_session *, int hard);