summaryrefslogtreecommitdiff
path: root/accel-pppd
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2018-06-04 20:50:30 +0300
committerDmitry Kozlov <xeb@mail.ru>2018-06-04 20:50:30 +0300
commitf92d8d426508915963c198baa9a16c2e9466122c (patch)
tree28c31227e2a802c59dd03a649e53f9b49df8950f /accel-pppd
parentac8e3062dd7c9f3b9d6b4c88ac34f005e9644468 (diff)
parented4697944f81ec155d8e11b7621cdcf19e38d7e3 (diff)
downloadaccel-ppp-xebd-f92d8d426508915963c198baa9a16c2e9466122c.tar.gz
accel-ppp-xebd-f92d8d426508915963c198baa9a16c2e9466122c.zip
Merge branch 'master' of https://github.com/xebd/accel-ppp
Diffstat (limited to 'accel-pppd')
-rw-r--r--accel-pppd/accel-ppp.conf1
-rw-r--r--accel-pppd/accel-ppp.conf.517
-rw-r--r--accel-pppd/ctrl/sstp/sstp.c101
3 files changed, 81 insertions, 38 deletions
diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf
index b187010..1d38ea1 100644
--- a/accel-pppd/accel-ppp.conf
+++ b/accel-pppd/accel-ppp.conf
@@ -118,6 +118,7 @@ verbose=1
#ssl-pemfile=/etc/ssl/sstp-cert.pem
#ssl-keyfile=/etc/ssl/sstp-key.pem
#host-name=domain.tld
+#http-error=allow
#timeout=60
#hello-interval=60
#ip-pool=sstp
diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5
index a06e781..4c1bee7 100644
--- a/accel-pppd/accel-ppp.conf.5
+++ b/accel-pppd/accel-ppp.conf.5
@@ -717,6 +717,23 @@ certificate or used directly for non-ssl mode.
.BI "host-name=" string
If this option is given, only sstp connection to specified host and with the same TLS SNI will be allowed.
.TP
+.BI "http-error=" deny|allow|http[s]://host.tld[/path]
+Specify http layer error behavior for non-sstp requests.
+.br
+.B deny
+- reset connection without any error response.
+.br
+.B allow
+- respond with http-specific status codes.
+.br
+.B http[s]://host.tld[/path]
+- respond with http redirect to the specified location.
+If
+.B /path
+is not specified, requested uri will be appended automatically
+.br
+Default value is allow.
+.TP
.BI "ifname=" ifname
If this option is given ppp interface will be renamed using
.B ifname
diff --git a/accel-pppd/ctrl/sstp/sstp.c b/accel-pppd/ctrl/sstp/sstp.c
index 0206b69..be8762d 100644
--- a/accel-pppd/ctrl/sstp/sstp.c
+++ b/accel-pppd/ctrl/sstp/sstp.c
@@ -166,6 +166,8 @@ 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;
+static int conf_http_mode = -1;
+static const char *conf_http_url = NULL;
static mempool_t conn_pool;
@@ -615,7 +617,7 @@ static int proxy_parse(struct buffer_t *buf, struct sockaddr_t *peer, struct soc
goto error;
}
peer->len = addr->len = sizeof(addr->u.sin6);
- peer->u.sin6.sin6_family = addr->u.sin6.sin6_family = AF_INET;
+ peer->u.sin6.sin6_family = addr->u.sin6.sin6_family = AF_INET6;
peer->u.sin6.sin6_port = htons(atoi(src_port));
addr->u.sin6.sin6_port = htons(atoi(dst_port));
} else if (strcasecmp(ptr, PROXY_UNKNOWN) != 0)
@@ -810,12 +812,10 @@ static char *http_getvalue(char *line, const char *name, int len)
static int http_send_response(struct sstp_conn_t *conn, char *proto, char *status, char *headers)
{
char datetime[sizeof("aaa, dd bbb yyyy HH:MM:SS GMT")];
- struct buffer_t *buf;
+ char linebuf[1024], *line;
+ struct buffer_t *buf, tmp;
time_t now = time(NULL);
- if (conf_verbose)
- log_ppp_info2("send [HTTP <%s %s>]\n", proto, status);
-
strftime(datetime, sizeof(datetime), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
buf = alloc_buf_printf(
"%s %s\r\n"
@@ -828,77 +828,87 @@ static int http_send_response(struct sstp_conn_t *conn, char *proto, char *statu
return -1;
}
+ if (conf_verbose) {
+ tmp = *buf;
+ while ((line = http_getline(&tmp, linebuf, sizeof(linebuf))) != NULL) {
+ if (*line == '\0')
+ break;
+ log_ppp_info2("send [HTTP <%s>]\n", line);
+ }
+ }
+
return sstp_send(conn, buf);
}
static int http_recv_request(struct sstp_conn_t *conn, uint8_t *data, int len)
{
- char linebuf[1024], protobuf[sizeof("HTTP/1.x")];
- char *line, *method, *request, *proto, *host, *ptr;
+ char httpbuf[1024], linebuf[1024];
+ char *line, *method, *request, *proto, *host;
struct buffer_t buf;
- int ret = -1;
+ int host_error;
buf.head = data;
buf.end = data + len;
buf_set_length(&buf, len);
- line = http_getline(&buf, linebuf, sizeof(linebuf));
+ line = http_getline(&buf, httpbuf, sizeof(httpbuf));
if (!line)
return -1;
if (conf_verbose)
log_ppp_info2("recv [HTTP <%s>]\n", line);
- host = NULL;
-
if (vstrsep(line, " ", &method, &request, &proto) < 3) {
- http_send_response(conn, "HTTP/1.1", "400 Bad Request", NULL);
- goto error;
+ if (conf_http_mode)
+ http_send_response(conn, "HTTP/1.1", "400 Bad Request", NULL);
+ return -1;
}
if (strncasecmp(proto, "HTTP/1", sizeof("HTTP/1") - 1) != 0) {
- http_send_response(conn, "HTTP/1.1", "505 HTTP Version Not Supported", NULL);
- goto error;
- }
- if (strcasecmp(method, SSTP_HTTP_METHOD) != 0) {
- http_send_response(conn, proto, "405 Method Not Allowed", NULL);
- goto error;
+ if (conf_http_mode)
+ http_send_response(conn, "HTTP/1.1", "505 HTTP Version Not Supported", NULL);
+ return -1;
}
- if (strcasecmp(request, SSTP_HTTP_URI) != 0) {
- http_send_response(conn, proto, "404 Not Found", NULL);
- goto error;
+ 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);
+ return -1;
}
- snprintf(protobuf, sizeof(protobuf), "%s", proto);
- proto = protobuf;
-
+ host_error = conf_hostname ? -1 : 0;
while ((line = http_getline(&buf, linebuf, sizeof(linebuf))) != NULL) {
if (*line == '\0')
break;
if (conf_verbose)
log_ppp_info2("recv [HTTP <%s>]\n", line);
- if (!host && conf_hostname) {
+ if (host_error < 0) {
host = http_getvalue(line, "Host", sizeof("Host") - 1);
if (host) {
- ptr = _strdup(host);
- host = strsep(&ptr, ":");
+ host = strsep(&host, ":");
+ host_error = (strcasecmp(host, conf_hostname) != 0);
}
}
}
- if (conf_hostname && strcasecmp(host ? : "", conf_hostname) != 0) {
- http_send_response(conn, proto, "434 Requested host unavailable", NULL);
- goto error;
+ if (host_error) {
+ if (conf_http_mode)
+ http_send_response(conn, proto, "404 Not Found", NULL);
+ return -1;
}
- if (http_send_response(conn, proto, "200 OK",
- "Content-Length: 18446744073709551615\r\n")) {
- goto error;
+ if (strcasecmp(method, SSTP_HTTP_METHOD) != 0 || strcasecmp(request, SSTP_HTTP_URI) != 0) {
+ if (conf_http_mode > 0) {
+ if (_asprintf(&line, "Location: %s%s\r\n",
+ conf_http_url, (conf_http_mode == 2) ? request : "") < 0)
+ return -1;
+ http_send_response(conn, proto, "301 Moved Permanently", line);
+ _free(line);
+ } else if (conf_http_mode < 0)
+ http_send_response(conn, proto, "404 Not Found", NULL);
+ return -1;
}
- ret = 0;
-error:
- _free(host);
- return ret;
+ return http_send_response(conn, proto, "200 OK",
+ "Content-Length: 18446744073709551615\r\n");
}
static int http_handler(struct sstp_conn_t *conn, struct buffer_t *buf)
@@ -2379,6 +2389,21 @@ static void load_config(void)
conf_hostname = conf_get_opt("sstp", "host-name");
+ opt = conf_get_opt("sstp", "http-error");
+ if (opt) {
+ if (strcmp(opt, "deny") == 0)
+ conf_http_mode = 0;
+ else if (strcmp(opt, "allow") == 0)
+ conf_http_mode = -1;
+ else if (strstr(opt, "://") != NULL) {
+ conf_http_url = opt;
+ opt = strstr(opt, "://") + 3;
+ while (*opt == '/')
+ opt++;
+ conf_http_mode = strchr(opt, '/') ? 1 : 2;
+ }
+ }
+
opt = conf_get_opt("sstp", "cert-hash-proto");
if (opt) {
conf_hash_protocol = 0;