Merge remote-tracking branch 'origin/develop' into MXS-122

Conflicts:
	server/core/CMakeLists.txt
	server/core/dcb.c
	server/include/dcb.h
	server/include/server.h
	server/modules/protocol/mysql_backend.c
This commit is contained in:
Martin Brampton
2015-06-19 23:12:54 +01:00
112 changed files with 3003 additions and 1188 deletions

View File

@ -3,48 +3,48 @@ if(BUILD_RABBITMQ)
include_directories(${RABBITMQ_HEADERS})
add_library(mqfilter SHARED mqfilter.c)
target_link_libraries(mqfilter query_classifier log_manager utils ${RABBITMQ_LIBRARIES})
install(TARGETS mqfilter DESTINATION modules)
install(TARGETS mqfilter DESTINATION ${MAXSCALE_LIBDIR})
endif()
add_library(regexfilter SHARED regexfilter.c)
target_link_libraries(regexfilter log_manager utils)
install(TARGETS regexfilter DESTINATION modules)
install(TARGETS regexfilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(testfilter SHARED testfilter.c)
target_link_libraries(testfilter log_manager utils)
install(TARGETS testfilter DESTINATION modules)
install(TARGETS testfilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(qlafilter SHARED qlafilter.c)
target_link_libraries(qlafilter log_manager utils)
install(TARGETS qlafilter DESTINATION modules)
install(TARGETS qlafilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(tee SHARED tee.c)
target_link_libraries(tee log_manager utils)
install(TARGETS tee DESTINATION modules)
install(TARGETS tee DESTINATION ${MAXSCALE_LIBDIR})
add_library(topfilter SHARED topfilter.c)
target_link_libraries(topfilter log_manager utils)
install(TARGETS topfilter DESTINATION modules)
install(TARGETS topfilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(dbfwfilter SHARED dbfwfilter.c)
target_link_libraries(dbfwfilter log_manager utils query_classifier)
install(TARGETS dbfwfilter DESTINATION modules)
install(TARGETS dbfwfilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(namedserverfilter SHARED namedserverfilter.c)
target_link_libraries(namedserverfilter log_manager utils)
install(TARGETS namedserverfilter DESTINATION modules)
install(TARGETS namedserverfilter DESTINATION ${MAXSCALE_LIBDIR})
if(BUILD_SLAVELAG)
add_library(slavelag SHARED slavelag.c)
target_link_libraries(slavelag log_manager utils query_classifier)
install(TARGETS slavelag DESTINATION modules)
install(TARGETS slavelag DESTINATION ${MAXSCALE_LIBDIR})
endif()
if(BUILD_TOOLS)
add_executable(ruleparser dbfwfilter.c)
target_compile_definitions(ruleparser PUBLIC "BUILD_RULE_PARSER")
target_link_libraries(ruleparser ${EMBEDDED_LIB} log_manager utils query_classifier fullcore)
install(TARGETS ruleparser DESTINATION tools)
install(TARGETS ruleparser DESTINATION ${MAXSCALE_BINDIR})
endif()
add_subdirectory(hint)

View File

@ -2214,15 +2214,13 @@ int main(int argc, char** argv)
return 1;
}
if((home = getenv("MAXSCALE_HOME")) == NULL)
home = malloc(sizeof(char)*(PATH_MAX+1));
if(getcwd(home,PATH_MAX) == NULL)
{
home = malloc(sizeof(char)*(PATH_MAX+1));
if(getcwd(home,PATH_MAX) == NULL)
{
free(home);
home = NULL;
}
free(home);
home = NULL;
}
printf("Log files written to: %s\n",home?home:"/tpm");
int argc_ = 2;

View File

@ -1,4 +1,4 @@
add_library(hintfilter SHARED hintfilter.c hintparser.c)
set_target_properties(hintfilter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${CMAKE_INSTALL_PREFIX}/lib)
set_target_properties(hintfilter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${MAXSCALE_LIBDIR})
target_link_libraries(hintfilter ssl log_manager utils)
install(TARGETS hintfilter DESTINATION modules)
install(TARGETS hintfilter DESTINATION ${MAXSCALE_LIBDIR})

View File

@ -305,7 +305,9 @@ char *remote, *userName;
sprintf(my_session->filename, "%s.%d",
my_instance->filebase,
my_instance->sessions);
atomic_add(&my_instance->sessions,1);
// Multiple sessions can try to update my_instance->sessions simultaneously
atomic_add(&(my_instance->sessions), 1);
if (my_session->active)
{

View File

@ -1,4 +1,3 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(harness_ui harness_ui.c harness_common.c)
add_executable(harness harness_util.c harness_common.c)
@ -25,7 +24,3 @@ add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
${TEST_PASSWORD}
${TEST_HOST}
${TEST_PORT})
set_tests_properties(TestHintfilter TestRegexfilter TestFwfilter1 TestFwfilter2 TestTeeRecursion
PROPERTIES
ENVIRONMENT MAXSCALE_HOME=${CMAKE_BINARY_DIR}/)

View File

@ -17,8 +17,8 @@ function execute_test()
return 1
fi
LAST_LOG=$(ls $BINDIR/log -1|grep err|sort|uniq|tail -n 1)
TEST_RESULT=$(cat $BINDIR/log/$LAST_LOG | grep -i recursive)
LAST_LOG=$(ls $BINDIR/ -1|grep error|sort|uniq|tail -n 1)
TEST_RESULT=$(cat $BINDIR/$LAST_LOG | grep -i recursive)
if [[ "$TEST_RESULT" != "" ]]
then
return 0
@ -49,8 +49,8 @@ USER=$3
PWD=$4
HOST=$5
PORT=$6
CONF=$BINDIR/etc/MaxScale.cnf
OLDCONF=$BINDIR/etc/MaxScale.cnf.old
CONF=$BINDIR/etc/maxscale.cnf
OLDCONF=$BINDIR/etc/maxscale.cnf.old
MAXPID=$BINDIR/log/$(ls -1 $BINDIR/log|grep maxscale)
TEST1=$SRCDIR/server/modules/filter/test/tee_recursion1.cnf
TEST2=$SRCDIR/server/modules/filter/test/tee_recursion2.cnf

View File

@ -54,7 +54,9 @@
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <service.h>
#include <router.h>
#include <poll.h>
@ -89,6 +91,10 @@
#define COM_QUIT_PACKET_SIZE (4+1)
struct dcb;
#define MYSQL_FAILED_AUTH 1
#define MYSQL_FAILED_AUTH_DB 2
#define MYSQL_FAILED_AUTH_SSL 3
typedef enum {
MYSQL_ALLOC,
MYSQL_PENDING_CONNECT,
@ -97,6 +103,11 @@ typedef enum {
MYSQL_AUTH_RECV,
MYSQL_AUTH_FAILED,
MYSQL_HANDSHAKE_FAILED,
MYSQL_AUTH_SSL_REQ, /*< client requested SSL but SSL_accept hasn't beed called */
MYSQL_AUTH_SSL_HANDSHAKE_DONE, /*< SSL handshake has been fully completed */
MYSQL_AUTH_SSL_HANDSHAKE_FAILED, /*< SSL handshake failed for any reason */
MYSQL_AUTH_SSL_HANDSHAKE_ONGOING, /*< SSL_accept has been called but the
* SSL handshake hasn't been completed */
MYSQL_IDLE
} mysql_auth_state_t;
@ -290,6 +301,7 @@ typedef struct {
unsigned long tid; /*< MySQL Thread ID, in
* handshake */
unsigned int charset; /*< MySQL character set at connect time */
bool use_ssl;
#if defined(SS_DEBUG)
skygw_chk_t protocol_chk_tail;
#endif
@ -309,7 +321,7 @@ typedef struct {
#define MYSQL_IS_CHANGE_USER(payload) (MYSQL_GET_COMMAND(payload)==0x11)
#define MYSQL_GET_NATTR(payload) ((int)payload[4])
#endif /** _MYSQL_PROTOCOL_H */
MySQLProtocol* mysql_protocol_init(DCB* dcb, int fd);
void mysql_protocol_done (DCB* dcb);
@ -405,4 +417,4 @@ void init_response_status (
int* npackets,
ssize_t* nbytes);
#endif /** _MYSQL_PROTOCOL_H */

View File

@ -1,16 +1,16 @@
add_library(mysqlmon SHARED mysql_mon.c monitor_common.c)
target_link_libraries(mysqlmon log_manager utils)
install(TARGETS mysqlmon DESTINATION modules)
install(TARGETS mysqlmon DESTINATION ${MAXSCALE_LIBDIR})
add_library(galeramon SHARED galeramon.c monitor_common.c)
target_link_libraries(galeramon log_manager utils)
install(TARGETS galeramon DESTINATION modules)
install(TARGETS galeramon DESTINATION ${MAXSCALE_LIBDIR})
add_library(ndbclustermon SHARED ndbclustermon.c monitor_common.c)
target_link_libraries(ndbclustermon log_manager utils)
install(TARGETS ndbclustermon DESTINATION modules)
install(TARGETS ndbclustermon DESTINATION ${MAXSCALE_LIBDIR})
if(BUILD_MMMON)
add_library(mmmon SHARED mmmon.c monitor_common.c)
target_link_libraries(mmmon log_manager utils)
install(TARGETS mmmon DESTINATION modules)
install(TARGETS mmmon DESTINATION ${MAXSCALE_LIBDIR})
endif()

View File

@ -123,7 +123,7 @@ startMonitor(void *arg,void* opt)
MONITOR* mon = arg;
GALERA_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
bool have_events = false;
bool have_events = false,script_error = false;
if (handle != NULL)
{
handle->shutdown = 0;
@ -163,6 +163,7 @@ startMonitor(void *arg,void* opt)
}
else
{
script_error = true;
if(access(params->value,F_OK) == 0)
{
skygw_log_write(LE,
@ -175,17 +176,24 @@ startMonitor(void *arg,void* opt)
"Error: The file cannot be found: %s",
params->value);
}
handle->script = NULL;
}
}
else if(!strcmp(params->name,"events"))
{
mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value);
have_events = true;
if(mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value) != 0)
script_error = true;
else
have_events = true;
}
params = params->next;
}
if(script_error)
{
skygw_log_write(LE,"Error: Errors were found in the script configuration parameters "
"for the monitor '%s'. The script will not be used.",mon->name);
free(handle->script);
handle->script = NULL;
}
/** If no specific events are given, enable them all */
if(!have_events)
{

View File

@ -113,7 +113,7 @@ startMonitor(void *arg,void* opt)
MONITOR* mon = (MONITOR*)arg;
MM_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
bool have_events = false;
bool have_events = false,script_error = false;
if (handle)
{
@ -148,6 +148,7 @@ startMonitor(void *arg,void* opt)
}
else
{
script_error = true;
if(access(params->value,F_OK) == 0)
{
skygw_log_write(LE,
@ -165,11 +166,20 @@ startMonitor(void *arg,void* opt)
}
else if(!strcmp(params->name,"events"))
{
mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value);
have_events = true;
if(mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value) != 0)
script_error = true;
else
have_events = true;
}
params = params->next;
}
if(script_error)
{
skygw_log_write(LE,"Error: Errors were found in the script configuration parameters "
"for the monitor '%s'. The script will not be used.",mon->name);
free(handle->script);
handle->script = NULL;
}
/** If no specific events are given, enable them all */
if(!have_events)
{

View File

@ -230,7 +230,7 @@ void mon_append_node_names(MONITOR_SERVERS* start,char* str, int len)
MONITOR_SERVERS* ptr = start;
bool first = true;
int slen = strlen(str);
char arr[256];
while(ptr && slen < len)
{
if(!first)
@ -238,7 +238,8 @@ void mon_append_node_names(MONITOR_SERVERS* start,char* str, int len)
strncat(str,",",len);
}
first = false;
strncat(str,ptr->server->unique_name,len);
sprintf(arr,"%s:%d",ptr->server->name,ptr->server->port);
strcat(str,arr);
ptr = ptr->next;
slen = strlen(str);
}
@ -299,10 +300,11 @@ void monitor_launch_script(MONITOR* mon,MONITOR_SERVERS* ptr, char* script)
EXTERNCMD* cmd;
snprintf(argstr,PATH_MAX + MON_ARG_MAX,
"%s --event=%s --initiator=%s --nodelist=",
"%s --event=%s --initiator=%s:%d --nodelist=",
script,
mon_get_event_name(ptr),
ptr->server->unique_name);
ptr->server->name,
ptr->server->port);
mon_append_node_names(mon->databases,argstr,PATH_MAX + MON_ARG_MAX + 1);
if((cmd = externcmd_allocate(argstr)) == NULL)
@ -343,7 +345,10 @@ int mon_parse_event_string(bool* events, size_t count,char* string)
{
event = mon_name_to_event(tok);
if(event == UNDEFINED_MONITOR_EVENT)
{
skygw_log_write(LE,"Error: Invalid event name %s",tok);
return -1;
}
events[event] = true;
tok = strtok_r(NULL,",| ",&saved);
}

View File

@ -140,7 +140,7 @@ startMonitor(void *arg, void* opt)
MONITOR* monitor = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR*)monitor->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
bool have_events = false;
bool have_events = false,script_error = false;
if (handle)
{
@ -176,6 +176,7 @@ startMonitor(void *arg, void* opt)
}
else
{
script_error = true;
if(access(params->value,F_OK) == 0)
{
skygw_log_write(LE,
@ -193,11 +194,20 @@ startMonitor(void *arg, void* opt)
}
else if(!strcmp(params->name,"events"))
{
mon_parse_event_string(handle->events,sizeof(handle->events),params->value);
have_events = true;
if(mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value) != 0)
script_error = true;
else
have_events = true;
}
params = params->next;
}
if(script_error)
{
skygw_log_write(LE,"Error: Errors were found in the script configuration parameters "
"for the monitor '%s'. The script will not be used.",monitor->name);
free(handle->script);
handle->script = NULL;
}
/** If no specific events are given, enable them all */
if(!have_events)
{
@ -313,6 +323,8 @@ char *server_string;
int read_timeout = mon->read_timeout;
int write_timeout = mon->write_timeout;
if(database->con)
mysql_close(database->con);
database->con = mysql_init(NULL);
mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);

View File

@ -111,7 +111,7 @@ startMonitor(void *arg,void* opt)
MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
bool have_events = false;
bool have_events = false,script_error = false;
if (handle != NULL)
{
@ -140,6 +140,7 @@ startMonitor(void *arg,void* opt)
}
else
{
script_error = true;
if(access(params->value,F_OK) == 0)
{
skygw_log_write(LE,
@ -157,10 +158,19 @@ startMonitor(void *arg,void* opt)
}
else if(!strcmp(params->name,"events"))
{
mon_parse_event_string(&handle->events,sizeof(handle->events),params->value);
have_events = true;
if(mon_parse_event_string((bool*)&handle->events,sizeof(handle->events),params->value) != 0)
script_error = true;
else
have_events = true;
}
params = params->next;
}
if(script_error)
{
skygw_log_write(LE,"Error: Errors were found in the script configuration parameters "
"for the monitor '%s'. The script will not be used.",mon->name);
free(handle->script);
handle->script = NULL;
}
/** If no specific events are given, enable them all */
if(!have_events)

View File

@ -1,27 +1,28 @@
add_library(MySQLClient SHARED mysql_client.c mysql_common.c)
target_link_libraries(MySQLClient log_manager utils)
install(TARGETS MySQLClient DESTINATION modules)
install(TARGETS MySQLClient DESTINATION ${MAXSCALE_LIBDIR})
add_library(MySQLBackend SHARED mysql_backend.c mysql_common.c)
target_link_libraries(MySQLBackend log_manager utils)
install(TARGETS MySQLBackend DESTINATION modules)
install(TARGETS MySQLBackend DESTINATION ${MAXSCALE_LIBDIR})
add_library(telnetd SHARED telnetd.c)
target_link_libraries(telnetd log_manager utils)
install(TARGETS telnetd DESTINATION modules)
install(TARGETS telnetd DESTINATION ${MAXSCALE_LIBDIR})
add_library(HTTPD SHARED httpd.c)
target_link_libraries(HTTPD log_manager utils)
install(TARGETS HTTPD DESTINATION modules)
install(TARGETS HTTPD DESTINATION ${MAXSCALE_LIBDIR})
if(BUILD_TESTS)
add_library(testprotocol SHARED testprotocol.c)
install(TARGETS testprotocol DESTINATION modules)
install(TARGETS testprotocol DESTINATION ${MAXSCALE_LIBDIR})
add_subdirectory(test)
endif()
add_library(maxscaled SHARED maxscaled.c)
target_link_libraries(maxscaled log_manager utils)
install(TARGETS maxscaled DESTINATION modules)
install(TARGETS maxscaled DESTINATION ${MAXSCALE_LIBDIR})

View File

@ -37,7 +37,7 @@
* 09/09/2014 Massimiliano Pinto Added: 777 permission for socket path
* 13/10/2014 Massimiliano Pinto Added: dbname authentication check
* 10/11/2014 Massimiliano Pinto Added: client charset added to protocol struct
*
* 29/05/2015 Markus Makela Added SSL support
*/
#include <skygw_utils.h>
#include <log_manager.h>
@ -46,6 +46,7 @@
#include <modinfo.h>
#include <sys/stat.h>
#include <modutil.h>
#include <netinet/tcp.h>
MODULE_INFO info = {
MODULE_API_PROTOCOL,
@ -69,14 +70,18 @@ static int gw_MySQLWrite_client(DCB *dcb, GWBUF *queue);
static int gw_error_client_event(DCB *dcb);
static int gw_client_close(DCB *dcb);
static int gw_client_hangup_event(DCB *dcb);
int gw_read_client_event_SSL(DCB* dcb);
int gw_MySQLWrite_client_SSL(DCB *dcb, GWBUF *queue);
int gw_write_client_event_SSL(DCB *dcb);
int mysql_send_ok(DCB *dcb, int packet_number, int in_affected_rows, const char* mysql_message);
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 **);
extern char* get_username_from_auth(char* ptr, uint8_t* data);
extern int check_db_name_after_auth(DCB *, char *, int);
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db);
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db,int);
int do_ssl_accept(MySQLProtocol* protocol);
/*
* The "module object" for the mysqld client protocol module.
@ -242,7 +247,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 +324,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);
@ -375,21 +389,24 @@ MySQLSendHandshake(DCB* dcb)
/**
* gw_mysql_do_authentication
*
* Performs the MySQL protocol 4.1 authentication, using data in GWBUF *queue
* Performs the MySQL protocol 4.1 authentication, using data in GWBUF **queue.
*
* (MYSQL_session*)client_data including: user, db, client_sha1 are copied into
* the dcb->data and later to dcb->session->data.
*
* client_capabilitiesa are copied into the dcb->protocol
* the dcb->data and later to dcb->session->data. client_capabilities are copied
* into the dcb->protocol.
*
* If SSL is enabled for the service, the SSL handshake will be done before the
* MySQL authentication.
*
* @param dcb Descriptor Control Block of the client
* @param queue The GWBUF with data from client
* @param queue Pointer to the location of the GWBUF with data from client
* @return 0 If succeed, otherwise non-zero value
*
* @note in case of failure, dcb->data is freed before returning. If succeed,
* dcb->data is freed in session.c:session_free.
*/
static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
static int gw_mysql_do_authentication(DCB *dcb, GWBUF **buf) {
GWBUF* queue = *buf;
MySQLProtocol *protocol = NULL;
/* int compress = -1; */
int connect_with_db = -1;
@ -402,7 +419,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);
@ -437,7 +454,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
/* Detect now if there are enough bytes to continue */
if (client_auth_packet_size < (4 + 4 + 4 + 1 + 23))
{
return 1;
return MYSQL_FAILED_AUTH;
}
memcpy(&protocol->client_capabilities, client_auth_packet + 4, 4);
@ -451,11 +468,66 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
&protocol->client_capabilities);
*/
/** Skip this if the SSL handshake is already done.
* If not, start the SSL handshake. */
if(protocol->protocol_auth_state != MYSQL_AUTH_SSL_HANDSHAKE_DONE)
{
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)
{
LOGIF(LT,(skygw_log_write(LT,"User %s@%s connected to service '%s' without SSL when SSL was required.",
protocol->owner_dcb->user,
protocol->owner_dcb->remote,
protocol->owner_dcb->service->name)));
return MYSQL_FAILED_AUTH_SSL;
}
if(LOG_IS_ENABLED(LT) && ssl)
{
skygw_log_write(LT,"User %s@%s connected to service '%s' with SSL.",
protocol->owner_dcb->user,
protocol->owner_dcb->remote,
protocol->owner_dcb->service->name);
}
/** Do the SSL Handshake */
if(ssl && protocol->owner_dcb->service->ssl_mode != SSL_DISABLED)
{
protocol->protocol_auth_state = MYSQL_AUTH_SSL_REQ;
if(do_ssl_accept(protocol) < 0)
{
return MYSQL_FAILED_AUTH;
}
else
{
return 0;
}
}
else if(dcb->service->ssl_mode == SSL_ENABLED)
{
/** This is a non-SSL connection to a SSL enabled service.
* We have only read enough of the packet to know that the client
* is not requesting SSL and the rest of the auth packet is still
* waiting in the socket. We need to read the data from the socket
* to find out the username of the connecting client. */
int bytes = dcb_read(dcb,&queue);
queue = gwbuf_make_contiguous(queue);
client_auth_packet = GWBUF_DATA(queue);
client_auth_packet_size = gwbuf_length(queue);
*buf = queue;
LOGIF(LD,(skygw_log_write(LD,"%lu Read %d bytes from fd %d",pthread_self(),bytes,dcb->fd)));
}
}
username = get_username_from_auth(username, client_auth_packet);
if (username == NULL)
{
return 1;
return MYSQL_FAILED_AUTH;
}
/* get charset */
@ -557,6 +629,24 @@ gw_MySQLWrite_client(DCB *dcb, GWBUF *queue)
return dcb_write(dcb, queue);
}
/**
* Write function for client DCB: writes data from MaxScale to Client using SSL
* encryption. The SSH handshake must have already been done.
*
* @param dcb The DCB of the client
* @param queue Queue of buffers to write
*/
int
gw_MySQLWrite_client_SSL(DCB *dcb, GWBUF *queue)
{
MySQLProtocol *protocol = NULL;
CHK_DCB(dcb);
protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
CHK_PROTOCOL(protocol);
return dcb_write_SSL(dcb, queue);
}
/**
* Client read event triggered by EPOLLIN
*
@ -580,9 +670,66 @@ int gw_read_client_event(
CHK_DCB(dcb);
protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
CHK_PROTOCOL(protocol);
rc = dcb_read(dcb, &read_buffer);
#ifdef SS_DEBUG
skygw_log_write(LD,"[gw_read_client_event] Protocol state: %s",
gw_mysql_protocol_state2string(protocol->protocol_auth_state));
#endif
/** SSL authentication is still going on, we need to call do_ssl_accept
* until it return 1 for success or -1 for error */
if(protocol->protocol_auth_state == MYSQL_AUTH_SSL_HANDSHAKE_ONGOING ||
protocol->protocol_auth_state == MYSQL_AUTH_SSL_REQ)
{
switch(do_ssl_accept(protocol))
{
case 0:
return 0;
break;
case 1:
{
int b = 0;
ioctl(dcb->fd,FIONREAD,&b);
if(b == 0)
{
skygw_log_write(LD,
"[gw_read_client_event] No data in socket after SSL auth");
return 0;
}
break;
}
case -1:
return 1;
break;
default:
return 1;
break;
}
}
if(protocol->use_ssl)
{
/** SSL handshake is done, communication is now encrypted with SSL */
rc = dcb_read_SSL(dcb, &read_buffer);
}
else if(dcb->service->ssl_mode != SSL_DISABLED &&
protocol->protocol_auth_state == MYSQL_AUTH_SENT)
{
/** The service allows both SSL and non-SSL connections.
* read only enough of the auth packet to know if the client is
* requesting SSL. If the client is not requesting SSL the rest of
the auth packet will be read later. */
rc = dcb_read_n(dcb, &read_buffer,(4 + 4 + 4 + 1 + 23));
}
else
{
/** Normal non-SSL connection */
rc = dcb_read(dcb, &read_buffer);
}
if (rc < 0)
{
dcb_close(dcb);
@ -690,8 +837,8 @@ int gw_read_client_event(
dcb->dcb_readqueue = gwbuf_append(dcb->dcb_readqueue, read_buffer);
nbytes_read = gwbuf_length(dcb->dcb_readqueue);
data = (uint8_t *)GWBUF_DATA(dcb->dcb_readqueue);
if (nbytes_read < 3 || nbytes_read < MYSQL_GET_PACKET_LEN(data))
int plen = MYSQL_GET_PACKET_LEN(data);
if (nbytes_read < 3 || nbytes_read < MYSQL_GET_PACKET_LEN(data) + 4)
{
rc = 0;
goto return_rc;
@ -719,7 +866,7 @@ int gw_read_client_event(
}
}
/**
* Now there should be at least one complete mysql packet in read_buffer.
*/
@ -729,8 +876,19 @@ int gw_read_client_event(
{
int auth_val;
auth_val = gw_mysql_do_authentication(dcb, read_buffer);
auth_val = gw_mysql_do_authentication(dcb, &read_buffer);
if(protocol->protocol_auth_state == MYSQL_AUTH_SSL_REQ ||
protocol->protocol_auth_state == MYSQL_AUTH_SSL_HANDSHAKE_ONGOING ||
protocol->protocol_auth_state == MYSQL_AUTH_SSL_HANDSHAKE_DONE ||
protocol->protocol_auth_state == MYSQL_AUTH_SSL_HANDSHAKE_FAILED)
{
/** SSL was requested and the handshake is either done or
* still ongoing. After the handshake is done, the client
* will send another auth packet. */
break;
}
if (auth_val == 0)
{
SESSION *session;
@ -796,7 +954,7 @@ int gw_read_client_event(
fail_str = create_auth_fail_str((char *)((MYSQL_session *)dcb->data)->user,
dcb->remote,
(char*)((MYSQL_session *)dcb->data)->client_sha1,
(char*)((MYSQL_session *)dcb->data)->db);
(char*)((MYSQL_session *)dcb->data)->db,auth_val);
modutil_send_mysql_err_packet(dcb, 2, 0, 1045, "28000", fail_str);
}
if (fail_str)
@ -824,6 +982,113 @@ int gw_read_client_event(
}
break;
case MYSQL_AUTH_SSL_HANDSHAKE_DONE:
{
int auth_val;
auth_val = gw_mysql_do_authentication(dcb, &read_buffer);
if (auth_val == 0)
{
SESSION *session;
protocol->protocol_auth_state = MYSQL_AUTH_RECV;
/**
* Create session, and a router session for it.
* If successful, there will be backend connection(s)
* after this point.
*/
session = session_alloc(dcb->service, dcb);
if (session != NULL)
{
CHK_SESSION(session);
ss_dassert(session->state != SESSION_STATE_ALLOC);
protocol->protocol_auth_state = MYSQL_IDLE;
/**
* Send an AUTH_OK packet to the client,
* packet sequence is # 2
*/
mysql_send_ok(dcb, 3, 0, NULL);
}
else
{
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [gw_read_client_event] session "
"creation failed. fd %d, "
"state = MYSQL_AUTH_FAILED.",
pthread_self(),
protocol->owner_dcb->fd)));
/** Send ERR 1045 to client */
mysql_send_auth_error(
dcb,
3,
0,
"failed to create new session");
dcb_close(dcb);
}
}
else
{
char* fail_str = NULL;
protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
if (auth_val == 2) {
/** Send error 1049 to client */
int message_len = 25 + MYSQL_DATABASE_MAXLEN;
fail_str = calloc(1, message_len+1);
snprintf(fail_str, message_len, "Unknown database '%s'",
(char*)((MYSQL_session *)dcb->data)->db);
modutil_send_mysql_err_packet(dcb, 3, 0, 1049, "42000", fail_str);
}else if(auth_val == 3){
/** Send error 1045 to client */
fail_str = create_auth_fail_str((char *)((MYSQL_session *)dcb->data)->user,
dcb->remote,
(char*)((MYSQL_session *)dcb->data)->client_sha1,
(char*)((MYSQL_session *)dcb->data)->db,auth_val);
modutil_send_mysql_err_packet(dcb, 3, 0, 1045, "28000", fail_str);
}else {
/** Send error 1045 to client */
fail_str = create_auth_fail_str((char *)((MYSQL_session *)dcb->data)->user,
dcb->remote,
(char*)((MYSQL_session *)dcb->data)->client_sha1,
(char*)((MYSQL_session *)dcb->data)->db,auth_val);
modutil_send_mysql_err_packet(dcb, 3, 0, 1045, "28000", fail_str);
}
if (fail_str)
free(fail_str);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [gw_read_client_event] after "
"gw_mysql_do_authentication, fd %d, "
"state = MYSQL_AUTH_FAILED.",
protocol->owner_dcb->fd,
pthread_self())));
/**
* Release MYSQL_session since it is not used anymore.
*/
if (!DCB_IS_CLONE(dcb))
{
free(dcb->data);
}
dcb->data = NULL;
dcb_close(dcb);
}
read_buffer = gwbuf_consume(read_buffer, nbytes_read);
}
break;
case MYSQL_IDLE:
{
uint8_t* payload = NULL;
@ -943,12 +1208,13 @@ return_rc:
return rc;
}
///////////////////////////////////////////////
// client write event to Client triggered by EPOLLOUT
//////////////////////////////////////////////
/**
/**
* @node Client's fd became writable, and EPOLLOUT event
* arrived. As a consequence, client input buffer (writeq) is flushed.
* arrived. As a consequence, client input buffer (writeq) is flushed.
*
* Parameters:
* @param dcb - in, use
@ -956,7 +1222,7 @@ return_rc:
*
* @return constantly 1
*
*
*
* @details (write detailed description here)
*
*/
@ -966,6 +1232,53 @@ int gw_write_client_event(DCB *dcb)
CHK_DCB(dcb);
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
if (dcb == NULL) {
goto return_1;
}
if (dcb->state == DCB_STATE_DISCONNECTED) {
goto return_1;
}
if (dcb->protocol == NULL) {
goto return_1;
}
protocol = (MySQLProtocol *)dcb->protocol;
CHK_PROTOCOL(protocol);
if (protocol->protocol_auth_state == MYSQL_IDLE)
{
dcb_drain_writeq(dcb);
goto return_1;
}
return_1:
#if defined(SS_DEBUG)
if (dcb->state == DCB_STATE_POLLING ||
dcb->state == DCB_STATE_NOPOLLING ||
dcb->state == DCB_STATE_ZOMBIE)
{
CHK_PROTOCOL(protocol);
}
#endif
return 1;
}
/**
* EPOLLOUT event arrived and as a consequence, client input buffer (writeq) is
* flushed. The data is encrypted and SSL is used. The SSL handshake must have
* been successfully completed prior to this function being called.
* @param client dcb
* @return constantly 1
*/
int gw_write_client_event_SSL(DCB *dcb)
{
MySQLProtocol *protocol = NULL;
CHK_DCB(dcb);
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
if (dcb == NULL) {
@ -984,7 +1297,7 @@ int gw_write_client_event(DCB *dcb)
if (protocol->protocol_auth_state == MYSQL_IDLE)
{
dcb_drain_writeq(dcb);
dcb_drain_writeq_SSL(dcb);
goto return_1;
}
@ -1064,6 +1377,9 @@ int gw_MySQLListener(
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,"Error: Failed to set socket options. Error %d: %s",errno,strerror(errno))));
}
if((syseno = setsockopt(l_so, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one))) != 0){
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,"Error: Failed to set socket options. Error %d: %s",errno,strerror(errno))));
}
// set NONBLOCKING mode
setnonblocking(l_so);
@ -1605,61 +1921,79 @@ return_rc:
return rc;
}
/**
* Create a character array including the query string.
* GWBUF given as input includes either one complete or partial query.
* Length of buffer is at most the query length+4 (length of packet header).
* Do the SSL authentication handshake.
* This creates the DCB SSL structure if one has not been created and starts the
* SSL handshake handling.
* @param protocol Protocol to connect with SSL
* @return 1 on success, 0 when the handshake is ongoing or -1 on error
*/
#if defined(NOT_USED)
static char* gw_get_or_create_querystr (
void* data,
bool* new_allocation)
int do_ssl_accept(MySQLProtocol* protocol)
{
GWBUF* buf = (GWBUF *)data;
size_t buflen; /*< first gw buffer data length */
size_t packetlen; /*< length of mysql packet */
size_t querylen; /*< total buffer length-<length of type indicator> */
size_t nbytes_copied;
char* startpos; /*< first byte of query in gw buffer */
char* str; /*< resulting query string */
CHK_GWBUF(buf);
packetlen = MYSQL_GET_PACKET_LEN((uint8_t *)GWBUF_DATA(buf));
str = (char *)malloc(packetlen); /*< leave space for terminating null */
if (str == NULL)
{
goto return_str;
}
*new_allocation = true;
/**
* First buffer includes 4 bytes header and a type indicator byte.
*/
buflen = GWBUF_LENGTH(buf);
querylen = packetlen-1;
ss_dassert(buflen<=querylen+5); /*< 5 == header+type indicator */
startpos = (char *)GWBUF_DATA(buf)+5;
nbytes_copied = MIN(querylen, buflen-5);
memcpy(str, startpos, nbytes_copied);
memset(&str[querylen-1], 0, 1);
buf = gwbuf_consume(buf, querylen-1);
/**
* In case of multi-packet statement whole buffer consists of query
* string.
*/
while (buf != NULL)
{
buflen = GWBUF_LENGTH(buf);
memcpy(str+nbytes_copied, GWBUF_DATA(buf), buflen);
nbytes_copied += buflen;
buf = gwbuf_consume(buf, buflen);
}
ss_dassert(str[querylen-1] == 0);
return_str:
return str;
}
int rval,errnum;
char errbuf[2014];
DCB* dcb = protocol->owner_dcb;
if(dcb->ssl == NULL)
{
if(dcb_create_SSL(dcb) != 0)
{
return -1;
}
}
rval = dcb_accept_SSL(dcb);
switch(rval)
{
case 0:
/** Not all of the data has been read. Go back to the poll
queue and wait for more.*/
rval = 0;
skygw_log_write_flush(LT,"SSL_accept ongoing for %s@%s",
protocol->owner_dcb->user,
protocol->owner_dcb->remote);
return 0;
break;
case 1:
spinlock_acquire(&protocol->protocol_lock);
protocol->protocol_auth_state = MYSQL_AUTH_SSL_HANDSHAKE_DONE;
protocol->use_ssl = true;
spinlock_release(&protocol->protocol_lock);
spinlock_acquire(&dcb->authlock);
dcb->func.write = gw_MySQLWrite_client_SSL;
dcb->func.write_ready = gw_write_client_event_SSL;
spinlock_release(&dcb->authlock);
rval = 1;
skygw_log_write_flush(LT,"SSL_accept done for %s@%s",
protocol->owner_dcb->user,
protocol->owner_dcb->remote);
break;
case -1:
spinlock_acquire(&protocol->protocol_lock);
protocol->protocol_auth_state = MYSQL_AUTH_SSL_HANDSHAKE_FAILED;
spinlock_release(&protocol->protocol_lock);
rval = -1;
skygw_log_write_flush(LE,
"Error: Fatal error in SSL_accept for %s",
protocol->owner_dcb->remote);
break;
default:
skygw_log_write_flush(LE,
"Error: Fatal error in SSL_accept, returned value was %d.",
rval);
break;
}
#ifdef SS_DEBUG
skygw_log_write(LD,"[do_ssl_accept] Protocol state: %s",
gw_mysql_protocol_state2string(protocol->protocol_auth_state));
#endif
return rval;
}

