Split off listener functionality and move SSL initiation from service to listener. Put GWPROTOCOL in its own header file.
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
add_library(maxscale-common SHARED adminusers.c atomic.c buffer.c config.c dbusers.c dcb.c filter.c externcmd.c gwbitmask.c gwdirs.c gw_utils.c hashtable.c hint.c housekeeper.c load_utils.c maxscale_pcre2.c memlog.c modutil.c monitor.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc ${CMAKE_SOURCE_DIR}/utils/skygw_utils.cc)
|
add_library(maxscale-common SHARED adminusers.c atomic.c buffer.c config.c dbusers.c dcb.c filter.c externcmd.c gwbitmask.c gwdirs.c gw_utils.c hashtable.c hint.c housekeeper.c listener.c load_utils.c maxscale_pcre2.c memlog.c modutil.c monitor.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc ${CMAKE_SOURCE_DIR}/utils/skygw_utils.cc)
|
||||||
|
|
||||||
target_link_libraries(maxscale-common ${EMBEDDED_LIB} ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} ${PCRE_LINK_FLAGS} ${CURL_LIBRARIES} ssl aio pthread crypt dl crypto inih z rt m stdc++)
|
target_link_libraries(maxscale-common ${EMBEDDED_LIB} ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} ${PCRE_LINK_FLAGS} ${CURL_LIBRARIES} ssl aio pthread crypt dl crypto inih z rt m stdc++)
|
||||||
|
|
||||||
|
@ -43,7 +43,8 @@
|
|||||||
* 20/02/15 Markus Mäkelä Added connection_timeout parameter for services
|
* 20/02/15 Markus Mäkelä Added connection_timeout parameter for services
|
||||||
* 05/03/15 Massimiliano Pinto Added notification_feedback support
|
* 05/03/15 Massimiliano Pinto Added notification_feedback support
|
||||||
* 20/04/15 Guillaume Lefranc Added available_when_donor parameter
|
* 20/04/15 Guillaume Lefranc Added available_when_donor parameter
|
||||||
* 22/04/15 Martin Brampton Added disable_master_role_setting parameter
|
* 22/04/15 Martin Brampton Added disable_master_role_setting parameter
|
||||||
|
* 26/01/16 Martin Brampton Transfer SSL processing to listener
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -90,6 +91,8 @@ static void global_defaults();
|
|||||||
static void feedback_defaults();
|
static void feedback_defaults();
|
||||||
static void check_config_objects(CONFIG_CONTEXT *context);
|
static void check_config_objects(CONFIG_CONTEXT *context);
|
||||||
static int maxscale_getline(char** dest, int* size, FILE* file);
|
static int maxscale_getline(char** dest, int* size, FILE* file);
|
||||||
|
static SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj);
|
||||||
|
|
||||||
int config_truth_value(char *str);
|
int config_truth_value(char *str);
|
||||||
int config_get_ifaddr(unsigned char *output);
|
int config_get_ifaddr(unsigned char *output);
|
||||||
int config_get_release_string(char* release);
|
int config_get_release_string(char* release);
|
||||||
@ -99,7 +102,7 @@ bool config_has_duplicate_sections(const char* config);
|
|||||||
int create_new_service(CONFIG_CONTEXT *obj);
|
int create_new_service(CONFIG_CONTEXT *obj);
|
||||||
int create_new_server(CONFIG_CONTEXT *obj);
|
int create_new_server(CONFIG_CONTEXT *obj);
|
||||||
int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE* monitorhash);
|
int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE* monitorhash);
|
||||||
int create_new_listener(CONFIG_CONTEXT *obj);
|
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow);
|
||||||
int create_new_filter(CONFIG_CONTEXT *obj);
|
int create_new_filter(CONFIG_CONTEXT *obj);
|
||||||
int configure_new_service(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj);
|
int configure_new_service(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj);
|
||||||
|
|
||||||
@ -150,6 +153,13 @@ static char *listener_params[] =
|
|||||||
"port",
|
"port",
|
||||||
"address",
|
"address",
|
||||||
"socket",
|
"socket",
|
||||||
|
"authenticator",
|
||||||
|
"ssl_cert",
|
||||||
|
"ssl_ca_cert",
|
||||||
|
"ssl",
|
||||||
|
"ssl_key",
|
||||||
|
"ssl_version",
|
||||||
|
"ssl_cert_verify_depth",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -585,7 +595,7 @@ process_config_context(CONFIG_CONTEXT *context)
|
|||||||
}
|
}
|
||||||
else if (!strcmp(type, "listener"))
|
else if (!strcmp(type, "listener"))
|
||||||
{
|
{
|
||||||
error_count += create_new_listener(obj);
|
error_count += create_new_listener(obj, false);
|
||||||
}
|
}
|
||||||
else if (!strcmp(type, "monitor"))
|
else if (!strcmp(type, "monitor"))
|
||||||
{
|
{
|
||||||
@ -909,6 +919,7 @@ static struct
|
|||||||
{ "log_info", LOG_INFO, NULL },
|
{ "log_info", LOG_INFO, NULL },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration handler for items in the global [MaxScale] section
|
* Configuration handler for items in the global [MaxScale] section
|
||||||
*
|
*
|
||||||
@ -1022,6 +1033,118 @@ handle_global_item(const char *name, const char *value)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form an SSL structure from listener section parameters
|
||||||
|
*
|
||||||
|
* @param name The item name
|
||||||
|
* @param value The item value
|
||||||
|
* @return 0 on error
|
||||||
|
*/
|
||||||
|
static SSL_LISTENER *
|
||||||
|
make_ssl_structure (CONFIG_CONTEXT *obj)
|
||||||
|
{
|
||||||
|
char *ssl, *ssl_version, *ssl_cert, *ssl_key, *ssl_ca_cert, *ssl_cert_verify_depth;
|
||||||
|
SSL_LISTENER *new_ssl;
|
||||||
|
int error_count = 0;
|
||||||
|
|
||||||
|
ssl = config_get_value(obj->parameters, "ssl");
|
||||||
|
if (ssl && !strcmp(ssl, "required"))
|
||||||
|
{
|
||||||
|
if ((new_ssl = malloc(sizeof(SSL_LISTENER))) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
new_ssl->ssl_method_type = SERVICE_SSL_TLS_MAX;
|
||||||
|
ssl_cert = config_get_value(obj->parameters, "ssl_cert");
|
||||||
|
ssl_key = config_get_value(obj->parameters, "ssl_key");
|
||||||
|
ssl_ca_cert = config_get_value(obj->parameters, "ssl_ca_cert");
|
||||||
|
ssl_version = config_get_value(obj->parameters, "ssl_version");
|
||||||
|
ssl_cert_verify_depth = config_get_value(obj->parameters, "ssl_cert_verify_depth");
|
||||||
|
new_ssl->ssl_init_done = false;
|
||||||
|
|
||||||
|
if (ssl_version)
|
||||||
|
{
|
||||||
|
if (listener_set_ssl_version(new_ssl, ssl_version) != 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Unknown parameter value for 'ssl_version' for"
|
||||||
|
" service '%s': %s", obj->object, ssl_version);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_cert_verify_depth)
|
||||||
|
{
|
||||||
|
new_ssl->ssl_cert_verify_depth = atoi(ssl_cert_verify_depth);
|
||||||
|
if (new_ssl->ssl_cert_verify_depth < 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Invalid parameter value for 'ssl_cert_verify_depth"
|
||||||
|
" for service '%s': %s", obj->object, ssl_cert_verify_depth);
|
||||||
|
new_ssl->ssl_cert_verify_depth = 0;
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listener_set_certificates(new_ssl, ssl_cert, ssl_key, ssl_ca_cert);
|
||||||
|
|
||||||
|
if (new_ssl->ssl_cert == NULL)
|
||||||
|
{
|
||||||
|
error_count++;
|
||||||
|
MXS_ERROR("Server certificate missing for service '%s'."
|
||||||
|
"Please provide the path to the server certificate by adding "
|
||||||
|
"the ssl_cert=<path> parameter", obj->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_ssl->ssl_ca_cert == NULL)
|
||||||
|
{
|
||||||
|
error_count++;
|
||||||
|
MXS_ERROR("CA Certificate missing for service '%s'."
|
||||||
|
"Please provide the path to the certificate authority "
|
||||||
|
"certificate by adding the ssl_ca_cert=<path> parameter",
|
||||||
|
obj->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_ssl->ssl_key == NULL)
|
||||||
|
{
|
||||||
|
error_count++;
|
||||||
|
MXS_ERROR("Server private key missing for service '%s'. "
|
||||||
|
"Please provide the path to the server certificate key by "
|
||||||
|
"adding the ssl_key=<path> parameter",
|
||||||
|
obj->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(new_ssl->ssl_ca_cert, F_OK) != 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Certificate authority file for service '%s' not found: %s",
|
||||||
|
obj->object,
|
||||||
|
new_ssl->ssl_ca_cert);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(new_ssl->ssl_cert, F_OK) != 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Server certificate file for service '%s' not found: %s",
|
||||||
|
obj->object,
|
||||||
|
new_ssl->ssl_cert);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access(new_ssl->ssl_key, F_OK) != 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Server private key file for service '%s' not found: %s",
|
||||||
|
obj->object,
|
||||||
|
new_ssl->ssl_key);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error_count == 0)
|
||||||
|
{
|
||||||
|
return new_ssl;
|
||||||
|
}
|
||||||
|
free(new_ssl);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration handler for items in the feedback [feedback] section
|
* Configuration handler for items in the feedback [feedback] section
|
||||||
*
|
*
|
||||||
@ -1386,52 +1509,7 @@ process_config_update(CONFIG_CONTEXT *context)
|
|||||||
}
|
}
|
||||||
else if (!strcmp(type, "listener"))
|
else if (!strcmp(type, "listener"))
|
||||||
{
|
{
|
||||||
char *service;
|
create_new_listener(obj, true);
|
||||||
char *port;
|
|
||||||
char *protocol;
|
|
||||||
char *address;
|
|
||||||
char *socket;
|
|
||||||
|
|
||||||
service = config_get_value(obj->parameters, "service");
|
|
||||||
address = config_get_value(obj->parameters, "address");
|
|
||||||
port = config_get_value(obj->parameters, "port");
|
|
||||||
protocol = config_get_value(obj->parameters, "protocol");
|
|
||||||
socket = config_get_value(obj->parameters, "socket");
|
|
||||||
|
|
||||||
if (service && socket && protocol)
|
|
||||||
{
|
|
||||||
CONFIG_CONTEXT *ptr = context;
|
|
||||||
while (ptr && strcmp(ptr->object, service) != 0)
|
|
||||||
{
|
|
||||||
ptr = ptr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr &&
|
|
||||||
ptr->element &&
|
|
||||||
serviceHasProtocol(ptr->element, protocol, 0) == 0)
|
|
||||||
{
|
|
||||||
serviceAddProtocol(ptr->element, protocol, socket, 0);
|
|
||||||
serviceStartProtocol(ptr->element, protocol, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service && port && protocol)
|
|
||||||
{
|
|
||||||
CONFIG_CONTEXT *ptr = context;
|
|
||||||
|
|
||||||
while (ptr && strcmp(ptr->object, service) != 0)
|
|
||||||
{
|
|
||||||
ptr = ptr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr &&
|
|
||||||
ptr->element &&
|
|
||||||
serviceHasProtocol(ptr->element, protocol, atoi(port)) == 0)
|
|
||||||
{
|
|
||||||
serviceAddProtocol(ptr->element, protocol, address, atoi(port));
|
|
||||||
serviceStartProtocol(ptr->element, protocol, atoi(port));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (strcmp(type, "server") != 0 &&
|
else if (strcmp(type, "server") != 0 &&
|
||||||
strcmp(type, "monitor") != 0 &&
|
strcmp(type, "monitor") != 0 &&
|
||||||
@ -2633,9 +2711,10 @@ int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE*
|
|||||||
/**
|
/**
|
||||||
* Create a new listener for a service
|
* Create a new listener for a service
|
||||||
* @param obj Listener configuration context
|
* @param obj Listener configuration context
|
||||||
|
* @param startnow If true, start the listener now
|
||||||
* @return Number of errors
|
* @return Number of errors
|
||||||
*/
|
*/
|
||||||
int create_new_listener(CONFIG_CONTEXT *obj)
|
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
|
||||||
{
|
{
|
||||||
int error_count = 0;
|
int error_count = 0;
|
||||||
char *service_name = config_get_value(obj->parameters, "service");
|
char *service_name = config_get_value(obj->parameters, "service");
|
||||||
@ -2643,20 +2722,52 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
|||||||
char *address = config_get_value(obj->parameters, "address");
|
char *address = config_get_value(obj->parameters, "address");
|
||||||
char *protocol = config_get_value(obj->parameters, "protocol");
|
char *protocol = config_get_value(obj->parameters, "protocol");
|
||||||
char *socket = config_get_value(obj->parameters, "socket");
|
char *socket = config_get_value(obj->parameters, "socket");
|
||||||
|
char *authenticator = config_get_value(obj->parameters, "authenticator");
|
||||||
|
|
||||||
if (service_name && protocol && (socket || port))
|
if (service_name && protocol && (socket || port))
|
||||||
{
|
{
|
||||||
SERVICE *service = service_find(service_name);
|
SERVICE *service = service_find(service_name);
|
||||||
if (service)
|
if (service)
|
||||||
{
|
{
|
||||||
|
SSL_LISTENER *ssl_info = make_ssl_structure(obj);
|
||||||
if (socket)
|
if (socket)
|
||||||
{
|
{
|
||||||
serviceAddProtocol(service, protocol, socket, 0);
|
if (serviceHasProtocol(service, protocol, 0))
|
||||||
|
{
|
||||||
|
MXS_ERROR("Listener '%s', for service '%s', socket %s, already have socket.",
|
||||||
|
obj->object,
|
||||||
|
service_name,
|
||||||
|
socket);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serviceAddProtocol(service, protocol, socket, 0, authenticator, ssl_info);
|
||||||
|
if (startnow)
|
||||||
|
{
|
||||||
|
serviceStartProtocol(service, protocol, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port)
|
if (port)
|
||||||
{
|
{
|
||||||
serviceAddProtocol(service, protocol, address, atoi(port));
|
if (serviceHasProtocol(service, protocol, atoi(port)))
|
||||||
|
{
|
||||||
|
MXS_ERROR("Listener '%s', for service '%s', already have port %s.",
|
||||||
|
obj->object,
|
||||||
|
service_name,
|
||||||
|
port);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serviceAddProtocol(service, protocol, address, atoi(port), authenticator, ssl_info);
|
||||||
|
if (startnow)
|
||||||
|
{
|
||||||
|
serviceStartProtocol(service, protocol, atoi(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
276
server/core/listener.c
Normal file
276
server/core/listener.c
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright MariaDB Corporation Ab 2013-2014
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file listener.c - Listener generic functions
|
||||||
|
*
|
||||||
|
* Listeners wait for new client connections and, if the connection is successful
|
||||||
|
* a new session is created. A listener typically knows about a port or a socket,
|
||||||
|
* and a few other things. It may know about SSL if it is expecting an SSL
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 26/01/16 Martin Brampton Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <listener.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
|
#include <log_manager.h>
|
||||||
|
|
||||||
|
static RSA *rsa_512 = NULL;
|
||||||
|
static RSA *rsa_1024 = NULL;
|
||||||
|
|
||||||
|
static RSA *tmp_rsa_callback(SSL *s, int is_export, int keylength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum SSL/TLS version the listener will support
|
||||||
|
* @param ssl_listener Listener data to configure
|
||||||
|
* @param version SSL/TLS version string
|
||||||
|
* @return 0 on success, -1 on invalid version string
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
listener_set_ssl_version(SSL_LISTENER *ssl_listener, char* version)
|
||||||
|
{
|
||||||
|
if (strcasecmp(version,"SSLV3") == 0)
|
||||||
|
{
|
||||||
|
ssl_listener->ssl_method_type = SERVICE_SSLV3;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(version,"TLSV10") == 0)
|
||||||
|
{
|
||||||
|
ssl_listener->ssl_method_type = SERVICE_TLS10;
|
||||||
|
}
|
||||||
|
#ifdef OPENSSL_1_0
|
||||||
|
else if (strcasecmp(version,"TLSV11") == 0)
|
||||||
|
{
|
||||||
|
ssl_listener->ssl_method_type = SERVICE_TLS11;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(version,"TLSV12") == 0)
|
||||||
|
{
|
||||||
|
ssl_listener->ssl_method_type = SERVICE_TLS12;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (strcasecmp(version,"MAX") == 0)
|
||||||
|
{
|
||||||
|
ssl_listener->ssl_method_type = SERVICE_SSL_TLS_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locations of the listener's SSL certificate, listener's private key
|
||||||
|
* and the CA certificate which both the client and the listener should trust.
|
||||||
|
* @param ssl_listener Listener data to configure
|
||||||
|
* @param cert SSL certificate
|
||||||
|
* @param key SSL private key
|
||||||
|
* @param ca_cert SSL CA certificate
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
listener_set_certificates(SSL_LISTENER *ssl_listener, char* cert, char* key, char* ca_cert)
|
||||||
|
{
|
||||||
|
if (ssl_listener->ssl_cert)
|
||||||
|
{
|
||||||
|
free(ssl_listener->ssl_cert);
|
||||||
|
}
|
||||||
|
ssl_listener->ssl_cert = strdup(cert);
|
||||||
|
|
||||||
|
if (ssl_listener->ssl_key)
|
||||||
|
{
|
||||||
|
free(ssl_listener->ssl_key);
|
||||||
|
}
|
||||||
|
ssl_listener->ssl_key = strdup(key);
|
||||||
|
|
||||||
|
if (ssl_listener->ssl_ca_cert)
|
||||||
|
{
|
||||||
|
free(ssl_listener->ssl_ca_cert);
|
||||||
|
}
|
||||||
|
ssl_listener->ssl_ca_cert = strdup(ca_cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the listener's SSL context. This sets up the generated RSA
|
||||||
|
* encryption keys, chooses the listener encryption level and configures the
|
||||||
|
* listener certificate, private key and certificate authority file.
|
||||||
|
* @param ssl_listener Listener data to initialize
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
listener_init_SSL(SSL_LISTENER *ssl_listener)
|
||||||
|
{
|
||||||
|
DH* dh;
|
||||||
|
RSA* rsa;
|
||||||
|
|
||||||
|
if (!ssl_listener->ssl_init_done)
|
||||||
|
{
|
||||||
|
switch(ssl_listener->ssl_method_type)
|
||||||
|
{
|
||||||
|
case SERVICE_SSLV3:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)SSLv3_server_method();
|
||||||
|
break;
|
||||||
|
case SERVICE_TLS10:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)TLSv1_server_method();
|
||||||
|
break;
|
||||||
|
#ifdef OPENSSL_1_0
|
||||||
|
case SERVICE_TLS11:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)TLSv1_1_server_method();
|
||||||
|
break;
|
||||||
|
case SERVICE_TLS12:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)TLSv1_2_server_method();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
/** Rest of these use the maximum available SSL/TLS methods */
|
||||||
|
case SERVICE_SSL_MAX:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)SSLv23_server_method();
|
||||||
|
break;
|
||||||
|
case SERVICE_TLS_MAX:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)SSLv23_server_method();
|
||||||
|
break;
|
||||||
|
case SERVICE_SSL_TLS_MAX:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)SSLv23_server_method();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ssl_listener->method = (SSL_METHOD*)SSLv23_server_method();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ssl_listener->ctx = SSL_CTX_new(ssl_listener->method)) == NULL)
|
||||||
|
{
|
||||||
|
MXS_ERROR("SSL context initialization failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enable all OpenSSL bug fixes */
|
||||||
|
SSL_CTX_set_options(ssl_listener->ctx,SSL_OP_ALL);
|
||||||
|
|
||||||
|
/** Generate the 512-bit and 1024-bit RSA keys */
|
||||||
|
if (rsa_512 == NULL)
|
||||||
|
{
|
||||||
|
rsa_512 = RSA_generate_key(512,RSA_F4,NULL,NULL);
|
||||||
|
if (rsa_512 == NULL)
|
||||||
|
{
|
||||||
|
MXS_ERROR("512-bit RSA key generation failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rsa_1024 == NULL)
|
||||||
|
{
|
||||||
|
rsa_1024 = RSA_generate_key(1024,RSA_F4,NULL,NULL);
|
||||||
|
if (rsa_1024 == NULL)
|
||||||
|
{
|
||||||
|
MXS_ERROR("1024-bit RSA key generation failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsa_512 != NULL && rsa_1024 != NULL)
|
||||||
|
{
|
||||||
|
SSL_CTX_set_tmp_rsa_callback(ssl_listener->ctx,tmp_rsa_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load the server certificate */
|
||||||
|
if (SSL_CTX_use_certificate_file(ssl_listener->ctx, ssl_listener->ssl_cert, SSL_FILETYPE_PEM) <= 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to set server SSL certificate.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the private-key corresponding to the server certificate */
|
||||||
|
if (SSL_CTX_use_PrivateKey_file(ssl_listener->ctx, ssl_listener->ssl_key, SSL_FILETYPE_PEM) <= 0)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to set server SSL key.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the server certificate and private-key matches */
|
||||||
|
if (!SSL_CTX_check_private_key(ssl_listener->ctx))
|
||||||
|
{
|
||||||
|
MXS_ERROR("Server SSL certificate and key do not match.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the RSA CA certificate into the SSL_CTX structure */
|
||||||
|
if (!SSL_CTX_load_verify_locations(ssl_listener->ctx, ssl_listener->ssl_ca_cert, NULL))
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to set Certificate Authority file.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set to require peer (client) certificate verification */
|
||||||
|
SSL_CTX_set_verify(ssl_listener->ctx,SSL_VERIFY_PEER,NULL);
|
||||||
|
|
||||||
|
/* Set the verification depth */
|
||||||
|
SSL_CTX_set_verify_depth(ssl_listener->ctx,ssl_listener->ssl_cert_verify_depth);
|
||||||
|
ssl_listener->ssl_init_done = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RSA key generation callback function for OpenSSL.
|
||||||
|
* @param s SSL structure
|
||||||
|
* @param is_export Not used
|
||||||
|
* @param keylength Length of the key
|
||||||
|
* @return Pointer to RSA structure
|
||||||
|
*/
|
||||||
|
static RSA *
|
||||||
|
tmp_rsa_callback(SSL *s, int is_export, int keylength)
|
||||||
|
{
|
||||||
|
RSA *rsa_tmp=NULL;
|
||||||
|
|
||||||
|
switch (keylength) {
|
||||||
|
case 512:
|
||||||
|
if (rsa_512)
|
||||||
|
{
|
||||||
|
rsa_tmp = rsa_512;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* generate on the fly, should not happen in this example */
|
||||||
|
rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL);
|
||||||
|
rsa_512 = rsa_tmp; /* Remember for later reuse */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1024:
|
||||||
|
if (rsa_1024)
|
||||||
|
{
|
||||||
|
rsa_tmp=rsa_1024;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Generating a key on the fly is very costly, so use what is there */
|
||||||
|
if (rsa_1024)
|
||||||
|
{
|
||||||
|
rsa_tmp=rsa_1024;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rsa_tmp=rsa_512; /* Use at least a shorter key */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(rsa_tmp);
|
||||||
|
}
|
@ -48,6 +48,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <session.h>
|
#include <session.h>
|
||||||
#include <service.h>
|
#include <service.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
|
#include <listener.h>
|
||||||
#include <server.h>
|
#include <server.h>
|
||||||
#include <router.h>
|
#include <router.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
@ -218,7 +220,7 @@ service_isvalid(SERVICE *service)
|
|||||||
* @return The number of listeners started
|
* @return The number of listeners started
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
|
serviceStartPort(SERVICE *service, SERV_LISTENER *port)
|
||||||
{
|
{
|
||||||
int listeners = 0;
|
int listeners = 0;
|
||||||
char config_bind[40];
|
char config_bind[40];
|
||||||
@ -232,6 +234,11 @@ serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
|
|||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port->ssl)
|
||||||
|
{
|
||||||
|
listener_init_SSL(port->ssl);
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(port->protocol, "MySQLClient") == 0)
|
if (strcmp(port->protocol, "MySQLClient") == 0)
|
||||||
{
|
{
|
||||||
int loaded;
|
int loaded;
|
||||||
@ -420,7 +427,7 @@ retblock:
|
|||||||
*/
|
*/
|
||||||
int serviceStartAllPorts(SERVICE* service)
|
int serviceStartAllPorts(SERVICE* service)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *port = service->ports;
|
SERV_LISTENER *port = service->ports;
|
||||||
int listeners = 0;
|
int listeners = 0;
|
||||||
while (!service->svc_do_shutdown && port)
|
while (!service->svc_do_shutdown && port)
|
||||||
{
|
{
|
||||||
@ -507,7 +514,7 @@ serviceStart(SERVICE *service)
|
|||||||
void
|
void
|
||||||
serviceStartProtocol(SERVICE *service, char *protocol, int port)
|
serviceStartProtocol(SERVICE *service, char *protocol, int port)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *ptr;
|
SERV_LISTENER *ptr;
|
||||||
|
|
||||||
ptr = service->ports;
|
ptr = service->ports;
|
||||||
while (ptr)
|
while (ptr)
|
||||||
@ -560,7 +567,7 @@ serviceStartAll()
|
|||||||
int
|
int
|
||||||
serviceStop(SERVICE *service)
|
serviceStop(SERVICE *service)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *port;
|
SERV_LISTENER *port;
|
||||||
int listeners = 0;
|
int listeners = 0;
|
||||||
|
|
||||||
port = service->ports;
|
port = service->ports;
|
||||||
@ -592,7 +599,7 @@ serviceStop(SERVICE *service)
|
|||||||
int
|
int
|
||||||
serviceRestart(SERVICE *service)
|
serviceRestart(SERVICE *service)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *port;
|
SERV_LISTENER *port;
|
||||||
int listeners = 0;
|
int listeners = 0;
|
||||||
|
|
||||||
port = service->ports;
|
port = service->ports;
|
||||||
@ -686,25 +693,20 @@ service_free(SERVICE *service)
|
|||||||
* @return TRUE if the protocol/port could be added
|
* @return TRUE if the protocol/port could be added
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
serviceAddProtocol(SERVICE *service, char *protocol, char *address, unsigned short port)
|
serviceAddProtocol(SERVICE *service, char *protocol, char *address, unsigned short port, char *authenticator, SSL_LISTENER *ssl)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *proto;
|
SERV_LISTENER *proto;
|
||||||
|
|
||||||
if ((proto = (SERV_PROTOCOL *)malloc(sizeof(SERV_PROTOCOL))) == NULL)
|
if ((proto = (SERV_LISTENER *)malloc(sizeof(SERV_LISTENER))) == NULL)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
proto->listener = NULL;
|
proto->listener = NULL;
|
||||||
proto->protocol = strdup(protocol);
|
proto->protocol = strdup(protocol);
|
||||||
if (address)
|
proto->address = address ? strdup(address) : NULL;
|
||||||
{
|
|
||||||
proto->address = strdup(address);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
proto->address = NULL;
|
|
||||||
}
|
|
||||||
proto->port = port;
|
proto->port = port;
|
||||||
|
proto->authenticator = authenticator ? strdup(authenticator) : NULL;
|
||||||
|
proto->ssl = ssl;
|
||||||
spinlock_acquire(&service->spin);
|
spinlock_acquire(&service->spin);
|
||||||
proto->next = service->ports;
|
proto->next = service->ports;
|
||||||
service->ports = proto;
|
service->ports = proto;
|
||||||
@ -724,7 +726,7 @@ serviceAddProtocol(SERVICE *service, char *protocol, char *address, unsigned sho
|
|||||||
int
|
int
|
||||||
serviceHasProtocol(SERVICE *service, char *protocol, unsigned short port)
|
serviceHasProtocol(SERVICE *service, char *protocol, unsigned short port)
|
||||||
{
|
{
|
||||||
SERV_PROTOCOL *proto;
|
SERV_LISTENER *proto;
|
||||||
|
|
||||||
spinlock_acquire(&service->spin);
|
spinlock_acquire(&service->spin);
|
||||||
proto = service->ports;
|
proto = service->ports;
|
||||||
@ -1457,7 +1459,7 @@ void
|
|||||||
dListListeners(DCB *dcb)
|
dListListeners(DCB *dcb)
|
||||||
{
|
{
|
||||||
SERVICE *service;
|
SERVICE *service;
|
||||||
SERV_PROTOCOL *lptr;
|
SERV_LISTENER *lptr;
|
||||||
|
|
||||||
spinlock_acquire(&service_spin);
|
spinlock_acquire(&service_spin);
|
||||||
service = allServices;
|
service = allServices;
|
||||||
@ -1930,7 +1932,7 @@ serviceListenerRowCallback(RESULTSET *set, void *data)
|
|||||||
char buf[20];
|
char buf[20];
|
||||||
RESULT_ROW *row;
|
RESULT_ROW *row;
|
||||||
SERVICE *service;
|
SERVICE *service;
|
||||||
SERV_PROTOCOL *lptr = NULL;
|
SERV_LISTENER *lptr = NULL;
|
||||||
|
|
||||||
spinlock_acquire(&service_spin);
|
spinlock_acquire(&service_spin);
|
||||||
service = allServices;
|
service = allServices;
|
||||||
@ -2135,6 +2137,9 @@ int serviceInitSSL(SERVICE* service)
|
|||||||
DH* dh;
|
DH* dh;
|
||||||
RSA* rsa;
|
RSA* rsa;
|
||||||
|
|
||||||
|
/* Pending removal in favour of processing in listener. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!service->ssl_init_done)
|
if (!service->ssl_init_done)
|
||||||
{
|
{
|
||||||
switch(service->ssl_method_type)
|
switch(service->ssl_method_type)
|
||||||
|
@ -70,7 +70,7 @@ init_test_env(NULL);
|
|||||||
ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
|
ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
|
||||||
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
|
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
|
||||||
ss_dfprintf(stderr, "\t..done\nAdding protocol testprotocol.");
|
ss_dfprintf(stderr, "\t..done\nAdding protocol testprotocol.");
|
||||||
ss_info_dassert(0 != serviceAddProtocol(service, "testprotocol", "localhost", 9876), "Add Protocol should succeed");
|
ss_info_dassert(0 != serviceAddProtocol(service, "testprotocol", "localhost", 9876, "MySQL", NULL), "Add Protocol should succeed");
|
||||||
ss_info_dassert(0 != serviceHasProtocol(service, "testprotocol", 9876), "Service should have new protocol as requested");
|
ss_info_dassert(0 != serviceHasProtocol(service, "testprotocol", 9876), "Service should have new protocol as requested");
|
||||||
serviceStartProtocol(service, "testprotocol", 9876);
|
serviceStartProtocol(service, "testprotocol", 9876);
|
||||||
mxs_log_flush_sync();
|
mxs_log_flush_sync();
|
||||||
|
@ -19,13 +19,11 @@
|
|||||||
*/
|
*/
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <gwbitmask.h>
|
#include <gwbitmask.h>
|
||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <openssl/crypto.h>
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
|
|
||||||
#define ERRHANDLE
|
#define ERRHANDLE
|
||||||
|
|
||||||
@ -59,50 +57,13 @@ struct service;
|
|||||||
* 27/08/2014 Mark Riddoch Addition of write event queuing
|
* 27/08/2014 Mark Riddoch Addition of write event queuing
|
||||||
* 23/09/2014 Mark Riddoch New poll processing queue
|
* 23/09/2014 Mark Riddoch New poll processing queue
|
||||||
* 19/06/2015 Martin Brampton Provision of persistent connections
|
* 19/06/2015 Martin Brampton Provision of persistent connections
|
||||||
|
* 20/01/2016 Martin Brampton Moved GWPROTOCOL to gw_protocol.h
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dcb;
|
struct dcb;
|
||||||
|
|
||||||
/**
|
|
||||||
* @verbatim
|
|
||||||
* The operations that can be performed on the descriptor
|
|
||||||
*
|
|
||||||
* read EPOLLIN handler for the socket
|
|
||||||
* write MaxScale data write entry point
|
|
||||||
* write_ready EPOLLOUT handler for the socket, indicates
|
|
||||||
* that the socket is ready to send more data
|
|
||||||
* error EPOLLERR handler for the socket
|
|
||||||
* hangup EPOLLHUP handler for the socket
|
|
||||||
* accept Accept handler for listener socket only
|
|
||||||
* connect Create a connection to the specified server
|
|
||||||
* for the session pased in
|
|
||||||
* close MaxScale close entry point for the socket
|
|
||||||
* listen Create a listener for the protocol
|
|
||||||
* auth Authentication entry point
|
|
||||||
* session Session handling entry point
|
|
||||||
* @endverbatim
|
|
||||||
*
|
|
||||||
* This forms the "module object" for protocol modules within the gateway.
|
|
||||||
*
|
|
||||||
* @see load_module
|
|
||||||
*/
|
|
||||||
typedef struct gw_protocol
|
|
||||||
{
|
|
||||||
int (*read)(struct dcb *);
|
|
||||||
int (*write)(struct dcb *, GWBUF *);
|
|
||||||
int (*write_ready)(struct dcb *);
|
|
||||||
int (*error)(struct dcb *);
|
|
||||||
int (*hangup)(struct dcb *);
|
|
||||||
int (*accept)(struct dcb *);
|
|
||||||
int (*connect)(struct dcb *, struct server *, struct session *);
|
|
||||||
int (*close)(struct dcb *);
|
|
||||||
int (*listen)(struct dcb *, char *);
|
|
||||||
int (*auth)(struct dcb *, struct server *, struct session *, GWBUF *);
|
|
||||||
int (*session)(struct dcb *, void *);
|
|
||||||
} GWPROTOCOL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event queue structure used in the polling loop to maintain a queue
|
* The event queue structure used in the polling loop to maintain a queue
|
||||||
* of events that need to be processed for the DCB.
|
* of events that need to be processed for the DCB.
|
||||||
@ -128,13 +89,6 @@ typedef struct
|
|||||||
unsigned long started;
|
unsigned long started;
|
||||||
} DCBEVENTQ;
|
} DCBEVENTQ;
|
||||||
|
|
||||||
/**
|
|
||||||
* The GWPROTOCOL version data. The following should be updated whenever
|
|
||||||
* the GWPROTOCOL structure is changed. See the rules defined in modinfo.h
|
|
||||||
* that define how these numbers should change.
|
|
||||||
*/
|
|
||||||
#define GWPROTOCOL_VERSION {1, 0, 0}
|
|
||||||
|
|
||||||
#define DCBFD_CLOSED -1
|
#define DCBFD_CLOSED -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
92
server/include/gw_protocol.h
Normal file
92
server/include/gw_protocol.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#ifndef GW_PROTOCOL_H
|
||||||
|
#define GW_PROTOCOL_H
|
||||||
|
/*
|
||||||
|
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright MariaDB Corporation Ab 2013-2014
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file protocol.h
|
||||||
|
*
|
||||||
|
* The listener definitions for MaxScale
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 22/01/16 Martin Brampton Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <buffer.h>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
|
||||||
|
struct dcb;
|
||||||
|
struct server;
|
||||||
|
struct session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @verbatim
|
||||||
|
* The operations that can be performed on the descriptor
|
||||||
|
*
|
||||||
|
* read EPOLLIN handler for the socket
|
||||||
|
* write MaxScale data write entry point
|
||||||
|
* write_ready EPOLLOUT handler for the socket, indicates
|
||||||
|
* that the socket is ready to send more data
|
||||||
|
* error EPOLLERR handler for the socket
|
||||||
|
* hangup EPOLLHUP handler for the socket
|
||||||
|
* accept Accept handler for listener socket only
|
||||||
|
* connect Create a connection to the specified server
|
||||||
|
* for the session pased in
|
||||||
|
* close MaxScale close entry point for the socket
|
||||||
|
* listen Create a listener for the protocol
|
||||||
|
* auth Authentication entry point
|
||||||
|
* session Session handling entry point
|
||||||
|
* @endverbatim
|
||||||
|
*
|
||||||
|
* This forms the "module object" for protocol modules within the gateway.
|
||||||
|
*
|
||||||
|
* @see load_module
|
||||||
|
*/
|
||||||
|
typedef struct gw_protocol
|
||||||
|
{
|
||||||
|
int (*read)(struct dcb *);
|
||||||
|
int (*write)(struct dcb *, GWBUF *);
|
||||||
|
int (*write_ready)(struct dcb *);
|
||||||
|
int (*error)(struct dcb *);
|
||||||
|
int (*hangup)(struct dcb *);
|
||||||
|
int (*accept)(struct dcb *);
|
||||||
|
int (*connect)(struct dcb *, struct server *, struct session *);
|
||||||
|
int (*close)(struct dcb *);
|
||||||
|
int (*listen)(struct dcb *, char *);
|
||||||
|
int (*auth)(struct dcb *, struct server *, struct session *, GWBUF *);
|
||||||
|
int (*session)(struct dcb *, void *);
|
||||||
|
} GWPROTOCOL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GWPROTOCOL version data. The following should be updated whenever
|
||||||
|
* the GWPROTOCOL structure is changed. See the rules defined in modinfo.h
|
||||||
|
* that define how these numbers should change.
|
||||||
|
*/
|
||||||
|
#define GWPROTOCOL_VERSION {1, 0, 0}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* GW_PROTOCOL_H */
|
||||||
|
|
89
server/include/listener.h
Normal file
89
server/include/listener.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#ifndef _LISTENER_H
|
||||||
|
#define _LISTENER_H
|
||||||
|
/*
|
||||||
|
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright MariaDB Corporation Ab 2013-2014
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file listener.h
|
||||||
|
*
|
||||||
|
* The listener definitions for MaxScale
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 19/01/16 Martin Brampton Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gw_protocol.h>
|
||||||
|
#include <dcb.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SERVICE_SSLV3,
|
||||||
|
SERVICE_TLS10,
|
||||||
|
#ifdef OPENSSL_1_0
|
||||||
|
SERVICE_TLS11,
|
||||||
|
SERVICE_TLS12,
|
||||||
|
#endif
|
||||||
|
SERVICE_SSL_MAX,
|
||||||
|
SERVICE_TLS_MAX,
|
||||||
|
SERVICE_SSL_TLS_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ssl_listener structure is used to aggregate the SSL configuration items
|
||||||
|
* and data for a particular listener
|
||||||
|
*/
|
||||||
|
typedef struct ssl_listener
|
||||||
|
{
|
||||||
|
SSL_CTX *ctx;
|
||||||
|
SSL_METHOD *method; /*< SSLv3 or TLS1.0/1.1/1.2 methods
|
||||||
|
* see: https://www.openssl.org/docs/ssl/SSL_CTX_new.html */
|
||||||
|
int ssl_cert_verify_depth; /*< SSL certificate verification depth */
|
||||||
|
int ssl_method_type; /*< Which of the SSLv3 or TLS1.0/1.1/1.2 methods to use */
|
||||||
|
char *ssl_cert; /*< SSL certificate */
|
||||||
|
char *ssl_key; /*< SSL private key */
|
||||||
|
char *ssl_ca_cert; /*< SSL CA certificate */
|
||||||
|
bool ssl_init_done; /*< If SSL has already been initialized for this service */
|
||||||
|
} SSL_LISTENER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The servlistener structure is used to link a service to the protocols that
|
||||||
|
* are used to support that service. It defines the name of the protocol module
|
||||||
|
* that should be loaded to support the client connection and the port that the
|
||||||
|
* protocol should use to listen for incoming client connections.
|
||||||
|
*/
|
||||||
|
typedef struct servlistener
|
||||||
|
{
|
||||||
|
char *protocol; /**< Protocol module to load */
|
||||||
|
unsigned short port; /**< Port to listen on */
|
||||||
|
char *address; /**< Address to listen with */
|
||||||
|
char *authenticator; /**< Name of authenticator */
|
||||||
|
SSL_LISTENER *ssl; /**< Structure of SSL data or NULL */
|
||||||
|
DCB *listener; /**< The DCB for the listener */
|
||||||
|
struct servlistener *next; /**< Next service protocol */
|
||||||
|
} SERV_LISTENER;
|
||||||
|
|
||||||
|
int listener_set_ssl_version(SSL_LISTENER *ssl_listener, char* version);
|
||||||
|
void listener_set_certificates(SSL_LISTENER *ssl_listener, char* cert, char* key, char* ca_cert);
|
||||||
|
int listener_init_SSL(SSL_LISTENER *ssl_listener);
|
||||||
|
|
||||||
|
#endif
|
@ -19,9 +19,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <server.h>
|
#include <server.h>
|
||||||
|
#include <listener.h>
|
||||||
#include <filter.h>
|
#include <filter.h>
|
||||||
#include <hashtable.h>
|
#include <hashtable.h>
|
||||||
#include <resultset.h>
|
#include <resultset.h>
|
||||||
@ -59,21 +61,6 @@ struct router;
|
|||||||
struct router_object;
|
struct router_object;
|
||||||
struct users;
|
struct users;
|
||||||
|
|
||||||
/**
|
|
||||||
* The servprotocol structure is used to link a service to the protocols that
|
|
||||||
* are used to support that service. It defines the name of the protocol module
|
|
||||||
* that should be loaded to support the client connection and the port that the
|
|
||||||
* protocol should use to listen for incoming client connections.
|
|
||||||
*/
|
|
||||||
typedef struct servprotocol
|
|
||||||
{
|
|
||||||
char *protocol; /**< Protocol module to load */
|
|
||||||
unsigned short port; /**< Port to listen on */
|
|
||||||
char *address; /**< Address to listen with */
|
|
||||||
DCB *listener; /**< The DCB for the listener */
|
|
||||||
struct servprotocol *next; /**< Next service protocol */
|
|
||||||
} SERV_PROTOCOL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service statistics structure
|
* The service statistics structure
|
||||||
*/
|
*/
|
||||||
@ -120,19 +107,6 @@ typedef enum
|
|||||||
SSL_REQUIRED
|
SSL_REQUIRED
|
||||||
} ssl_mode_t;
|
} ssl_mode_t;
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SERVICE_SSLV3,
|
|
||||||
SERVICE_TLS10,
|
|
||||||
#ifdef OPENSSL_1_0
|
|
||||||
SERVICE_TLS11,
|
|
||||||
SERVICE_TLS12,
|
|
||||||
#endif
|
|
||||||
SERVICE_SSL_MAX,
|
|
||||||
SERVICE_TLS_MAX,
|
|
||||||
SERVICE_SSL_TLS_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFAULT_SSL_CERT_VERIFY_DEPTH 100 /*< The default certificate verification depth */
|
#define DEFAULT_SSL_CERT_VERIFY_DEPTH 100 /*< The default certificate verification depth */
|
||||||
#define SERVICE_MAX_RETRY_INTERVAL 3600 /*< The maximum interval between service start retries */
|
#define SERVICE_MAX_RETRY_INTERVAL 3600 /*< The maximum interval between service start retries */
|
||||||
|
|
||||||
@ -156,7 +130,7 @@ typedef struct service
|
|||||||
{
|
{
|
||||||
char *name; /**< The service name */
|
char *name; /**< The service name */
|
||||||
int state; /**< The service state */
|
int state; /**< The service state */
|
||||||
SERV_PROTOCOL *ports; /**< Linked list of ports and protocols
|
SERV_LISTENER *ports; /**< Linked list of ports and protocols
|
||||||
* that this service will listen on.
|
* that this service will listen on.
|
||||||
*/
|
*/
|
||||||
char *routerModule; /**< Name of router module to use */
|
char *routerModule; /**< Name of router module to use */
|
||||||
@ -218,7 +192,7 @@ extern SERVICE *service_alloc(const char *, const char *);
|
|||||||
extern int service_free(SERVICE *);
|
extern int service_free(SERVICE *);
|
||||||
extern SERVICE *service_find(char *);
|
extern SERVICE *service_find(char *);
|
||||||
extern int service_isvalid(SERVICE *);
|
extern int service_isvalid(SERVICE *);
|
||||||
extern int serviceAddProtocol(SERVICE *, char *, char *, unsigned short);
|
extern int serviceAddProtocol(SERVICE *, char *, char *, unsigned short, char *, SSL_LISTENER *);
|
||||||
extern int serviceHasProtocol(SERVICE *, char *, unsigned short);
|
extern int serviceHasProtocol(SERVICE *, char *, unsigned short);
|
||||||
extern void serviceAddBackend(SERVICE *, SERVER *);
|
extern void serviceAddBackend(SERVICE *, SERVER *);
|
||||||
extern int serviceHasBackend(SERVICE *, SERVER *);
|
extern int serviceHasBackend(SERVICE *, SERVER *);
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <httpd.h>
|
#include <httpd.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <gw.h>
|
#include <gw.h>
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <service.h>
|
#include <service.h>
|
||||||
#include <session.h>
|
#include <session.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
|
|
||||||
MODULE_INFO info =
|
MODULE_INFO info =
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
* 11/01/2016 Martin Brampton Remove SSL write code, now handled at lower level;
|
* 11/01/2016 Martin Brampton Remove SSL write code, now handled at lower level;
|
||||||
* replace gwbuf_consume by gwbuf_free (multiple).
|
* replace gwbuf_consume by gwbuf_free (multiple).
|
||||||
*/
|
*/
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <mysql_client_server_protocol.h>
|
#include <mysql_client_server_protocol.h>
|
||||||
@ -74,16 +75,15 @@ static int gw_MySQLWrite_client(DCB *dcb, GWBUF *queue);
|
|||||||
static int gw_error_client_event(DCB *dcb);
|
static int gw_error_client_event(DCB *dcb);
|
||||||
static int gw_client_close(DCB *dcb);
|
static int gw_client_close(DCB *dcb);
|
||||||
static int gw_client_hangup_event(DCB *dcb);
|
static int gw_client_hangup_event(DCB *dcb);
|
||||||
int gw_read_client_event_SSL(DCB* dcb);
|
static int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message);
|
||||||
int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message);
|
static int MySQLSendHandshake(DCB* dcb);
|
||||||
int MySQLSendHandshake(DCB* dcb);
|
|
||||||
static int gw_mysql_do_authentication(DCB *dcb, GWBUF **queue);
|
static int gw_mysql_do_authentication(DCB *dcb, GWBUF **queue);
|
||||||
static int route_by_statement(SESSION *, GWBUF **);
|
static int route_by_statement(SESSION *, GWBUF **);
|
||||||
extern char* get_username_from_auth(char* ptr, uint8_t* data);
|
extern char* get_username_from_auth(char* ptr, uint8_t* data);
|
||||||
extern int check_db_name_after_auth(DCB *, char *, int);
|
extern int check_db_name_after_auth(DCB *, char *, int);
|
||||||
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db,int);
|
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db,int);
|
||||||
|
|
||||||
int do_ssl_accept(MySQLProtocol* protocol);
|
static int do_ssl_accept(MySQLProtocol* protocol);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The "module object" for the mysqld client protocol module.
|
* The "module object" for the mysqld client protocol module.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
#include <service.h>
|
#include <service.h>
|
||||||
#include <session.h>
|
#include <session.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
|
#include <gw_protocol.h>
|
||||||
|
|
||||||
MODULE_INFO info =
|
MODULE_INFO info =
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user