diff options
author | Vladislav Grishenko <themiron@mail.ru> | 2017-12-03 21:55:10 +0500 |
---|---|---|
committer | Vladislav Grishenko <themiron@mail.ru> | 2017-12-30 22:49:29 +0500 |
commit | 4d6d7e6edc224cfc10ed389d85d1343a54848538 (patch) | |
tree | f0d28034a4093bfc1c2fa87d75830bc2aac8278e | |
parent | 6697db732031d11ac937c8955a90f0a827047f70 (diff) | |
download | accel-ppp-4d6d7e6edc224cfc10ed389d85d1343a54848538.tar.gz accel-ppp-4d6d7e6edc224cfc10ed389d85d1343a54848538.zip |
sstp: implement HTTP host header and TLS SNI checking
-rw-r--r-- | accel-pppd/accel-ppp.conf | 1 | ||||
-rw-r--r-- | accel-pppd/ctrl/sstp/sstp.c | 45 |
2 files changed, 45 insertions, 1 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 68cb45cf..f1f66e27 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -119,6 +119,7 @@ verbose=1 #ssl-ca-file=/etc/ssl/sstp-ca.crt #ssl-pemfile=/etc/ssl/sstp-cert.pem #ssl-keyfile=/etc/ssl/sstp-key.pem +#host-name=domain.tld #timeout=60 #hello-interval=60 #ip-pool=sstp diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c index 26db08e6..fb379f25 100644 --- a/accel-pppd/ctrl/sstp/sstp.c +++ b/accel-pppd/ctrl/sstp/sstp.c @@ -164,6 +164,7 @@ static int conf_hash_protocol = CERT_HASH_PROTOCOL_SHA1 | CERT_HASH_PROTOCOL_SHA static struct hash_t conf_hash_sha1 = { .len = 0 }; static struct hash_t conf_hash_sha256 = { .len = 0 }; //static int conf_bypass_auth = 0; +static const char *conf_hostname = NULL; #ifdef CRYPTO_OPENSSL static X509 *conf_ssl_cert = NULL; @@ -566,7 +567,7 @@ static int http_send_response(struct sstp_conn_t *conn, char *proto, char *statu static int http_recv_request(struct sstp_conn_t *conn) { char buf[1024]; - char *line, *method, *request, *proto; + char *line, *method, *request, *proto, *host; int pos = 0; if (conn->sstp_state != STATE_SERVER_CALL_DISCONNECTED) @@ -581,6 +582,7 @@ static int http_recv_request(struct sstp_conn_t *conn) method = strsep(&line, " "); request = strsep(&line, " "); proto = strsep(&line, " "); + host = NULL; if (!method || !request || !proto) { http_send_response(conn, "HTTP/1.1", "400 Bad Request", NULL); @@ -604,8 +606,19 @@ static int http_recv_request(struct sstp_conn_t *conn) break; if (conf_verbose) log_sstp_info2(conn, "recv [HTTP <%s>]\n", line); + + if (conf_hostname && strncmp(line, "Host", sizeof("Host") - 1) == 0) { + host = line + sizeof("Host") - 1; + while (*host == ' ' || *host == ':') + host++; + } } while (*line); + if (conf_hostname && (!host || strcasecmp(host, conf_hostname) != 0)) { + http_send_response(conn, proto, "434 Requested host unavailable", NULL); + goto error; + } + if (http_send_response(conn, proto, "200 OK", "Content-Length: 18446744073709551615\r\n")) { goto error; @@ -1691,6 +1704,27 @@ static void sstp_disconnect(struct sstp_conn_t *conn) log_info2("sstp: disconnected\n"); } +#ifdef CRYPTO_OPENSSL +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME +static int sstp_servername(SSL *ssl, int *al, void *arg) +{ + struct sstp_conn_t *conn = (struct sstp_conn_t *)arg; + const char *servername; + + servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (conf_verbose) + log_sstp_info2(conn, "recv [SSL SNI <%s>]\n", servername ? : ""); + + if (conf_hostname && (!servername || strcasecmp(servername, conf_hostname) != 0)) { + log_sstp_error(conn, "recv [SSL SNI error]\n"); + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + return SSL_TLSEXT_ERR_OK; +} +#endif +#endif + static void sstp_start(struct sstp_conn_t *conn) { log_sstp_debug(conn, "start\n"); @@ -1734,6 +1768,13 @@ static void sstp_start(struct sstp_conn_t *conn) goto error; } +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if (SSL_CTX_set_tlsext_servername_callback(conn->ssl_ctx, sstp_servername) == 1) + SSL_CTX_set_tlsext_servername_arg(conn->ssl_ctx, conn); + else + log_sstp_warn(conn, "SSl library has no tlsext support"); +#endif + conn->stream = ssl_stream_init(conn->hnd.fd, conn->ssl_ctx); } else #endif @@ -2027,6 +2068,8 @@ static void load_config(void) conf_hash_sha256.hash, sizeof(conf_hash_sha256.hash)); } + conf_hostname = conf_get_opt("sstp", "host-name"); + opt = conf_get_opt("sstp", "timeout"); if (opt && atoi(opt) > 0) conf_timeout = atoi(opt); |