From 1ebeb54932de01323356e8201d465656b8723d46 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 20 Oct 1998 18:27:49 +0000 Subject: some quite important bug-fixes i missed because i transferred the wrong smb.tgz file from my portable. particularly the call to mem_data followed by a realloc of that data in cli_pipe.c's rpc_read() function. smbd responses now use p->rdata_i which is a faked-up pointer into p->rdata's response data. rdata can be very long; rdata_i is limited to point to no more than max_tsize - 0x18 in length. this will make it an almost trivial task to add the encrypted rpc headers after rdata_i, and mem_buf_copy will cope admirably with rhdr chained to rdata_i chained to auth_verifier etc etc... (This used to be commit 05a297e3a98c14360782af4ad0d851638fb5da9a) --- source3/include/ntdomain.h | 1 + source3/include/proto.h | 2 +- source3/lib/membuffer.c | 8 ++++---- source3/lib/util.c | 4 +++- source3/rpc_client/cli_pipe.c | 13 +++++++------ source3/rpc_server/srv_pipe_hnd.c | 10 ++++------ source3/rpc_server/srv_util.c | 31 +++++++++++++++++++------------ source3/smbd/ipc.c | 27 ++++++++------------------- 8 files changed, 47 insertions(+), 49 deletions(-) (limited to 'source3') diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index b7c3b5b577..97122c8169 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -67,6 +67,7 @@ typedef struct pipes_struct prs_struct rhdr; /* output header */ prs_struct rdata; /* output data */ + prs_struct rdata_i; /* output data (intermediate, for fragments) */ prs_struct rauth; /* output authentication verifier */ prs_struct rverf; /* output verifier */ prs_struct rntlm; /* output ntlmssp */ diff --git a/source3/include/proto.h b/source3/include/proto.h index b1322f5e9f..2cec5f91f7 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -122,7 +122,7 @@ void mdfour(unsigned char *out, unsigned char *in, int n); /*The following definitions come from lib/membuffer.c */ void mem_init(struct mem_buf *buf, int margin); -void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic); +void mem_create(struct mem_buf *buf, char *data, int offset, int size, int margin, BOOL dynamic); BOOL mem_alloc_data(struct mem_buf *buf, int size); BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf, uint32 offset, uint32 len); diff --git a/source3/lib/membuffer.c b/source3/lib/membuffer.c index 18e9fa9453..92bc2be439 100644 --- a/source3/lib/membuffer.c +++ b/source3/lib/membuffer.c @@ -79,7 +79,7 @@ void mem_init(struct mem_buf *buf, int margin) dynamic indicates memory has been dynamically allocated. if mem_free is called, the memory will be freed. ********************************************************************/ -void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic) +void mem_create(struct mem_buf *buf, char *data, int offset, int size, int margin, BOOL dynamic) { buf->dynamic = dynamic; buf->data = data; @@ -90,8 +90,8 @@ void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dyna buf->next = NULL; - buf->offset.start = 0; - buf->offset.end = size; + buf->offset.start = offset; + buf->offset.end = offset + size; } /******************************************************************* @@ -109,7 +109,7 @@ BOOL mem_alloc_data(struct mem_buf *buf, int size) buf->data = malloc(buf->data_size); - if (buf->data == NULL) + if (buf->data == NULL && size != 0) { DEBUG(3,("mem_alloc: could not malloc size %d\n", buf->data_size)); diff --git a/source3/lib/util.c b/source3/lib/util.c index f2cd2a99d1..e5486e6159 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -2262,8 +2262,10 @@ BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout) { ret = receive_smb(fd, buffer, timeout); - if(ret == False) + if (!ret) + { return ret; + } /* Ignore session keepalive packets. */ if(CVAL(buffer,0) != 0x85) diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 08b3575733..f5587567cd 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -54,12 +54,10 @@ static BOOL rpc_read(struct cli_state *cli, int size = cli->max_recv_frag; int file_offset = rdata_offset; int num_read; - char *data = rdata->data->data; + char *data; uint32 err; uint32 new_data_size = rdata->data->data_used + data_to_read; - data += rdata_offset; - file_offset -= rdata_offset; DEBUG(5,("rpc_read: data_to_read: %d data offset: %d file offset: %d\n", @@ -71,6 +69,8 @@ static BOOL rpc_read(struct cli_state *cli, DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); } + data = rdata->data->data + rdata_offset; + do /* read data using SMBreadX */ { if (size > data_to_read) @@ -84,7 +84,7 @@ static BOOL rpc_read(struct cli_state *cli, DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); } - num_read = cli_read(cli, cli->nt_pipe_fnum, data, file_offset + 0x100000, size); + num_read = cli_read(cli, cli->nt_pipe_fnum, data, file_offset, size); DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n", file_offset, num_read, data_to_read)); @@ -101,9 +101,10 @@ static BOOL rpc_read(struct cli_state *cli, mem_realloc_data(rdata->data, file_offset + rdata_offset); rdata->data->offset.end = file_offset + rdata_offset; - DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read)); + DEBUG(5,("rpc_read: offset end: 0x%x. data left to read:0x%x\n", + rdata->data->offset.end, data_to_read)); - return data_to_read == 0; + return data_to_read >= 0; } /**************************************************************************** diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index d5c99b89c4..54ecbf707e 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -3,8 +3,8 @@ * Unix SMB/Netbios implementation. * Version 1.9. * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, * * 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 @@ -175,7 +175,7 @@ ssize_t write_pipe(pipes_struct *p, char *data, size_t n) dump_data(50, data, n); /* fake up a data buffer from the write_pipe data parameters */ - mem_create(&data_buf, data, n, 0, False); + mem_create(&data_buf, data, 0, n, 0, False); data_buf.offset.start = 0; data_buf.offset.end = n; @@ -196,7 +196,7 @@ ssize_t write_pipe(pipes_struct *p, char *data, size_t n) this function is called, the start of the data could possibly have been read by an SMBtrans (file_offset != 0). - calling create_rpc_request() here is a fudge. the data should already + calling create_rpc_reply() here is a fudge. the data should already have been prepared into arrays of headers + data stream sections. ****************************************************************************/ @@ -268,8 +268,6 @@ int read_pipe(pipes_struct *p, char *data, uint32 pos, int n) mem_buf_copy(data, p->rhdr.data, 0, 0x18); data += 0x18; - p->frag_len_left = p->hdr.frag_len; - p->next_frag_start += p->hdr.frag_len; p->hdr_offsets += 0x18; } } diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c index 7ddc2da5d1..59db0bed2c 100644 --- a/source3/rpc_server/srv_util.c +++ b/source3/rpc_server/srv_util.c @@ -165,6 +165,9 @@ int make_dom_gids(char *gids_str, DOM_GID **ppgids) BOOL create_rpc_reply(pipes_struct *p, uint32 data_start, uint32 data_end) { + char *data; + uint32 data_len; + DEBUG(5,("create_rpc_reply: data_start: %d data_end: %d max_tsize: %d\n", data_start, data_end, p->hdr_ba.bba.max_tsize)); @@ -197,6 +200,8 @@ BOOL create_rpc_reply(pipes_struct *p, p->hdr.frag_len = p->hdr_ba.bba.max_tsize; } + data_len = p->hdr.frag_len; + p->rhdr.data->offset.start = 0; p->rhdr.data->offset.end = 0x18; @@ -205,6 +210,20 @@ BOOL create_rpc_reply(pipes_struct *p, smb_io_rpc_hdr ("hdr", &(p->hdr ), &(p->rhdr), 0); smb_io_rpc_hdr_resp("resp", &(p->hdr_resp), &(p->rhdr), 0); + p->frag_len_left = p->hdr.frag_len - p->file_offset; + p->next_frag_start = p->hdr.frag_len; + + /* don't use rdata: use rdata_i instead, which moves... */ + /* make a pointer to the rdata data. NOT A COPY */ + + prs_init(&p->rdata_i, 0, p->rdata.align, p->rdata.data->margin, p->rdata.io); + data = mem_data(&(p->rdata.data), data_start); + mem_create(p->rdata_i.data, data, data_start, data_len, 0, False); + + /* set up the data chain */ + prs_link(NULL , &p->rhdr , &p->rdata_i); + prs_link(&p->rhdr, &p->rdata_i, NULL ); + return p->rhdr.data != NULL && p->rhdr.offset == 0x18; } @@ -703,18 +722,6 @@ BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds return False; } - p->frag_len_left = p->hdr.frag_len - p->file_offset; - p->next_frag_start = p->hdr.frag_len; - - /* set up the data chain */ - p->rhdr.data->offset.start = 0; - p->rhdr.data->offset.end = p->rhdr.offset; - p->rhdr.data->next = p->rdata.data; - - p->rdata.data->offset.start = p->rhdr.data->offset.end; - p->rdata.data->offset.end = p->rhdr.data->offset.end + p->rdata.offset; - p->rdata.data->next = NULL; - return True; } diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 2b8b8698db..3e697a59ce 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3101,6 +3101,7 @@ static void api_rpc_trans_reply(char *outbuf, /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); mem_free_data(p->rdata.data); + mem_free_data(p->rdata_i.data); } } @@ -3190,20 +3191,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, int subcommand; pipes_struct *p = NULL; prs_struct pd; - struct mem_buf data_buf; DEBUG(5,("api_fd_reply\n")); - /* fake up a data buffer from the api_fd_reply data parameters */ - mem_create(&data_buf, data, tdscnt, 0, False); - data_buf.offset.start = 0; - data_buf.offset.end = tdscnt; - - /* fake up a parsing structure */ - pd.data = &data_buf; - pd.align = 4; - pd.io = True; - pd.offset = 0; + /* make a static data parsing structure from the api_fd_reply data */ + prs_init(&pd, 0, 4, True, 0); + mem_create(pd.data, data, 0, tdscnt, 0, False); /* First find out the name of this file. */ if (suwcnt != 2) @@ -3259,6 +3252,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf, DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); } + mem_free_data(pd.data); + if (!reply) { return api_no_reply(outbuf, mdrcnt); @@ -3410,14 +3405,8 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data &rdata,&rparam,&rdata_len,&rparam_len); - mem_create(&rdata_buf , rdata , rdata_len , 0, False); - mem_create(&rparam_buf, rparam, rparam_len, 0, False); - - rdata_buf.offset.start = 0; - rdata_buf.offset.end = rdata_len; - - rparam_buf.offset.start = 0; - rparam_buf.offset.end = rparam_len; + mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False); + mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False); /* now send the reply */ send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); -- cgit