From: Volker Lendecke Date: Thu, 6 Jul 2023 14:19:06 +0000 (+0200) Subject: libcli: Make symlink_reparse_buffer_parse() more flexible X-Git-Tag: tevent-0.16.0~1073 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9831fbeb8f08587a36372da653bc78ed2ff0493c;p=thirdparty%2Fsamba.git libcli: Make symlink_reparse_buffer_parse() more flexible Allow the destination struct to be preallocated Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/libcli/smb/py_reparse_symlink.c b/libcli/smb/py_reparse_symlink.c index 57dc6032f99..b998b2e27a1 100644 --- a/libcli/smb/py_reparse_symlink.c +++ b/libcli/smb/py_reparse_symlink.c @@ -104,8 +104,11 @@ static PyObject *py_reparse_symlink_get(PyObject *module, PyObject *args) { char *buf = NULL; Py_ssize_t buflen; - struct symlink_reparse_struct *syml = NULL; + struct symlink_reparse_struct syml = { + .flags = 0, + }; PyObject *result = NULL; + int ret; bool ok; ok = PyArg_ParseTuple(args, PYARG_BYTES_LEN ":get", &buf, &buflen); @@ -113,19 +116,21 @@ static PyObject *py_reparse_symlink_get(PyObject *module, PyObject *args) return NULL; } - syml = symlink_reparse_buffer_parse(NULL, (uint8_t *)buf, buflen); - if (syml == NULL) { - PyErr_NoMemory(); + ret = symlink_reparse_buffer_parse(NULL, &syml, (uint8_t *)buf, buflen); + if (ret != 0) { + errno = ret; + PyErr_SetFromErrno(PyExc_RuntimeError); return NULL; } - result = Py_BuildValue( - "ssII", - syml->substitute_name, - syml->print_name, - (unsigned)syml->unparsed_path_length, - (unsigned)syml->flags); - TALLOC_FREE(syml); + result = Py_BuildValue("ssII", + syml.substitute_name, + syml.print_name, + (unsigned)syml.unparsed_path_length, + (unsigned)syml.flags); + + TALLOC_FREE(syml.print_name); + TALLOC_FREE(syml.substitute_name); return result; } diff --git a/libcli/smb/reparse_symlink.c b/libcli/smb/reparse_symlink.c index 51570b563e4..2871974cbdc 100644 --- a/libcli/smb/reparse_symlink.c +++ b/libcli/smb/reparse_symlink.c @@ -166,10 +166,11 @@ fail: return ret; } -struct symlink_reparse_struct *symlink_reparse_buffer_parse( - TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen) +int symlink_reparse_buffer_parse(TALLOC_CTX *mem_ctx, + struct symlink_reparse_struct *dst, + const uint8_t *src, + size_t srclen) { - struct symlink_reparse_struct *result = NULL; uint16_t reparse_data_length; uint16_t substitute_name_offset, substitute_name_length; uint16_t print_name_offset, print_name_length; @@ -177,13 +178,13 @@ struct symlink_reparse_struct *symlink_reparse_buffer_parse( if (srclen < 20) { DBG_DEBUG("srclen = %zu, expected >= 20\n", srclen); - goto fail; + return EINVAL; } if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) { DBG_DEBUG("Got ReparseTag %8.8x, expected %8.8x\n", IVAL(src, 0), IO_REPARSE_TAG_SYMLINK); - goto fail; + return EINVAL; } reparse_data_length = SVAL(src, 4); @@ -195,14 +196,14 @@ struct symlink_reparse_struct *symlink_reparse_buffer_parse( if (reparse_data_length < 12) { DBG_DEBUG("reparse_data_length = %"PRIu16", expected >= 12\n", reparse_data_length); - goto fail; + return EINVAL; } if (smb_buffer_oob(srclen - 8, reparse_data_length, 0)) { DBG_DEBUG("reparse_data_length (%"PRIu16") too large for " "src_len (%zu)\n", reparse_data_length, srclen); - goto fail; + return EINVAL; } if (smb_buffer_oob(reparse_data_length - 12, substitute_name_offset, substitute_name_length)) { @@ -211,7 +212,7 @@ struct symlink_reparse_struct *symlink_reparse_buffer_parse( substitute_name_offset, substitute_name_length, reparse_data_length - 12); - goto fail; + return EINVAL; } if (smb_buffer_oob(reparse_data_length - 12, print_name_offset, print_name_length)) { @@ -220,47 +221,41 @@ struct symlink_reparse_struct *symlink_reparse_buffer_parse( print_name_offset, print_name_length, reparse_data_length - 12); - goto fail; + return EINVAL; } - result = talloc_zero(mem_ctx, struct symlink_reparse_struct); - if (result == NULL) { - DBG_DEBUG("talloc failed\n"); - goto fail; - } + *dst = (struct symlink_reparse_struct) { + .unparsed_path_length = PULL_LE_U16(src, 6), + .flags = PULL_LE_U32(src, 16), + }; - ok = convert_string_talloc( - result, - CH_UTF16, - CH_UNIX, - src + 20 + substitute_name_offset, - substitute_name_length, - &result->substitute_name, - NULL); + ok = convert_string_talloc(mem_ctx, + CH_UTF16, + CH_UNIX, + src + 20 + substitute_name_offset, + substitute_name_length, + &dst->substitute_name, + NULL); if (!ok) { + int ret = errno; DBG_DEBUG("convert_string_talloc for substitute_name " "failed\n"); - goto fail; + return ret; } - ok = convert_string_talloc( - result, - CH_UTF16, - CH_UNIX, - src + 20 + print_name_offset, - print_name_length, - &result->print_name, - NULL); + ok = convert_string_talloc(mem_ctx, + CH_UTF16, + CH_UNIX, + src + 20 + print_name_offset, + print_name_length, + &dst->print_name, + NULL); if (!ok) { + int ret = errno; DBG_DEBUG("convert_string_talloc for print_name failed\n"); - goto fail; + TALLOC_FREE(dst->substitute_name); + return ret; } - result->unparsed_path_length = SVAL(src, 6); - result->flags = IVAL(src, 16); - - return result; -fail: - TALLOC_FREE(result); - return NULL; + return 0; } diff --git a/libcli/smb/reparse_symlink.h b/libcli/smb/reparse_symlink.h index 2f57a592eec..0718f34395d 100644 --- a/libcli/smb/reparse_symlink.h +++ b/libcli/smb/reparse_symlink.h @@ -50,7 +50,9 @@ bool symlink_reparse_buffer_marshall( TALLOC_CTX *mem_ctx, uint8_t **pdst, size_t *pdstlen); -struct symlink_reparse_struct *symlink_reparse_buffer_parse( - TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen); +int symlink_reparse_buffer_parse(TALLOC_CTX *mem_ctx, + struct symlink_reparse_struct *dst, + const uint8_t *src, + size_t srclen); #endif diff --git a/libcli/smb/smb2cli_create.c b/libcli/smb/smb2cli_create.c index dbad297a3f0..1197eec28ae 100644 --- a/libcli/smb/smb2cli_create.c +++ b/libcli/smb/smb2cli_create.c @@ -198,6 +198,7 @@ static NTSTATUS smb2cli_parse_symlink_error_response( { struct symlink_reparse_struct *symlink = NULL; uint32_t symlink_length, error_tag; + int ret; if (buflen < 8) { DBG_DEBUG("buffer too short: %zu bytes\n", buflen); @@ -219,10 +220,15 @@ static NTSTATUS smb2cli_parse_symlink_error_response( return NT_STATUS_INVALID_NETWORK_RESPONSE; } - symlink = symlink_reparse_buffer_parse( - mem_ctx, buf+8, buflen-8); + symlink = talloc(mem_ctx, struct symlink_reparse_struct); if (symlink == NULL) { - DBG_DEBUG("symlink_reparse_buffer_parse failed\n"); + return NT_STATUS_NO_MEMORY; + } + + ret = symlink_reparse_buffer_parse( + symlink, symlink, buf+8, buflen-8); + if (ret != 0) { + DBG_DEBUG("symlink_reparse_buffer_parse failed: %s\n", strerror(ret)); return NT_STATUS_INVALID_NETWORK_RESPONSE; } diff --git a/source3/libsmb/clisymlink.c b/source3/libsmb/clisymlink.c index 12d644eb68d..1155526f96d 100644 --- a/source3/libsmb/clisymlink.c +++ b/source3/libsmb/clisymlink.c @@ -368,8 +368,9 @@ NTSTATUS cli_readlink_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, { struct cli_readlink_state *state = tevent_req_data( req, struct cli_readlink_state); - struct symlink_reparse_struct *symlink = NULL; + struct symlink_reparse_struct symlink = { .flags = 0, }; NTSTATUS status; + int ret; if (tevent_req_is_nterror(req, &status)) { return status; @@ -392,26 +393,27 @@ NTSTATUS cli_readlink_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - symlink = symlink_reparse_buffer_parse( - talloc_tos(), state->data, state->num_data); - if (symlink == NULL) { + ret = symlink_reparse_buffer_parse( + talloc_tos(), &symlink, state->data, state->num_data); + if (ret != 0) { return NT_STATUS_INVALID_NETWORK_RESPONSE; } if (psubstitute_name != NULL) { *psubstitute_name = talloc_move( - mem_ctx, &symlink->substitute_name); + mem_ctx, &symlink.substitute_name); } if (pprint_name != NULL) { - *pprint_name = talloc_move(mem_ctx, &symlink->print_name); + *pprint_name = talloc_move(mem_ctx, &symlink.print_name); } if (pflags != NULL) { - *pflags = symlink->flags; + *pflags = symlink.flags; } - TALLOC_FREE(symlink); + TALLOC_FREE(symlink.print_name); + TALLOC_FREE(symlink.substitute_name); return NT_STATUS_OK; }