MXS-862: Add authenticator options and instances

Authenticators now have a similar mechanism to the `router_options`
parameter which enables configurable authentication.

The authenticators also have a new initialize entry point which is similar
to the createInstance entry point of the filters and routers. The value of
`authenticator_options` is passed as a parameter to this function. The
return vaulue of the `initialize` entry point is passed to the `create`
entry point.
This commit is contained in:
Markus Makela 2016-10-11 22:44:43 +03:00
parent a2a8562c39
commit 9d8c5cd410
27 changed files with 236 additions and 62 deletions

View File

@ -1,4 +1,4 @@
add_library(maxscale-common SHARED adminusers.c alloc.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 listmanager.c load_utils.c log_manager.cc maxscale_pcre2.c memlog.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c slist.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c gw_ssl.c mysql_utils.c mysql_binlog.c)
add_library(maxscale-common SHARED adminusers.c alloc.c authenticator.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 listmanager.c load_utils.c log_manager.cc maxscale_pcre2.c memlog.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c slist.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c gw_ssl.c mysql_utils.c mysql_binlog.c)
target_link_libraries(maxscale-common ${MARIADB_CONNECTOR_LIBRARIES} ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} ${CURL_LIBRARIES} ssl pthread crypt dl crypto inih z rt m stdc++)

103
server/core/authenticator.c Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
*
* Change Date: 2019-07-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#include <gw_authenticator.h>
#include <modutil.h>
#include <modules.h>
#include <maxscale/alloc.h>
/**
* @file authenticator.c - Authenticator module functions
*/
/**
* @brief Initialize an authenticator module
*
* Process the options into an array and pass them to the authenticator
* initialization function
*
* The authenticator must implement the @c initialize entry point if this
* function is called. If the authenticator does not implement this, behavior is
* undefined.
*
* @param func Authenticator entry point
* @param options Authenticator options
* @return Authenticator instance or NULL on error
*/
bool authenticator_init(void** dest, const char *authenticator, const char *options)
{
bool rval = true;
void *instance = NULL;
GWAUTHENTICATOR *func = (GWAUTHENTICATOR*)load_module(authenticator, MODULE_AUTHENTICATOR);
if (func == NULL)
{
rval = false;
}
else if (func->initialize)
{
char *optarray[AUTHENTICATOR_MAX_OPTIONS + 1];
size_t optlen = options ? strlen(options) : 0;
char optcopy[optlen + 1];
int optcount = 0;
if (options)
{
strcpy(optcopy, options);
char *opt = optcopy;
while (opt && optcount < AUTHENTICATOR_MAX_OPTIONS)
{
char *end = strnchr_esc(opt, ',', sizeof(optcopy) - (opt - optcopy));
if (end)
{
*end++ = '\0';
}
optarray[optcount++] = opt;
opt = end;
}
}
optarray[optcount] = NULL;
if ((instance = func->initialize(optarray)) == NULL)
{
rval = false;
}
}
*dest = instance;
return rval;
}
/**
* @brief Get the default authenticator for a protocol
*
* @param protocol Protocol to inspect
* @return The default authenticator for the protocol or NULL if the protocol
* does not provide one
*/
char* get_default_authenticator(const char *protocol)
{
char *rval = NULL;
GWPROTOCOL *protofuncs = (GWPROTOCOL*)load_module(protocol, MODULE_PROTOCOL);
if (protofuncs && protofuncs->auth_default)
{
rval = MXS_STRDUP(protofuncs->auth_default());
}
return rval;
}

View File

