Commit 8a2fbac4 authored by Sergey Lyubka's avatar Sergey Lyubka

Calling event handler in MITM mode before making connection to the target host

parent 96ce6bac
...@@ -4028,13 +4028,42 @@ static void proxy_request(struct ns_connection *pc, struct mg_connection *c) { ...@@ -4028,13 +4028,42 @@ static void proxy_request(struct ns_connection *pc, struct mg_connection *c) {
} }
#ifdef NS_ENABLE_SSL
int mg_terminate_ssl(struct mg_connection *c, const char *cert) {
static const char ok[] = "HTTP/1.0 200 OK\r\n\r\n";
struct connection *conn = MG_CONN_2_CONN(c);
int n;
SSL_CTX *ctx;
DBG(("%p MITM", conn));
SSL_library_init();
if ((ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) return 0;
SSL_CTX_use_certificate_file(ctx, cert, 1);
SSL_CTX_use_PrivateKey_file(ctx, cert, 1);
SSL_CTX_use_certificate_chain_file(ctx, cert);
// When clear-text reply is pushed to client, switch to SSL mode.
n = send(conn->ns_conn->sock, ok, sizeof(ok) - 1, 0);
DBG(("%p %lu %d SEND", c, sizeof(ok) - 1, n));
conn->ns_conn->send_iobuf.len = 0;
conn->endpoint_type = EP_USER; // To keep-alive in close_local_endpoint()
close_local_endpoint(conn); // Clean up current CONNECT request
if ((conn->ns_conn->ssl = SSL_new(ctx)) != NULL) {
SSL_set_fd(conn->ns_conn->ssl, conn->ns_conn->sock);
}
SSL_CTX_free(ctx);
return 1;
}
#endif
static void proxify_connection(struct connection *conn) { static void proxify_connection(struct connection *conn) {
char proto[10], host[500], cert[500]; char proto[10], host[500], cert[500];
unsigned short port = 80; unsigned short port = 80;
struct mg_connection *c = &conn->mg_conn; struct mg_connection *c = &conn->mg_conn;
struct ns_server *server = &conn->server->ns_server; struct ns_server *server = &conn->server->ns_server;
struct ns_connection *pc = NULL; struct ns_connection *pc = NULL;
int n = 0, use_ssl = 0; int n = 0;
const char *url = c->uri; const char *url = c->uri;
proto[0] = host[0] = cert[0] = '\0'; proto[0] = host[0] = cert[0] = '\0';
...@@ -4051,23 +4080,24 @@ static void proxify_connection(struct connection *conn) { ...@@ -4051,23 +4080,24 @@ static void proxify_connection(struct connection *conn) {
int host_len = strlen(host); int host_len = strlen(host);
struct vec a, b; struct vec a, b;
while ((certs = next_option(certs, &a, &b)) != NULL) { while (conn->ns_conn->ssl == NULL && port != 80 &&
if (a.len == host_len && mg_strncasecmp(a.ptr, host, a.len) == 0) { (certs = next_option(certs, &a, &b)) != NULL) {
if (a.len != host_len || mg_strncasecmp(a.ptr, host, a.len)) continue;
snprintf(cert, sizeof(cert), "%.*s", b.len, b.ptr); snprintf(cert, sizeof(cert), "%.*s", b.len, b.ptr);
break; mg_terminate_ssl(&conn->mg_conn, cert);
} return;
} }
} }
#endif #endif
use_ssl = port != 80 && cert[0] != '\0';
if (n > 0 && if (n > 0 &&
(pc = ns_connect(server, host, port, use_ssl, conn)) != NULL) { (pc = ns_connect(server, host, port, conn->ns_conn->ssl != NULL,
conn)) != NULL) {
// Interlink two connections // Interlink two connections
pc->flags |= MG_PROXY_CONN; pc->flags |= MG_PROXY_CONN;
conn->endpoint_type = EP_PROXY; conn->endpoint_type = EP_PROXY;
conn->endpoint.nc = pc; conn->endpoint.nc = pc;
DBG(("%p [%s] -> %p %d", conn, c->uri, pc, use_ssl)); DBG(("%p [%s] -> %p %p", conn, c->uri, pc, conn->ns_conn->ssl));
if (strcmp(c->request_method, "CONNECT") == 0) { if (strcmp(c->request_method, "CONNECT") == 0) {
// For CONNECT request, reply with 200 OK. Tunnel is established. // For CONNECT request, reply with 200 OK. Tunnel is established.
...@@ -4075,34 +4105,6 @@ static void proxify_connection(struct connection *conn) { ...@@ -4075,34 +4105,6 @@ static void proxify_connection(struct connection *conn) {
conn->request_len = 0; conn->request_len = 0;
free(conn->request); free(conn->request);
conn->request = NULL; conn->request = NULL;
#ifdef NS_ENABLE_SSL
if (use_ssl) {
SSL_CTX *ctx;
DBG(("%s", "Triggering MITM mode: terminating SSL connection"));
SSL_library_init();
ctx = SSL_CTX_new(SSLv23_server_method());
if (ctx == NULL) {
pc->flags |= NSF_CLOSE_IMMEDIATELY;
} else {
SSL_CTX_use_certificate_file(ctx, cert, 1);
SSL_CTX_use_PrivateKey_file(ctx, cert, 1);
SSL_CTX_use_certificate_chain_file(ctx, cert);
// When clear-text reply is pushed to client, switch to SSL mode.
n = send(conn->ns_conn->sock, conn->ns_conn->send_iobuf.buf,
conn->ns_conn->send_iobuf.len, 0);
DBG(("%p %lu %d SEND", c, conn->ns_conn->send_iobuf.len, n));
conn->ns_conn->send_iobuf.len = 0;
if ((conn->ns_conn->ssl = SSL_new(ctx)) != NULL) {
//SSL_set_fd((SSL *) c->connection_param, conn->ns_conn->sock);
SSL_set_fd(conn->ns_conn->ssl, conn->ns_conn->sock);
}
SSL_CTX_free(ctx);
}
}
#endif
} else { } else {
// For other methods, forward the request to the target host. // For other methods, forward the request to the target host.
c->uri += n; c->uri += n;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment