diff --git a/changelogs/unreleased/update-box.schema.usesr.password-method.md b/changelogs/unreleased/update-box.schema.usesr.password-method.md new file mode 100644 index 0000000000000000000000000000000000000000..ca7ee3fe52f9ca0701e3d90731381cb0c5a61339 --- /dev/null +++ b/changelogs/unreleased/update-box.schema.usesr.password-method.md @@ -0,0 +1,4 @@ +## box +* Since auth methods can use user name for hashing, user name is + added to argument list of `box.schema.user.password`. + Now it takes 2 arguments: password and user name. diff --git a/src/box/alter.cc b/src/box/alter.cc index b8badc5ab75848b42a3237707966d42b586a9582..1ffe1c2ffbc2f078d499753ed493bcd20eeca1ea 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -2949,7 +2949,7 @@ user_def_fill_auth_data(struct user_def *user, const char *auth_data) return -1; /* The guest user may only have an empty password. */ if (user->uid == GUEST && - !authenticate_password(auth, "", 0)) { + !authenticate_password(auth, "", 0, user->name)) { authenticator_delete(auth); diag_set(ClientError, ER_GUEST_USER_PASSWORD); return -1; diff --git a/src/box/applier.cc b/src/box/applier.cc index 01642beac5bb14c518cac67adcfa74a345cc7345..e9a600b43c3bf22205fc738710c64faa1c32a9cf 100644 --- a/src/box/applier.cc +++ b/src/box/applier.cc @@ -746,7 +746,8 @@ applier_connect(struct applier *applier) diag_raise(); const char *auth_request, *auth_request_end; assert(greeting.salt_len >= AUTH_SALT_SIZE); - auth_request_prepare(method, password, strlen(password), greeting.salt, + auth_request_prepare(method, password, strlen(password), + uri->login, greeting.salt, &auth_request, &auth_request_end); xrow_encode_auth(&row, uri->login, strlen(uri->login), method->name, strlen(method->name), diff --git a/src/box/auth_chap_sha1.c b/src/box/auth_chap_sha1.c index 093f2b8c3596130e7bf07830fc22069d24c72c55..af2b1534e3dc3293d0426701c8231bc4b174589e 100644 --- a/src/box/auth_chap_sha1.c +++ b/src/box/auth_chap_sha1.c @@ -141,10 +141,12 @@ auth_chap_sha1_delete(struct auth_method *method) static void auth_chap_sha1_data_prepare(const struct auth_method *method, const char *password, int password_len, + const char *user, const char **auth_data, const char **auth_data_end) { (void)method; + (void)user; struct region *region = &fiber()->gc; size_t size = mp_sizeof_str(SCRAMBLE_BASE64_SIZE); char *p = xregion_alloc(region, size); @@ -158,11 +160,13 @@ auth_chap_sha1_data_prepare(const struct auth_method *method, static void auth_chap_sha1_request_prepare(const struct auth_method *method, const char *password, int password_len, + const char *user, const char *salt, const char **auth_request, const char **auth_request_end) { (void)method; + (void)user; struct region *region = &fiber()->gc; size_t size = mp_sizeof_str(SCRAMBLE_SIZE); char *p = xregion_alloc(region, size); diff --git a/src/box/authentication.c b/src/box/authentication.c index d9b26985523a4cb1100cc5d8cb41dbccfd837341..fadd4defdc251460202419599c6d5d0170c55776 100644 --- a/src/box/authentication.c +++ b/src/box/authentication.c @@ -34,7 +34,7 @@ static struct mh_strnptr_t *auth_methods = NULL; bool authenticate_password(const struct authenticator *auth, - const char *password, int password_len) + const char *password, int password_len, const char *user) { /* * We don't really need to zero the salt here, because any salt would @@ -46,7 +46,7 @@ authenticate_password(const struct authenticator *auth, struct region *region = &fiber()->gc; size_t region_svp = region_used(region); const char *auth_request, *auth_request_end; - auth_request_prepare(auth->method, password, password_len, salt, + auth_request_prepare(auth->method, password, password_len, user, salt, &auth_request, &auth_request_end); bool ret = authenticate_request(auth, salt, auth_request, auth_request_end); diff --git a/src/box/authentication.h b/src/box/authentication.h index e8903c14f40b1a808ebed73e72027f881c176573..1c1b932bf82d39846450a8dba922e9e8b265727c 100644 --- a/src/box/authentication.h +++ b/src/box/authentication.h @@ -80,6 +80,7 @@ struct auth_method { void (*auth_data_prepare)(const struct auth_method *method, const char *password, int password_len, + const char *user, const char **auth_data, const char **auth_data_end); /** @@ -95,6 +96,7 @@ struct auth_method { void (*auth_request_prepare)(const struct auth_method *method, const char *password, int password_len, + const char *user, const char *salt, const char **auth_request, const char **auth_request_end); @@ -143,19 +145,20 @@ struct auth_method { static inline void auth_data_prepare(const struct auth_method *method, - const char *password, int password_len, + const char *password, int password_len, const char *user, const char **auth_data, const char **auth_data_end) { method->auth_data_prepare(method, password, password_len, - auth_data, auth_data_end); + user, auth_data, auth_data_end); } static inline void auth_request_prepare(const struct auth_method *method, - const char *password, int password_len, const char *salt, + const char *password, int password_len, + const char *user, const char *salt, const char **auth_request, const char **auth_request_end) { - method->auth_request_prepare(method, password, password_len, salt, + method->auth_request_prepare(method, password, password_len, user, salt, auth_request, auth_request_end); } @@ -208,7 +211,7 @@ authenticate_request(const struct authenticator *auth, const char *salt, */ bool authenticate_password(const struct authenticator *auth, - const char *password, int password_len); + const char *password, int password_len, const char *user); /** * Authenticates a user. diff --git a/src/box/lua/misc.cc b/src/box/lua/misc.cc index 8fc1e148de95215ec3ab554c7dfa6abdf40da0de..1d0c517bb6c3f90ede7a40b32024611e5c9aeaa0 100644 --- a/src/box/lua/misc.cc +++ b/src/box/lua/misc.cc @@ -237,7 +237,7 @@ lbox_generate_space_id(lua_State *L) /** {{{ Helper that generates user auth data. **/ /** - * Takes authentication method name (e.g. 'chap-sha1') and a password. + * Takes authentication method name (e.g. 'chap-sha1'), password and user name. * Returns authentication data that can be stored in the _user space. * Raises Lua error if the specified authentication method doesn't exist. */ @@ -255,10 +255,17 @@ lbox_prepare_auth(lua_State *L) tt_cstr(method_name, method_name_len)); return luaT_error(L); } + size_t user_len; + const char *user = luaL_checklstring(L, 3, &user_len); + /* + * User name shouldn't be verified, because this routine is called + * by box.schema.user.create before the user is actually creted. + */ + struct region *region = &fiber()->gc; size_t region_svp = region_used(region); const char *auth_data, *auth_data_end; - auth_data_prepare(method, password, password_len, + auth_data_prepare(method, password, password_len, user, &auth_data, &auth_data_end); luamp_decode(L, luaL_msgpack_default, &auth_data); assert(auth_data == auth_data_end); diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c index 6fcb3b31ae0d481682c2b3305c48eee99be94bcc..c18cf3467fcfd3376e762f194a3c1ee07ba9d546 100644 --- a/src/box/lua/net_box.c +++ b/src/box/lua/net_box.c @@ -715,7 +715,7 @@ netbox_encode_auth(struct lua_State *L, struct ibuf *ibuf, uint64_t sync, struct region *region = &fiber()->gc; size_t region_svp = region_used(region); const char *auth_request, *auth_request_end; - auth_request_prepare(method, password, strlen(password), salt, + auth_request_prepare(method, password, strlen(password), user, salt, &auth_request, &auth_request_end); struct mpstream stream; mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index c987170abda65d1fd3a48f23328ce4669279ec92..1015b92f885c4f60abffe000c484dffa111f793a 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -3200,13 +3200,14 @@ end box.schema.user = {} -box.schema.user.password = function(password) - return internal.prepare_auth(box.cfg.auth_type, password) +box.schema.user.password = function(password, name) + return internal.prepare_auth(box.cfg.auth_type, password, name) end -local function prepare_auth_list(password) +local function prepare_auth_list(password, name) return { - [box.cfg.auth_type] = internal.prepare_auth(box.cfg.auth_type, password) + [box.cfg.auth_type] = + internal.prepare_auth(box.cfg.auth_type, password, name) } end @@ -3224,11 +3225,11 @@ local function check_password(password, auth_history) end end -local function chpasswd(uid, new_password) +local function chpasswd(uid, new_password, name) local _user = box.space[box.schema.USER_ID] local auth_history = prepare_auth_history(uid) check_password(new_password, auth_history) - _user:update({uid}, {{'=', 5, prepare_auth_list(new_password)}, + _user:update({uid}, {{'=', 5, prepare_auth_list(new_password, name)}, {'=', 6, auth_history}, {'=', 7, math.floor(fiber.time())}}) end @@ -3240,14 +3241,14 @@ box.schema.user.passwd = function(name, new_password) if new_password == nil then -- change password for current user new_password = name - box.session.su('admin', chpasswd, session.uid(), new_password) + box.session.su('admin', chpasswd, session.uid(), new_password, name) else -- change password for other user local uid = user_resolve(name) if uid == nil then box.error(box.error.NO_SUCH_USER, name) end - return chpasswd(uid, new_password) + return chpasswd(uid, new_password, name) end end @@ -3264,7 +3265,7 @@ box.schema.user.create = function(name, opts) local auth_list if opts.password then check_password(opts.password) - auth_list = prepare_auth_list(opts.password) + auth_list = prepare_auth_list(opts.password, name) else auth_list = setmap({}) end diff --git a/test/box/access.result b/test/box/access.result index f7e481a8ee930701a4c3a0f1148b502024973e82..684b48282bd29e23da432e82541fad631e37995c 100644 --- a/test/box/access.result +++ b/test/box/access.result @@ -36,11 +36,11 @@ session.user(nil) ... -- password() is a function which returns base64(sha1(sha1(password)) -- a string to store in _user table -box.schema.user.password('test') +box.schema.user.password('test', "user") --- - lL3OvhkIPOKh+Vn9Avlkx69M/Ck= ... -box.schema.user.password('test1') +box.schema.user.password('test1', "user") --- - BsC/W2Ts4vZItfBIpxkDkGugjlw= ... diff --git a/test/box/access.test.lua b/test/box/access.test.lua index 9c81b11aa86f4b042d59a637a78ced33591c4737..0c0a885865f07997c9db887847cb25a465a181c7 100644 --- a/test/box/access.test.lua +++ b/test/box/access.test.lua @@ -14,8 +14,8 @@ session.effective_user() session.user(nil) -- password() is a function which returns base64(sha1(sha1(password)) -- a string to store in _user table -box.schema.user.password('test') -box.schema.user.password('test1') +box.schema.user.password('test', "user") +box.schema.user.password('test1', "user") -- admin can create any user box.schema.user.create('test', { password = 'test' }) -- su() let's you change the user of the session