Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -2387,6 +2387,49 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
#endif
return result;
}

/*
* Turn the connection into SSL mode.
* `cert` is the certificate file in PEM format. For listening connections,
* certificate file must contain private key and server certificate,
* concatenated. It may also contain DH params - these will be used for more
* secure key exchange. `ca_cert` is a certificate authority (CA) PEM file, and
* it is optional (can be set to NULL). If `ca_cert` is non-NULL, then
* the connection is so-called two-way-SSL: other peer's certificate is
* checked against the `ca_cert`.
*
* Handy OpenSSL command to generate test self-signed certificate:
*
* openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 999
*
* Return NULL on success, or error message on failure.
*/
const char *mg_set_ssl_server(struct mg_connection *nc, const char *cert,
const char *ca_cert) {
const char *result = NULL;
DBG(("%p %s %s", nc, (cert ? cert : ""), (ca_cert ? ca_cert : "")));

if ((nc->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
result = "SSL_CTX_new() failed";
} else if (mg_use_cert(nc->ssl_ctx, cert) != 0) {
result = "Invalid ssl cert";
} else if (mg_use_ca_cert(nc->ssl_ctx, ca_cert) != 0) {
result = "Invalid CA cert";
} else if ((nc->ssl = SSL_new(nc->ssl_ctx)) == NULL) {
result = "SSL_new() failed";
} else if (nc->sock != INVALID_SOCKET) {
SSL_set_fd(nc->ssl, nc->sock);
}

nc->flags |= MG_F_SSL_SERVER_TRANSITION;

/* TODO(rojer): remove when krypton exposes this function, even a dummy one */
#ifdef OPENSSL_VERSION_NUMBER
SSL_CTX_set_cipher_list(nc->ssl_ctx, mg_s_cipher_list);
#endif
return result;
}

#endif /* MG_ENABLE_SSL */

struct mg_connection *mg_if_accept_tcp_cb(struct mg_connection *lc,
Expand Down Expand Up @@ -3139,7 +3182,7 @@ static int mg_ssl_err(struct mg_connection *conn, int res) {
}

static void mg_ssl_begin(struct mg_connection *nc) {
int server_side = nc->listener != NULL;
int server_side = nc->listener != NULL || nc->flags & MG_F_SSL_SERVER_TRANSITION;
int res = server_side ? SSL_accept(nc->ssl) : SSL_connect(nc->ssl);
DBG(("%p %d res %d %d %d", nc, server_side, res, errno, mg_ssl_err(nc, res)));

Expand Down
17 changes: 17 additions & 0 deletions mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ struct mg_connection {
#define MG_F_WANT_READ (1 << 5) /* SSL specific */
#define MG_F_WANT_WRITE (1 << 6) /* SSL specific */
#define MG_F_IS_WEBSOCKET (1 << 7) /* Websocket specific */
#define MG_F_SSL_SERVER_TRANSITION (1 << 8) /* Transition from plain socket to server */

/* Flags that are settable by user */
#define MG_F_SEND_AND_CLOSE (1 << 10) /* Push remaining data and close */
Expand Down Expand Up @@ -1012,6 +1013,14 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *, const char *,
const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
const char *ca_cert);

/*
* Enable SSL for a given connection; make the connection an SSL server
* The meaning of certification parameters are the same as in mg_set_ssl.
* Return: NULL on success, or error message on error.
*/
const char *mg_set_ssl_server(struct mg_connection *nc, const char *cert,
const char *ca_cert);

/*
* Send data to the connection.
*
Expand Down Expand Up @@ -1137,6 +1146,10 @@ double mg_set_timer(struct mg_connection *c, double timestamp);
#ifndef MG_NET_IF_HEADER_INCLUDED
#define MG_NET_IF_HEADER_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*
* Internal async networking core interface.
* Consists of calls made by the core, which should not block,
Expand Down Expand Up @@ -1201,6 +1214,10 @@ void mg_close_conn(struct mg_connection *nc);
void mg_if_get_conn_addr(struct mg_connection *nc, int remote,
union socket_address *sa);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* MG_NET_IF_HEADER_INCLUDED */
/*
* Copyright (c) 2014 Cesanta Software Limited
Expand Down