From 4a0cc8223e9805524e3a1d583ef848bf9efd178d Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov <rojer@cesanta.com> Date: Wed, 24 Feb 2016 14:14:07 +0100 Subject: [PATCH] Add SSL options to mg_{bind,connect}_opt PUBLISHED_FROM=7e28eb43742b76c073c9c2c879c64d7b4d3e9a7e --- mongoose.c | 38 ++++++++++++++++++++++++++++++++++++++ mongoose.h | 34 +++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/mongoose.c b/mongoose.c index 35ce2cfa5..6a20d0eb9 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2525,6 +2525,10 @@ const char *mg_set_ssl(struct mg_connection *nc, const char *cert, const char *result = NULL; DBG(("%p %s %s", nc, (cert ? cert : ""), (ca_cert ? ca_cert : ""))); + if (nc->flags & MG_F_UDP) { + return "SSL for UDP is not supported"; + } + if (nc->ssl != NULL) { SSL_free(nc->ssl); nc->ssl = NULL; @@ -2786,6 +2790,30 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, nc->flags |= (proto == SOCK_DGRAM) ? MG_F_UDP : 0; nc->user_data = opts.user_data; +#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; + } + if (opts.ssl_ca_cert != NULL && (opts.ssl_server_name == NULL || + strcmp(opts.ssl_server_name, "*") != 0)) { + if (opts.ssl_server_name == NULL) opts.ssl_server_name = host; +#ifdef SSL_KRYPTON + SSL_CTX_kr_set_verify_name(nc->ssl_ctx, opts.ssl_server_name); +#else + /* TODO(rojer): Implement server name verification on OpenSSL. */ + MG_SET_PTRPTR(opts.error_string, + "Server name verification requested but is not supported"); + mg_destroy_conn(nc); + return NULL; +#endif /* SSL_KRYPTON */ + } + } +#endif /* MG_ENABLE_SSL */ + if (rc == 0) { #ifndef MG_DISABLE_RESOLVER /* @@ -2858,6 +2886,16 @@ struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, mg_destroy_conn(nc); 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); return nc; diff --git a/mongoose.h b/mongoose.h index 928b49e5c..4b198f90b 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1191,6 +1191,11 @@ struct mg_bind_opts { void *user_data; /* Initial value for connection's user_data */ unsigned int flags; /* Extra connection flags */ const char **error_string; /* Placeholder for the error string */ +#ifdef MG_ENABLE_SSL + /* SSL settings. */ + const char *ssl_cert; /* Server certificate to present to clients */ + const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */ +#endif }; /* @@ -1217,14 +1222,29 @@ struct mg_connection *mg_bind(struct mg_mgr *, const char *, * Return a new listening connection, or `NULL` on error. * NOTE: Connection remains owned by the manager, do not free(). */ -struct mg_connection *mg_bind_opt(struct mg_mgr *, const char *, - mg_event_handler_t, struct mg_bind_opts); +struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler, + struct mg_bind_opts opts); /* Optional parameters to mg_connect_opt() */ struct mg_connect_opts { void *user_data; /* Initial value for connection's user_data */ unsigned int flags; /* Extra connection flags */ const char **error_string; /* Placeholder for the error string */ +#ifdef MG_ENABLE_SSL + /* SSL settings. */ + const char *ssl_cert; /* Client certificate to present to the server */ + const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */ + + /* + * Server name verification. If ssl_ca_cert is set and the certificate has + * passed verification, its subject will be verified against this string. + * By default (if ssl_server_name is NULL) hostname part of the address will + * be used. Wildcard matching is supported. A special value of "*" disables + * name verification. + */ + const char *ssl_server_name; +#endif }; /* @@ -1232,8 +1252,8 @@ struct mg_connect_opts { * * See `mg_connect_opt()` for full documentation. */ -struct mg_connection *mg_connect(struct mg_mgr *, const char *, - mg_event_handler_t); +struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler); /* * Connect to a remote host. @@ -1284,9 +1304,9 @@ struct mg_connection *mg_connect(struct mg_mgr *, const char *, * mg_connect(mgr, "my_site.com:80", ev_handler); * ---- */ -struct mg_connection *mg_connect_opt(struct mg_mgr *, const char *, - mg_event_handler_t, - struct mg_connect_opts); +struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address, + mg_event_handler_t handler, + struct mg_connect_opts opts); /* * Enable SSL for a given connection. -- GitLab