Commit dcf1cede authored by rojer's avatar rojer Committed by Cesanta Bot

SimpleLink SSL support; split cert and key opts

SL requires cert and key to be separate files in DER format.

Date verification is disabled for now.

PUBLISHED_FROM=7d76150ed356140728a1e5fd82d8a0456347b7dc
parent 845e6082
...@@ -7,12 +7,14 @@ signature: | ...@@ -7,12 +7,14 @@ signature: |
const char *ca_cert); const char *ca_cert);
--- ---
Note: This function is deprecated, please use SSL options in mg_connect_opt.
Enable SSL for a given connection. Enable SSL for a given connection.
`cert` is a server certificate file name for a listening connection, `cert` is a server certificate file name for a listening connection,
or a client certificate file name for an outgoing connection. or a client certificate file name for an outgoing connection.
Certificate files must be in PEM format. Server certificate file Certificate files must be in PEM format. Server certificate file
must contain a certificate, concatenated with a private key, optionally must contain a certificate, concatenated with a private key, optionally
concatenated with parameters. concatenated with DH parameters.
`ca_cert` is a CA certificate, or NULL if peer verification is not `ca_cert` is a CA certificate, or NULL if peer verification is not
required. required.
Return: NULL on success, or error message on error. Return: NULL on success, or error message on error.
......
...@@ -10,6 +10,9 @@ signature: | ...@@ -10,6 +10,9 @@ signature: |
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
/* SSL settings. */ /* SSL settings. */
const char *ssl_cert; /* Server certificate to present to clients */ const char *ssl_cert; /* Server certificate to present to clients */
const char *ssl_key; /* Private key corresponding to the certificate.
If ssl_cert is set but ssl_key is not, ssl_cert
is used. */
const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */ const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
#endif #endif
}; };
......
...@@ -10,6 +10,9 @@ signature: | ...@@ -10,6 +10,9 @@ signature: |
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
/* SSL settings. */ /* SSL settings. */
const char *ssl_cert; /* Client certificate to present to the server */ const char *ssl_cert; /* Client certificate to present to the server */
const char *ssl_key; /* Private key corresponding to the certificate.
If ssl_cert is set but ssl_key is not, ssl_cert
is used. */
const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */ const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
/* /*
......
...@@ -14,8 +14,17 @@ signature: | ...@@ -14,8 +14,17 @@ signature: |
size_t recv_mbuf_limit; /* Max size of recv buffer */ size_t recv_mbuf_limit; /* Max size of recv buffer */
struct mbuf recv_mbuf; /* Received data */ struct mbuf recv_mbuf; /* Received data */
struct mbuf send_mbuf; /* Data scheduled for sending */ struct mbuf send_mbuf; /* Data scheduled for sending */
#if defined(MG_ENABLE_SSL)
#if !defined(MG_SOCKET_SIMPLELINK)
SSL *ssl; SSL *ssl;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
#else
char *ssl_cert;
char *ssl_key;
char *ssl_ca_cert;
char *ssl_server_name;
#endif
#endif
time_t last_io_time; /* Timestamp of the last socket IO */ time_t last_io_time; /* Timestamp of the last socket IO */
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
mg_event_handler_t proto_handler; /* Protocol-specific event handler */ mg_event_handler_t proto_handler; /* Protocol-specific event handler */
......
...@@ -22,7 +22,7 @@ IPATH = . ../.. $(REPO_PATH) ...@@ -22,7 +22,7 @@ IPATH = . ../.. $(REPO_PATH)
VPATH = ../.. VPATH = ../..
MONGOOSE_FEATURES = -DMG_ENABLE_HTTP_STREAMING_MULTIPART MONGOOSE_FEATURES = -DMG_ENABLE_SSL -DMG_ENABLE_HTTP_STREAMING_MULTIPART
SDK_FLAGS = -DUSE_FREERTOS -DSL_PLATFORM_MULTI_THREADED SDK_FLAGS = -DUSE_FREERTOS -DSL_PLATFORM_MULTI_THREADED
# -DTARGET_IS_CC3200 would reduce code size by using functions in ROM # -DTARGET_IS_CC3200 would reduce code size by using functions in ROM
......
...@@ -167,7 +167,21 @@ static void mg_init(struct mg_mgr *mgr) { ...@@ -167,7 +167,21 @@ static void mg_init(struct mg_mgr *mgr) {
LOG(LL_ERROR, ("Failed to start NWP")); LOG(LL_ERROR, ("Failed to start NWP"));
return; return;
} }
LOG(LL_INFO, ("NWP started"));
{
SlVersionFull ver;
unsigned char opt = SL_DEVICE_GENERAL_VERSION;
unsigned char len = sizeof(ver);
memset(&ver, 0, sizeof(ver));
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &opt, &len,
(unsigned char *) (&ver));
LOG(LL_INFO, ("NWP v%d.%d.%d.%d started, host v%d.%d.%d.%d",
ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2],
ver.NwpVersion[3], SL_MAJOR_VERSION_NUM, SL_MINOR_VERSION_NUM,
SL_VERSION_NUM, SL_SUB_VERSION_NUM));
}
GPIO_IF_LedToggle(MCU_RED_LED_GPIO); GPIO_IF_LedToggle(MCU_RED_LED_GPIO);
data_init_sensors(TMP006_ADDR, BM222_ADDR); data_init_sensors(TMP006_ADDR, BM222_ADDR);
...@@ -194,7 +208,7 @@ static void mg_init(struct mg_mgr *mgr) { ...@@ -194,7 +208,7 @@ static void mg_init(struct mg_mgr *mgr) {
memset(&opts, 0, sizeof(opts)); memset(&opts, 0, sizeof(opts));
opts.error_string = &err; opts.error_string = &err;
struct mg_connection *nc = mg_bind(mgr, "80", mg_ev_handler); struct mg_connection *nc = mg_bind_opt(mgr, "80", mg_ev_handler, opts);
if (nc != NULL) { if (nc != NULL) {
mg_set_protocol_http_websocket(nc); mg_set_protocol_http_websocket(nc);
nc->ev_timer_time = mg_time(); /* Start data collection */ nc->ev_timer_time = mg_time(); /* Start data collection */
......
...@@ -2204,9 +2204,13 @@ void mg_if_timer(struct mg_connection *c, double now) { ...@@ -2204,9 +2204,13 @@ void mg_if_timer(struct mg_connection *c, double now) {
} }
void mg_if_poll(struct mg_connection *nc, time_t now) { void mg_if_poll(struct mg_connection *nc, time_t now) {
#if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (nc->ssl == NULL || (nc->flags & MG_F_SSL_HANDSHAKE_DONE)) { if (nc->ssl == NULL || (nc->flags & MG_F_SSL_HANDSHAKE_DONE)) {
mg_call(nc, NULL, MG_EV_POLL, &now); mg_call(nc, NULL, MG_EV_POLL, &now);
} }
#else
mg_call(nc, NULL, MG_EV_POLL, &now);
#endif
} }
static void mg_destroy_conn(struct mg_connection *conn) { static void mg_destroy_conn(struct mg_connection *conn) {
...@@ -2214,9 +2218,16 @@ static void mg_destroy_conn(struct mg_connection *conn) { ...@@ -2214,9 +2218,16 @@ static void mg_destroy_conn(struct mg_connection *conn) {
conn->proto_data_destructor(conn->proto_data); conn->proto_data_destructor(conn->proto_data);
} }
mg_if_destroy_conn(conn); mg_if_destroy_conn(conn);
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL)
#if !defined(MG_SOCKET_SIMPLELINK)
if (conn->ssl != NULL) SSL_free(conn->ssl); if (conn->ssl != NULL) SSL_free(conn->ssl);
if (conn->ssl_ctx != NULL) SSL_CTX_free(conn->ssl_ctx); if (conn->ssl_ctx != NULL) SSL_CTX_free(conn->ssl_ctx);
#else
MG_FREE(conn->ssl_cert);
MG_FREE(conn->ssl_key);
MG_FREE(conn->ssl_ca_cert);
MG_FREE(conn->ssl_server_name);
#endif
#endif #endif
mbuf_free(&conn->recv_mbuf); mbuf_free(&conn->recv_mbuf);
mbuf_free(&conn->send_mbuf); mbuf_free(&conn->send_mbuf);
...@@ -2250,7 +2261,7 @@ void mg_mgr_init(struct mg_mgr *m, void *user_data) { ...@@ -2250,7 +2261,7 @@ void mg_mgr_init(struct mg_mgr *m, void *user_data) {
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
#endif #endif
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
{ {
static int init_done; static int init_done;
if (!init_done) { if (!init_done) {
...@@ -2484,6 +2495,8 @@ MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa, ...@@ -2484,6 +2495,8 @@ MG_INTERNAL int mg_parse_address(const char *str, union socket_address *sa,
} }
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
#ifndef MG_SOCKET_SIMPLELINK
/* /*
* Certificate generation script is at * Certificate generation script is at
* https://github.com/cesanta/mongoose/blob/master/scripts/generate_ssl_certificates.sh * https://github.com/cesanta/mongoose/blob/master/scripts/generate_ssl_certificates.sh
...@@ -2559,13 +2572,13 @@ static int mg_use_ca_cert(SSL_CTX *ctx, const char *cert) { ...@@ -2559,13 +2572,13 @@ static int mg_use_ca_cert(SSL_CTX *ctx, const char *cert) {
return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? 0 : -2; return SSL_CTX_load_verify_locations(ctx, cert, NULL) == 1 ? 0 : -2;
} }
static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) { static int mg_use_cert(SSL_CTX *ctx, const char *cert, const char *key) {
if (ctx == NULL) { if (ctx == NULL) {
return -1; return -1;
} else if (pem_file == NULL || pem_file[0] == '\0') { } else if (cert == NULL || cert[0] == '\0' || key == NULL || key[0] == '\0') {
return 0; return 0;
} else if (SSL_CTX_use_certificate_file(ctx, pem_file, 1) == 0 || } else if (SSL_CTX_use_certificate_file(ctx, cert, 1) == 0 ||
SSL_CTX_use_PrivateKey_file(ctx, pem_file, 1) == 0) { SSL_CTX_use_PrivateKey_file(ctx, key, 1) == 0) {
return -2; return -2;
} else { } else {
#ifndef MG_DISABLE_PFS #ifndef MG_DISABLE_PFS
...@@ -2573,7 +2586,7 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) { ...@@ -2573,7 +2586,7 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) {
DH *dh = NULL; DH *dh = NULL;
/* Try to read DH parameters from the cert/key file. */ /* Try to read DH parameters from the cert/key file. */
bio = BIO_new_file(pem_file, "r"); bio = BIO_new_file(cert, "r");
if (bio != NULL) { if (bio != NULL) {
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio); BIO_free(bio);
...@@ -2594,7 +2607,7 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) { ...@@ -2594,7 +2607,7 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) {
} }
#endif #endif
SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
SSL_CTX_use_certificate_chain_file(ctx, pem_file); SSL_CTX_use_certificate_chain_file(ctx, cert);
return 0; return 0;
} }
} }
...@@ -2615,15 +2628,18 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) { ...@@ -2615,15 +2628,18 @@ static int mg_use_cert(SSL_CTX *ctx, const char *pem_file) {
* *
* Return NULL on success, or error message on failure. * Return NULL on success, or error message on failure.
*/ */
const char *mg_set_ssl(struct mg_connection *nc, const char *cert, static const char *mg_set_ssl2(struct mg_connection *nc, const char *cert,
const char *ca_cert) { const char *key, const char *ca_cert) {
const char *result = NULL; const char *result = NULL;
DBG(("%p %s %s", nc, (cert ? cert : ""), (ca_cert ? ca_cert : ""))); DBG(("%p %s,%s,%s", nc, (cert ? cert : ""), (key ? key : ""),
(ca_cert ? ca_cert : "")));
if (nc->flags & MG_F_UDP) { if (nc->flags & MG_F_UDP) {
return "SSL for UDP is not supported"; return "SSL for UDP is not supported";
} }
if (key == NULL && cert != NULL) key = cert;
if (nc->ssl != NULL) { if (nc->ssl != NULL) {
SSL_free(nc->ssl); SSL_free(nc->ssl);
nc->ssl = NULL; nc->ssl = NULL;
...@@ -2639,19 +2655,13 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert, ...@@ -2639,19 +2655,13 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
} else if (!(nc->flags & MG_F_LISTENING) && } else if (!(nc->flags & MG_F_LISTENING) &&
(nc->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { (nc->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
result = "SSL_CTX_new() failed"; result = "SSL_CTX_new() failed";
} else if (mg_use_cert(nc->ssl_ctx, cert) != 0) { } else if (mg_use_cert(nc->ssl_ctx, cert, key) != 0) {
result = "Invalid ssl cert"; result = "Invalid ssl cert";
} else if (mg_use_ca_cert(nc->ssl_ctx, ca_cert) != 0) { } else if (mg_use_ca_cert(nc->ssl_ctx, ca_cert) != 0) {
result = "Invalid CA cert"; result = "Invalid CA cert";
} else if (!(nc->flags & MG_F_LISTENING) && } else if (!(nc->flags & MG_F_LISTENING) &&
(nc->ssl = SSL_new(nc->ssl_ctx)) == NULL) { (nc->ssl = SSL_new(nc->ssl_ctx)) == NULL) {
result = "SSL_new() failed"; result = "SSL_new() failed";
} else if (!(nc->flags & MG_F_LISTENING) && nc->sock != INVALID_SOCKET) {
/*
* Socket is open here only if we are connecting to IP address
* and does not open if we are connecting using async DNS resolver
*/
SSL_set_fd(nc->ssl, nc->sock);
} }
#ifndef MG_DISABLE_PFS #ifndef MG_DISABLE_PFS
...@@ -2659,6 +2669,37 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert, ...@@ -2659,6 +2669,37 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
#endif #endif
return result; return result;
} }
const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
const char *ca_cert) {
return mg_set_ssl2(nc, cert, NULL, ca_cert);
}
#else /* !MG_SOCKET_SIMPLELINK */
static const char *mg_set_ssl2(struct mg_connection *nc, const char *cert,
const char *key, const char *ca_cert) {
DBG(("%p %s,%s,%s", nc, (cert ? cert : ""), (key ? key : ""),
(ca_cert ? ca_cert : "")));
if (nc->flags & MG_F_UDP) {
return "SSL for UDP is not supported";
}
if (cert != NULL || key != NULL) {
if (cert != NULL && key != NULL) {
nc->ssl_cert = strdup(cert);
nc->ssl_key = strdup(key);
} else {
return "both cert and key are required";
}
}
if (ca_cert != NULL) nc->ssl_ca_cert = strdup(ca_cert);
return NULL;
}
#endif /* MG_SOCKET_SIMPLELINK */
#endif /* MG_ENABLE_SSL */ #endif /* MG_ENABLE_SSL */
struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc) { struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc) {
...@@ -2672,8 +2713,7 @@ struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc) { ...@@ -2672,8 +2713,7 @@ struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc) {
nc->user_data = lc->user_data; nc->user_data = lc->user_data;
nc->recv_mbuf_limit = lc->recv_mbuf_limit; nc->recv_mbuf_limit = lc->recv_mbuf_limit;
mg_add_conn(nc->mgr, nc); mg_add_conn(nc->mgr, nc);
DBG(("%p %p %d %d, %p %p", lc, nc, nc->sock, (int) nc->flags, lc->ssl_ctx, DBG(("%p %p %d %d", lc, nc, nc->sock, (int) nc->flags));
nc->ssl));
return nc; return nc;
} }
...@@ -2875,20 +2915,28 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, ...@@ -2875,20 +2915,28 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
if ((nc = mg_create_connection(mgr, callback, add_sock_opts)) == NULL) { if ((nc = mg_create_connection(mgr, callback, add_sock_opts)) == NULL) {
return NULL; return NULL;
} else if ((rc = mg_parse_address(address, &nc->sa, &proto, host, }
sizeof(host))) < 0) {
if ((rc = mg_parse_address(address, &nc->sa, &proto, host, sizeof(host))) <
0) {
/* Address is malformed */ /* Address is malformed */
MG_SET_PTRPTR(opts.error_string, "cannot parse address"); MG_SET_PTRPTR(opts.error_string, "cannot parse address");
mg_destroy_conn(nc); mg_destroy_conn(nc);
return NULL; return NULL;
} }
nc->flags |= opts.flags & _MG_ALLOWED_CONNECT_FLAGS_MASK; nc->flags |= opts.flags & _MG_ALLOWED_CONNECT_FLAGS_MASK;
nc->flags |= (proto == SOCK_DGRAM) ? MG_F_UDP : 0; nc->flags |= (proto == SOCK_DGRAM) ? MG_F_UDP : 0;
nc->user_data = opts.user_data; nc->user_data = opts.user_data;
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
DBG(("%p %s %s %s %s", nc, address, (opts.ssl_cert ? opts.ssl_cert : ""),
(opts.ssl_key ? opts.ssl_key : ""),
(opts.ssl_ca_cert ? opts.ssl_ca_cert : "")));
if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) { if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
const char *err = mg_set_ssl(nc, opts.ssl_cert, opts.ssl_ca_cert); const char *err =
mg_set_ssl2(nc, opts.ssl_cert, opts.ssl_key, opts.ssl_ca_cert);
if (err != NULL) { if (err != NULL) {
MG_SET_PTRPTR(opts.error_string, err); MG_SET_PTRPTR(opts.error_string, err);
mg_destroy_conn(nc); mg_destroy_conn(nc);
...@@ -2899,6 +2947,8 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, ...@@ -2899,6 +2947,8 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
if (opts.ssl_server_name == NULL) opts.ssl_server_name = host; if (opts.ssl_server_name == NULL) opts.ssl_server_name = host;
#ifdef SSL_KRYPTON #ifdef SSL_KRYPTON
SSL_CTX_kr_set_verify_name(nc->ssl_ctx, opts.ssl_server_name); SSL_CTX_kr_set_verify_name(nc->ssl_ctx, opts.ssl_server_name);
#elif defined(MG_SOCKET_SIMPLELINK)
nc->ssl_server_name = strdup(opts.ssl_server_name);
#else #else
/* TODO(rojer): Implement server name verification on OpenSSL. */ /* TODO(rojer): Implement server name verification on OpenSSL. */
MG_SET_PTRPTR(opts.error_string, MG_SET_PTRPTR(opts.error_string,
...@@ -2970,8 +3020,25 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, ...@@ -2970,8 +3020,25 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
nc->sa = sa; nc->sa = sa;
nc->flags |= MG_F_LISTENING; nc->flags |= MG_F_LISTENING;
if (proto == SOCK_DGRAM) { if (proto == SOCK_DGRAM) nc->flags |= MG_F_UDP;
nc->flags |= MG_F_UDP;
#ifdef MG_ENABLE_SSL
DBG(("%p %s %s %s %s", nc, address, (opts.ssl_cert ? opts.ssl_cert : ""),
(opts.ssl_key ? opts.ssl_key : ""),
(opts.ssl_ca_cert ? opts.ssl_ca_cert : "")));
if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
const char *err =
mg_set_ssl2(nc, opts.ssl_cert, opts.ssl_key, opts.ssl_ca_cert);
if (err != NULL) {
MG_SET_PTRPTR(opts.error_string, err);
mg_destroy_conn(nc);
return NULL;
}
}
#endif /* MG_ENABLE_SSL */
if (nc->flags & MG_F_UDP) {
rc = mg_if_listen_udp(nc, &nc->sa); rc = mg_if_listen_udp(nc, &nc->sa);
} else { } else {
rc = mg_if_listen_tcp(nc, &nc->sa); rc = mg_if_listen_tcp(nc, &nc->sa);
...@@ -2982,16 +3049,6 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, ...@@ -2982,16 +3049,6 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
mg_destroy_conn(nc); mg_destroy_conn(nc);
return NULL; return NULL;
} }
#ifdef MG_ENABLE_SSL
if (opts.ssl_cert != NULL || opts.ssl_ca_cert != NULL) {
const char *err = mg_set_ssl(nc, opts.ssl_cert, opts.ssl_ca_cert);
if (err != NULL) {
MG_SET_PTRPTR(opts.error_string, err);
mg_destroy_conn(nc);
return NULL;
}
}
#endif /* MG_ENABLE_SSL */
mg_add_conn(nc->mgr, nc); mg_add_conn(nc->mgr, nc);
return nc; return nc;
...@@ -3130,8 +3187,9 @@ double mg_time() { ...@@ -3130,8 +3187,9 @@ double mg_time() {
#define MG_TCP_RECV_BUFFER_SIZE 1024 #define MG_TCP_RECV_BUFFER_SIZE 1024
#define MG_UDP_RECV_BUFFER_SIZE 1500 #define MG_UDP_RECV_BUFFER_SIZE 1500
static sock_t mg_open_listening_socket(union socket_address *sa, int proto); static sock_t mg_open_listening_socket(union socket_address *sa, int type,
#ifdef MG_ENABLE_SSL int proto);
#if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
static void mg_ssl_begin(struct mg_connection *nc); static void mg_ssl_begin(struct mg_connection *nc);
static int mg_ssl_err(struct mg_connection *conn, int res); static int mg_ssl_err(struct mg_connection *conn, int res);
#endif #endif
...@@ -3169,18 +3227,28 @@ int mg_is_error(int n) { ...@@ -3169,18 +3227,28 @@ int mg_is_error(int n) {
void mg_if_connect_tcp(struct mg_connection *nc, void mg_if_connect_tcp(struct mg_connection *nc,
const union socket_address *sa) { const union socket_address *sa) {
int rc; int rc, proto = 0;
nc->sock = socket(AF_INET, SOCK_STREAM, 0); #if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
if (nc->ssl_cert != NULL || nc->ssl_ca_cert != NULL) proto = SL_SEC_SOCKET;
#endif
nc->sock = socket(AF_INET, SOCK_STREAM, proto);
if (nc->sock == INVALID_SOCKET) { if (nc->sock == INVALID_SOCKET) {
nc->err = errno ? errno : 1; nc->err = errno ? errno : 1;
return; return;
} }
#if !defined(MG_SOCKET_SIMPLELINK) && !defined(MG_ESP8266) #if !defined(MG_SOCKET_SIMPLELINK) && !defined(MG_ESP8266)
mg_set_non_blocking_mode(nc->sock); mg_set_non_blocking_mode(nc->sock);
#endif
#if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
int is_ssl_no_vrfy = (nc->ssl_ca_cert != NULL && nc->ssl_ca_cert[0] == '\0');
if (!sl_set_ssl_opts(nc)) return;
#endif #endif
rc = connect(nc->sock, &sa->sa, sizeof(sa->sin)); rc = connect(nc->sock, &sa->sa, sizeof(sa->sin));
#if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
if (is_ssl_no_vrfy && rc == SL_ESECSNOVERIFY) rc = 0;
#endif
nc->err = mg_is_error(rc) ? errno : 0; nc->err = mg_is_error(rc) ? errno : 0;
DBG(("%p sock %d err %d", nc, nc->sock, nc->err)); LOG(LL_INFO, ("%p sock %d err %d", nc, nc->sock, nc->err));
} }
void mg_if_connect_udp(struct mg_connection *nc) { void mg_if_connect_udp(struct mg_connection *nc) {
...@@ -3193,16 +3261,23 @@ void mg_if_connect_udp(struct mg_connection *nc) { ...@@ -3193,16 +3261,23 @@ void mg_if_connect_udp(struct mg_connection *nc) {
} }
int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
sock_t sock = mg_open_listening_socket(sa, SOCK_STREAM); int proto = 0;
#if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
if (nc->ssl_cert != NULL || nc->ssl_ca_cert != NULL) proto = SL_SEC_SOCKET;
#endif
sock_t sock = mg_open_listening_socket(sa, SOCK_STREAM, proto);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
return (errno ? errno : 1); return (errno ? errno : 1);
} }
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
#if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
if (!sl_set_ssl_opts(nc)) return nc->err;
#endif
return 0; return 0;
} }
int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
sock_t sock = mg_open_listening_socket(sa, SOCK_DGRAM); sock_t sock = mg_open_listening_socket(sa, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) return (errno ? errno : 1); if (sock == INVALID_SOCKET) return (errno ? errno : 1);
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
return 0; return 0;
...@@ -3262,7 +3337,7 @@ static int mg_accept_conn(struct mg_connection *lc) { ...@@ -3262,7 +3337,7 @@ static int mg_accept_conn(struct mg_connection *lc) {
DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr), DBG(("%p conn from %s:%d", nc, inet_ntoa(sa.sin.sin_addr),
ntohs(sa.sin.sin_port))); ntohs(sa.sin.sin_port)));
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (lc->ssl_ctx != NULL) { if (lc->ssl_ctx != NULL) {
nc->ssl = SSL_new(lc->ssl_ctx); nc->ssl = SSL_new(lc->ssl_ctx);
if (nc->ssl == NULL || SSL_set_fd(nc->ssl, sock) != 1) { if (nc->ssl == NULL || SSL_set_fd(nc->ssl, sock) != 1) {
...@@ -3278,7 +3353,8 @@ static int mg_accept_conn(struct mg_connection *lc) { ...@@ -3278,7 +3353,8 @@ static int mg_accept_conn(struct mg_connection *lc) {
} }
/* 'sa' must be an initialized address to bind to */ /* 'sa' must be an initialized address to bind to */
static sock_t mg_open_listening_socket(union socket_address *sa, int proto) { static sock_t mg_open_listening_socket(union socket_address *sa, int type,
int proto) {
socklen_t sa_len = socklen_t sa_len =
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6); (sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
sock_t sock = INVALID_SOCKET; sock_t sock = INVALID_SOCKET;
...@@ -3286,7 +3362,7 @@ static sock_t mg_open_listening_socket(union socket_address *sa, int proto) { ...@@ -3286,7 +3362,7 @@ static sock_t mg_open_listening_socket(union socket_address *sa, int proto) {
int on = 1; int on = 1;
#endif #endif
if ((sock = socket(sa->sa.sa_family, proto, 0)) != INVALID_SOCKET && if ((sock = socket(sa->sa.sa_family, type, proto)) != INVALID_SOCKET &&
#if !defined(MG_SOCKET_SIMPLELINK) && \ #if !defined(MG_SOCKET_SIMPLELINK) && \
!defined(MG_LWIP) /* SimpleLink and LWIP don't support either */ !defined(MG_LWIP) /* SimpleLink and LWIP don't support either */
#if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE) #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)
...@@ -3310,7 +3386,7 @@ static sock_t mg_open_listening_socket(union socket_address *sa, int proto) { ...@@ -3310,7 +3386,7 @@ static sock_t mg_open_listening_socket(union socket_address *sa, int proto) {
#endif /* !MG_SOCKET_SIMPLELINK && !MG_LWIP */ #endif /* !MG_SOCKET_SIMPLELINK && !MG_LWIP */
!bind(sock, &sa->sa, sa_len) && !bind(sock, &sa->sa, sa_len) &&
(proto == SOCK_DGRAM || listen(sock, SOMAXCONN) == 0)) { (type == SOCK_DGRAM || listen(sock, SOMAXCONN) == 0)) {
#if !defined(MG_SOCKET_SIMPLELINK) && \ #if !defined(MG_SOCKET_SIMPLELINK) && \
!defined(MG_LWIP) /* TODO(rojer): Fix this. */ !defined(MG_LWIP) /* TODO(rojer): Fix this. */
mg_set_non_blocking_mode(sock); mg_set_non_blocking_mode(sock);
...@@ -3348,7 +3424,7 @@ static void mg_write_to_socket(struct mg_connection *nc) { ...@@ -3348,7 +3424,7 @@ static void mg_write_to_socket(struct mg_connection *nc) {
return; return;
} }
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (nc->ssl != NULL) { if (nc->ssl != NULL) {
if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) { if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
n = SSL_write(nc->ssl, io->buf, io->len); n = SSL_write(nc->ssl, io->buf, io->len);
...@@ -3396,7 +3472,7 @@ static void mg_read_from_socket(struct mg_connection *conn) { ...@@ -3396,7 +3472,7 @@ static void mg_read_from_socket(struct mg_connection *conn) {
return; return;
} }
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (conn->ssl != NULL) { if (conn->ssl != NULL) {
if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) { if (conn->flags & MG_F_SSL_HANDSHAKE_DONE) {
/* SSL library may have more bytes ready to read then we ask to read. /* SSL library may have more bytes ready to read then we ask to read.
...@@ -3464,7 +3540,7 @@ static void mg_handle_udp_read(struct mg_connection *nc) { ...@@ -3464,7 +3540,7 @@ static void mg_handle_udp_read(struct mg_connection *nc) {
mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len); mg_if_recv_udp_cb(nc, buf, n, &sa, sa_len);
} }
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
static int mg_ssl_err(struct mg_connection *conn, int res) { static int mg_ssl_err(struct mg_connection *conn, int res) {
int ssl_err = SSL_get_error(conn->ssl, res); int ssl_err = SSL_get_error(conn->ssl, res);
DBG(("%p %d -> %d", conn, res, ssl_err)); DBG(("%p %d -> %d", conn, res, ssl_err));
...@@ -3507,7 +3583,7 @@ static void mg_ssl_begin(struct mg_connection *nc) { ...@@ -3507,7 +3583,7 @@ static void mg_ssl_begin(struct mg_connection *nc) {
} }
} }
} }
#endif /* MG_ENABLE_SSL */ #endif /* defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK) */
#define _MG_F_FD_CAN_READ 1 #define _MG_F_FD_CAN_READ 1
#define _MG_F_FD_CAN_WRITE 1 << 1 #define _MG_F_FD_CAN_WRITE 1 << 1
...@@ -3533,8 +3609,12 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) { ...@@ -3533,8 +3609,12 @@ void mg_mgr_handle_conn(struct mg_connection *nc, int fd_flags, double now) {
* TODO(rojer): Figure out why it fails where blocking succeeds. * TODO(rojer): Figure out why it fails where blocking succeeds.
*/ */
err = nc->err; err = nc->err;
#if defined(MG_SOCKET_SIMPLELINK)
/* TODO(rojer): Provide API to set date. */
if (err == SL_ESECDATEERROR) err = 0;
#endif #endif
#ifdef MG_ENABLE_SSL #endif
#if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (nc->ssl != NULL && err == 0) { if (nc->ssl != NULL && err == 0) {
SSL_set_fd(nc->ssl, nc->sock); SSL_set_fd(nc->ssl, nc->sock);
mg_ssl_begin(nc); mg_ssl_begin(nc);
...@@ -7233,7 +7313,11 @@ static void mg_prepare_cgi_environment(struct mg_connection *nc, ...@@ -7233,7 +7313,11 @@ static void mg_prepare_cgi_environment(struct mg_connection *nc,
mg_addenv(blk, "PATH_TRANSLATED=%.*s", (int) path_info->len, path_info->p); mg_addenv(blk, "PATH_TRANSLATED=%.*s", (int) path_info->len, path_info->p);
} }
#ifdef MG_ENABLE_SSL
mg_addenv(blk, "HTTPS=%s", nc->ssl != NULL ? "on" : "off"); mg_addenv(blk, "HTTPS=%s", nc->ssl != NULL ? "on" : "off");
#else
mg_addenv(blk, "HTTPS=off");
#endif
if ((h = mg_get_http_header((struct http_message *) hm, "Content-Type")) != if ((h = mg_get_http_header((struct http_message *) hm, "Content-Type")) !=
NULL) { NULL) {
...@@ -7708,9 +7792,14 @@ struct mg_connection *mg_connect_http_base( ...@@ -7708,9 +7792,14 @@ struct mg_connection *mg_connect_http_base(
return NULL; return NULL;
} }
#endif #endif
#if defined(MG_ENABLE_SSL) && defined(MG_SOCKET_SIMPLELINK)
if (use_ssl && opts.ssl_ca_cert == NULL) {
opts.ssl_ca_cert = "";
}
#endif
if ((nc = mg_connect_opt(mgr, *addr, ev_handler, opts)) != NULL) { if ((nc = mg_connect_opt(mgr, *addr, ev_handler, opts)) != NULL) {
#ifdef MG_ENABLE_SSL #if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
if (use_ssl && nc->ssl_ctx == NULL) { if (use_ssl && nc->ssl_ctx == NULL) {
/* /*
* Schema requires SSL, but no SSL parameters were provided in * Schema requires SSL, but no SSL parameters were provided in
...@@ -11001,7 +11090,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { ...@@ -11001,7 +11090,7 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) {
char *inet_ntoa(struct in_addr n) { char *inet_ntoa(struct in_addr n) {
static char a[16]; static char a[16];
return (char *) inet_ntop(AF_INET, &n, a, sizeof(n)); return (char *) inet_ntop(AF_INET, &n, a, sizeof(a));
} }
int inet_pton(int af, const char *src, void *dst) { int inet_pton(int af, const char *src, void *dst) {
...@@ -11021,6 +11110,50 @@ int inet_pton(int af, const char *src, void *dst) { ...@@ -11021,6 +11110,50 @@ int inet_pton(int af, const char *src, void *dst) {
return 1; return 1;
} }
#ifdef MG_ENABLE_SSL
int sl_set_ssl_opts(struct mg_connection *nc) {
DBG(("%p %s,%s,%s,%s", nc, (nc->ssl_cert ? nc->ssl_cert : ""), (nc->ssl_key ? nc->ssl_cert : ""), (nc->ssl_ca_cert ? nc->ssl_ca_cert : ""), (nc->ssl_server_name ? nc->ssl_server_name : "")));
if (nc->ssl_cert != NULL && nc->ssl_key != NULL) {
nc->err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME,
nc->ssl_cert,
strlen(nc->ssl_cert));
DBG(("CERTIFICATE_FILE_NAME %s -> %d", nc->ssl_cert, nc->err));
if (nc->err != 0) return 0;
nc->err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME,
nc->ssl_key,
strlen(nc->ssl_key));
DBG(("PRIVATE_KEY_FILE_NAME %s -> %d", nc->ssl_key, nc->err));
if (nc->err != 0) return 0;
MG_FREE(nc->ssl_cert);
MG_FREE(nc->ssl_key);
nc->ssl_cert = nc->ssl_key = NULL;
}
if (nc->ssl_ca_cert != NULL && nc->ssl_ca_cert[0] != '\0') {
nc->err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CA_FILE_NAME,
nc->ssl_ca_cert,
strlen(nc->ssl_ca_cert));
DBG(("CA_FILE_NAME %s -> %d", nc->ssl_ca_cert, nc->err));
if (nc->err != 0) return 0;
MG_FREE(nc->ssl_ca_cert);
nc->ssl_ca_cert = NULL;
}
if (nc->ssl_server_name != NULL) {
nc->err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET,
SO_SECURE_DOMAIN_NAME_VERIFICATION,
nc->ssl_server_name,
strlen(nc->ssl_server_name));
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", nc->ssl_server_name, nc->err));
if (nc->err != 0) return 0;
MG_FREE(nc->ssl_server_name);
nc->ssl_server_name = NULL;
}
return 1;
}
#endif
#endif /* CS_COMMON_PLATFORMS_SIMPLELINK_SL_SOCKET_C_ */ #endif /* CS_COMMON_PLATFORMS_SIMPLELINK_SL_SOCKET_C_ */
#ifdef MG_MODULE_LINES #ifdef MG_MODULE_LINES
#line 1 "./src/../../common/platforms/simplelink/sl_mg_task.c" #line 1 "./src/../../common/platforms/simplelink/sl_mg_task.c"
......
...@@ -731,6 +731,7 @@ char *inet_ntoa(struct in_addr in); ...@@ -731,6 +731,7 @@ char *inet_ntoa(struct in_addr in);
int inet_pton(int af, const char *src, void *dst); int inet_pton(int af, const char *src, void *dst);
struct mg_mgr; struct mg_mgr;
struct mg_connection;
typedef void (*mg_init_cb)(struct mg_mgr *mgr); typedef void (*mg_init_cb)(struct mg_mgr *mgr);
bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init); bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init);
...@@ -739,6 +740,8 @@ void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg); ...@@ -739,6 +740,8 @@ void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg);
int sl_fs_init(); int sl_fs_init();
int sl_set_ssl_opts(struct mg_connection *nc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
...@@ -1172,11 +1175,10 @@ int json_emit_va(char *buf, int buf_len, const char *fmt, va_list); ...@@ -1172,11 +1175,10 @@ int json_emit_va(char *buf, int buf_len, const char *fmt, va_list);
#ifdef __APPLE__ #ifdef __APPLE__
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif #endif
#if !defined(MG_SOCKET_SIMPLELINK)
#include <openssl/ssl.h> #include <openssl/ssl.h>
#else
typedef void *SSL;
typedef void *SSL_CTX;
#endif #endif
#endif /* MG_ENABLE_SSL */
#ifndef MG_VPRINTF_BUFFER_SIZE #ifndef MG_VPRINTF_BUFFER_SIZE
#define MG_VPRINTF_BUFFER_SIZE 100 #define MG_VPRINTF_BUFFER_SIZE 100
...@@ -1257,8 +1259,17 @@ struct mg_connection { ...@@ -1257,8 +1259,17 @@ struct mg_connection {
size_t recv_mbuf_limit; /* Max size of recv buffer */ size_t recv_mbuf_limit; /* Max size of recv buffer */
struct mbuf recv_mbuf; /* Received data */ struct mbuf recv_mbuf; /* Received data */
struct mbuf send_mbuf; /* Data scheduled for sending */ struct mbuf send_mbuf; /* Data scheduled for sending */
#if defined(MG_ENABLE_SSL)
#if !defined(MG_SOCKET_SIMPLELINK)
SSL *ssl; SSL *ssl;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
#else
char *ssl_cert;
char *ssl_key;
char *ssl_ca_cert;
char *ssl_server_name;
#endif
#endif
time_t last_io_time; /* Timestamp of the last socket IO */ time_t last_io_time; /* Timestamp of the last socket IO */
double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */ double ev_timer_time; /* Timestamp of the future MG_EV_TIMER */
mg_event_handler_t proto_handler; /* Protocol-specific event handler */ mg_event_handler_t proto_handler; /* Protocol-specific event handler */
...@@ -1402,6 +1413,9 @@ struct mg_bind_opts { ...@@ -1402,6 +1413,9 @@ struct mg_bind_opts {
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
/* SSL settings. */ /* SSL settings. */
const char *ssl_cert; /* Server certificate to present to clients */ const char *ssl_cert; /* Server certificate to present to clients */
const char *ssl_key; /* Private key corresponding to the certificate.
If ssl_cert is set but ssl_key is not, ssl_cert
is used. */
const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */ const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
#endif #endif
}; };
...@@ -1442,6 +1456,9 @@ struct mg_connect_opts { ...@@ -1442,6 +1456,9 @@ struct mg_connect_opts {
#ifdef MG_ENABLE_SSL #ifdef MG_ENABLE_SSL
/* SSL settings. */ /* SSL settings. */
const char *ssl_cert; /* Client certificate to present to the server */ const char *ssl_cert; /* Client certificate to present to the server */
const char *ssl_key; /* Private key corresponding to the certificate.
If ssl_cert is set but ssl_key is not, ssl_cert
is used. */
const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */ const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
/* /*
...@@ -1515,19 +1532,23 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, ...@@ -1515,19 +1532,23 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
mg_event_handler_t handler, mg_event_handler_t handler,
struct mg_connect_opts opts); struct mg_connect_opts opts);
#if defined(MG_ENABLE_SSL) && !defined(MG_SOCKET_SIMPLELINK)
/* /*
* Note: This function is deprecated, please use SSL options in mg_connect_opt.
*
* Enable SSL for a given connection. * Enable SSL for a given connection.
* `cert` is a server certificate file name for a listening connection, * `cert` is a server certificate file name for a listening connection,
* or a client certificate file name for an outgoing connection. * or a client certificate file name for an outgoing connection.
* Certificate files must be in PEM format. Server certificate file * Certificate files must be in PEM format. Server certificate file
* must contain a certificate, concatenated with a private key, optionally * must contain a certificate, concatenated with a private key, optionally
* concatenated with parameters. * concatenated with DH parameters.
* `ca_cert` is a CA certificate, or NULL if peer verification is not * `ca_cert` is a CA certificate, or NULL if peer verification is not
* required. * required.
* Return: NULL on success, or error message on error. * Return: NULL on success, or error message on error.
*/ */
const char *mg_set_ssl(struct mg_connection *nc, const char *cert, const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
const char *ca_cert); const char *ca_cert);
#endif
/* /*
* Send data to the connection. * Send data to the connection.
......
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