From f4ef76617fd5456d44cee02c37740b5fd730645c Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sat, 2 Jun 2018 22:51:54 +0500 Subject: sstp: drop port from calling_station_id/called_station_id --- accel-pppd/ctrl/sstp/sstp.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index be8762d5..5cd1370d 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -59,6 +59,7 @@ #endif #define ADDRSTR_MAXLEN (sizeof("unix:") + sizeof(((struct sockaddr_un *)0)->sun_path)) +#define FLAG_NOPORT 1 enum { STATE_INIT = 0, @@ -285,24 +286,26 @@ static in_addr_t sockaddr_ipv4(struct sockaddr_t *addr) } } -static int sockaddr_ntop(struct sockaddr_t *addr, char *dst, socklen_t size) +static int sockaddr_ntop(struct sockaddr_t *addr, char *dst, socklen_t size, int flags) { char ipv6_buf[INET6_ADDRSTRLEN], *path, sign; switch (addr->u.sa.sa_family) { case AF_INET: - return snprintf(dst, size, "%s:%d", + return snprintf(dst, size, (flags & FLAG_NOPORT) ? "%s" : "%s:%d", inet_ntoa(addr->u.sin.sin_addr), ntohs(addr->u.sin.sin_port)); case AF_INET6: if (IN6_IS_ADDR_V4MAPPED(&addr->u.sin6.sin6_addr)) { inet_ntop(AF_INET, &addr->u.sin6.sin6_addr.s6_addr32[3], ipv6_buf, sizeof(ipv6_buf)); + return snprintf(dst, size, (flags & FLAG_NOPORT) ? "%s" : "%s:%d", + ipv6_buf, ntohs(addr->u.sin6.sin6_port)); } else { inet_ntop(AF_INET6, &addr->u.sin6.sin6_addr, ipv6_buf, sizeof(ipv6_buf)); + return snprintf(dst, size, (flags & FLAG_NOPORT) ? "%s" : "[%s]:%d", + ipv6_buf, ntohs(addr->u.sin6.sin6_port)); } - return snprintf(dst, size, "%s:%d", - ipv6_buf, ntohs(addr->u.sin6.sin6_port)); case AF_UNIX: if (addr->len <= offsetof(typeof(addr->u.sun), sun_path)) { path = "NULL"; @@ -733,7 +736,7 @@ static int proxy_handler(struct sstp_conn_t *conn, struct buffer_t *buf) if (ip && triton_module_loaded("connlimit") && connlimit_check(cl_key_from_ipv4(ip))) return -1; - sockaddr_ntop(&conn->addr, addr_buf, sizeof(addr_buf)); + sockaddr_ntop(&conn->addr, addr_buf, sizeof(addr_buf), 0); log_info2("sstp: proxy: connection from %s\n", addr_buf); if (ip && iprange_client_check(ip)) { @@ -742,11 +745,14 @@ static int proxy_handler(struct sstp_conn_t *conn, struct buffer_t *buf) } if (addr.u.sa.sa_family != AF_UNSPEC) { + _free(conn->ppp.ses.chan_name); + conn->ppp.ses.chan_name = _strdup(addr_buf); + + sockaddr_ntop(&conn->addr, addr_buf, sizeof(addr_buf), FLAG_NOPORT); _free(conn->ctrl.calling_station_id); conn->ctrl.calling_station_id = _strdup(addr_buf); - conn->ppp.ses.chan_name = conn->ctrl.calling_station_id; - sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf)); + sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf), FLAG_NOPORT); _free(conn->ctrl.called_station_id); conn->ctrl.called_station_id = _strdup(addr_buf); } @@ -2072,6 +2078,7 @@ static void sstp_disconnect(struct sstp_conn_t *conn) free_buf(buf); } + _free(conn->ppp.ses.chan_name); _free(conn->ctrl.calling_station_id); _free(conn->ctrl.called_station_id); @@ -2136,7 +2143,7 @@ static int sstp_connect(struct triton_md_handler_t *h) return 0; } - sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf)); + sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf), 0); log_info2("sstp: new connection from %s\n", addr_buf); if (ip && iprange_client_check(addr.u.sin.sin_addr.s_addr)) { @@ -2207,20 +2214,22 @@ static int sstp_connect(struct triton_md_handler_t *h) conn->ctrl.ifname = ""; conn->ctrl.mppe = MPPE_DENY; - conn->ctrl.calling_station_id = _strdup(addr_buf); - addr.len = sizeof(addr.u); - getsockname(sock, &addr.u.sa, &addr.len); - sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf)); - conn->ctrl.called_station_id = _strdup(addr_buf); - ppp_init(&conn->ppp); conn->ppp.ses.ctrl = &conn->ctrl; - conn->ppp.ses.chan_name = conn->ctrl.calling_station_id; + conn->ppp.ses.chan_name = _strdup(addr_buf); if (conf_ip_pool) conn->ppp.ses.ipv4_pool_name = _strdup(conf_ip_pool); if (conf_ifname) conn->ppp.ses.ifname_rename = _strdup(conf_ifname); + sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf), FLAG_NOPORT); + conn->ctrl.calling_station_id = _strdup(addr_buf); + + addr.len = sizeof(addr.u); + getsockname(sock, &addr.u.sa, &addr.len); + sockaddr_ntop(&addr, addr_buf, sizeof(addr_buf), FLAG_NOPORT); + conn->ctrl.called_station_id = _strdup(addr_buf); + triton_context_register(&conn->ctx, &conn->ppp.ses); triton_context_call(&conn->ctx, (triton_event_func)sstp_start, conn); triton_context_wakeup(&conn->ctx); -- cgit v1.2.3 From 3b5a479a573f27a1efddb01351d61d142bb46a11 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 3 Jun 2018 04:18:59 +0500 Subject: sstp: add session events & stat support --- accel-pppd/ctrl/sstp/sstp.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 5cd1370d..cfebf4fb 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -172,6 +172,9 @@ static const char *conf_http_url = NULL; static mempool_t conn_pool; +static unsigned int stat_starting; +static unsigned int stat_active; + static int sstp_write(struct triton_md_handler_t *h); static inline void sstp_queue(struct sstp_conn_t *conn, struct buffer_t *buf); static int sstp_send(struct sstp_conn_t *conn, struct buffer_t *buf); @@ -1453,16 +1456,17 @@ static int sstp_recv_msg_call_connect_request(struct sstp_conn_t *conn, struct s triton_md_register_handler(&conn->ctx, &conn->ppp_hnd); triton_md_enable_handler(&conn->ppp_hnd, MD_MODE_READ); -// triton_event_fire(EV_CTRL_STARTED, &conn->ppp.ses); - if (conn->nonce) read(urandom_fd, conn->nonce, SSTP_NONCE_SIZE); if (sstp_send_msg_call_connect_ack(conn)) goto error; conn->sstp_state = STATE_SERVER_CALL_CONNECTED_PENDING; - conn->ppp_state = STATE_STARTING; + __sync_sub_and_fetch(&stat_starting, 1); + __sync_add_and_fetch(&stat_active, 1); + triton_event_fire(EV_CTRL_STARTED, &conn->ppp.ses); + conn->ppp_state = STATE_STARTING; conn->ppp.fd = slave; if (establish_ppp(&conn->ppp)) { conn->ppp_state = STATE_FINISHED; @@ -1591,7 +1595,6 @@ static int sstp_recv_msg_call_disconnect(struct sstp_conn_t *conn) } conn->sstp_state = STATE_CALL_DISCONNECT_IN_PROGRESS_2; - ret = sstp_send_msg_call_disconnect_ack(conn); conn->timeout_timer.period = SSTP_DISCONNECT_TIMEOUT_2 * 1000; @@ -2055,12 +2058,20 @@ static void sstp_disconnect(struct sstp_conn_t *conn) triton_md_unregister_handler(&conn->ppp_hnd, 1); switch (conn->ppp_state) { + case STATE_INIT: + __sync_sub_and_fetch(&stat_starting, 1); + break; case STATE_STARTING: case STATE_STARTED: conn->ppp_state = STATE_FINISHED; + __sync_sub_and_fetch(&stat_active, 1); ap_session_terminate(&conn->ppp.ses, TERM_LOST_CARRIER, 1); + break; + case STATE_FINISHED: + __sync_sub_and_fetch(&stat_active, 1); + break; } -// triton_event_fire(EV_CTRL_FINISHED, &conn->ppp.ses); + triton_event_fire(EV_CTRL_FINISHED, &conn->ppp.ses); triton_context_unregister(&conn->ctx); @@ -2089,7 +2100,7 @@ static void sstp_disconnect(struct sstp_conn_t *conn) static void sstp_start(struct sstp_conn_t *conn) { - log_debug("sstp: start\n"); + log_debug("sstp: starting\n"); #ifdef CRYPTO_OPENSSL if (serv.ssl_ctx) @@ -2106,7 +2117,6 @@ static void sstp_start(struct sstp_conn_t *conn) triton_md_enable_handler(&conn->hnd, MD_MODE_READ); log_info2("sstp: started\n"); -// triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses); return; @@ -2234,6 +2244,9 @@ static int sstp_connect(struct triton_md_handler_t *h) triton_context_call(&conn->ctx, (triton_event_func)sstp_start, conn); triton_context_wakeup(&conn->ctx); + __sync_add_and_fetch(&stat_starting, 1); + triton_event_fire(EV_CTRL_STARTING, &conn->ppp.ses); + triton_timer_add(&conn->ctx, &conn->timeout_timer, 0); } @@ -2387,6 +2400,15 @@ error: } #endif +static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) +{ + cli_send(client, "sstp:\r\n"); + cli_sendv(client," starting: %u\r\n", stat_starting); + cli_sendv(client," active: %u\r\n", stat_active); + + return CLI_CMD_OK; +} + static void load_config(void) { int ipmode; @@ -2572,6 +2594,8 @@ static void sstp_init(void) triton_md_enable_handler(&serv.hnd, MD_MODE_READ); triton_context_wakeup(&serv.ctx); + cli_register_simple_cmd2(show_stat_exec, NULL, 2, "show", "stat"); + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); return; -- cgit v1.2.3 From 0d454ad7102506ecd12a36239f6604f7e4b57aae Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 3 Jun 2018 04:23:59 +0500 Subject: sstp: add snmp support --- accel-pppd/ctrl/sstp/sstp.c | 6 ++++++ accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt | 28 +++++++++++++++++++++++--- accel-pppd/extra/net-snmp/CMakeLists.txt | 1 + accel-pppd/extra/net-snmp/agent.c | 2 ++ accel-pppd/extra/net-snmp/sessionTable_enums.h | 1 + 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index cfebf4fb..3f3f48ce 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -2409,6 +2409,12 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, return CLI_CMD_OK; } +void __export sstp_get_stat(unsigned int **starting, unsigned int **active) +{ + *starting = &stat_starting; + *active = &stat_active; +} + static void load_config(void) { int ipmode; diff --git a/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt b/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt index b536a9b7..e175771a 100644 --- a/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt +++ b/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt @@ -34,7 +34,8 @@ statPPTP OBJECT IDENTIFIER ::= { accelPPPStat 3 } statL2TP OBJECT IDENTIFIER ::= { accelPPPStat 4 } statPPPOE OBJECT IDENTIFIER ::= { accelPPPStat 5 } statIPOE OBJECT IDENTIFIER ::= { accelPPPStat 6 } ---statRadius OBJECT IDENTIFIER ::= { accelPPPStat 6 } +statSSTP OBJECT IDENTIFIER ::= { accelPPPStat 7 } +--statRadius OBJECT IDENTIFIER ::= { accelPPPStat 8 } statCoreUpTime OBJECT-TYPE @@ -177,6 +178,26 @@ statIPOEActive OBJECT-TYPE "count of active connections" ::= { statIPOE 2 } +-- +-- SSTP stats +-- + +statSSTPStarting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of connections which are + in starting phase" + ::= { statSSTP 1 } + +statSSTPActive OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active connections" + ::= { statSSTP 2 } -- -- PPP session table @@ -252,8 +273,9 @@ sesType OBJECT-TYPE SYNTAX INTEGER { pptp(1), l2tp(2), - pppoe(3) - ipoe(4) + pppoe(3), + ipoe(4), + sstp(6) } MAX-ACCESS read-only STATUS current diff --git a/accel-pppd/extra/net-snmp/CMakeLists.txt b/accel-pppd/extra/net-snmp/CMakeLists.txt index 5feaec6f..737f0b20 100644 --- a/accel-pppd/extra/net-snmp/CMakeLists.txt +++ b/accel-pppd/extra/net-snmp/CMakeLists.txt @@ -11,6 +11,7 @@ SET(sources statPPPOE.c statPPTP.c statIPOE.c + statSSTP.c terminate.c shutdown.c exec_cli.c diff --git a/accel-pppd/extra/net-snmp/agent.c b/accel-pppd/extra/net-snmp/agent.c index 162cdbc0..4cc04c1d 100644 --- a/accel-pppd/extra/net-snmp/agent.c +++ b/accel-pppd/extra/net-snmp/agent.c @@ -17,6 +17,7 @@ #include "statL2TP.h" #include "statPPPOE.h" #include "statIPOE.h" +#include "statSSTP.h" #include "terminate.h" #include "shutdown.h" #include "sessionTable.h" @@ -108,6 +109,7 @@ static void *snmp_thread(void *a) init_statL2TP(); init_statPPPOE(); init_statIPOE(); + init_statSSTP(); init_terminate(); init_shutdown(); init_sessionTable(); diff --git a/accel-pppd/extra/net-snmp/sessionTable_enums.h b/accel-pppd/extra/net-snmp/sessionTable_enums.h index 74268eef..fff47fe0 100644 --- a/accel-pppd/extra/net-snmp/sessionTable_enums.h +++ b/accel-pppd/extra/net-snmp/sessionTable_enums.h @@ -45,6 +45,7 @@ extern "C" { #define SESTYPE_L2TP 2 #define SESTYPE_PPPOE 3 #define SESTYPE_IPOE 4 +#define SESTYPE_SSTP 6 #endif /* SESTYPE_ENUMS */ -- cgit v1.2.3 From 6a08f5d4644780381e06a853162682a4788d9ed8 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 3 Jun 2018 23:10:01 +0500 Subject: sstp: implement Compound MAC validation --- accel-pppd/ctrl/sstp/sstp.c | 66 ++++++++++++++++++++++++++++++++-------- accel-pppd/ctrl/sstp/sstp_prot.h | 3 ++ 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 3f3f48ce..83176e7d 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -127,8 +127,8 @@ struct sstp_conn_t { // int bypass_auth:1; // char *http_cookie; -// uint8_t auth_key[32]; uint8_t *nonce; + uint8_t *hlak_key; struct buffer_t *in; struct list_head out_queue; @@ -1458,6 +1458,8 @@ static int sstp_recv_msg_call_connect_request(struct sstp_conn_t *conn, struct s if (conn->nonce) read(urandom_fd, conn->nonce, SSTP_NONCE_SIZE); + if (conn->hlak_key) + memset(conn->hlak_key, 0, SSTP_HLAK_SIZE); if (sstp_send_msg_call_connect_ack(conn)) goto error; @@ -1490,7 +1492,10 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct struct { struct sstp_ctrl_hdr hdr; struct sstp_attrib_crypto_binding attr; - } __attribute__((packed)) *msg = (void *)hdr; + } __attribute__((packed)) buf, *msg = (void *)hdr; + uint8_t md[EVP_MAX_MD_SIZE], hash, *ptr; + const EVP_MD *evp; + unsigned int len, mdlen; if (conf_verbose) log_ppp_info2("recv [SSTP SSTP_MSG_CALL_CONNECTED]\n"); @@ -1518,25 +1523,44 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct if (conn->nonce && memcmp(msg->attr.nonce, conn->nonce, SSTP_NONCE_SIZE) != 0) return sstp_abort(conn, 0); - switch (msg->attr.hash_protocol_bitmask & conf_hash_protocol) { - case CERT_HASH_PROTOCOL_SHA1: - if (conf_hash_sha1.len == SHA_DIGEST_LENGTH && - memcmp(msg->attr.cert_hash, conf_hash_sha1.hash, SHA_DIGEST_LENGTH) != 0) + hash = msg->attr.hash_protocol_bitmask & conf_hash_protocol; + if (hash & CERT_HASH_PROTOCOL_SHA256) { + len = SHA256_DIGEST_LENGTH; + if (conf_hash_sha256.len == len && + memcmp(msg->attr.cert_hash, conf_hash_sha256.hash, len) != 0) return sstp_abort(conn, 0); - break; - case CERT_HASH_PROTOCOL_SHA256: - if (conf_hash_sha256.len == SHA256_DIGEST_LENGTH && - memcmp(msg->attr.cert_hash, conf_hash_sha256.hash, SHA256_DIGEST_LENGTH) != 0) + evp = EVP_sha256(); + } else if (hash & CERT_HASH_PROTOCOL_SHA1) { + len = SHA_DIGEST_LENGTH; + if (conf_hash_sha1.len == len && + memcmp(msg->attr.cert_hash, conf_hash_sha1.hash, len) != 0) return sstp_abort(conn, 0); - break; - default: + evp = EVP_sha1(); + } else return sstp_abort(conn, 0); + + if (conn->hlak_key) { + ptr = mempcpy(md, SSTP_CMK_SEED, SSTP_CMK_SEED_SIZE); + *ptr++ = len; + *ptr++ = 0; + *ptr++ = 1; + mdlen = sizeof(md); + HMAC(evp, conn->hlak_key, SSTP_HLAK_SIZE, md, ptr - md, md, &mdlen); + + memcpy(&buf, msg, sizeof(buf)); + memset(buf.attr.compound_mac, 0, sizeof(buf.attr.compound_mac)); + HMAC(evp, md, mdlen, (void *)&buf, sizeof(buf), buf.attr.compound_mac, &len); + + if (memcmp(msg->attr.compound_mac, buf.attr.compound_mac, len) != 0) + return sstp_abort(conn, 0); } conn->sstp_state = STATE_SERVER_CALL_CONNECTED; _free(conn->nonce); conn->nonce = NULL; + _free(conn->hlak_key); + conn->hlak_key = NULL; if (conn->hello_interval) { conn->hello_timer.period = conn->hello_interval * 1000; @@ -2076,6 +2100,7 @@ static void sstp_disconnect(struct sstp_conn_t *conn) triton_context_unregister(&conn->ctx); _free(conn->nonce); + _free(conn->hlak_key); if (conn->stream) conn->stream->free(conn->stream); @@ -2205,8 +2230,8 @@ static int sstp_connect(struct triton_md_handler_t *h) //conn->bypass_auth = conf_bypass_auth; //conn->http_cookie = NULL: - //conn->auth_key... conn->nonce = _malloc(SSTP_NONCE_SIZE); + conn->hlak_key = _malloc(SSTP_HLAK_SIZE); conn->in = alloc_buf(SSTP_MAX_PACKET_SIZE*2); INIT_LIST_HEAD(&conn->out_queue); @@ -2400,6 +2425,20 @@ error: } #endif +static void ev_mppe_keys(struct ev_mppe_keys_t *ev) +{ + struct ppp_t *ppp = ev->ppp; + struct sstp_conn_t *conn = container_of(ppp, typeof(*conn), ppp); + + if (ppp->ses.ctrl->type != CTRL_TYPE_SSTP) + return; + + if (conn->hlak_key) { + memcpy(conn->hlak_key, ev->recv_key, 16); + memcpy(conn->hlak_key + 16, ev->send_key, 16); + } +} + static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { cli_send(client, "sstp:\r\n"); @@ -2602,6 +2641,7 @@ static void sstp_init(void) cli_register_simple_cmd2(show_stat_exec, NULL, 2, "show", "stat"); + triton_event_register_handler(EV_MPPE_KEYS, (triton_event_func)ev_mppe_keys); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); return; diff --git a/accel-pppd/ctrl/sstp/sstp_prot.h b/accel-pppd/ctrl/sstp/sstp_prot.h index f9f78d88..e3c4c9c5 100644 --- a/accel-pppd/ctrl/sstp/sstp_prot.h +++ b/accel-pppd/ctrl/sstp/sstp_prot.h @@ -10,6 +10,9 @@ #define SSTP_VERSION 0x10 #define SSTP_MAX_PACKET_SIZE 4095 #define SSTP_NONCE_SIZE 32 +#define SSTP_HLAK_SIZE 32 +#define SSTP_CMK_SEED "SSTP inner method derived CMK" +#define SSTP_CMK_SEED_SIZE 29 #define SSTP_NEGOTIOATION_TIMEOUT 60 #define SSTP_HELLO_TIMEOUT 60 #define SSTP_ABORT_TIMEOUT_1 3 -- cgit v1.2.3 From b990f248e336eff6e787356ed6d393ca8222374a Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 3 Jun 2018 23:12:07 +0500 Subject: sstp: add disconnection reason logging --- accel-pppd/ctrl/sstp/sstp.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 83176e7d..68bec394 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -1520,24 +1520,33 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct return sstp_abort(conn, 0); } - if (conn->nonce && memcmp(msg->attr.nonce, conn->nonce, SSTP_NONCE_SIZE) != 0) + if (conn->nonce && memcmp(msg->attr.nonce, conn->nonce, SSTP_NONCE_SIZE) != 0) { + log_ppp_error("sstp: invalid Nonce"); return sstp_abort(conn, 0); + } hash = msg->attr.hash_protocol_bitmask & conf_hash_protocol; if (hash & CERT_HASH_PROTOCOL_SHA256) { len = SHA256_DIGEST_LENGTH; if (conf_hash_sha256.len == len && - memcmp(msg->attr.cert_hash, conf_hash_sha256.hash, len) != 0) + memcmp(msg->attr.cert_hash, conf_hash_sha256.hash, len) != 0) { + log_ppp_error("sstp: invalid SHA256 Cert Hash"); return sstp_abort(conn, 0); + } evp = EVP_sha256(); } else if (hash & CERT_HASH_PROTOCOL_SHA1) { len = SHA_DIGEST_LENGTH; if (conf_hash_sha1.len == len && - memcmp(msg->attr.cert_hash, conf_hash_sha1.hash, len) != 0) + memcmp(msg->attr.cert_hash, conf_hash_sha1.hash, len) != 0) { + log_ppp_error("sstp: invalid SHA1 Cert Hash"); return sstp_abort(conn, 0); + } evp = EVP_sha1(); - } else + } else { + log_ppp_error("sstp: invalid Hash Protocol 0x%02x\n", + msg->attr.hash_protocol_bitmask); return sstp_abort(conn, 0); + } if (conn->hlak_key) { ptr = mempcpy(md, SSTP_CMK_SEED, SSTP_CMK_SEED_SIZE); @@ -1551,8 +1560,10 @@ static int sstp_recv_msg_call_connected(struct sstp_conn_t *conn, struct sstp_ct memset(buf.attr.compound_mac, 0, sizeof(buf.attr.compound_mac)); HMAC(evp, md, mdlen, (void *)&buf, sizeof(buf), buf.attr.compound_mac, &len); - if (memcmp(msg->attr.compound_mac, buf.attr.compound_mac, len) != 0) + if (memcmp(msg->attr.compound_mac, buf.attr.compound_mac, len) != 0) { + log_ppp_error("sstp: invalid Compound MAC"); return sstp_abort(conn, 0); + } } conn->sstp_state = STATE_SERVER_CALL_CONNECTED; @@ -1798,7 +1809,7 @@ static int sstp_recv_packet(struct sstp_conn_t *conn, struct sstp_hdr *hdr) case SSTP_MSG_ECHO_RESPONSE: return sstp_recv_msg_echo_response(conn); default: - log_ppp_warn("recv [SSTP unknown message type %04x]\n", ntohs(msg->message_type)); + log_ppp_warn("recv [SSTP unknown message type 0x%04x]\n", ntohs(msg->message_type)); return 0; } } @@ -1811,7 +1822,7 @@ static int sstp_handler(struct sstp_conn_t *conn, struct buffer_t *buf) while (buf->len >= sizeof(*hdr)) { hdr = (struct sstp_hdr *)buf->head; if (hdr->version != SSTP_VERSION) { - log_ppp_error("recv [SSTP invalid version]\n"); + log_ppp_error("recv [SSTP invalid version 0x%02x]\n", hdr->version); return -1; } -- cgit v1.2.3 From a7d641243bd154fce02ee2b2bbc2d710f6719d21 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sun, 3 Jun 2018 23:29:19 +0500 Subject: sstp: use generic HTTP/1.0 error codes for better compatibility --- accel-pppd/ctrl/sstp/sstp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 68bec394..2fc26623 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -873,12 +873,12 @@ static int http_recv_request(struct sstp_conn_t *conn, uint8_t *data, int len) } if (strncasecmp(proto, "HTTP/1", sizeof("HTTP/1") - 1) != 0) { if (conf_http_mode) - http_send_response(conn, "HTTP/1.1", "505 HTTP Version Not Supported", NULL); + http_send_response(conn, "HTTP/1.1", "400 Bad Request", NULL); return -1; } if (strcasecmp(method, SSTP_HTTP_METHOD) != 0 && strcasecmp(method, "GET") != 0) { if (conf_http_mode) - http_send_response(conn, proto, "405 Method Not Allowed", NULL); + http_send_response(conn, proto, "501 Not Implemented", NULL); return -1; } -- cgit v1.2.3 From 0fe6eb8b4fef670780f4bc5aa4f9f2522ebfc992 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Mon, 4 Jun 2018 09:29:51 +0500 Subject: sstp: snmp: add missed files, fix 0d454ad7102506ecd12a36239f6604f7e4b57aae --- accel-pppd/extra/net-snmp/statSSTP.c | 93 ++++++++++++++++++++++++++++++++++++ accel-pppd/extra/net-snmp/statSSTP.h | 11 +++++ 2 files changed, 104 insertions(+) create mode 100644 accel-pppd/extra/net-snmp/statSSTP.c create mode 100644 accel-pppd/extra/net-snmp/statSSTP.h diff --git a/accel-pppd/extra/net-snmp/statSSTP.c b/accel-pppd/extra/net-snmp/statSSTP.c new file mode 100644 index 00000000..06ba6aa1 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statSSTP.c @@ -0,0 +1,93 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ + +#include +#include +#include + +#include "triton.h" +#include "statSSTP.h" + +/* + * The variables we want to tie the relevant OIDs to. + * The agent will handle all GET and (if applicable) SET requests + * to these variables automatically, changing the values as needed. + */ + +void sstp_get_stat(unsigned int **, unsigned int **); + +static unsigned int *stat_starting; +static unsigned int *stat_active; + +/* + * Our initialization routine, called automatically by the agent + * (Note that the function name must match init_FILENAME()) + */ +void +init_statSSTP(void) +{ + netsnmp_handler_registration *reg; + netsnmp_watcher_info *winfo; + + static oid statSSTPStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,7,1 }; + static oid statSSTPActive_oid[] = { 1,3,6,1,4,1,8072,100,1,7,2 }; + + /* + * a debugging statement. Run the agent with -DstatSSTP to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("statSSTP", "Initializing the statSSTP module\n")); + + if (!triton_module_loaded("sstp")) + return; + + sstp_get_stat(&stat_starting, &stat_active); + + /* + * Register scalar watchers for each of the MIB objects. + * The ASN type and RO/RW status are taken from the MIB definition, + * but can be adjusted if needed. + * + * In most circumstances, the scalar watcher will handle all + * of the necessary processing. But the NULL parameter in the + * netsnmp_create_handler_registration() call can be used to + * supply a user-provided handler if necessary. + * + * This approach can also be used to handle Counter64, string- + * and OID-based watched scalars (although variable-sized writeable + * objects will need some more specialised initialisation). + */ + DEBUGMSGTL(("statSSTP", + "Initializing statSSTPStarting scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statSSTPStarting", NULL, + statSSTPStarting_oid, OID_LENGTH(statSSTPStarting_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_starting, sizeof(*stat_starting), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statSSTPStarting" ); + } + + DEBUGMSGTL(("statSSTP", + "Initializing statSSTPActive scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statSSTPActive", NULL, + statSSTPActive_oid, OID_LENGTH(statSSTPActive_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_active, sizeof(*stat_active), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statSSTPActive" ); + } + + + DEBUGMSGTL(("statSSTP", + "Done initalizing statSSTP module\n")); +} diff --git a/accel-pppd/extra/net-snmp/statSSTP.h b/accel-pppd/extra/net-snmp/statSSTP.h new file mode 100644 index 00000000..900f89e0 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statSSTP.h @@ -0,0 +1,11 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ +#ifndef STATSSTP_H +#define STATSSTP_H + +/* function declarations */ +void init_statSSTP(void); + +#endif /* STATSSTP_H */ -- cgit v1.2.3 From 9dd52874d21025adc27fa6e0fedebbb805d8c398 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Tue, 5 Jun 2018 21:48:55 +0500 Subject: sstp: add ssl-dhparam option for DHE ciphers --- accel-pppd/accel-ppp.conf | 1 + accel-pppd/accel-ppp.conf.5 | 3 +++ accel-pppd/ctrl/sstp/sstp.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 1d38ea15..3d097f59 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -112,6 +112,7 @@ verbose=1 #cert-hash-sha1= #cert-hash-sha256= #accept=ssl,proxy +#ssl-dhparam=/etc/ssl/dhparam.pem #ssl-ciphers=DEFAULT #ssl-prefer-server-ciphers=0 #ssl-ca-file=/etc/ssl/sstp-ca.crt diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 4c1bee76..7439de19 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -681,6 +681,9 @@ Specifies incoming connection acceptance mode. .B proxy - enable PROXY protocol 1 & 2 support. .TP +.BI "ssl-dhparam=" pemfile +Specifies a file with DH parameters for DHE ciphers. +.TP .BI "ssl-ciphers=" string Specifies the enabled ciphers. The ciphers are specified in the format understood by the OpenSSL library. .TP diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 2fc26623..aadf746a 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -2367,6 +2367,9 @@ static void ssl_load_config(struct sstp_serv_t *serv, const char *servername) SSL_CTX_set_options(ssl_ctx, #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS | +#endif +#ifndef OPENSSL_NO_DH + SSL_OP_SINGLE_DH_USE | #endif SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | @@ -2376,6 +2379,27 @@ static void ssl_load_config(struct sstp_serv_t *serv, const char *servername) SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_read_ahead(ssl_ctx, 1); +#ifndef OPENSSL_NO_DH + opt = conf_get_opt("sstp", "ssl-dhparam"); + if (opt) { + DH *dh; + + if (BIO_read_filename(in, opt) <= 0) { + log_error("sstp: SSL dhparam error: %s\n", ERR_error_string(ERR_get_error(), NULL)); + goto error; + } + + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + if (dh == NULL) { + log_error("sstp: SSL dhparam error: %s\n", ERR_error_string(ERR_get_error(), NULL)); + goto error; + } + + SSL_CTX_set_tmp_dh(ssl_ctx, dh); + DH_free(dh); + } +#endif + opt = conf_get_opt("sstp", "ssl-ciphers"); if (opt && SSL_CTX_set_cipher_list(ssl_ctx, opt) != 1) { log_error("sstp: SSL cipher list error: %s\n", ERR_error_string(ERR_get_error(), NULL)); -- cgit v1.2.3 From d84c4b94a958b7cc79aad44439bed8029b3b549b Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Tue, 5 Jun 2018 22:08:55 +0500 Subject: sstp: add ECDSA certs support and ssl-ecdh-curve option for ECDHE ciphers --- accel-pppd/accel-ppp.conf | 1 + accel-pppd/accel-ppp.conf.5 | 3 +++ accel-pppd/ctrl/sstp/sstp.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 3d097f59..f28a3aa7 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -113,6 +113,7 @@ verbose=1 #cert-hash-sha256= #accept=ssl,proxy #ssl-dhparam=/etc/ssl/dhparam.pem +#ssl-ecdh-curve=prime256v1 #ssl-ciphers=DEFAULT #ssl-prefer-server-ciphers=0 #ssl-ca-file=/etc/ssl/sstp-ca.crt diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index 7439de19..9ccac7d5 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -684,6 +684,9 @@ Specifies incoming connection acceptance mode. .BI "ssl-dhparam=" pemfile Specifies a file with DH parameters for DHE ciphers. .TP +.BI "ssl-ecdh-curve=" string +Specifies a curves for ECDHE ciphers. Value is specified in the format understood by the OpenSSL library. +.TP .BI "ssl-ciphers=" string Specifies the enabled ciphers. The ciphers are specified in the format understood by the OpenSSL library. .TP diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index aadf746a..e60d2cb0 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -2370,6 +2370,9 @@ static void ssl_load_config(struct sstp_serv_t *serv, const char *servername) #endif #ifndef OPENSSL_NO_DH SSL_OP_SINGLE_DH_USE | +#endif +#ifndef OPENSSL_NO_ECDH + SSL_OP_SINGLE_ECDH_USE | #endif SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | @@ -2400,6 +2403,40 @@ static void ssl_load_config(struct sstp_serv_t *serv, const char *servername) } #endif +#ifndef OPENSSL_NO_ECDH + opt = conf_get_opt("sstp", "ssl-ecdh-curve"); + { +#if defined(SSL_CTX_set1_curves_list) || defined(SSL_CTRL_SET_CURVES_LIST) +#ifdef SSL_CTRL_SET_ECDH_AUTO + /* not needed in OpenSSL 1.1.0+ */ + SSL_CTX_set_ecdh_auto(ssl_ctx, 1); +#endif + if (opt && SSL_CTX_set1_curves_list(ssl_ctx, opt) == 0) { + log_error("sstp: SSL ecdh-curve error: %s\n", ERR_error_string(ERR_get_error(), NULL)); + goto error; + } +#else + EC_KEY *ecdh; + int nid; + + nid = OBJ_sn2nid(opt ? : "prime256v1"); + if (nid == 0) { + log_error("sstp: SSL ecdh-curve error: %s\n", ERR_error_string(ERR_get_error(), NULL)); + goto error; + } + + ecdh = EC_KEY_new_by_curve_name(nid); + if (ecdh == NULL) { + log_error("sstp: SSL ecdh-curve error: %s\n", ERR_error_string(ERR_get_error(), NULL)); + goto error; + } + + SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); + EC_KEY_free(ecdh); +#endif + } +#endif + opt = conf_get_opt("sstp", "ssl-ciphers"); if (opt && SSL_CTX_set_cipher_list(ssl_ctx, opt) != 1) { log_error("sstp: SSL cipher list error: %s\n", ERR_error_string(ERR_get_error(), NULL)); -- cgit v1.2.3