diff --git a/server/core/config.c b/server/core/config.c index 274522468..ccbeee0e0 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -420,7 +420,7 @@ hashtable_memory_fns(monitorhash,strdup,NULL,free,NULL); /** Add the 5.5.5- string to the start of the version string if * the version string starts with "10.". - * This mimics MariaDB 10.0 replication which adds 5.5.5- for backwards compatibility. */ + * This mimics MariaDB 10.0 behavior which adds 5.5.5- for backwards compatibility. */ if(strncmp(version_string,"10.",3) == 0) { ((SERVICE *)(obj->element))->version_string = malloc((strlen(version_string) + diff --git a/server/core/service.c b/server/core/service.c index 5ba5d539d..8297ea6fd 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -136,7 +136,8 @@ SERVICE *service; service->routerModule = strdup(router); service->users_from_all = false; service->resources = NULL; - + service->ssl_mode = SSL_REQUIRED; + if (service->name == NULL || service->routerModule == NULL) { if (service->name) @@ -855,6 +856,16 @@ serviceOptimizeWildcard(SERVICE *service, int action) return 1; } +/** Enable or disable the service SSL capability*/ +int +serviceSetSSL(SERVICE *service, int action) +{ + if(action) + service->ssl_mode = SSL_REQUIRED; + else + service->ssl_mode = SSL_DISABLED; +} + /** * Whether to strip escape characters from the name of the database the client * is connecting to. diff --git a/server/include/service.h b/server/include/service.h index f26c99806..a6fea6d56 100644 --- a/server/include/service.h +++ b/server/include/service.h @@ -105,6 +105,12 @@ typedef struct server_ref_t{ SERVER* server; }SERVER_REF; +typedef enum { + SSL_DISABLED, + SSL_ENABLED, + SSL_REQUIRED +} ssl_mode_t; + /** * Defines a service within the gateway. * @@ -149,6 +155,7 @@ typedef struct service { FILTER_DEF **filters; /**< Ordered list of filters */ int n_filters; /**< Number of filters */ int conn_timeout; /*< Session timeout in seconds */ + ssl_mode_t ssl_mode; /*< one of DISABLED, ENABLED or REQUIRED */ char *weightby; struct service *next; /**< The next service in the linked list */ } SERVICE; diff --git a/server/modules/include/mysql_client_server_protocol.h b/server/modules/include/mysql_client_server_protocol.h index 46bbe296c..de8118659 100644 --- a/server/modules/include/mysql_client_server_protocol.h +++ b/server/modules/include/mysql_client_server_protocol.h @@ -97,6 +97,10 @@ typedef enum { MYSQL_AUTH_RECV, MYSQL_AUTH_FAILED, MYSQL_HANDSHAKE_FAILED, + MYSQL_AUTH_SSL_REQ, /*< client requested SSL */ + MYSQL_AUTH_SSL_EXCHANGE_DONE, /*< SSL handshake done */ + MYSQL_AUTH_SSL_EXCHANGE_ERR, /*< SSL handshake failure */ + MYSQL_AUTH_SSL_RECV, /*< */ MYSQL_IDLE } mysql_auth_state_t; diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index abdb4422c..d1e188281 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -242,7 +242,7 @@ MySQLSendHandshake(DCB* dcb) char server_scramble[GW_MYSQL_SCRAMBLE_SIZE + 1]=""; char *version_string; int len_version_string=0; - + MySQLProtocol *protocol = DCB_PROTOCOL(dcb, MySQLProtocol); GWBUF *buf; @@ -319,7 +319,16 @@ MySQLSendHandshake(DCB* dcb) mysql_server_capabilities_one[0] &= ~GW_MYSQL_CAPABILITIES_COMPRESS; - mysql_server_capabilities_one[0] &= ~GW_MYSQL_CAPABILITIES_SSL; + + if(dcb->service->ssl_mode != SSL_DISABLED) + { + mysql_server_capabilities_one[1] |= GW_MYSQL_CAPABILITIES_SSL >> 8; + } + else + { + mysql_server_capabilities_one[0] &= ~GW_MYSQL_CAPABILITIES_SSL; + } + memcpy(mysql_handshake_payload, mysql_server_capabilities_one, sizeof(mysql_server_capabilities_one)); mysql_handshake_payload = mysql_handshake_payload + sizeof(mysql_server_capabilities_one); @@ -402,7 +411,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) { uint8_t *stage1_hash = NULL; int auth_ret = -1; MYSQL_session *client_data = NULL; - + int ssl = 0; CHK_DCB(dcb); protocol = DCB_PROTOCOL(dcb, MySQLProtocol); @@ -451,6 +460,15 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) { &protocol->client_capabilities); */ + + ssl = protocol->client_capabilities & GW_MYSQL_CAPABILITIES_SSL; + + /** Client didn't requested SSL when SSL mode was required*/ + if(!ssl && protocol->owner_dcb->service->ssl_mode == SSL_REQUIRED) + { + return 1; + } + username = get_username_from_auth(username, client_auth_packet); if (username == NULL)