diff --git a/src/box/authentication.cc b/src/box/authentication.cc index 65a37870252f0c8060dbdd9bc8fc6b2fde59eef7..c078e55c7437e432b1e3e7f12b1ba2adc6def3b9 100644 --- a/src/box/authentication.cc +++ b/src/box/authentication.cc @@ -32,50 +32,73 @@ #include "user.h" #include "session.h" #include "iproto_constants.h" +#include "xrow.h" static char zero_hash[SCRAMBLE_SIZE]; -void -auth_request_decode_xc(struct auth_request *request, uint64_t sync, - const char *data, uint32_t len) +int +xrow_decode_auth(const struct xrow_header *row, struct auth_request *request) { - const char *end = data + len; - uint32_t map_size; - if (mp_typeof(*data) != MP_MAP || mp_check_map(data, end) > 0) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "packet body"); + if (row->bodycnt == 0) { + diag_set(ClientError, ER_INVALID_MSGPACK, + "missing request body"); + return 1; + } + + assert(row->bodycnt == 1); + const char *data = (const char *) row->body[0].iov_base; + const char *end = data + row->body[0].iov_len; + assert((end - data) > 0); + + if (mp_typeof(*data) != MP_MAP || mp_check_map(data, end) > 0) { +error: + diag_set(ClientError, ER_INVALID_MSGPACK, "packet body"); + return 1; + } + + memset(request, 0, sizeof(*request)); + request->header = row; - map_size = mp_decode_map(&data); - request->user_name = NULL; - request->scramble = NULL; - request->sync = sync; + uint32_t map_size = mp_decode_map(&data); for (uint32_t i = 0; i < map_size; ++i) { - uint8_t key = *data; - if (key != IPROTO_USER_NAME && key != IPROTO_TUPLE) { - /* Skip key + value. */ - mp_check(&data, end); - mp_check(&data, end); - continue; - } - const char *value = ++data; - if (mp_check(&data, end) != 0) { - tnt_raise(ClientError, ER_INVALID_MSGPACK, - "packet body"); - } - if (key == IPROTO_USER_NAME) + if ((end - data) < 1 || mp_typeof(*data) != MP_UINT) + goto error; + + uint64_t key = mp_decode_uint(&data); + const char *value = data; + if (mp_check(&data, end) != 0) + goto error; + + switch (key) { + case IPROTO_USER_NAME: + if (mp_typeof(*value) != MP_STR) + goto error; request->user_name = value; - else + break; + case IPROTO_TUPLE: + if (mp_typeof(*value) != MP_ARRAY) + goto error; request->scramble = value; + break; + default: + continue; /* unknown key */ + } + } + if (data != end) { + diag_set(ClientError, ER_INVALID_MSGPACK, "packet end"); + return 1; } if (request->user_name == NULL) { - tnt_raise(ClientError, ER_MISSING_REQUEST_FIELD, + diag_set(ClientError, ER_MISSING_REQUEST_FIELD, iproto_key_name(IPROTO_USER_NAME)); + return 1; } if (request->scramble == NULL) { - tnt_raise(ClientError, ER_MISSING_REQUEST_FIELD, - iproto_key_name(IPROTO_TUPLE)); + diag_set(ClientError, ER_MISSING_REQUEST_FIELD, + iproto_key_name(IPROTO_TUPLE)); + return 1; } - if (data != end) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "packet body"); + return 0; } void diff --git a/src/box/authentication.h b/src/box/authentication.h index 6989628a3b6a037d4705463ec7ca84f87a7864d9..1cf9d6d8737da94ae47b28db5253a6c7e26f111d 100644 --- a/src/box/authentication.h +++ b/src/box/authentication.h @@ -33,29 +33,37 @@ #include <stdint.h> -/** Auth request details. */ +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +struct xrow_header; + +/** + * AUTH request + */ struct auth_request { - /** - * MessagePack encoded name of the user to - * authenticate. - */ + /** Request header */ + const struct xrow_header *header; + /** MessagePack encoded name of the user to authenticate. */ const char *user_name; /** Auth scramble. @sa scramble.h */ const char *scramble; - /** Request sync. */ - uint64_t sync; }; /** - * Decode auth request from MessagePack. - * @param[out] request Request to decode to. - * @param sync Request sync. - * @param data Request MessagePack body. - * @param len @data length. + * Decode AUTH request from MessagePack. + * @param row request header. + * @param[out] request Request to decode. + * @retval 0 on success + * @retval -1 on error */ -void -auth_request_decode_xc(struct auth_request *request, uint64_t sync, - const char *data, uint32_t len); +int +xrow_decode_auth(const struct xrow_header *row, struct auth_request *request); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ void authenticate(const char *user_name, uint32_t len, const char *tuple); diff --git a/src/box/box.cc b/src/box/box.cc index 67c925afc991b6bf4478d44689b51a4d6d00d2ca..3b29ad7f05b563094725afb7f969ae1b5306a71e 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -961,7 +961,7 @@ box_process_auth(struct auth_request *request, struct obuf *out) const char *user = request->user_name; uint32_t len = mp_decode_strl(&user); authenticate(user, len, request->scramble); - iproto_reply_ok_xc(out, request->sync, ::schema_version); + iproto_reply_ok_xc(out, request->header->sync, ::schema_version); } void diff --git a/src/box/call.cc b/src/box/call.cc index c6fd46c36d166cdcce70e76ccd47e67c65fc466b..59b0d66f56d5c6c115533b3f3a8bb9129ce10a3e 100644 --- a/src/box/call.cc +++ b/src/box/call.cc @@ -45,67 +45,82 @@ static const char empty_args[] = { (char)0x90 }; -void -call_request_decode_xc(struct call_request *request, uint8_t type, - uint64_t sync, const char *data, uint32_t len) +int +xrow_decode_call(const struct xrow_header *row, struct call_request *request) { - assert(type == IPROTO_CALL || type == IPROTO_CALL_16 || type == IPROTO_EVAL); - const char *end = data + len; - uint32_t map_size; - if (mp_typeof(*data) != MP_MAP || mp_check_map(data, end) > 0) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "packet body"); + if (row->bodycnt == 0) { + diag_set(ClientError, ER_INVALID_MSGPACK, + "missing request body"); + return 1; + } + + assert(row->bodycnt == 1); + const char *data = (const char *) row->body[0].iov_base; + const char *end = data + row->body[0].iov_len; + assert((end - data) > 0); + + if (mp_typeof(*data) != MP_MAP || mp_check_map(data, end) > 0) { +error: + diag_set(ClientError, ER_INVALID_MSGPACK, "packet body"); + return 1; + } - map_size = mp_decode_map(&data); - request->name = NULL; - request->args = NULL; - request->args_end = NULL; - request->type = type; - request->sync = sync; + memset(request, 0, sizeof(*request)); + request->header = row; + + uint32_t map_size = mp_decode_map(&data); for (uint32_t i = 0; i < map_size; ++i) { - uint8_t key = *data; - if (key != IPROTO_EXPR && key != IPROTO_FUNCTION_NAME && - key != IPROTO_TUPLE) { - /* Skip key + value. */ - mp_check(&data, end); - mp_check(&data, end); - continue; - } - const char *value = ++data; - if (mp_check(&data, end) != 0) { - tnt_raise(ClientError, ER_INVALID_MSGPACK, - "packet body"); - } - switch(key) { - case IPROTO_EXPR: - request->expr = value; - break; + if ((end - data) < 1 || mp_typeof(*data) != MP_UINT) + goto error; + + uint64_t key = mp_decode_uint(&data); + const char *value = data; + if (mp_check(&data, end) != 0) + goto error; + + switch (key) { case IPROTO_FUNCTION_NAME: + if (mp_typeof(*value) != MP_STR) + goto error; request->name = value; break; + case IPROTO_EXPR: + if (mp_typeof(*value) != MP_STR) + goto error; + request->expr = value; + break; case IPROTO_TUPLE: + if (mp_typeof(*value) != MP_ARRAY) + goto error; request->args = value; request->args_end = data; break; default: - unreachable(); + continue; /* unknown key */ } } - if (type == IPROTO_EVAL) { + if (data != end) { + diag_set(ClientError, ER_INVALID_MSGPACK, "packet end"); + return 1; + } + if (row->type == IPROTO_EVAL) { if (request->expr == NULL) { - tnt_raise(ClientError, ER_MISSING_REQUEST_FIELD, - iproto_key_name(IPROTO_EXPR)); + diag_set(ClientError, ER_MISSING_REQUEST_FIELD, + iproto_key_name(IPROTO_EXPR)); + return 1; } } else if (request->name == NULL) { - assert(type == IPROTO_CALL_16 || type == IPROTO_CALL); - tnt_raise(ClientError, ER_MISSING_REQUEST_FIELD, - iproto_key_name(IPROTO_FUNCTION_NAME)); + assert(row->type == IPROTO_CALL_16 || + row->type == IPROTO_CALL); + diag_set(ClientError, ER_MISSING_REQUEST_FIELD, + iproto_key_name(IPROTO_FUNCTION_NAME)); + return 1; } if (request->args == NULL) { request->args = empty_args; request->args_end = empty_args + sizeof(empty_args); } - if (data != end) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "packet body"); + return 0; } static inline struct func * @@ -164,16 +179,16 @@ func_call(struct func *func, struct call_request *request, struct obuf *out) if (iproto_prepare_select(out, &svp) != 0) goto error; - if (request->type == IPROTO_CALL_16) { + if (request->header->type == IPROTO_CALL_16) { /* Tarantool < 1.7.1 compatibility */ if (port_dump(&port, out) != 0) { obuf_rollback_to_svp(out, &svp); goto error; } - iproto_reply_select(out, &svp, request->sync, + iproto_reply_select(out, &svp, request->header->sync, ::schema_version, port.size); } else { - assert(request->type == IPROTO_CALL); + assert(request->header->type == IPROTO_CALL); char *size_buf = (char *) obuf_alloc(out, mp_sizeof_array(port.size)); if (size_buf == NULL) @@ -183,7 +198,7 @@ func_call(struct func *func, struct call_request *request, struct obuf *out) obuf_rollback_to_svp(out, &svp); goto error; } - iproto_reply_select(out, &svp, request->sync, + iproto_reply_select(out, &svp, request->header->sync, ::schema_version, 1); } diff --git a/src/box/call.h b/src/box/call.h index 1c1cc6c4ba44072d404ceac27f87c5d6cef58e08..fd0e4ca28511950b80f340e95e17029bcfd8edfb 100644 --- a/src/box/call.h +++ b/src/box/call.h @@ -33,43 +33,46 @@ #include <stdint.h> -struct obuf; +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ -/** Request details of call and eval. */ +/** + * CALL/EVAL request. + */ struct call_request { - /** - * Set either name to function name of call request or - * set expr to lua expression for eval request. - */ - union { - const char *name; - const char *expr; - }; - /** Call/eval parameters. */ + /** Request header */ + const struct xrow_header *header; + /** Function name for CALL request. MessagePack String. */ + const char *name; + /** Expression for EVAL request. MessagePack String. */ + const char *expr; + /** CALL/EVAL parameters. MessagePack Array. */ const char *args; const char *args_end; - /** IPROTO_CALL/IPROTO_CALL_16/IPROTO_EVAL */ - uint8_t type; - /** Request sync. @sa xrow_header. */ - uint64_t sync; -}; - -struct box_function_ctx { - struct call_request *request; - struct port *port; }; /** - * Decode call request from a given MessagePack map. + * Decode CALL/EVAL request from a given MessagePack map. * @param[out] call_request Request to decode to. * @param type Request type - either CALL or CALL_16 or EVAL. * @param sync Request sync. * @param data Request MessagePack encoded body. * @param len @data length. */ -void -call_request_decode_xc(struct call_request *request, uint8_t type, - uint64_t sync, const char *data, uint32_t len); +int +xrow_decode_call(const struct xrow_header *row, struct call_request *request); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +struct obuf; + +struct box_function_ctx { + struct call_request *request; + struct port *port; +}; void box_process_call(struct call_request *request, struct obuf *out); diff --git a/src/box/iproto.cc b/src/box/iproto.cc index 819669910b2a05934e179c90f2de5d09659a5a74..7f14fc648def037c76eebc82e238cde2eb57b2aa 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -620,7 +620,6 @@ iproto_decode_msg(struct iproto_msg *msg, const char **pos, const char *reqend, assert(*pos == reqend); const char *body; uint8_t type = msg->header.type; - uint64_t sync = msg->header.sync; switch (type) { case IPROTO_SELECT: @@ -650,11 +649,8 @@ iproto_decode_msg(struct iproto_msg *msg, const char **pos, const char *reqend, case IPROTO_CALL_16: case IPROTO_CALL: case IPROTO_EVAL: - if (msg->header.bodycnt == 0) - goto err_no_body; - body = (const char *) msg->header.body[0].iov_base; - call_request_decode_xc(&msg->call_request, type, sync, body, - msg->header.body[0].iov_len); + if (xrow_decode_call(&msg->header, &msg->call_request) != 0) + diag_raise(); cmsg_init(msg, misc_route); break; case IPROTO_PING: @@ -666,11 +662,8 @@ iproto_decode_msg(struct iproto_msg *msg, const char **pos, const char *reqend, *stop_input = true; break; case IPROTO_AUTH: - if (msg->header.bodycnt == 0) - goto err_no_body; - body = (const char *) msg->header.body[0].iov_base; - auth_request_decode_xc(&msg->auth_request, sync, body, - msg->header.body[0].iov_len); + if (xrow_decode_auth(&msg->header, &msg->auth_request) != 0) + diag_raise(); cmsg_init(msg, misc_route); break; default: @@ -1034,11 +1027,9 @@ tx_process_misc(struct cmsg *m) switch (msg->header.type) { case IPROTO_CALL: case IPROTO_CALL_16: - assert(msg->call_request.type == msg->header.type); box_process_call(&msg->call_request, out); break; case IPROTO_EVAL: - assert(msg->call_request.type == msg->header.type); box_process_eval(&msg->call_request, out); break; case IPROTO_AUTH: diff --git a/src/box/lua/call.c b/src/box/lua/call.c index 62fc549b5d0a4237cc8318d173b56c6ec36af86e..f0bc7863deb056f2ec3a6580ebaa17b9058ccf02 100644 --- a/src/box/lua/call.c +++ b/src/box/lua/call.c @@ -311,11 +311,11 @@ execute_lua_call(lua_State *L) luamp_error, L); int count; - if (request->type == IPROTO_CALL_16) { + if (request->header->type == IPROTO_CALL_16) { /* Tarantool < 1.7.1 compatibility */ count = luamp_encode_call(L, cfg, &stream); } else { - assert(request->type == IPROTO_CALL); + assert(request->header->type == IPROTO_CALL); count = lua_gettop(L); for (int k = 1; k <= count; ++k) { luamp_encode(L, cfg, &stream, k); @@ -323,7 +323,8 @@ execute_lua_call(lua_State *L) } mpstream_flush(&stream); - iproto_reply_select(out, svp, request->sync, schema_version, count); + iproto_reply_select(out, svp, request->header->sync, schema_version, + count); return 0; /* truncate Lua stack */ } @@ -368,7 +369,8 @@ execute_lua_eval(lua_State *L) luamp_encode(L, luaL_msgpack_default, &stream, k); } mpstream_flush(&stream); - iproto_reply_select(out, svp, request->sync, schema_version, nrets); + iproto_reply_select(out, svp, request->header->sync, schema_version, + nrets); return 0; }