From 01441dba6422832485b39b2a757f7b5aea580c77 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 24 Jul 2013 14:01:01 +0200 Subject: [PATCH] Addition of password encryption and decryption for passwords stored in the configuration file --- .bzrignore | 2 + core/Makefile | 16 ++- core/dbusers.c | 8 +- core/depend.mk | 118 +++++++++++++++- core/maxkeys.c | 47 +++++++ core/maxpasswd.c | 55 ++++++++ core/secrets.c | 238 +++++++++++++++++++++----------- include/secrets.h | 17 ++- modules/monitor/depend.mk | 9 +- modules/monitor/galera_mon.c | 9 +- modules/monitor/mysql_mon.c | 9 +- modules/routing/debugcli.c | 5 +- modules/routing/depend.mk | 13 +- modules/routing/readconnroute.c | 4 +- 14 files changed, 444 insertions(+), 106 deletions(-) create mode 100644 core/maxkeys.c create mode 100644 core/maxpasswd.c diff --git a/.bzrignore b/.bzrignore index 9f657093f..5ae09b517 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,3 +1,5 @@ core/tags gateway core/maxscale +core/maxkeys +core/maxpasswd diff --git a/core/Makefile b/core/Makefile index 79cf3dcb0..4f59b319d 100644 --- a/core/Makefile +++ b/core/Makefile @@ -32,6 +32,7 @@ # are behind SS_DEBUG macros. # 29/06/13 Vilho Raatikka Reverted Query classifier changes because # gateway needs mysql client lib, not qc. +# 24/07/13 Mark Ridoch Addition of encryption routines include ../../build_gateway.inc @@ -54,7 +55,7 @@ LDFLAGS=-rdynamic -L$(LOGPATH) \ 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 \ poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c \ - monitor.c adminusers.c + monitor.c adminusers.c secrets.c HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \ ../include/gateway_mysql.h ../include/gw.h ../include/mysql_protocol.h \ @@ -65,14 +66,25 @@ HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \ OBJ=$(SRCS:.c=.o) +KOBJS=maxkeys.o secrets.o utils.o +POBJS=maxpasswd.o secrets.o utils.o + LIBS=-L../inih/extra -linih -lssl -lstdc++ \ -L$(MARIADB_SRC_PATH)/libmysqld \ -lz -lm -lcrypt -lcrypto -ldl -pthread -llog_manager \ -lmysqld +all: maxscale maxkeys maxpasswd + maxscale: $(OBJ) $(CC) $(LDFLAGS) $(OBJ) $(UTILSPATH)/skygw_utils.o $(LIBS) -o $@ +maxkeys: $(KOBJS) + $(CC) $(LDFLAGS) $(KOBJS) $(UTILSPATH)/skygw_utils.o $(LIBS) -o $@ + +maxpasswd: $(POBJS) + $(CC) $(LDFLAGS) $(POBJS) $(UTILSPATH)/skygw_utils.o $(LIBS) -o $@ + .c.o: $(CC) $(CFLAGS) $< -o $@ @@ -87,7 +99,7 @@ depend: @rm -f depend.mk cc -M $(CFLAGS) $(SRCS) > depend.mk -install: maxscale +install: maxscale maxkeys maxpasswd @mkdir -p $(DEST)/bin install -D $< $(DEST)/bin diff --git a/core/dbusers.c b/core/dbusers.c index 1129129c0..03cbad10d 100644 --- a/core/dbusers.c +++ b/core/dbusers.c @@ -36,6 +36,7 @@ #include #include #include +#include static int getUsers(SERVICE *service, struct users *users); @@ -94,6 +95,7 @@ getUsers(SERVICE *service, struct users *users) int num_fields = 0; char *service_user = NULL; char *service_passwd = NULL; + char *dpwd; int total_users = 0; SERVER *server; @@ -122,17 +124,19 @@ getUsers(SERVICE *service, struct users *users) * to try */ server = service->databases; + dpwd = decryptPassword(service_passwd); while (server && mysql_real_connect(con, server->name, service_user, - service_passwd, + dpwd, NULL, server->port, NULL, 0) == NULL) { server = server->nextdb; - } + } + free(dpwd); if (server == NULL) { skygw_log_write(NULL, LOGFILE_ERROR, diff --git a/core/depend.mk b/core/depend.mk index b20eea9e4..c7cae395b 100644 --- a/core/depend.mk +++ b/core/depend.mk @@ -228,7 +228,16 @@ utils.o: utils.c ../include/gw.h /usr/include/stdio.h \ ../include/session.h ../include/mysql_protocol.h \ /usr/include/openssl/sha.h /usr/include/openssl/e_os2.h \ /usr/include/openssl/opensslconf.h \ - /usr/include/openssl/opensslconf-x86_64.h ../include/poll.h + /usr/include/openssl/opensslconf-x86_64.h ../include/poll.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h dcb.o: dcb.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ @@ -277,7 +286,16 @@ dcb.o: dcb.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/arpa/inet.h \ /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdbool.h \ ../include/gateway_mysql.h ../include/mysql_protocol.h ../include/dcb.h \ - ../include/poll.h ../include/atomic.h + ../include/poll.h ../include/atomic.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h load_utils.o: load_utils.c /usr/include/sys/param.h \ /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/limits.h \ /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/syslimits.h \ @@ -306,7 +324,16 @@ load_utils.o: load_utils.c /usr/include/sys/param.h \ /usr/include/dlfcn.h /usr/include/bits/dlfcn.h ../include/modules.h \ ../include/dcb.h ../include/spinlock.h ../include/thread.h \ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \ - /usr/include/bits/setjmp.h ../include/buffer.h ../include/gwbitmask.h + /usr/include/bits/setjmp.h ../include/buffer.h ../include/gwbitmask.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h session.o: session.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ @@ -437,7 +464,18 @@ config.o: config.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \ /usr/include/bits/setjmp.h ../include/dcb.h ../include/buffer.h \ ../include/gwbitmask.h ../include/server.h ../include/users.h \ - ../include/hashtable.h ../include/atomic.h ../include/monitor.h + ../include/hashtable.h ../include/atomic.h ../include/monitor.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \ + /usr/include/bits/confname.h /usr/include/getopt.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h users.o: users.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ @@ -510,7 +548,16 @@ dbusers.o: dbusers.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/assert.h /usr/include/unistd.h \ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \ /usr/include/bits/confname.h /usr/include/getopt.h \ - /home/mriddoch/Repository/skygateway/log_manager/log_manager.h + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h \ + ../include/secrets.h /usr/include/string.h /usr/include/stdlib.h \ + /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \ + /usr/include/alloca.h /usr/include/sys/stat.h /usr/include/bits/stat.h \ + /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \ + /usr/include/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \ + /usr/include/asm-generic/errno-base.h /usr/include/openssl/aes.h \ + /usr/include/openssl/opensslconf.h \ + /usr/include/openssl/opensslconf-x86_64.h thread.o: thread.c ../include/thread.h /usr/include/pthread.h \ /usr/include/features.h /usr/include/sys/cdefs.h \ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \ @@ -556,7 +603,18 @@ monitor.o: monitor.c /usr/include/stdio.h /usr/include/features.h \ ../include/server.h ../include/dcb.h ../include/spinlock.h \ ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \ /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/buffer.h \ - ../include/gwbitmask.h ../include/modules.h + ../include/gwbitmask.h ../include/modules.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \ + /usr/include/bits/confname.h /usr/include/getopt.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h adminusers.o: adminusers.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ @@ -579,4 +637,50 @@ adminusers.o: adminusers.c /usr/include/stdio.h /usr/include/features.h \ ../include/thread.h /usr/include/pthread.h /usr/include/sched.h \ /usr/include/bits/sched.h /usr/include/bits/setjmp.h ../include/atomic.h \ ../include/dcb.h ../include/buffer.h ../include/gwbitmask.h \ - ../include/adminusers.h + ../include/adminusers.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h +secrets.o: secrets.c ../include/secrets.h /usr/include/stdio.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \ + /usr/include/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \ + /usr/include/bits/types.h /usr/include/bits/typesizes.h \ + /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \ + /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \ + /usr/include/string.h /usr/include/xlocale.h /usr/include/stdlib.h \ + /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \ + /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/bits/byteswap.h /usr/include/sys/types.h \ + /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/bits/time.h \ + /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \ + /usr/include/alloca.h /usr/include/sys/stat.h /usr/include/bits/stat.h \ + /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \ + /usr/include/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \ + /usr/include/asm-generic/errno-base.h /usr/include/openssl/aes.h \ + /usr/include/openssl/opensslconf.h \ + /usr/include/openssl/opensslconf-x86_64.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/bits/sched.h /usr/include/bits/setjmp.h \ + /usr/include/unistd.h /usr/include/bits/posix_opt.h \ + /usr/include/bits/environments.h /usr/include/bits/confname.h \ + /usr/include/getopt.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h \ + /usr/include/ctype.h diff --git a/core/maxkeys.c b/core/maxkeys.c new file mode 100644 index 000000000..9ae59f8c7 --- /dev/null +++ b/core/maxkeys.c @@ -0,0 +1,47 @@ +/* + * 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 maxkeys.c - Create the random encryption keys for maxscale + * + * @verbatim + * Revision History + * + * Date Who Description + * 24/07/13 Mark Riddoch Initial implementation + * + * @endverbatim + */ +#include +#include + +main(int argc, char **argv) +{ + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + if (secrets_writeKeys(argv[1])) + { + fprintf(stderr, "Failed to encode the password\n"); + exit(1); + } + exit(0); +} diff --git a/core/maxpasswd.c b/core/maxpasswd.c new file mode 100644 index 000000000..ac8b0a042 --- /dev/null +++ b/core/maxpasswd.c @@ -0,0 +1,55 @@ +/* + * 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 maxpasswd.c - Implementation of pasword encoding + * + * @verbatim + * Revision History + * + * Date Who Description + * 24/07/13 Mark Riddoch Initial implementation + * + * @endverbatim + */ +#include +#include + +/** + * Encrypt a password for storing in the MaxScale.cnf file + * + * @param argc Argument count + * @param arv Argument vector + */ +int +main(int argc, char **argv) +{ +char *enc; + + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + if ((enc = encryptPassword(argv[1])) != NULL) + printf("%s\n", enc); + else + fprintf(stderr, "Failed to encode the password\n"); + return 0; +} diff --git a/core/secrets.c b/core/secrets.c index a9a207725..e2839dea4 100644 --- a/core/secrets.c +++ b/core/secrets.c @@ -16,83 +16,104 @@ * Copyright SkySQL Ab 2013 */ +#include +#include +#include +#include +#include -#include "secrets.h" +static MAXKEYS *maxkeys = NULL; -static char secrets_randomchar() { - return (char)((rand() % 78) + 30); +/** + * Generate a random printable character + * + * @return A random printable character + */ +static unsigned char +secrets_randomchar() +{ + return (char)((rand() % ('~' - ' ')) + ' '); } -static int secrets_random_str(char *output, int len) { - int i; - srand(time(0L)); +static int +secrets_random_str(unsigned char *output, int len) +{ +int i; + srand(time(0L)); - for ( i = 0; i < len; ++i ) { + for ( i = 0; i < len; ++i ) + { output[i] = secrets_randomchar(); } - - output[len]='\0'; - return 0; } /** * secrets_readKeys * - * This routine reads data from a binary file and exracts the AES encryption key + * This routine reads data from a binary file and extracts the AES encryption key * and the AES Init Vector - * - * Input parameters must be preallocated - * @param enc_key Will contain the encryption key found in file - * @param iv Will contain the Init vector found in file - * @param secret_file The file with secret keys - * @return 0 on success and 1 on failure */ +static void +secrets_readKeys() +{ +char secret_file[180]; +char *home; +MAXKEYS *keys; +struct stat secret_stats; +int fd; -int secrets_readKeys(char *enc_key, char *iv, char *secret_file) { - struct stat secret_stats; - char read_buffer[1 + AES_BLOCK_SIZE * 2 + AES_BLOCK_SIZE + 3]=""; - int fd =0; - int secret_file_size = 0; + if ((home = getenv("MAXSCALE_HOME")) == NULL) + home = "/usr/local/skysql/MaxScale"; + sprintf(secret_file, "%s/etc/.secrets", home); /* open secret file */ - fd = open(secret_file, O_RDONLY); - - if (fd < 0) { - fprintf(stderr, "secrets_readKeys, failed opening secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); - return 1; + if ((fd = open(secret_file, O_RDONLY)) < 0) + { + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_readKeys, failed opening secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + return; } /* accessing file details */ if (fstat(fd, &secret_stats) < 0) { - fprintf(stderr, "secrets_readKeys, failed accessing secret file details [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); - return 1; + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_readKeys, failed accessing secret file details [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + return; } - secret_file_size = secret_stats.st_size; - - fprintf(stderr, "The secret file has %i bytes\n", secret_file_size); - - /* read all data from file */ - if (read(fd, read_buffer, sizeof(read_buffer)-1) < 0) { - fprintf(stderr, "secrets_readKeys, failed reading from secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); - return 1; + if (secret_stats.st_size != sizeof(MAXKEYS)) + { + skygw_log_write(NULL, LOGFILE_ERROR, "Secrets file %s is incorrect size\n", secret_file); + return; + } + if (secret_stats.st_mode != (S_IRUSR|S_IFREG)) + { + skygw_log_write(NULL, LOGFILE_ERROR, "Ignoring secrets file, permissions must be read only fo rthe owner\n"); + return; } - /* Now filling input parameters */ - memcpy(enc_key, read_buffer+1, MAXSCALE_SECRETS_ONE); - memcpy(iv, read_buffer+1+MAXSCALE_SECRETS_ONE, MAXSCALE_SECRETS_INIT_VAL_ONE); - memcpy(enc_key+ MAXSCALE_SECRETS_ONE, read_buffer+1+MAXSCALE_SECRETS_ONE+MAXSCALE_SECRETS_INIT_VAL_ONE, MAXSCALE_SECRETS_TWO); - memcpy(iv+MAXSCALE_SECRETS_INIT_VAL_ONE, read_buffer+1+MAXSCALE_SECRETS_ONE+MAXSCALE_SECRETS_INIT_VAL_ONE+MAXSCALE_SECRETS_TWO, MAXSCALE_SECRETS_INIT_VAL_TWO); + if ((keys = (MAXKEYS *)malloc(sizeof(MAXKEYS))) == NULL) + { + skygw_log_write(NULL, LOGFILE_ERROR, + "Insufficient memory to create the keys structure.\n"); + return; + } + + /* read all data from file */ + if (read(fd, keys, sizeof(MAXKEYS)) != sizeof(MAXKEYS)) + { + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_readKeys, failed reading from secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + return; + } /* Close the file */ if (close(fd) < 0) { - fprintf(stderr, "secrets_readKeys, failed closing the secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); - return 1; + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_readKeys, failed closing the secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + return; } - return 0; + maxkeys = keys; + return; } /** @@ -106,54 +127,111 @@ int secrets_readKeys(char *enc_key, char *iv, char *secret_file) { */ int secrets_writeKeys(char *secret_file) { - char enc_key[1 + AES_BLOCK_SIZE * 2]=""; - char iv[1 + AES_BLOCK_SIZE]=""; - char secret_buffer[1 + AES_BLOCK_SIZE * 3 + 3] = ""; - char scramble_secret[1 + AES_BLOCK_SIZE * 3 + 3] = ""; - - char one_byte[1 + 1]=""; - char two_bytes[1 + 2]=""; - - int fd =0; +int fd; +MAXKEYS key; /* Open for writing | Create | Truncate the file for writing */ - fd = open(secret_file, O_CREAT | O_WRONLY | O_TRUNC); - - if (fd < 0) { - fprintf(stderr, "secrets_createKeys, failed opening secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + if ((fd = open(secret_file, O_CREAT | O_WRONLY | O_TRUNC), S_IRUSR) < 0) + { + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_createKeys, failed opening secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); return 1; } srand(time(NULL)); - secrets_random_str(secret_buffer, AES_BLOCK_SIZE * 3 + 3); - - /* assign key and iv from random buffer */ - memcpy(one_byte, secret_buffer, 1); - memcpy(enc_key, secret_buffer + 1, AES_BLOCK_SIZE * 2); - memcpy(iv, secret_buffer + 1 + AES_BLOCK_SIZE * 2, AES_BLOCK_SIZE); - memcpy(two_bytes, secret_buffer + 1 + AES_BLOCK_SIZE * 2 + AES_BLOCK_SIZE + 1, 2); - - //fprintf(stderr, "<<< Key32 is [%s]\n", enc_key); - //fprintf(stderr, "<<< IV16 is [%s]\n", iv); - - /* prepare data */ - memcpy(scramble_secret, one_byte, 1); - memcpy(scramble_secret + 1, enc_key, MAXSCALE_SECRETS_ONE); - memcpy(scramble_secret + 1 + MAXSCALE_SECRETS_ONE, iv, MAXSCALE_SECRETS_INIT_VAL_ONE); - memcpy(scramble_secret + 1 + MAXSCALE_SECRETS_ONE + MAXSCALE_SECRETS_INIT_VAL_ONE, enc_key + MAXSCALE_SECRETS_ONE, MAXSCALE_SECRETS_TWO); - memcpy(scramble_secret + 1 + MAXSCALE_SECRETS_ONE + MAXSCALE_SECRETS_INIT_VAL_ONE + MAXSCALE_SECRETS_TWO, iv + MAXSCALE_SECRETS_INIT_VAL_ONE, MAXSCALE_SECRETS_INIT_VAL_TWO); - memcpy(scramble_secret + 1 + MAXSCALE_SECRETS_ONE + MAXSCALE_SECRETS_INIT_VAL_ONE + MAXSCALE_SECRETS_TWO + MAXSCALE_SECRETS_INIT_VAL_TWO, two_bytes, 2); + secrets_random_str(key.enckey, MAXSCALE_KEYLEN); + secrets_random_str(key.initvector, MAXSCALE_IV_LEN); /* Write data */ - if(write(fd, scramble_secret, sizeof(scramble_secret)-1) < 0) { - fprintf(stderr, "secrets_createKeys, failed writing into secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + if (write(fd, &key, sizeof(key)) < 0) + { + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_createKeys, failed writing into secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); return 1; } /* close file */ - if (close(fd) < 0) { - fprintf(stderr, "secrets_createKeys, failed closing the secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); + if (close(fd) < 0) + { + skygw_log_write(NULL, LOGFILE_ERROR, "secrets_createKeys, failed closing the secret file [%s]. Error %i, %s\n", secret_file, errno, strerror(errno)); } + chmod(secret_file, S_IRUSR); + return 0; } + +/** + * Decrypt a password that is stored inthe MaxScale configuration file. + * If the password is not encrypted, ie is not a HEX string, then the + * original is returned, this allows for backward compatibility with + * unencrypted password. + * + * Note the return is always a malloc'd string that the caller must free + * + * @param crypt The encrypted password + * @return The decrypted password + */ +char * +decryptPassword(char *crypt) +{ +AES_KEY aeskey; +unsigned char *plain; +char *ptr; +unsigned char encrypted[80]; +int enlen; + + if (!maxkeys) + secrets_readKeys(); + if (!maxkeys) + return strdup(crypt); + /* If the input is not a HEX string return the input - it probably was not encrypted */ + for (ptr = crypt; *ptr; ptr++) + if (!isxdigit(*ptr)) + return strdup(crypt); + + enlen = strlen(crypt) / 2; + gw_hex2bin(encrypted, crypt, strlen(crypt)); + + if ((plain = (unsigned char *)malloc(80)) == NULL) + return NULL; + + AES_set_decrypt_key(maxkeys->enckey, 8 * MAXSCALE_KEYLEN, &aeskey); + + AES_cbc_encrypt(encrypted, plain, enlen, &aeskey, maxkeys->initvector, AES_DECRYPT); + + return (char *)plain; +} + +/** + * Encrypt a password that can be stored in the MaxScale configuration file. + * + * Note the return is always a malloc'd string that the caller must free + * + * @param password The password to encrypt + * @return The encrypted password + */ +char * +encryptPassword(char *password) +{ +AES_KEY aeskey; +int padded_len; +char *hex_output; +unsigned char padded_passwd[80]; +unsigned char encrypted[80]; + + if (!maxkeys) + secrets_readKeys(); + if (!maxkeys) + return NULL; + + memset(padded_passwd, 0, 80); + strcpy((char *)padded_passwd, password); + padded_len = ((strlen(password) / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + + AES_set_encrypt_key(maxkeys->enckey, 8 * MAXSCALE_KEYLEN, &aeskey); + + AES_cbc_encrypt(padded_passwd, encrypted, padded_len, &aeskey, maxkeys->initvector, AES_ENCRYPT); + hex_output = (char *)malloc(padded_len * 2); + gw_bin2hex(hex_output, encrypted, padded_len * 2); + + return hex_output; +} diff --git a/include/secrets.h b/include/secrets.h index 9b992d2b2..0325d75ae 100644 --- a/include/secrets.h +++ b/include/secrets.h @@ -40,9 +40,18 @@ #include -#define MAXSCALE_SECRETS_ONE 4 -#define MAXSCALE_SECRETS_TWO 28 -#define MAXSCALE_SECRETS_INIT_VAL_ONE 11 -#define MAXSCALE_SECRETS_INIT_VAL_TWO 5 +#define MAXSCALE_KEYLEN 32 +#define MAXSCALE_IV_LEN 16 +/** + * The key structure held in the secrets file + */ +typedef struct maxkeys { + unsigned char enckey[MAXSCALE_KEYLEN]; + unsigned char initvector[MAXSCALE_IV_LEN]; +} MAXKEYS; + +extern int secrets_writeKeys(char *filename); +extern char *decryptPassword(char *); +extern char *encryptPassword(char *); #endif diff --git a/modules/monitor/depend.mk b/modules/monitor/depend.mk index bc757dc22..653e9c7e6 100644 --- a/modules/monitor/depend.mk +++ b/modules/monitor/depend.mk @@ -32,4 +32,11 @@ mysql_mon.o: mysql_mon.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/assert.h /usr/include/unistd.h \ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \ /usr/include/bits/confname.h /usr/include/getopt.h \ - /home/mriddoch/Repository/skygateway/log_manager/log_manager.h + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h \ + ../../include/secrets.h /usr/include/sys/stat.h /usr/include/bits/stat.h \ + /usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/errno.h \ + /usr/include/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \ + /usr/include/asm-generic/errno-base.h /usr/include/openssl/aes.h \ + /usr/include/openssl/opensslconf.h \ + /usr/include/openssl/opensslconf-x86_64.h diff --git a/modules/monitor/galera_mon.c b/modules/monitor/galera_mon.c index 2e8cab8a3..daec03119 100644 --- a/modules/monitor/galera_mon.c +++ b/modules/monitor/galera_mon.c @@ -38,6 +38,7 @@ #include #include #include +#include static void monitorMain(void *); @@ -69,7 +70,8 @@ version() void ModuleInit() { - fprintf(stderr, "Initialise the MySQL Galera Monitor module.\n"); + skygw_log_write(NULL, LOGFILE_MESSAGE, "Initialise the MySQL Galera Monitor module %s.\n", + version_str); } /** @@ -237,13 +239,16 @@ char *uname = defaultUser, *passwd = defaultPasswd; if (database->con == NULL || mysql_ping(database->con) != 0) { + char *dpwd = decryptPassword(passwd); database->con = mysql_init(NULL); if (mysql_real_connect(database->con, database->server->name, - uname, passwd, NULL, database->server->port, NULL, 0) == NULL) + uname, dpwd, NULL, database->server->port, NULL, 0) == NULL) { server_clear_status(database->server, SERVER_RUNNING); + free(dpwd); return; } + free(dpwd); } /* If we get this far then we have a working connection */ diff --git a/modules/monitor/mysql_mon.c b/modules/monitor/mysql_mon.c index 0fb326888..4fa2dff4e 100644 --- a/modules/monitor/mysql_mon.c +++ b/modules/monitor/mysql_mon.c @@ -40,6 +40,7 @@ #include #include #include +#include static void monitorMain(void *); @@ -71,7 +72,8 @@ version() void ModuleInit() { - fprintf(stderr, "Initialise the MySQL Monitor module.\n"); + skygw_log_write(NULL, LOGFILE_MESSAGE, "Initialise the MySQL Monitor module %s.\n", + version_str); } /** @@ -240,13 +242,16 @@ char *uname = defaultUser, *passwd = defaultPasswd; return; if (database->con == NULL || mysql_ping(database->con) != 0) { + char *dpwd = decryptPassword(passwd); database->con = mysql_init(NULL); if (mysql_real_connect(database->con, database->server->name, - uname, passwd, NULL, database->server->port, NULL, 0) == NULL) + uname, dpwd, NULL, database->server->port, NULL, 0) == NULL) { + free(dpwd); server_clear_status(database->server, SERVER_RUNNING); return; } + free(dpwd); } /* If we get this far then we have a working connection */ diff --git a/modules/routing/debugcli.c b/modules/routing/debugcli.c index 1b165e060..c8fa95699 100644 --- a/modules/routing/debugcli.c +++ b/modules/routing/debugcli.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include static char *version_str = "V1.0.1"; @@ -76,7 +78,7 @@ version() void ModuleInit() { - fprintf(stderr, "Initial debug router module.\n"); + skygw_log_write(NULL, LOGFILE_MESSAGE, "Initialise debug CLI router module %s.\n", version_str); spinlock_init(&instlock); instances = NULL; } @@ -92,7 +94,6 @@ ModuleInit() ROUTER_OBJECT * GetModuleObject() { - fprintf(stderr, "Returing debug router module object.\n"); return &MyObject; } diff --git a/modules/routing/depend.mk b/modules/routing/depend.mk index 19835f6cd..d774cd963 100644 --- a/modules/routing/depend.mk +++ b/modules/routing/depend.mk @@ -90,7 +90,18 @@ debugcli.o: debugcli.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/bits/setjmp.h ../../include/dcb.h ../../include/buffer.h \ ../../include/gwbitmask.h ../../include/server.h ../../include/session.h \ ../../include/router.h ../../include/modules.h ../../include/atomic.h \ - ../../include/poll.h ../include/debugcli.h + ../../include/poll.h ../include/debugcli.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_utils.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_types.h \ + /usr/include/math.h /usr/include/bits/huge_val.h \ + /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \ + /usr/include/bits/inf.h /usr/include/bits/nan.h \ + /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \ + /home/mriddoch/Repository/skygateway/utils/skygw_debug.h \ + /usr/include/assert.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \ + /usr/include/bits/confname.h /usr/include/getopt.h \ + /home/mriddoch/Repository/skygateway/log_manager/log_manager.h debugcmd.o: debugcmd.c /usr/include/stdio.h /usr/include/features.h \ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \ diff --git a/modules/routing/readconnroute.c b/modules/routing/readconnroute.c index 5136ce885..6128f97e3 100644 --- a/modules/routing/readconnroute.c +++ b/modules/routing/readconnroute.c @@ -115,8 +115,7 @@ ModuleInit() { skygw_log_write(NULL, LOGFILE_MESSAGE, - strdup("Initial test router module.\n")); - fprintf(stderr, "Initial test router module.\n"); + "Initialise readconnroute router module %s.\n", version_str); spinlock_init(&instlock); instances = NULL; } @@ -132,7 +131,6 @@ ModuleInit() ROUTER_OBJECT * GetModuleObject() { - fprintf(stderr, "Returning test router module object.\n"); return &MyObject; }