From 67626d49c91e2c043352571a32e1a0dfa0e9b279 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov <rojer@cesanta.com> Date: Tue, 10 Jan 2017 00:44:44 +0100 Subject: [PATCH] Add ssl_cipher_suites to mg_{bind,connect}_opts Optional specification of SSL/TLS cipher suites. PUBLISHED_FROM=e8968c6c7a92f10514d3ee575c2fb9be862e6cf8 --- docs/c-api/net.h/struct_mg_bind_opts.md | 33 +++++++--- docs/c-api/net.h/struct_mg_connect_opts.md | 36 ++++++++--- mongoose.c | 22 +++++-- mongoose.h | 70 ++++++++++++++++------ 4 files changed, 119 insertions(+), 42 deletions(-) diff --git a/docs/c-api/net.h/struct_mg_bind_opts.md b/docs/c-api/net.h/struct_mg_bind_opts.md index 18dfc3d4a..13217ec79 100644 --- a/docs/c-api/net.h/struct_mg_bind_opts.md +++ b/docs/c-api/net.h/struct_mg_bind_opts.md @@ -9,15 +9,30 @@ signature: | const char **error_string; /* Placeholder for the error string */ struct mg_iface *iface; /* Interface instance */ #if MG_ENABLE_SSL - /* SSL settings. */ - const char *ssl_cert; /* Server certificate to present to clients - * Or client certificate to present to tunnel - * dispatcher. */ - 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; /* CA bundle used to verify client certificates or - * tunnel dispatchers. */ + /* + * SSL settings. + * + * Server certificate to present to clients or client certificate to + * present to tunnel dispatcher (for tunneled connections). + */ + const char *ssl_cert; + /* Private key corresponding to the certificate. If ssl_cert is set but + * ssl_key is not, ssl_cert is used. */ + const char *ssl_key; + /* CA bundle used to verify client certificates or tunnel dispatchers. */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; #endif }; --- diff --git a/docs/c-api/net.h/struct_mg_connect_opts.md b/docs/c-api/net.h/struct_mg_connect_opts.md index 2d07a21f8..00ee8dd56 100644 --- a/docs/c-api/net.h/struct_mg_connect_opts.md +++ b/docs/c-api/net.h/struct_mg_connect_opts.md @@ -9,15 +9,33 @@ signature: | const char **error_string; /* Placeholder for the error string */ struct mg_iface *iface; /* Interface instance */ #if MG_ENABLE_SSL - /* SSL settings. */ - 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. - If set to "*", then SSL is enabled but no cert - verification is performed. */ - + /* + * SSL settings. + * Client certificate to present to the server. + */ + const char *ssl_cert; + /* + * Private key corresponding to the certificate. + * If ssl_cert is set but ssl_key is not, ssl_cert is used. + */ + const char *ssl_key; + /* + * Verify server certificate using this CA bundle. If set to "*", then SSL + * is enabled but no cert verification is performed. + */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; /* * Server name verification. If ssl_ca_cert is set and the certificate has * passed verification, its subject will be verified against this string. diff --git a/mongoose.c b/mongoose.c index ec452a8c9..8958a9c1a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2746,6 +2746,7 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, params.cert = opts.ssl_cert; params.key = opts.ssl_key; params.ca_cert = opts.ssl_ca_cert; + params.cipher_suites = opts.ssl_cipher_suites; if (opts.ssl_ca_cert != NULL) { if (opts.ssl_server_name != NULL) { if (strcmp(opts.ssl_server_name, "*") != 0) { @@ -2850,6 +2851,7 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, params.cert = opts.ssl_cert; params.key = opts.ssl_key; params.ca_cert = opts.ssl_ca_cert; + params.cipher_suites = opts.ssl_cipher_suites; if (mg_ssl_if_conn_init(nc, ¶ms, &err_msg) != MG_SSL_OK) { MG_SET_PTRPTR(opts.error_string, err_msg); mg_destroy_conn(nc, 1 /* destroy_if */); @@ -4060,7 +4062,7 @@ enum mg_ssl_if_result mg_ssl_if_conn_accept(struct mg_connection *nc, static enum mg_ssl_if_result mg_use_cert(SSL_CTX *ctx, const char *cert, const char *key, const char **err_msg); static enum mg_ssl_if_result mg_use_ca_cert(SSL_CTX *ctx, const char *cert); -static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx); +static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl); enum mg_ssl_if_result mg_ssl_if_conn_init( struct mg_connection *nc, const struct mg_ssl_if_conn_params *params, @@ -4105,7 +4107,10 @@ enum mg_ssl_if_result mg_ssl_if_conn_init( #endif } - mg_set_cipher_list(ctx->ssl_ctx); + if (mg_set_cipher_list(ctx->ssl_ctx, params->cipher_suites) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid cipher suite list"); + return MG_SSL_ERROR; + } if (!(nc->flags & MG_F_LISTENING) && (ctx->ssl = SSL_new(ctx->ssl_ctx)) == NULL) { @@ -4287,9 +4292,10 @@ static enum mg_ssl_if_result mg_use_cert(SSL_CTX *ctx, const char *cert, return MG_SSL_OK; } -static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx) { - return (SSL_CTX_set_cipher_list(ctx, mg_s_cipher_list) == 1 ? MG_SSL_OK - : MG_SSL_ERROR); +static enum mg_ssl_if_result mg_set_cipher_list(SSL_CTX *ctx, const char *cl) { + return (SSL_CTX_set_cipher_list(ctx, cl ? cl : mg_s_cipher_list) == 1 + ? MG_SSL_OK + : MG_SSL_ERROR); } const char *mg_set_ssl(struct mg_connection *nc, const char *cert, @@ -4418,7 +4424,10 @@ enum mg_ssl_if_result mg_ssl_if_conn_init( return MG_SSL_ERROR; } - mg_set_cipher_list(ctx, NULL); + if (mg_set_cipher_list(ctx, params->cipher_suites) != MG_SSL_OK) { + MG_SET_PTRPTR(err_msg, "Invalid cipher suite list"); + return MG_SSL_ERROR; + } if (!(nc->flags & MG_F_LISTENING)) { ctx->ssl = MG_CALLOC(1, sizeof(*ctx->ssl)); @@ -13493,6 +13502,7 @@ enum mg_ssl_if_result mg_ssl_if_conn_init( if (params->ca_cert != NULL && strcmp(params->ca_cert, "*") != 0) { ctx->ssl_ca_cert = strdup(params->ca_cert); } + /* TODO(rojer): cipher_suites. */ if (params->server_name != NULL) { ctx->ssl_server_name = strdup(params->server_name); } diff --git a/mongoose.h b/mongoose.h index bb27c3fb6..84e2fcfd5 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3152,6 +3152,7 @@ struct mg_ssl_if_conn_params { const char *key; const char *ca_cert; const char *server_name; + const char *cipher_suites; }; enum mg_ssl_if_result mg_ssl_if_conn_init( @@ -3471,15 +3472,30 @@ struct mg_bind_opts { const char **error_string; /* Placeholder for the error string */ struct mg_iface *iface; /* Interface instance */ #if MG_ENABLE_SSL - /* SSL settings. */ - const char *ssl_cert; /* Server certificate to present to clients - * Or client certificate to present to tunnel - * dispatcher. */ - 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; /* CA bundle used to verify client certificates or - * tunnel dispatchers. */ + /* + * SSL settings. + * + * Server certificate to present to clients or client certificate to + * present to tunnel dispatcher (for tunneled connections). + */ + const char *ssl_cert; + /* Private key corresponding to the certificate. If ssl_cert is set but + * ssl_key is not, ssl_cert is used. */ + const char *ssl_key; + /* CA bundle used to verify client certificates or tunnel dispatchers. */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; #endif }; @@ -3519,15 +3535,33 @@ struct mg_connect_opts { const char **error_string; /* Placeholder for the error string */ struct mg_iface *iface; /* Interface instance */ #if MG_ENABLE_SSL - /* SSL settings. */ - 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. - If set to "*", then SSL is enabled but no cert - verification is performed. */ - + /* + * SSL settings. + * Client certificate to present to the server. + */ + const char *ssl_cert; + /* + * Private key corresponding to the certificate. + * If ssl_cert is set but ssl_key is not, ssl_cert is used. + */ + const char *ssl_key; + /* + * Verify server certificate using this CA bundle. If set to "*", then SSL + * is enabled but no cert verification is performed. + */ + const char *ssl_ca_cert; + /* Colon-delimited list of acceptable cipher suites. + * Names depend on the library used, for example: + * + * ECDH-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256 (OpenSSL) + * TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 + * (mbedTLS) + * + * For OpenSSL the list can be obtained by running "openssl ciphers". + * For mbedTLS, names can be found in library/ssl_ciphersuites.c + * If NULL, a reasonable default is used. + */ + const char *ssl_cipher_suites; /* * Server name verification. If ssl_ca_cert is set and the certificate has * passed verification, its subject will be verified against this string. -- GitLab