@ -147,6 +147,7 @@ static char *service_params[] =
static char *listener_params[] =
{
"authenticator_options",
"type",
"service",
"protocol",
@ -2506,10 +2507,11 @@ int create_new_server(CONFIG_CONTEXT *obj)
char *monuser = config_get_value(obj->parameters, "monitoruser");
char *monpw = config_get_value(obj->parameters, "monitorpw");
char *auth = config_get_value(obj->parameters, "authenticator");
char *auth_opts = config_get_value(obj->parameters, "authenticator_options");
if (address && port && protocol)
{
if ((obj->element = server_alloc(address, protocol, atoi(port))))
if ((obj->element = server_alloc(address, protocol, atoi(port), auth, auth_opts)))
{
server_set_unique_name(obj->element, obj->object);
}
@ -2542,11 +2544,6 @@ int create_new_server(CONFIG_CONTEXT *obj)
error_count++;
}
if (auth && (server->authenticator = MXS_STRDUP(auth)) == NULL)
{
error_count++;
}
char *endptr;
const char *poolmax = config_get_value_string(obj->parameters, "persistpoolmax");
if (poolmax)
@ -2810,6 +2807,7 @@ int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
char *protocol = config_get_value(obj->parameters, "protocol");
char *socket = config_get_value(obj->parameters, "socket");
char *authenticator = config_get_value(obj->parameters, "authenticator");
char *authenticator_options = config_get_value(obj->parameters, "authenticator_options");
if (service_name && protocol && (socket || port))
{
@ -2828,7 +2826,7 @@ int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
else
{
serviceAddProtocol(service, obj->object, protocol, socket, 0,
authenticator, ssl_info);
authenticator, authenticator_options, ssl_info);
if (startnow)
{
serviceStartProtocol(service, protocol, 0);
@ -2848,8 +2846,8 @@ int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
}
else
{
serviceAddProtocol(service, obj->object, protocol, address,
atoi(port), authenticator, ssl_info);
serviceAddProtocol(service, obj->object, protocol, address, atoi(port),
authenticator, authenticator_options, ssl_info);
if (startnow)
{
serviceStartProtocol(service, protocol, atoi(port));

View File

@ -814,12 +814,6 @@ dcb_connect(SERVER *server, SESSION *session, const char *protocol)
memcpy(&dcb->authfunc, authfuncs, sizeof(GWAUTHENTICATOR));
/** Allocate DCB specific authentication data */
if (dcb->authfunc.create)
{
dcb->authenticator_data = dcb->authfunc.create();
}
/**
* Link dcb to session. Unlink is called in dcb_final_free
*/
@ -879,6 +873,16 @@ dcb_connect(SERVER *server, SESSION *session, const char *protocol)
* is established.
*/
/** Allocate DCB specific authentication data */
if (dcb->authfunc.create &&
(dcb->authenticator_data = dcb->authfunc.create(dcb->server->auth_instance)) == NULL)
{
MXS_ERROR("Failed to create authenticator for backend DCB.");
dcb->state = DCB_STATE_DISCONNECTED;
dcb_final_free(dcb);
return NULL;
}
/**
* Add the dcb in the poll set
*/
@ -3180,9 +3184,13 @@ dcb_accept(DCB *listener, GWPROTOCOL *protocol_funcs)
memcpy(&(client_dcb->authfunc), authfuncs, sizeof(GWAUTHENTICATOR));
/** Allocate DCB specific authentication data */
if (client_dcb->authfunc.create)
if (client_dcb->authfunc.create &&
(client_dcb->authenticator_data = client_dcb->authfunc.create(
client_dcb->listener->auth_instance)) == NULL)
{
client_dcb->authenticator_data = client_dcb->authfunc.create();
MXS_ERROR("Failed to create authenticator for client DCB.");
dcb_close(client_dcb);
return NULL;
}
if (client_dcb->service->max_connections &&

View File

@ -36,6 +36,7 @@
#include <log_manager.h>
#include <maxscale/alloc.h>
#include <users.h>
#include <modules.h>
static RSA *rsa_512 = NULL;
static RSA *rsa_1024 = NULL;
@ -49,12 +50,13 @@ static RSA *tmp_rsa_callback(SSL *s, int is_export, int keylength);
* @param address The address to listen with
* @param port The port to listen on
* @param authenticator Name of the authenticator to be used
* @param options Authenticator options
* @param ssl SSL configuration
* @return New listener object or NULL if unable to allocate
*/
SERV_LISTENER *
listener_alloc(struct service* service, char* name, char *protocol, char *address,
unsigned short port, char *authenticator, SSL_LISTENER *ssl)
unsigned short port, char *authenticator, char* auth_options, SSL_LISTENER *ssl)
{
if (address)
{
@ -68,20 +70,30 @@ listener_alloc(struct service* service, char* name, char *protocol, char *addres
if (authenticator)
{
authenticator = MXS_STRDUP(authenticator);
if (!authenticator)
{
MXS_FREE(address);
return NULL;
}
}
else if ((authenticator = get_default_authenticator(protocol)) == NULL)
{
MXS_ERROR("No authenticator defined for listener '%s' and could not get "
"default authenticator for protocol '%s'.", name, protocol);
}
void *auth_instance = NULL;
if (!authenticator_init(&auth_instance, authenticator, auth_options))
{
MXS_ERROR("Failed to initialize authenticator module '%s' for "
"listener '%s'.", authenticator, name);
}
protocol = MXS_STRDUP(protocol);
name = MXS_STRDUP(name);
SERV_LISTENER *proto = (SERV_LISTENER*)MXS_MALLOC(sizeof(SERV_LISTENER));
if (!protocol || !proto || !name)
if (!protocol || !proto || !name || !authenticator)
{
MXS_FREE(authenticator);
MXS_FREE(protocol);
MXS_FREE(address);
MXS_FREE(proto);
MXS_FREE(name);
return NULL;
@ -98,6 +110,7 @@ listener_alloc(struct service* service, char* name, char *protocol, char *addres
proto->users = NULL;
proto->resources = NULL;
proto->next = NULL;
proto->auth_instance = auth_instance;
spinlock_init(&proto->lock);
return proto;

View File

@ -44,6 +44,7 @@
#include <log_manager.h>
#include <gw_ssl.h>
#include <maxscale/alloc.h>
#include <modules.h>
static SPINLOCK server_spin = SPINLOCK_INIT;
static SERVER *allServers = NULL;
@ -62,18 +63,40 @@ static void server_parameter_free(SERVER_PARAM *tofree);
* @return The newly created server or NULL if an error occured
*/
SERVER *
server_alloc(char *servname, char *protocol, unsigned short port)
server_alloc(char *servname, char *protocol, unsigned short port, char *authenticator,
char *auth_options)
{
if (authenticator)
{
authenticator = MXS_STRDUP(authenticator);
}
else if ((authenticator = get_default_authenticator(protocol)) == NULL)
{
MXS_ERROR("No authenticator defined for server at %s:%u and no default "
"authenticator for protocol '%s'.", servname, port, protocol);
}
void *auth_instance = NULL;
if (!authenticator_init(&auth_instance, authenticator, auth_options))
{
MXS_ERROR("Failed to initialize authenticator module '%s' for server"
" at %s:%u.", authenticator, servname, port);
MXS_FREE(authenticator);
return NULL;
}
servname = MXS_STRNDUP(servname, MAX_SERVER_NAME_LEN);
protocol = MXS_STRDUP(protocol);
SERVER *server = (SERVER *)MXS_CALLOC(1, sizeof(SERVER));
if (!servname || !protocol || !server)
if (!servname || !protocol || !server || !authenticator)
{
MXS_FREE(servname);
MXS_FREE(protocol);
MXS_FREE(server);
MXS_FREE(authenticator);
return NULL;
}
@ -83,7 +106,8 @@ server_alloc(char *servname, char *protocol, unsigned short port)
#endif
server->name = servname;
server->protocol = protocol;
server->authenticator = NULL;
server->authenticator = authenticator;
server->auth_instance = auth_instance;
server->port = port;
server->status = SERVER_RUNNING;
server->node_id = -1;

View File

@ -672,11 +672,12 @@ service_free(SERVICE *service)
* @return TRUE if the protocol/port could be added
*/
int
serviceAddProtocol(SERVICE *service, char *name, char *protocol, char *address, unsigned short port, char *authenticator,
serviceAddProtocol(SERVICE *service, char *name, char *protocol, char *address,
unsigned short port, char *authenticator, char *options,
SSL_LISTENER *ssl)
{
SERV_LISTENER *proto = listener_alloc(service, name, protocol, address,
port, authenticator, ssl);
port, authenticator, options, ssl);
if (proto)
{

View File

@ -213,7 +213,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
return ret;
}
SERV_LISTENER *port = listener_alloc(service, "testlistener", "MySQLClient", NULL, 4006, NULL, NULL);
SERV_LISTENER *port = listener_alloc(service, "testlistener", "MySQLClient", NULL, 4006, "MySQLAuth", NULL, NULL);
dcb = dcb_alloc(DCB_ROLE_INTERNAL, port);

View File

@ -50,7 +50,7 @@ test1()
/* Server tests */
ss_dfprintf(stderr,
"testserver : creating server called MyServer");
server = server_alloc("MyServer", "HTTPD", 9876);
server = server_alloc("MyServer", "HTTPD", 9876, "NullAuthAccept", NULL);
mxs_log_flush_sync();
//ss_info_dassert(NULL != service, "New server with valid protocol and port must not be null");

View File

@ -69,7 +69,7 @@ test1()
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
ss_dfprintf(stderr, "\t..done\nAdding protocol testprotocol.");
ss_info_dassert(0 != serviceAddProtocol(service, "TestProtocol", "testprotocol",
"localhost", 9876, "MySQL", NULL),
"localhost", 9876, "MySQLClient", "MySQLAuth", NULL),
"Add Protocol should succeed");
ss_info_dassert(0 != serviceHasProtocol(service, "testprotocol", "localhost", 9876),
"Service should have new protocol as requested");

View File

@ -33,6 +33,9 @@
#include <openssl/err.h>
#include <openssl/dh.h>
/** Maximum number of authenticator options */
#define AUTHENTICATOR_MAX_OPTIONS 256
struct dcb;
struct server;
struct session;
@ -42,14 +45,30 @@ struct servlistener;
* @verbatim
* The operations that can be performed on the descriptor
*
* create Create a data structure unique to this DCB, stored in dcb->authenticator_data
* initialize Initialize the authenticator instance. The return value
* of this function will be given to the `create` entry point.
* If a module does not implement this entry point, the value
* given to the `create` is NULL.
*
* create Create a data structure unique to this DCB, stored in
* `dcb->authenticator_data`. If a module does not implement
* this entry point, `dcb->authenticator_data` will be set to NULL.
*
* extract Extract the data from a buffer and place in a structure
* shared at the session level, stored in dcb->data
* connectssl Determine whether the connection can support SSL
* shared at the session level, stored in `dcb->data`
*
* connectSSL Determine whether the connection can support SSL
*
* authenticate Carry out the authentication
* free Free extracted data
* destroy Destroy the unique DCB data
* loadusers Load or update authenticator user data
*
* free Free extracted data. This is only called for the client
* side authenticators so backend authenticators should not
* implement it.
*
* destroy Destroy the unique DCB data returned by the `create`
* entry point.
*
* loadUsers Load or update authenticator user data
* @endverbatim
*
* This forms the "module object" for authenticator modules within the gateway.
@ -58,13 +77,14 @@ struct servlistener;
*/
typedef struct gw_authenticator
{
void *(*create)();
int (*extract)(struct dcb *, GWBUF *);
bool (*connectssl)(struct dcb *);
int (*authenticate)(struct dcb *);
void (*free)(struct dcb *);
void (*destroy)(void *);
int (*loadusers)(struct servlistener *);
void* (*initialize)(char **options);
void* (*create)(void* instance);
int (*extract)(struct dcb *, GWBUF *);
bool (*connectssl)(struct dcb *);
int (*authenticate)(struct dcb *);
void (*free)(struct dcb *);
void (*destroy)(void *);
int (*loadusers)(struct servlistener *);
} GWAUTHENTICATOR;
/** Return values for extract and authenticate entry points */
@ -111,5 +131,8 @@ typedef enum
#define GWAUTHENTICATOR_VERSION {1, 1, 0}
bool authenticator_init(void **instance, const char *authenticator, const char *options);
char* get_default_authenticator(const char *protocol);
#endif /* GW_AUTHENTICATOR_H */

View File

@ -47,6 +47,7 @@ typedef struct servlistener
unsigned short port; /**< Port to listen on */
char *address; /**< Address to listen with */
char *authenticator; /**< Name of authenticator */
void *auth_instance; /**< Authenticator instance created in GWAUTHENTICATOR::initialize() */
SSL_LISTENER *ssl; /**< Structure of SSL data or NULL */
struct dcb *listener; /**< The DCB for the listener */
struct users *users; /**< The user data for this listener */
@ -58,7 +59,7 @@ typedef struct servlistener
SERV_LISTENER *listener_alloc(struct service* service, char *name, char *protocol,
char *address, unsigned short port, char *authenticator,
SSL_LISTENER *ssl);
char* options, SSL_LISTENER *ssl);
void listener_free(SERV_LISTENER* 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);

View File

@ -87,6 +87,7 @@ typedef struct server
unsigned short port; /**< Port to listen on */
char *protocol; /**< Protocol module to use */
char *authenticator; /**< Authenticator module name */
void *auth_instance; /**< Authenticator instance */
SSL_LISTENER *server_ssl; /**< SSL data structure for server, if any */
unsigned int status; /**< Status flag bitmap for the server */
char *monuser; /**< User name to use to monitor the db */
@ -193,7 +194,7 @@ typedef struct server
(((server)->status & (SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE|SERVER_MAINT)) == \
(SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE))
extern SERVER *server_alloc(char *, char *, unsigned short);
extern SERVER *server_alloc(char *, char *, unsigned short, char*, char*);
extern int server_free(SERVER *);
extern SERVER *server_find_by_unique_name(char *);
extern SERVER *server_find(char *, unsigned short);

View File

@ -173,7 +173,8 @@ extern SERVICE *service_find(char *);
extern int service_isvalid(SERVICE *);
extern int serviceAddProtocol(SERVICE *service, char *name, char *protocol,
char *address, unsigned short port,
char *authenticator, SSL_LISTENER *ssl);
char *authenticator, char *options,
SSL_LISTENER *ssl);
extern int serviceHasProtocol(SERVICE *service, const char *protocol,
const char* address, unsigned short port);
extern void serviceAddBackend(SERVICE *, SERVER *);

View File

@ -67,6 +67,7 @@ extern char *decryptPassword(char *crypt);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
cdc_auth_set_protocol_data, /* Extract data into structure */
cdc_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -294,6 +294,7 @@ int gssapi_auth_load_users(SERV_LISTENER *listener)
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* TODO: implement initialize entry point */
gssapi_auth_alloc, /* Allocate authenticator data */
gssapi_auth_extract, /* Extract data into structure */
gssapi_auth_connectssl, /* Check if client supports SSL */

View File

@ -42,7 +42,7 @@ typedef struct gssapi_auth
} gssapi_auth_t;
/** These functions can used for the `create` and `destroy` entry points */
void* gssapi_auth_alloc();
void* gssapi_auth_alloc(void *instance);
void gssapi_auth_free(void *data);
/** Report GSSAPI errors */

View File

@ -14,7 +14,7 @@
#include "gssapi_auth.h"
#include <maxscale/alloc.h>
void* gssapi_auth_alloc()
void* gssapi_auth_alloc(void *instance)
{
gssapi_auth_t* rval = MXS_MALLOC(sizeof(gssapi_auth_t));

View File

@ -170,6 +170,7 @@ static int gssapi_backend_auth_authenticate(DCB *dcb)
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* TODO: implement initialize entry point */
gssapi_auth_alloc, /* Allocate authenticator data */
gssapi_backend_auth_extract, /* Extract data into structure */
gssapi_backend_auth_connectssl, /* Check if client supports SSL */

View File

@ -59,6 +59,7 @@ static void http_auth_free_client_data(DCB *dcb);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
http_auth_set_protocol_data, /* Extract data into structure */
http_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -59,6 +59,7 @@ static void max_admin_auth_free_client_data(DCB *dcb);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
max_admin_auth_set_protocol_data, /* Extract data into structure */
max_admin_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -62,6 +62,7 @@ static int mysql_auth_load_users(SERV_LISTENER *port);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
mysql_auth_set_protocol_data, /* Extract data into structure */
mysql_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -52,7 +52,7 @@ typedef struct mysql_backend_auth
* @brief Allocate a new mysql_backend_auth object
* @return Allocated object or NULL if memory allocation failed
*/
void* auth_backend_create()
void* auth_backend_create(void *instance)
{
mysql_backend_auth_t* mba = MXS_MALLOC(sizeof(*mba));
@ -148,14 +148,6 @@ static bool auth_backend_ssl(DCB *dcb)
return dcb->server->server_ssl != NULL;
}
/**
* @brief Dummy function for the loadusers entry point
*/
static int auth_backend_load_users(SERV_LISTENER *port)
{
return MXS_AUTH_LOADUSERS_OK;
}
/* @see function load_module in load_utils.c for explanation of the following
* lint directives.
*/
@ -176,6 +168,7 @@ static char *version_str = "V1.0.0";
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
auth_backend_create, /* Create authenticator */
auth_backend_extract, /* Extract data into structure */
auth_backend_ssl, /* Check if client supports SSL */

View File

@ -58,6 +58,7 @@ static void null_auth_free_client_data(DCB *dcb);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
null_auth_set_protocol_data, /* Extract data into structure */
null_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -58,6 +58,7 @@ static void null_auth_free_client_data(DCB *dcb);
*/
static GWAUTHENTICATOR MyObject =
{
NULL, /* No initialize entry point */
NULL, /* No create entry point */
null_auth_set_protocol_data, /* Extract data into structure */
null_auth_is_client_ssl_capable, /* Check if client supports SSL */

View File

@ -598,7 +598,7 @@ createInstance(SERVICE *service, char **options)
{
SERVER *server;
SSL_LISTENER *ssl_cfg;
server = server_alloc("_none_", "MySQLBackend", (int)3306);
server = server_alloc("_none_", "MySQLBackend", 3306, "MySQLBackendAuth", NULL);
if (server == NULL)
{
MXS_ERROR("%s: Error for server_alloc in createInstance",

View File

@ -105,7 +105,7 @@ int main(int argc, char **argv) {
s = strtok_r(NULL, ",", &lasts);
}
server = server_alloc("_none_", "MySQLBackend", (int)3306);
server = server_alloc("_none_", "MySQLBackend", 3306, "MySQLBackendAuth", NULL);
if (server == NULL) {
return 1;
}