Addition of admin user support
This commit is contained in:
@ -56,13 +56,15 @@ LDFLAGS=-rdynamic -L$(LOGPATH) \
|
|||||||
SRCS= atomic.c buffer.c spinlock.c gateway.c gateway_mysql_protocol.c \
|
SRCS= atomic.c buffer.c spinlock.c gateway.c gateway_mysql_protocol.c \
|
||||||
gw_utils.c utils.c dcb.c load_utils.c session.c service.c server.c \
|
gw_utils.c utils.c dcb.c load_utils.c session.c service.c server.c \
|
||||||
poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c \
|
poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c \
|
||||||
monitor.c
|
monitor.c adminusers.c
|
||||||
|
|
||||||
HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \
|
HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \
|
||||||
../include/gateway_mysql.h ../include/gw.h ../include/mysql_protocol.h \
|
../include/gateway_mysql.h ../include/gw.h ../include/mysql_protocol.h \
|
||||||
../include/session.h ../include/spinlock.h ../include/thread.h \
|
../include/session.h ../include/spinlock.h ../include/thread.h \
|
||||||
../include/modules.h ../include/poll.h ../include/config.h \
|
../include/modules.h ../include/poll.h ../include/config.h \
|
||||||
../include/users.h ../include/hashtable.h ../include/gwbitmask.h
|
../include/users.h ../include/hashtable.h ../include/gwbitmask.h \
|
||||||
|
../include/adminusers.h
|
||||||
|
|
||||||
OBJ=$(SRCS:.c=.o)
|
OBJ=$(SRCS:.c=.o)
|
||||||
|
|
||||||
LIBS=-L../inih/extra -linih -lssl -lstdc++ \
|
LIBS=-L../inih/extra -linih -lssl -lstdc++ \
|
||||||
|
|||||||
169
core/adminusers.c
Normal file
169
core/adminusers.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. 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 SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#define _XOPEN_SOURCE
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <crypt.h>
|
||||||
|
#include <users.h>
|
||||||
|
#include <adminusers.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file adminusers.c - Administration user account management
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 18/07/13 Mark Riddoch Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
static USERS *loadUsers();
|
||||||
|
static void initialise();
|
||||||
|
|
||||||
|
static USERS *users = NULL;
|
||||||
|
static int admin_init = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Admin Users initialisation
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
initialise()
|
||||||
|
{
|
||||||
|
if (admin_init)
|
||||||
|
return;
|
||||||
|
admin_init = 1;
|
||||||
|
users = loadUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify a username and password
|
||||||
|
*
|
||||||
|
* @param username Username to verify
|
||||||
|
* @param password Password to verify
|
||||||
|
* @return Non-zero if the username/password combination is valid
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
admin_verify(char *username, char *password)
|
||||||
|
{
|
||||||
|
char *pw;
|
||||||
|
|
||||||
|
initialise();
|
||||||
|
if (users == NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(username, "admin") == 0 && strcmp(password, "skysql") == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((pw = users_fetch(users, username)) == NULL)
|
||||||
|
return 0;
|
||||||
|
if (strcmp(pw, crypt(password, ADMIN_SALT)) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the admin users
|
||||||
|
*
|
||||||
|
* @return Table of users
|
||||||
|
*/
|
||||||
|
static USERS *
|
||||||
|
loadUsers()
|
||||||
|
{
|
||||||
|
USERS *rval;
|
||||||
|
FILE *fp;
|
||||||
|
char fname[1024], *home;
|
||||||
|
char uname[80], passwd[80];
|
||||||
|
|
||||||
|
initialise();
|
||||||
|
if ((home = getenv("MAXSCALE_HOME")) != NULL)
|
||||||
|
sprintf(fname, "%s/etc/passwd", home);
|
||||||
|
else
|
||||||
|
sprintf(fname, "/usr/local/skysql/MaxScale/etc/passwd");
|
||||||
|
if ((fp = fopen(fname, "r")) == NULL)
|
||||||
|
return NULL;
|
||||||
|
if ((rval = users_alloc()) == NULL)
|
||||||
|
return NULL;
|
||||||
|
while (fscanf(fp, "%[^:]:%s\n", uname, passwd) == 2)
|
||||||
|
{
|
||||||
|
users_add(rval, uname, passwd);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add user
|
||||||
|
*
|
||||||
|
* @param username Name of the new user
|
||||||
|
* @param password Password for the new user
|
||||||
|
* @return The number of users added
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
admin_add_user(char *uname, char *passwd)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char fname[1024], *home, *cpasswd;
|
||||||
|
|
||||||
|
initialise();
|
||||||
|
if ((home = getenv("MAXSCALE_HOME")) != NULL)
|
||||||
|
sprintf(fname, "%s/etc/passwd", home);
|
||||||
|
else
|
||||||
|
sprintf(fname, "/usr/local/skysql/MaxScale/etc/passwd");
|
||||||
|
if (users == NULL)
|
||||||
|
{
|
||||||
|
if ((users = users_alloc()) == NULL)
|
||||||
|
return 0;
|
||||||
|
if ((fp = fopen(fname, "w")) == NULL)
|
||||||
|
return 0;
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
if (users_fetch(users, uname) != NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cpasswd = crypt(passwd, ADMIN_SALT);
|
||||||
|
users_add(users, uname, cpasswd);
|
||||||
|
if ((fp = fopen(fname, "a")) == NULL)
|
||||||
|
return 0;
|
||||||
|
fprintf(fp, "%s:%s\n", uname, cpasswd);
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for existance of the user
|
||||||
|
*
|
||||||
|
* @param user The user name to test
|
||||||
|
* @return Non-zero if the user exists
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
admin_test_user(char *user)
|
||||||
|
{
|
||||||
|
initialise();
|
||||||
|
if (users == NULL)
|
||||||
|
return 0;
|
||||||
|
return users_fetch(users, user) != NULL;
|
||||||
|
}
|
||||||
38
include/adminusers.h
Normal file
38
include/adminusers.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef _ADMINUSERS_H
|
||||||
|
#define _ADMINUSERS_H
|
||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. 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 SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file adminusers.h - Administration users support routines
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 18/07/13 Mark Riddoch Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
#define ADMIN_SALT "MS"
|
||||||
|
|
||||||
|
extern int admin_verify(char *, char *);
|
||||||
|
extern int admin_add_user(char *, char *);
|
||||||
|
extern int admin_test_user(char *);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -29,7 +29,11 @@
|
|||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
#include <dcb.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The telnetd specific protocol structure to put in the DCB.
|
||||||
|
*/
|
||||||
typedef struct telnetd {
|
typedef struct telnetd {
|
||||||
int state; /**< The connection state */
|
int state; /**< The connection state */
|
||||||
char *username; /**< The login name of the user */
|
char *username; /**< The login name of the user */
|
||||||
@ -57,5 +61,4 @@ typedef struct telnetd {
|
|||||||
#define TELNET_IAC 255
|
#define TELNET_IAC 255
|
||||||
#define TELNET_ECHO 1
|
#define TELNET_ECHO 1
|
||||||
#define TELNET_SUPPRESS_GO_AHEAD 3
|
#define TELNET_SUPPRESS_GO_AHEAD 3
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -57,7 +57,7 @@ libMySQLBackend.so: $(MYSQLBACKENDOBJ)
|
|||||||
$(CC) $(LDFLAGS) $(MYSQLBACKENDOBJ) $(LIBS) -o $@
|
$(CC) $(LDFLAGS) $(MYSQLBACKENDOBJ) $(LIBS) -o $@
|
||||||
|
|
||||||
libtelnetd.so: $(TELNETDOBJ)
|
libtelnetd.so: $(TELNETDOBJ)
|
||||||
$(CC) $(LDFLAGS) $(TELNETDOBJ) $(LIBS) -o $@
|
$(CC) $(LDFLAGS) $(TELNETDOBJ) $(LIBS) -lcrypt -o $@
|
||||||
|
|
||||||
libHTTPD.so: $(HTTPDOBJ)
|
libHTTPD.so: $(HTTPDOBJ)
|
||||||
$(CC) $(LDFLAGS) $(HTTPDOBJ) $(LIBS) -o $@
|
$(CC) $(LDFLAGS) $(HTTPDOBJ) $(LIBS) -o $@
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <buffer.h>
|
#include <buffer.h>
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
#include <gw.h>
|
#include <gw.h>
|
||||||
#include <telnetd.h>
|
#include <telnetd.h>
|
||||||
|
#include <adminusers.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file telnetd.c - telnet daemon protocol module
|
* @file telnetd.c - telnet daemon protocol module
|
||||||
@ -82,9 +84,8 @@ static GWPROTOCOL MyObject = {
|
|||||||
NULL /**< Session */
|
NULL /**< Session */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void telnetd_command(DCB *, unsigned char *cmd);
|
static void telnetd_command(DCB *, unsigned char *cmd);
|
||||||
static void telnetd_echo(DCB *dcb, int enable);
|
static void telnetd_echo(DCB *dcb, int enable);
|
||||||
static int password_verify(char *, char *);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the mandatory version entry point
|
* Implementation of the mandatory version entry point
|
||||||
@ -137,7 +138,7 @@ ROUTER_OBJECT *router = session->service->router;
|
|||||||
ROUTER *router_instance = session->service->router_instance;
|
ROUTER *router_instance = session->service->router_instance;
|
||||||
void *rsession = session->router_session;
|
void *rsession = session->router_session;
|
||||||
TELNETD *telnetd = (TELNETD *)dcb->protocol;
|
TELNETD *telnetd = (TELNETD *)dcb->protocol;
|
||||||
char *password;
|
char *password, *t;
|
||||||
|
|
||||||
if ((n = dcb_read(dcb, &head)) != -1)
|
if ((n = dcb_read(dcb, &head)) != -1)
|
||||||
{
|
{
|
||||||
@ -158,13 +159,22 @@ char *password;
|
|||||||
{
|
{
|
||||||
case TELNETD_STATE_LOGIN:
|
case TELNETD_STATE_LOGIN:
|
||||||
telnetd->username = strndup(GWBUF_DATA(head), GWBUF_LENGTH(head));
|
telnetd->username = strndup(GWBUF_DATA(head), GWBUF_LENGTH(head));
|
||||||
|
/* Strip the cr/lf from the username */
|
||||||
|
t = strstr(telnetd->username, "\r\n");
|
||||||
|
if (t)
|
||||||
|
*t = 0;
|
||||||
telnetd->state = TELNETD_STATE_PASSWD;
|
telnetd->state = TELNETD_STATE_PASSWD;
|
||||||
dcb_printf(dcb, "Password: ");
|
dcb_printf(dcb, "Password: ");
|
||||||
telnetd_echo(dcb, 0);
|
telnetd_echo(dcb, 0);
|
||||||
|
GWBUF_CONSUME(head, GWBUF_LENGTH(head));
|
||||||
break;
|
break;
|
||||||
case TELNETD_STATE_PASSWD:
|
case TELNETD_STATE_PASSWD:
|
||||||
password = strndup(GWBUF_DATA(head), GWBUF_LENGTH(head));
|
password = strndup(GWBUF_DATA(head), GWBUF_LENGTH(head));
|
||||||
if (password_verify(telnetd->username, password))
|
/* Strip the cr/lf from the username */
|
||||||
|
t = strstr(password, "\r\n");
|
||||||
|
if (t)
|
||||||
|
*t = 0;
|
||||||
|
if (admin_verify(telnetd->username, password))
|
||||||
{
|
{
|
||||||
telnetd_echo(dcb, 1);
|
telnetd_echo(dcb, 1);
|
||||||
telnetd->state = TELNETD_STATE_DATA;
|
telnetd->state = TELNETD_STATE_DATA;
|
||||||
@ -176,6 +186,8 @@ char *password;
|
|||||||
telnetd_echo(dcb, 1);
|
telnetd_echo(dcb, 1);
|
||||||
telnetd->state = TELNETD_STATE_LOGIN;
|
telnetd->state = TELNETD_STATE_LOGIN;
|
||||||
}
|
}
|
||||||
|
GWBUF_CONSUME(head, GWBUF_LENGTH(head));
|
||||||
|
free(password);
|
||||||
break;
|
break;
|
||||||
case TELNETD_STATE_DATA:
|
case TELNETD_STATE_DATA:
|
||||||
router->routeQuery(router_instance, rsession, head);
|
router->routeQuery(router_instance, rsession, head);
|
||||||
@ -385,27 +397,3 @@ char *buf;
|
|||||||
buf[2] = TELNET_ECHO;
|
buf[2] = TELNET_ECHO;
|
||||||
dcb_write(dcb, gwbuf);
|
dcb_write(dcb, gwbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a username and password
|
|
||||||
*
|
|
||||||
* @param username Username to verify
|
|
||||||
* @param password Password to verify
|
|
||||||
* @return Non-zero if the username/password combination is valid
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
password_verify(char *username, char *password)
|
|
||||||
{
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
/* Strip the cr/lf from the username and password */
|
|
||||||
t = strstr(username, "\r\n");
|
|
||||||
if (t)
|
|
||||||
*t = 0;
|
|
||||||
t = strstr(password, "\r\n");
|
|
||||||
if (t)
|
|
||||||
*t = 0;
|
|
||||||
if (strcmp(username, "admin") == 0 && strcmp(password, "skysql") == 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -54,6 +54,8 @@
|
|||||||
#include <users.h>
|
#include <users.h>
|
||||||
#include <dbusers.h>
|
#include <dbusers.h>
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include <telnetd.h>
|
||||||
|
#include <adminusers.h>
|
||||||
#include <debugcli.h>
|
#include <debugcli.h>
|
||||||
|
|
||||||
#define MAXARGS 5
|
#define MAXARGS 5
|
||||||
@ -166,6 +168,17 @@ struct subcommand reloadoptions[] = {
|
|||||||
{0, 0, 0} }
|
{0, 0, 0} }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void telnetdAddUser(DCB *, char *, char *);
|
||||||
|
/**
|
||||||
|
* The subcommands of the add command
|
||||||
|
*/
|
||||||
|
struct subcommand addoptions[] = {
|
||||||
|
{ "user", 2, telnetdAddUser, "Add a new user for the debug interface. E.g. add user john today",
|
||||||
|
{ARG_TYPE_STRING, ARG_TYPE_STRING, 0} },
|
||||||
|
{ NULL, 0, NULL, NULL,
|
||||||
|
{0, 0, 0} }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The debug command table
|
* The debug command table
|
||||||
*/
|
*/
|
||||||
@ -179,6 +192,7 @@ static struct {
|
|||||||
{ "set", setoptions },
|
{ "set", setoptions },
|
||||||
{ "clear", clearoptions },
|
{ "clear", clearoptions },
|
||||||
{ "reload", reloadoptions },
|
{ "reload", reloadoptions },
|
||||||
|
{ "add", addoptions },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -446,3 +460,24 @@ reload_config(DCB *dcb)
|
|||||||
dcb_printf(dcb, "Reloading configuration from file.\n");
|
dcb_printf(dcb, "Reloading configuration from file.\n");
|
||||||
config_reload();
|
config_reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new admin user
|
||||||
|
*
|
||||||
|
* @param dcb The DCB for messages
|
||||||
|
* @param user The user name
|
||||||
|
* @param passwd The Password of the user
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
telnetdAddUser(DCB *dcb, char *user, char *passwd)
|
||||||
|
{
|
||||||
|
if (admin_test_user(user))
|
||||||
|
{
|
||||||
|
dcb_printf(dcb, "User %s already exists.\n", user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (admin_add_user(user, passwd))
|
||||||
|
dcb_printf(dcb, "User %s has been succesfully added.\n", user);
|
||||||
|
else
|
||||||
|
dcb_printf(dcb, "Failed to add new user.\n");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user