From 76d3bc36a5ce13d2a7bd08f9c18b2cfd0ab0210f Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Tue, 21 Apr 1998 02:36:37 +0000 Subject: put server-side long dce/rpc code in main branch. (This used to be commit 2e1a08b28c1c0c9ea988a09067cd149926f25c69) --- source3/include/ntdomain.h | 90 +++++++++++++++++++------------------ source3/rpc_client/cli_pipe.c | 95 ++++++++++++++++++++++----------------- source3/rpc_server/srv_pipe_hnd.c | 89 ++++++++++++++++++++++++------------ source3/smbd/ipc.c | 12 ++--- 4 files changed, 167 insertions(+), 119 deletions(-) diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 67fe879f9b..329cb1e325 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -46,44 +46,46 @@ typedef struct { - struct mem_buf *data; /* memory buffer */ - uint32 offset; /* offset currently being accessed in memory buffer */ - uint8 align; /* data alignment */ - BOOL io; /* parsing in or out of data stream */ + struct mem_buf *data; /* memory buffer */ + uint32 offset; /* offset currently being accessed in memory buffer */ + uint8 align; /* data alignment */ + BOOL io; /* parsing in or out of data stream */ } prs_struct; typedef struct { - int cnum; - int uid; - BOOL open; /* open connection */ - uint16 device_state; - fstring name; - fstring pipe_srv_name; - - prs_struct rhdr; /* output header */ - prs_struct rdata; /* output data */ - prs_struct rauth; /* output authentication verifier */ - - RPC_HDR hdr; - RPC_HDR_BA hdr_ba; - RPC_HDR_RB hdr_rb; - RPC_HDR_REQ hdr_req; - RPC_HDR_RESP hdr_resp; - - RPC_AUTH_NTLMSSP_REQ ntlmssp_req; - RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; - - uint32 max_rdata_len; - uint32 hdr_offsets; + int cnum; + int uid; + BOOL open; /* open connection */ + uint16 device_state; + fstring name; + fstring pipe_srv_name; + + prs_struct rhdr; /* output header */ + prs_struct rdata; /* output data */ + prs_struct rauth; /* output authentication verifier */ + + RPC_HDR hdr; + RPC_HDR_BA hdr_ba; + RPC_HDR_RB hdr_rb; + RPC_HDR_REQ hdr_req; + RPC_HDR_RESP hdr_resp; + + RPC_AUTH_NTLMSSP_REQ ntlmssp_req; + RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; + + uint32 file_offset; + uint32 hdr_offsets; + uint32 frag_len_left; + uint32 next_frag_start; } pipes_struct; struct acct_info { - fstring acct_name; /* account name */ - uint32 smb_userid; /* domain-relative RID */ + fstring acct_name; /* account name */ + uint32 smb_userid; /* domain-relative RID */ }; struct api_struct @@ -95,33 +97,33 @@ struct api_struct struct mem_desc { - /* array memory offsets */ - uint32 start; - uint32 end; + /* array memory offsets */ + uint32 start; + uint32 end; }; struct mem_buf { - BOOL dynamic; /* True iff data has been dynamically allocated - (and therefore can be freed) */ - char *data; - uint32 data_size; - uint32 data_used; + BOOL dynamic; /* True iff data has been dynamically allocated + (and therefore can be freed) */ + char *data; + uint32 data_size; + uint32 data_used; - uint32 margin; /* safety margin when reallocing. */ - /* this can be abused quite nicely */ - uint8 align; /* alignment of data structures (smb, dce/rpc, udp etc) */ + uint32 margin; /* safety margin when reallocing. */ + /* this can be abused quite nicely */ + uint8 align; /* alignment of data structures (smb, dce/rpc, udp etc) */ - struct mem_desc offset; + struct mem_desc offset; - struct mem_buf *next; + struct mem_buf *next; }; typedef struct { - uint32 rid; - char *name; - + uint32 rid; + char *name; + } rid_name; #endif /* _NT_DOMAIN_H */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 625b774167..91ba8a263e 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -47,18 +47,24 @@ uint32 get_rpc_call_id(void) uses SMBreadX to get rest of rpc data ********************************************************************/ static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum, - prs_struct *rdata, uint32 data_to_read) + prs_struct *rdata, uint32 data_to_read, uint32 rdata_offset) { - uint32 data_offset = rdata->data->data_used; - int size = 512; + int size = 0x1630; + int file_offset = rdata_offset; int num_read; char *data = rdata->data->data; uint32 err; - data += rdata->data->data_used; + uint32 new_data_size = rdata->data->data_used + data_to_read; + data += rdata_offset; - if (data_offset + data_to_read > rdata->data->data_size) + file_offset -= rdata_offset; + + DEBUG(5,("rpc_read: data_to_read: %d data offset: %d file offset: %d\n", + data_to_read, rdata_offset, file_offset)); + + if (new_data_size > rdata->data->data_size) { - mem_grow_data(&rdata->data, True, rdata->data->data_used + data_to_read); + mem_grow_data(&rdata->data, True, new_data_size, True); DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); } @@ -66,27 +72,29 @@ static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum, { if (size > data_to_read) size = data_to_read; - if (data_offset + size > rdata->data->data_size) + new_data_size = rdata->data->data_used + size; + + if (new_data_size > rdata->data->data_size) { - mem_grow_data(&rdata->data, True, rdata->data->data_used + size); + mem_grow_data(&rdata->data, True, new_data_size, True); DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); } - num_read = cli_readx(cli, t_idx, fnum, data, data_offset, size); + num_read = cli_readx(cli, t_idx, fnum, data, file_offset + 0x100000, size); DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n", - data_offset, num_read, data_to_read)); + file_offset, num_read, data_to_read)); data_to_read -= num_read; - data_offset += num_read; + file_offset += num_read; data += num_read; if (cli_error(cli, NULL, &err)) return False; } while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */ - mem_realloc_data(rdata->data, rdata->data->data_used); - rdata->data->offset.end = rdata->data->data_used; + 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)); @@ -97,10 +105,12 @@ static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum, checks the header ****************************************************************************/ static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type, - BOOL *first, BOOL *last, uint32 *len) + BOOL *first, BOOL *last, int *len) { RPC_HDR rhdr; + DEBUG(5,("rpc_check_hdr: rdata->data->data_used: %d\n", rdata->data->data_used)); + smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0); if (!rdata->offset || rdata->offset != 0x10) @@ -109,6 +119,8 @@ static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type, return False; } + DEBUG(5,("rpc_check_hdr: (after smb_io_rpc_hdr call) rdata->data->data_used: %d\n", rdata->data->data_used)); + (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST); (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST ); (*len ) = rhdr.frag_len - rdata->data->data_used; @@ -139,7 +151,7 @@ BOOL rpc_api_pipe(struct cli_state *cli, int t_idx, prs_struct *param , prs_struct *data, prs_struct *rparam, prs_struct *rdata) { - uint32 len; + int len; uint16 setup[2]; /* only need 2 uint16 setup parameters */ uint32 err; @@ -188,30 +200,31 @@ BOOL rpc_api_pipe(struct cli_state *cli, int t_idx, if (pkt_type == RPC_RESPONSE) { - RPC_HDR_RR rhdr_rr; - smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, rdata, 0); + RPC_HDR_RESP rhdr_resp; + smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0); } - if (first && last) - { - DEBUG(6,("rpc_api_pipe: fragment first and last both set\n")); - return True; - } + DEBUG(5,("rpc_api_pipe: len left: %d smbtrans read: %d\n", + len, rdata->data->data_used)); /* check if data to be sent back was too large for one SMB. */ /* err status is only informational: the _real_ check is on the length */ - if (len < rdata->data->data_used) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */ + if (len > 0) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */ { - if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False; + if (!rpc_read(cli, t_idx, fnum, rdata, len, rdata->data->data_used)) return False; } /* only one rpc fragment, and it has been read */ - if (first && last) return True; + if (first && last) + { + DEBUG(6,("rpc_api_pipe: fragment first and last both set\n")); + return True; + } while (!last) /* read more fragments until we get the last one */ { - RPC_HDR rhdr; - RPC_HDR_RR rhdr_rr; + RPC_HDR rhdr; + RPC_HDR_RESP rhdr_resp; int num_read; prs_struct hps; @@ -222,8 +235,8 @@ BOOL rpc_api_pipe(struct cli_state *cli, int t_idx, if (num_read != 0x18) return False; - smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0); - smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, &hps, 0); + smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0); + smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0); prs_mem_free(&hps); @@ -239,7 +252,7 @@ BOOL rpc_api_pipe(struct cli_state *cli, int t_idx, } len = rhdr.frag_len - hps.offset; - if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False; + if (!rpc_read(cli, t_idx, fnum, rdata, len, rdata->data->data_used)) return False; } return True; @@ -332,22 +345,22 @@ static BOOL create_rpc_bind_req(prs_struct *rhdr, ********************************************************************/ static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len) { - RPC_HDR_RR hdr_rr; - RPC_HDR hdr; + RPC_HDR_REQ hdr_req; + RPC_HDR hdr; DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n", - op_num, data_len)); + op_num, data_len)); /* create the rpc header RPC_HDR */ - make_rpc_hdr (&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST, - get_rpc_call_id(), data_len + 0x18, 0); + make_rpc_hdr(&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST, + get_rpc_call_id(), data_len + 0x18, 0); - /* create the rpc request RPC_HDR_RR */ - make_rpc_hdr_rr(&hdr_rr, data_len, op_num); + /* create the rpc request RPC_HDR_REQ */ + make_rpc_hdr_req(&hdr_req, data_len, op_num); /* stream-time... */ - smb_io_rpc_hdr ("hdr" , &hdr , rhdr, 0); - smb_io_rpc_hdr_rr("hdr_rr", &hdr_rr, rhdr, 0); + smb_io_rpc_hdr ("hdr ", &hdr , rhdr, 0); + smb_io_rpc_hdr_req("hdr_req", &hdr_req, rhdr, 0); if (rhdr->data == NULL || rhdr->offset != 0x18) return False; @@ -605,7 +618,7 @@ BOOL do_session_open(struct cli_state *cli, int t_idx, /******************* open the pipe *****************/ - if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE, + if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_WRONLY, DENY_NONE, NULL, NULL, NULL)) == 0xffff) { DEBUG(1,("do_session_open: cli_open failed\n")); @@ -643,7 +656,7 @@ BOOL do_ntlm_session_open(struct cli_state *cli, int t_idx, RPC_IFACE transfer; /******************* open the pipe *****************/ - if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE, + if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_WRONLY, DENY_NONE, NULL, NULL, NULL)) == 0xffff) { DEBUG(1,("do_ntlm_session_open: cli_open failed\n")); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index a371e48bfd..7ab2b3aec6 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -81,8 +81,10 @@ void init_rpc_pipe_hnd(void) Pipes[i].rhdr.offset = 0; Pipes[i].rdata.offset = 0; - Pipes[i].max_rdata_len = 0; - Pipes[i].hdr_offsets = 0; + Pipes[i].file_offset = 0; + Pipes[i].hdr_offsets = 0; + Pipes[i].frag_len_left = 0; + Pipes[i].next_frag_start = 0; } return; @@ -110,8 +112,10 @@ int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid) Pipes[i].rhdr.offset = 0; Pipes[i].rdata.offset = 0; - Pipes[i].max_rdata_len = 0; - Pipes[i].hdr_offsets = 0; + Pipes[i].file_offset = 0; + Pipes[i].hdr_offsets = 0; + Pipes[i].frag_len_left = 0; + Pipes[i].next_frag_start = 0; fstrcpy(Pipes[i].name, pipe_name); @@ -134,7 +138,7 @@ int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid) headers are interspersed with the data at regular intervals. by the time this function is called, the start of the data could possibly have been - read by an SMBtrans (max_rdata_len != 0). + read by an SMBtrans (file_offset != 0). calling create_rpc_request() here is a fudge. the data should already have been prepared into arrays of headers + data stream sections. @@ -142,13 +146,14 @@ int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid) ****************************************************************************/ int read_pipe(uint16 pnum, char *data, uint32 pos, int n) { - int data_pos = pos; + int data_hdr_pos; + int data_pos; pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET]; DEBUG(6,("read_pipe: %x", pnum)); if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) { - DEBUG(6,("name: %s cnum: %d open: %s data_pos: %lx len: %lx", + DEBUG(6,("name: %s cnum: %d open: %s data_pos: %d len: %d", p->name, p->cnum, BOOLSTR(p->open), @@ -160,7 +165,6 @@ int read_pipe(uint16 pnum, char *data, uint32 pos, int n) int num = 0; int len = 0; uint32 hdr_num = 0; - uint32 rpc_frag_pos = 0; DEBUG(6,("OK\n")); @@ -170,29 +174,38 @@ int read_pipe(uint16 pnum, char *data, uint32 pos, int n) return 0; } - DEBUG(6,("read_pipe: p: %p max_rdata_len: %d data_pos: %d num: %d\n", - p, p->max_rdata_len, data_pos, num)); + DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n", + p, p->file_offset, n)); + DEBUG(6,("read_pipe: frag_len_left: %d next_frag_start: %d\n", + p->frag_len_left, p->next_frag_start)); /* the read request starts from where the SMBtrans2 left off. */ - data_pos += p->max_rdata_len; - - rpc_frag_pos = data_pos % p->hdr.frag_len; - - /* headers accumulate an offset */ - data_pos -= p->hdr_offsets; + data_pos = p->file_offset - p->hdr_offsets; + data_hdr_pos = p->file_offset; len = mem_buf_len(p->rhdr.data); num = len - (int)data_pos; + DEBUG(6,("read_pipe: len: %d num: %d n: %d\n", len, num, n)); + if (num > n) num = n; + if (num <= 0) + { + DEBUG(5,("read_pipe: 0 or -ve data length\n")); + return 0; + } if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST)) { - DEBUG(5,("read_pipe: hdr_offsets: %d rpc_frag_pos: %d frag_len: %d\n", - p->hdr_offsets, rpc_frag_pos, p->hdr.frag_len)); + /* intermediate fragment - possibility of another header */ + + DEBUG(5,("read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d\n", + p->hdr.frag_len, data_pos, data_hdr_pos)); - if (rpc_frag_pos == 0) + if (data_hdr_pos == p->next_frag_start) { + DEBUG(6,("read_pipe: next fragment header\n")); + /* this is subtracted from the total data bytes, later */ hdr_num = 0x18; @@ -200,24 +213,44 @@ int read_pipe(uint16 pnum, char *data, uint32 pos, int n) create_rpc_reply(p, data_pos, p->rdata.offset); mem_buf_copy(data, p->rhdr.data, 0, 0x18); - /* make room in data stream for header */ - p->hdr_offsets += 0x18; data += 0x18; + p->frag_len_left = p->hdr.frag_len; + p->next_frag_start += p->hdr.frag_len; + p->hdr_offsets += 0x18; - DEBUG(6,("read_pipe: hdr_offsets: %d\n", p->hdr_offsets)); + /*DEBUG(6,("read_pipe: hdr_offsets: %d\n", p->hdr_offsets));*/ } } - if (num > 0) + if (num < hdr_num) { - DEBUG(6,("read_pipe: adjusted data_pos: %d num: %d\n", - data_pos, num - hdr_num)); - mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num); + DEBUG(5,("read_pipe: warning - data read only part of a header\n")); + } + + DEBUG(6,("read_pipe: adjusted data_pos: %d num-hdr_num: %d\n", + data_pos, num - hdr_num)); + mem_buf_copy(data, p->rhdr.data, data_pos, num - hdr_num); + + data_pos += num; + data_hdr_pos += num; + + if (hdr_num == 0x18 && num == 0x18) + { + DEBUG(6,("read_pipe: just header read\n")); - return num; + /* advance to the next fragment */ + p->frag_len_left -= 0x18; } + else if (data_hdr_pos == p->next_frag_start) + { + DEBUG(6,("read_pipe: next fragment expected\n")); + + /* advance to the next fragment */ + } + + p->file_offset += num; - return 0; + return num; } else diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 7cf4d6f5b8..74ae115217 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -3255,9 +3255,9 @@ static BOOL api_dce_rpc_command(char *outbuf, if (reply) { /* now send the reply */ - send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len); + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset); - if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len) + if (mem_buf_len(p->rhdr.data) <= p->file_offset) { /* all of data was sent: no need to wait for SMBreadX calls */ mem_free_data(p->rhdr .data); @@ -3283,7 +3283,7 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) if (set_rpc_pipe_hnd_state(p, id)) { /* now send the reply */ - send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len); + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset); return True; } @@ -3366,10 +3366,10 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); /* record maximum data length that can be transmitted in an SMBtrans */ - p->max_rdata_len = mdrcnt; + p->file_offset = mdrcnt; - DEBUG(10,("api_fd_reply: p:%p max_rdata_len: %d\n", - p, p->max_rdata_len)); + DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n", + p, p->file_offset)); switch (subcommand) { -- cgit