diff --git a/include/maxscale/adminusers.h.in b/include/maxscale/adminusers.h.in index a06f75dcb..2a1b4cfba 100644 --- a/include/maxscale/adminusers.h.in +++ b/include/maxscale/adminusers.h.in @@ -74,14 +74,17 @@ typedef struct admin_session void admin_users_init(); const char* admin_enable_linux_account(const char *uname); +const char *admin_enable_linux_admin_account(const char *uname); const char* admin_disable_linux_account(const char *uname); bool admin_linux_account_enabled(const char *uname); const char* admin_add_inet_user(const char *uname, const char *password); +const char *admin_add_inet_admin_user(const char *uname, const char* password); const char* admin_remove_inet_user(const char* uname); bool admin_inet_user_exists(const char *uname); bool admin_verify_inet_user(const char *uname, const char *password); bool admin_is_admin_user(const char* username); +bool admin_have_admin(); /** * @brief Convert all admin users to JSON diff --git a/server/core/adminusers.cc b/server/core/adminusers.cc index 68b233bb8..32458c475 100644 --- a/server/core/adminusers.cc +++ b/server/core/adminusers.cc @@ -34,12 +34,6 @@ static USERS *load_linux_users(); static USERS *load_inet_users(); -static const char *admin_add_user(USERS** pusers, const char* fname, - const char* uname, const char* password); -static const char* admin_remove_user(USERS *users, const char* fname, const char *uname); - - - static USERS *linux_users = NULL; static USERS *inet_users = NULL; @@ -85,14 +79,15 @@ static bool admin_dump_users(USERS* users, const char* fname) } static const char *admin_add_user(USERS** pusers, const char* fname, - const char* uname, const char* password) + const char* uname, const char* password, + account_type type) { if (*pusers == NULL) { *pusers = users_alloc(); } - if (!users_add(*pusers, uname, password ? password : "", ACCOUNT_ADMIN)) + if (!users_add(*pusers, uname, password ? password : "", type)) { return ADMIN_ERR_DUPLICATE; } @@ -340,7 +335,19 @@ static USERS *load_inet_users() */ const char *admin_enable_linux_account(const char *uname) { - return admin_add_user(&linux_users, LINUX_USERS_FILE_NAME, uname, NULL); + return admin_add_user(&linux_users, LINUX_USERS_FILE_NAME, uname, NULL, ACCOUNT_BASIC); +} + +/** + * Enable Linux account + * + * @param uname Name of Linux user + * + * @return NULL on success or an error string on failure. + */ +const char *admin_enable_linux_admin_account(const char *uname) +{ + return admin_add_user(&linux_users, LINUX_USERS_FILE_NAME, uname, NULL, ACCOUNT_ADMIN); } /** @@ -396,8 +403,15 @@ void mxs_crypt(const char* password, const char* salt, char* output) #endif } +static const char* add_inet_user(const char *uname, const char* password, account_type type) +{ + char cpassword[MXS_CRYPT_SIZE]; + mxs_crypt(password, ADMIN_SALT, cpassword); + return admin_add_user(&inet_users, INET_USERS_FILE_NAME, uname, cpassword, type); +} + /** - * Add insecure remote (network) user. + * Add insecure remote (network) basic user. * * @param uname Name of the new user. * @param password Password of the new user. @@ -406,10 +420,20 @@ void mxs_crypt(const char* password, const char* salt, char* output) */ const char *admin_add_inet_user(const char *uname, const char* password) { - char cpassword[MXS_CRYPT_SIZE]; - mxs_crypt(password, ADMIN_SALT, cpassword); + return add_inet_user(uname, password, ACCOUNT_BASIC); +} - return admin_add_user(&inet_users, INET_USERS_FILE_NAME, uname, cpassword); +/** + * Add insecure remote (network) admin user. + * + * @param uname Name of the new user. + * @param password Password of the new user. + * + * @return NULL on success or an error string on failure. + */ +const char *admin_add_inet_admin_user(const char *uname, const char* password) +{ + return add_inet_user(uname, password, ACCOUNT_ADMIN); } /** @@ -487,6 +511,12 @@ bool admin_is_admin_user(const char* username) return rval; } +bool admin_have_admin() +{ + return (inet_users && users_have_admin(inet_users)) || + (linux_users && users_have_admin(linux_users)); +} + /** * Print Linux and and inet users * diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index f1e2fc643..0238d2708 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -701,6 +701,7 @@ static void disable_syslog(); static void enable_maxlog(); static void disable_maxlog(); static void enable_account(DCB *, char *user); +static void enable_admin_account(DCB *, char *user); static void disable_account(DCB *, char *user); /** @@ -762,7 +763,20 @@ struct subcommand enableoptions[] = "account", 1, 1, enable_account, - "Activate a Linux user account for MaxAdmin use", + "Activate a Linux user account for read-only MaxAdmin use", + "Usage: enable account USER\n" + "\n" + "Parameters:\n" + "USER The user account to enable\n" + "\n" + "Example: enable account alice", + {ARG_TYPE_STRING} + }, + { + "admin-account", + 1, 1, + enable_admin_account, + "Activate a Linux user account for administrative MaxAdmin use", "Usage: enable account USER\n" "\n" "Parameters:\n" @@ -851,7 +865,8 @@ struct subcommand disableoptions[] = } }; -static void telnetdAddUser(DCB *, char *user, char *password); +static void inet_add_user(DCB *, char *user, char *password); +static void inet_add_admin_user(DCB *, char *user, char *password); static void cmd_AddServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3, char *v4, char *v5, char *v6, char *v7, char *v8, char *v9, @@ -913,8 +928,8 @@ struct subcommand pingoptions[] = struct subcommand addoptions[] = { { - "user", 2, 2, telnetdAddUser, - "Add insecure account for using maxadmin over the network", + "user", 2, 2, inet_add_user, + "Add a read-only account for using maxadmin over the network", "Usage: add user USER PASSWORD\n" "\n" "Parameters:\n" @@ -924,6 +939,18 @@ struct subcommand addoptions[] = "Example: add user bob somepass", {ARG_TYPE_STRING, ARG_TYPE_STRING} }, + { + "admin", 2, 2, inet_add_admin_user, + "Add an administrative account for using maxadmin over the network", + "Usage: add user USER PASSWORD\n" + "\n" + "Parameters:\n" + "USER User to add\n" + "PASSWORD Password for the user\n" + "\n" + "Example: add user admin-bob somepass", + {ARG_TYPE_STRING, ARG_TYPE_STRING} + }, { "server", 2, 12, cmd_AddServer, "Add a new server to a service", @@ -1482,8 +1509,8 @@ static void alterService(DCB *dcb, SERVICE *service, char *v1, char *v2, char *v } static void alterMaxScale(DCB *dcb, char *v1, char *v2, char *v3, - char *v4, char *v5, char *v6, char *v7, char *v8, char *v9, - char *v10, char *v11) + char *v4, char *v5, char *v6, char *v7, char *v8, char *v9, + char *v10, char *v11) { char *values[11] = {v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11}; const int items = sizeof(values) / sizeof(values[0]); @@ -1601,7 +1628,7 @@ struct subcommand alteroptions[] = ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING, ARG_TYPE_STRING } }, - { + { "maxscale", 1, 11, alterMaxScale, "Alter maxscale parameters", "Usage: alter maxscale KEY=VALUE ...\n" @@ -2231,8 +2258,7 @@ reload_config(DCB *dcb) * @param user The user name * @param user The user password */ -static void -telnetdAddUser(DCB *dcb, char *user, char *password) +static void do_inet_add_user(DCB *dcb, char *user, char *password, enum account_type type) { const char *err; @@ -2242,7 +2268,10 @@ telnetdAddUser(DCB *dcb, char *user, char *password) return; } - if ((err = admin_add_inet_user(user, password)) == NULL) + const char* (*f)(const char*, const char*) = type == ACCOUNT_ADMIN ? + admin_add_inet_admin_user : admin_add_inet_user; + + if ((err = f(user, password)) == NULL) { dcb_printf(dcb, "Account %s for remote (network) usage has been successfully added.\n", user); } @@ -2252,6 +2281,24 @@ telnetdAddUser(DCB *dcb, char *user, char *password) } } +static void inet_add_user(DCB *dcb, char *user, char *password) +{ + if (admin_have_admin()) + { + do_inet_add_user(dcb, user, password, ACCOUNT_BASIC); + } + else + { + dcb_printf(dcb, "No admin user created, create an admin account first\n" + "by executing `add admin USER PASSWORD`\n"); + } +} + +static void inet_add_admin_user(DCB *dcb, char *user, char *password) +{ + do_inet_add_user(dcb, user, password, ACCOUNT_ADMIN); +} + /** * Remove a remote (insecure, over the network) maxscale admin user * @@ -2539,8 +2586,7 @@ disable_maxlog() * @param dcb The DCB for messages * @param user The Linux user name */ -static void -enable_account(DCB *dcb, char *user) +static void do_enable_account(DCB *dcb, char *user, enum account_type type) { const char *err; @@ -2550,7 +2596,10 @@ enable_account(DCB *dcb, char *user) return; } - if ((err = admin_enable_linux_account(user)) == NULL) + const char* (*f)(const char*) = type == ACCOUNT_ADMIN ? + admin_enable_linux_admin_account : admin_enable_linux_account; + + if ((err = f(user)) == NULL) { dcb_printf(dcb, "The Linux user %s has successfully been enabled.\n", user); } @@ -2560,6 +2609,30 @@ enable_account(DCB *dcb, char *user) } } +static void enable_account(DCB *dcb, char *user) +{ + if (admin_have_admin()) + { + do_enable_account(dcb, user, ACCOUNT_BASIC); + } + else + { + dcb_printf(dcb, "No admin user created, create an admin account first\n" + "by executing `enable admin-account USER PASSWORD`\n"); + } +} + +/** + * Enable a Linux account + * + * @param dcb The DCB for messages + * @param user The Linux user name + */ +static void enable_admin_account(DCB *dcb, char *user) +{ + do_enable_account(dcb, user, ACCOUNT_ADMIN); +} + /** * Disable a Linux account *