diff --git a/libcli/named_pipe_auth/tstream_u32_read.c b/libcli/named_pipe_auth/tstream_u32_read.c new file mode 100644 index 00000000000..c8e95ef6b99 --- /dev/null +++ b/libcli/named_pipe_auth/tstream_u32_read.c @@ -0,0 +1,159 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Volker Lendecke 2019 + * + * This program 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; either version 3 of the License, or + * (at your option) any later version. + * + * 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, see . + */ + +#include "replace.h" +#include "system/filesys.h" +#include "tstream_u32_read.h" +#include "lib/util/byteorder.h" +#include "lib/util/tevent_unix.h" + +struct tstream_u32_read_state { + size_t max_msglen; + size_t buflen; + uint8_t *buf; +}; + +static int tstream_u32_read_next_vector(struct tstream_context *stream, + void *private_data, + TALLOC_CTX *mem_ctx, + struct iovec **_vector, + size_t *_count); +static void tstream_u32_read_done(struct tevent_req *subreq); + +struct tevent_req *tstream_u32_read_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + uint32_t max_msglen, + struct tstream_context *stream) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct tstream_u32_read_state *state = NULL; + + req = tevent_req_create( + mem_ctx, &state, struct tstream_u32_read_state); + if (req == NULL) { + return NULL; + } + state->max_msglen = max_msglen; + + subreq = tstream_readv_pdu_send( + state, + ev, + stream, + tstream_u32_read_next_vector, + state); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, tstream_u32_read_done, req); + return req; +} + +static int tstream_u32_read_next_vector(struct tstream_context *stream, + void *private_data, + TALLOC_CTX *mem_ctx, + struct iovec **_vector, + size_t *_count) +{ + struct tstream_u32_read_state *state = talloc_get_type_abort( + private_data, struct tstream_u32_read_state); + size_t buflen = talloc_get_size(state->buf); + struct iovec *vector; + uint32_t msg_len; + size_t ofs = 0; + size_t count; + + if (buflen == 0) { + msg_len = 4; + state->buf = talloc_array(state, uint8_t, msg_len); + if (state->buf == NULL) { + return -1; + } + } else if (buflen == 4) { + + ofs = 4; + + msg_len = RIVAL(state->buf, 0); + if ((msg_len == 0) || (msg_len > state->max_msglen)) { + errno = EMSGSIZE; + return -1; + } + msg_len += ofs; + if (msg_len < ofs) { + errno = EMSGSIZE; + return -1; + } + + state->buf = talloc_realloc( + state, state->buf, uint8_t, msg_len); + if (state->buf == NULL) { + return -1; + } + } else { + *_vector = NULL; + *_count = 0; + return 0; + } + + vector = talloc(mem_ctx, struct iovec); + if (vector == NULL) { + return -1; + } + *vector = (struct iovec) { + .iov_base = state->buf + ofs, .iov_len = msg_len - ofs, + }; + count = 1; + + *_vector = vector; + *_count = count; + return 0; +} + +static void tstream_u32_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + int ret, err; + + ret = tstream_readv_pdu_recv(subreq, &err); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_error(req, err); + return; + } + tevent_req_done(req); +} + +int tstream_u32_read_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uint8_t **buf, + size_t *buflen) +{ + struct tstream_u32_read_state *state = tevent_req_data( + req, struct tstream_u32_read_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + return err; + } + *buflen = talloc_get_size(state->buf); + *buf = talloc_move(mem_ctx, &state->buf); + return 0; +} diff --git a/libcli/named_pipe_auth/tstream_u32_read.h b/libcli/named_pipe_auth/tstream_u32_read.h new file mode 100644 index 00000000000..1356ff03631 --- /dev/null +++ b/libcli/named_pipe_auth/tstream_u32_read.h @@ -0,0 +1,37 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) Volker Lendecke 2019 + * + * This program 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; either version 3 of the License, or + * (at your option) any later version. + * + * 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, see . + */ + +#ifndef TSTREAM_U32_READ_H +#define TSTREAM_U32_READ_H + +#include "replace.h" +#include "tsocket.h" + +struct tevent_req *tstream_u32_read_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + uint32_t max_msglen, + struct tstream_context *stream); +int tstream_u32_read_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + uint8_t **buf, + size_t *buflen); + +#endif diff --git a/libcli/named_pipe_auth/wscript_build b/libcli/named_pipe_auth/wscript_build index 53fbd84ab69..46986994b9d 100644 --- a/libcli/named_pipe_auth/wscript_build +++ b/libcli/named_pipe_auth/wscript_build @@ -2,7 +2,7 @@ bld.SAMBA_LIBRARY('npa_tstream', - source='npa_tstream.c', + source='npa_tstream.c tstream_u32_read.c', private_library=True, public_deps='NDR_NAMED_PIPE_AUTH tevent LIBTSOCKET' )