View File

@ -44,6 +44,7 @@
#include <skygw_types.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <netinet/tcp.h>
/** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask;
@ -137,7 +138,7 @@ void mysql_protocol_done (
goto retblock;
}
scmd = p->protocol_cmd_history;
while (scmd != NULL)
{
scmd2 = scmd->scom_next;
@ -812,6 +813,23 @@ int gw_do_connect_to_backend(
goto close_so;
}
int one = 1;
if(setsockopt(so, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) != 0)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error: Failed to set socket options "
"%s:%d failed.\n\t\t Socket configuration failed "
"due %d, %s.",
host,
port,
errno,
strerror(errno))));
rv = -1;
/** Close socket */
goto close_so;
}
/* set socket to as non-blocking here */
setnonblocking(so);
rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
@ -890,7 +908,11 @@ gw_mysql_protocol_state2string (int state) {
case MYSQL_AUTH_FAILED:
return "MySQL Authentication failed";
case MYSQL_IDLE:
return "MySQL authentication is succesfully done.";
return "MySQL authentication is succesfully done.";
case MYSQL_AUTH_SSL_REQ: return "MYSQL_AUTH_SSL_REQ";
case MYSQL_AUTH_SSL_HANDSHAKE_DONE: return "MYSQL_AUTH_SSL_HANDSHAKE_DONE";
case MYSQL_AUTH_SSL_HANDSHAKE_FAILED: return "MYSQL_AUTH_SSL_HANDSHAKE_FAILED";
case MYSQL_AUTH_SSL_HANDSHAKE_ONGOING: return "MYSQL_AUTH_SSL_HANDSHAKE_ONGOING";
default:
return "MySQL (unknown protocol state)";
}
@ -2199,7 +2221,8 @@ char *create_auth_fail_str(
char *username,
char *hostaddr,
char *sha1,
char *db)
char *db,
int errcode)
{
char* errstr;
const char* ferrstr;
@ -2214,6 +2237,10 @@ char *create_auth_fail_str(
{
ferrstr = "Access denied for user '%s'@'%s' (using password: %s) to database '%s'";
}
else if(errcode == MYSQL_FAILED_AUTH_SSL)
{
ferrstr = "Access without SSL denied";
}
else
{
ferrstr = "Access denied for user '%s'@'%s' (using password: %s)";
@ -2233,6 +2260,10 @@ char *create_auth_fail_str(
{
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"), db);
}
else if(errcode == MYSQL_FAILED_AUTH_SSL)
{
sprintf(errstr, ferrstr);
}
else
{
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));

View File

@ -0,0 +1,11 @@
configure_file(test_ssl.sh ${CMAKE_CURRENT_BINARY_DIR}/test_ssl.sh @ONLY)
configure_file(no_ca.cnf ${CMAKE_CURRENT_BINARY_DIR}/no_ca.cnf @ONLY)
configure_file(no_server_cert.cnf ${CMAKE_CURRENT_BINARY_DIR}/no_server_cert.cnf @ONLY)
configure_file(no_server_key.cnf ${CMAKE_CURRENT_BINARY_DIR}/no_server_key.cnf @ONLY)
configure_file(bad_ca.cnf ${CMAKE_CURRENT_BINARY_DIR}/bad_ca.cnf @ONLY)
configure_file(bad_cert.cnf ${CMAKE_CURRENT_BINARY_DIR}/bad_cert.cnf @ONLY)
configure_file(bad_key.cnf ${CMAKE_CURRENT_BINARY_DIR}/bad_key.cnf @ONLY)
configure_file(bad_ssl.cnf ${CMAKE_CURRENT_BINARY_DIR}/bad_ssl.cnf @ONLY)
configure_file(bad_ssl_version.cnf ${CMAKE_CURRENT_BINARY_DIR}/bad_ssl_version.cnf @ONLY)
configure_file(ok.cnf ${CMAKE_CURRENT_BINARY_DIR}/ok.cnf @ONLY)
add_test(NAME SSLTest COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_ssl.sh)

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=This is not a value
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=This is not a value
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=This is not a value
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=testing
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,29 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
ssl_version=Don't use SSL, it's not needed!
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
#ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
#ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
#ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,28 @@
[maxscale]
threads=1
logdir=@CMAKE_CURRENT_BINARY_DIR@
datadir=@CMAKE_CURRENT_BINARY_DIR@
piddir=@CMAKE_CURRENT_BINARY_DIR@
cachedir=@CMAKE_CURRENT_BINARY_DIR@
[Testservice]
type=service
router=readconnroute
servers=server1
user=user
passwd=pwd
ssl=enabled
ssl_ca_cert=@CMAKE_CURRENT_BINARY_DIR@/ca
ssl_cert=@CMAKE_CURRENT_BINARY_DIR@/server-cert
ssl_key=@CMAKE_CURRENT_BINARY_DIR@/server-key
[Testlistener]
type=listener
service=Testservice
protocol=MySQLBackend
port=12345
[server1]
type=server
address=127.0.0.1
port=4321

View File

@ -0,0 +1,83 @@
#!/usr/bin/env bash
function create_certs()
{
echo "CA cert" > @CMAKE_CURRENT_BINARY_DIR@/ca.pem
echo "Server Certificate" > @CMAKE_CURRENT_BINARY_DIR@/server-cert.pem
echo "Server Key" > @CMAKE_CURRENT_BINARY_DIR@/server-key.pem
}
function start_maxscale ()
{
local result=$(@CMAKE_INSTALL_PREFIX@/@MAXSCALE_BINDIR@/maxscale -d -f $1 &> $1.log;echo $?)
if [[ $result == "0" ]]
then
echo "Error: $1 exited with status $result!"
exit 1
fi
}
# All test cases expect that MaxScale will not start with a bad configuration or missing certificates
# No CA defined
printf "Testing No CA defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/no_ca.cnf
echo " OK"
# No cert defined
printf "Testing No cert defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/no_cert.cnf
echo " OK"
# No key defined
printf "Testing No key defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/no_key.cnf
echo " OK"
# Bad SSL value defined
printf "Testing Bad SSL defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/bad_ssl.cnf
echo " OK"
# Bad SSL version defined
printf "Testing Bad SSL version defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/bad_ssl_version.cnf
echo " OK"
# Bad CA value defined
printf "Testing Bad CA defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/bad_ca.cnf
echo " OK"
# Bad server certificate defined
printf "Testing Bad cert defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/bad_cert.cnf
echo " OK"
# Bad server key defined
printf "Testing Bad key defined"
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/bad_key.cnf
echo " OK"
# No CA file
printf "Testing No CA file"
create_certs
rm @CMAKE_CURRENT_BINARY_DIR@/ca.pem
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/ok.cnf
echo " OK"
# No server certificate file
printf "Testing No cert file"
create_certs
rm @CMAKE_CURRENT_BINARY_DIR@/server-cert.pem
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/ok.cnf
echo " OK"
# No server key file
printf "Testing No key file"
create_certs
rm @CMAKE_CURRENT_BINARY_DIR@/server-key.pem
start_maxscale @CMAKE_CURRENT_BINARY_DIR@/ok.cnf
echo " OK"
exit 0

View File

@ -2,20 +2,20 @@ if(BUILD_TESTS)
add_subdirectory(test)
add_library(testroute SHARED testroute.c)
target_link_libraries(testroute log_manager utils)
install(TARGETS testroute DESTINATION modules)
install(TARGETS testroute DESTINATION ${MAXSCALE_LIBDIR})
endif()
add_library(readconnroute SHARED readconnroute.c)
target_link_libraries(readconnroute log_manager utils)
install(TARGETS readconnroute DESTINATION modules)
install(TARGETS readconnroute DESTINATION ${MAXSCALE_LIBDIR})
add_library(debugcli SHARED debugcli.c debugcmd.c)
target_link_libraries(debugcli log_manager utils)
install(TARGETS debugcli DESTINATION modules)
install(TARGETS debugcli DESTINATION ${MAXSCALE_LIBDIR})
add_library(cli SHARED cli.c debugcmd.c)
target_link_libraries(cli log_manager utils)
install(TARGETS cli DESTINATION modules)
install(TARGETS cli DESTINATION ${MAXSCALE_LIBDIR})
add_subdirectory(readwritesplit)
add_subdirectory(schemarouter)

View File

@ -1,4 +1,4 @@
add_library(binlogrouter SHARED blr.c blr_master.c blr_cache.c blr_slave.c blr_file.c)
set_target_properties(binlogrouter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${CMAKE_INSTALL_PREFIX}/lib)
set_target_properties(binlogrouter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${MAXSCALE_LIBDIR})
target_link_libraries(binlogrouter ssl pthread log_manager)
install(TARGETS binlogrouter DESTINATION modules)
install(TARGETS binlogrouter DESTINATION ${MAXSCALE_LIBDIR})

View File

@ -71,7 +71,7 @@ static void blr_log_header(logfile_id_t file, char *msg, uint8_t *ptr);
int
blr_file_init(ROUTER_INSTANCE *router)
{
char *ptr, path[PATH_MAX], filename[PATH_MAX];
char *ptr, path[PATH_MAX+1], filename[PATH_MAX+1];
int file_found, n = 1;
int root_len, i;
DIR *dirp;
@ -79,12 +79,8 @@ struct dirent *dp;
if (router->binlogdir == NULL)
{
strcpy(path, "/usr/local/mariadb-maxscale");
if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
{
strncpy(path, ptr,PATH_MAX);
}
strncat(path, "/",PATH_MAX);
strcpy(path, get_datadir());
strncat(path,"/",PATH_MAX);
strncat(path, router->service->name,PATH_MAX);
if (access(path, R_OK) == -1)
@ -660,24 +656,20 @@ struct stat statb;
void
blr_cache_response(ROUTER_INSTANCE *router, char *response, GWBUF *buf)
{
char path[4097], *ptr;
char path[PATH_MAX+1], *ptr;
int fd;
strcpy(path, "/usr/local/mariadb-maxscale");
if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
{
strncpy(path, ptr, 4096);
}
strncat(path, "/", 4096);
strncat(path, router->service->name, 4096);
strcpy(path,get_datadir());
strncat(path,"/",PATH_MAX);
strncat(path, router->service->name, PATH_MAX);
if (access(path, R_OK) == -1)
mkdir(path, 0777);
strncat(path, "/.cache", 4096);
strncat(path, "/.cache", PATH_MAX);
if (access(path, R_OK) == -1)
mkdir(path, 0777);
strncat(path, "/", 4096);
strncat(path, response, 4096);
strncat(path, response, PATH_MAX);
if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
return;
@ -698,19 +690,15 @@ GWBUF *
blr_cache_read_response(ROUTER_INSTANCE *router, char *response)
{
struct stat statb;
char path[4097], *ptr;
char path[PATH_MAX+1], *ptr;
int fd;
GWBUF *buf;
strcpy(path, "/usr/local/mariadb-maxscale");
if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
{
strncpy(path, ptr, 4096);
}
strncat(path, "/", 4096);
strncat(path, router->service->name, 4096);
strncat(path, "/.cache/", 4096);
strncat(path, response, 4096);
strcpy(path, get_datadir());
strncat(path, "/", PATH_MAX);
strncat(path, router->service->name, PATH_MAX);
strncat(path, "/.cache/", PATH_MAX);
strncat(path, response, PATH_MAX);
if ((fd = open(path, O_RDONLY)) == -1)
return NULL;

View File

@ -1,4 +1,4 @@
add_library(maxinfo SHARED maxinfo.c maxinfo_parse.c maxinfo_error.c maxinfo_exec.c)
set_target_properties(maxinfo PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${CMAKE_INSTALL_PREFIX}/lib)
set_target_properties(maxinfo PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${MAXSCALE_LIBDIR})
target_link_libraries(maxinfo pthread log_manager)
install(TARGETS maxinfo DESTINATION modules)
install(TARGETS maxinfo DESTINATION ${MAXSCALE_LIBDIR})

View File

@ -1,6 +1,6 @@
add_library(readwritesplit SHARED readwritesplit.c)
target_link_libraries(readwritesplit ssl pthread log_manager utils query_classifier)
install(TARGETS readwritesplit DESTINATION modules)
install(TARGETS readwritesplit DESTINATION ${MAXSCALE_LIBDIR})
if(BUILD_TESTS)
add_subdirectory(test)
endif()

View File

@ -1,10 +1,10 @@
add_library(schemarouter SHARED schemarouter.c sharding_common.c)
target_link_libraries(schemarouter log_manager utils query_classifier)
install(TARGETS schemarouter DESTINATION modules)
install(TARGETS schemarouter DESTINATION ${MAXSCALE_LIBDIR})
add_library(shardrouter SHARED shardrouter.c svcconn.c sharding_common.c)
target_link_libraries(shardrouter log_manager utils query_classifier)
install(TARGETS shardrouter DESTINATION modules)
install(TARGETS shardrouter DESTINATION ${MAXSCALE_LIBDIR})
if(BUILD_TESTS)
add_subdirectory(test)