diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-12-13 13:27:58 +0000 |
commit | 3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7 (patch) | |
tree | 866dd15416c3d8554bb207709f433a87ad0c012d /source3/rpc_server/srv_pipe_hnd.c | |
parent | f6276724bafdb6145c0c7b565172d80cb04516ea (diff) | |
download | samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.gz samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.tar.bz2 samba-3db52feb1f3b2c07ce0b06ad4a7099fa6efe3fc7.zip |
first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
(This used to be commit 453a822a76780063dff23526c35408866d0c0154)
Diffstat (limited to 'source3/rpc_server/srv_pipe_hnd.c')
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 371 |
1 files changed, 162 insertions, 209 deletions
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index f8bde1bf9b..b21b768a6e 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -5,6 +5,7 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1998, * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Jeremy Allison 1999. * * 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 @@ -55,7 +56,7 @@ void set_pipe_handle_offset(int max_open_files) } /**************************************************************************** - reset pipe chain handle number + Reset pipe chain handle number. ****************************************************************************/ void reset_chain_p(void) { @@ -63,63 +64,64 @@ void reset_chain_p(void) } /**************************************************************************** - initialise pipe handle states... + Initialise pipe handle states. ****************************************************************************/ + void init_rpc_pipe_hnd(void) { bmap = bitmap_allocate(MAX_OPEN_PIPES); - if (!bmap) { + if (!bmap) exit_server("out of memory in init_rpc_pipe_hnd\n"); - } } +/**************************************************************************** + Initialise an outgoing packet. +****************************************************************************/ + +BOOL pipe_init_outgoing_data( pipes_struct *p) +{ + + memset(p->current_pdu, '\0', sizeof(p->current_pdu)); + + /* Free any memory in the current return data buffer. */ + prs_mem_free(&p->rdata); + + /* + * Initialize the outgoing RPC data buffer. + * we will use this as the raw data area for replying to rpc requests. + */ + if(!prs_init(&p->rdata, 1024, 4, MARSHALL)) { + DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n")); + return False; + } + + /* Reset the offset counters. */ + p->data_sent_length = 0; + p->current_pdu_len = 0; + p->current_pdu_sent = 0; + + return True; +} /**************************************************************************** - find first available file slot + Find first available pipe slot. ****************************************************************************/ + pipes_struct *open_rpc_pipe_p(char *pipe_name, connection_struct *conn, uint16 vuid) { int i; pipes_struct *p; static int next_pipe; - struct msrpc_state *m = NULL; - struct rpcsrv_struct *l = NULL; - user_struct *vuser = get_valid_user_struct(vuid); - struct user_creds usr; - - ZERO_STRUCT(usr); DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n", pipe_name, pipes_open)); - if (vuser == NULL) - { - DEBUG(4,("invalid vuid %d\n", vuid)); - return NULL; - } - - /* set up unix credentials from the smb side, to feed over the pipe */ - make_creds_unix(&usr.uxc, vuser->name, vuser->requested_name, - vuser->real_name, vuser->guest); - usr.ptr_uxc = 1; - make_creds_unix_sec(&usr.uxs, vuser->uid, vuser->gid, - vuser->n_groups, vuser->groups); - usr.ptr_uxs = 1; - - /* set up nt credentials from the smb side, to feed over the pipe */ - /* lkclXXXX todo! - make_creds_nt(&usr.ntc); - make_creds_nt_sec(&usr.nts); - */ - /* not repeating pipe numbers makes it easier to track things in log files and prevents client bugs where pipe numbers are reused over connection restarts */ if (next_pipe == 0) - { next_pipe = (getpid() ^ time(NULL)) % MAX_OPEN_PIPES; - } i = bitmap_find(bmap, next_pipe); @@ -131,44 +133,19 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, next_pipe = (i+1) % MAX_OPEN_PIPES; for (p = Pipes; p; p = p->next) - { DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); - } - - m = msrpc_use_add(pipe_name, &usr, False); - if (m == NULL) - { - DEBUG(5,("open pipes: msrpc redirect failed\n")); - return NULL; - } -#if 0 - } - else - { - l = malloc(sizeof(*l)); - if (l == NULL) - { - DEBUG(5,("open pipes: local msrpc malloc failed\n")); - return NULL; - } - ZERO_STRUCTP(l); - l->rhdr.data = NULL; - l->rdata.data = NULL; - l->rhdr.offset = 0; - l->rdata.offset = 0; - - l->ntlmssp_validated = False; - l->ntlmssp_auth = False; - - memcpy(l->user_sess_key, vuser->user_sess_key, - sizeof(l->user_sess_key)); - } -#endif p = (pipes_struct *)malloc(sizeof(*p)); - if (!p) return NULL; + if (!p) + return NULL; ZERO_STRUCTP(p); + + /* + * Initialize the RPC and PDU data buffers with no memory. + */ + prs_init(&p->rdata, 0, 4, MARSHALL); + DLIST_ADD(Pipes, p); bitmap_set(bmap, i); @@ -177,24 +154,28 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, pipes_open++; p->pnum = i; - p->m = m; - p->l = l; p->open = True; p->device_state = 0; p->priority = 0; p->conn = conn; p->vuid = vuid; + + p->max_trans_reply = 0; - p->file_offset = 0; - p->prev_pdu_file_offset = 0; - p->hdr_offsets = 0; - - fstrcpy(p->name, pipe_name); + p->ntlmssp_chal_flags = 0; + p->ntlmssp_auth_validated = False; + p->ntlmssp_auth_requested = False; - prs_init(&p->smb_pdu, 0, 4, 0, True); - prs_init(&p->rsmb_pdu, 0, 4, 0, False); + p->current_pdu_len = 0; + p->current_pdu_sent = 0; + p->data_sent_length = 0; + p->uid = (uid_t)-1; + p->gid = (gid_t)-1; + + fstrcpy(p->name, pipe_name); + DEBUG(4,("Opened pipe %s with handle %x (pipes_open=%d)\n", pipe_name, i, pipes_open)); @@ -202,182 +183,179 @@ pipes_struct *open_rpc_pipe_p(char *pipe_name, /* OVERWRITE p as a temp variable, to display all open pipes */ for (p = Pipes; p; p = p->next) - { DEBUG(5,("open pipes: name %s pnum=%x\n", p->name, p->pnum)); - } return chain_p; } /**************************************************************************** - writes data to a pipe. + Accepts incoming data on an rpc pipe. - SERIOUSLY ALPHA CODE! + This code is probably incorrect at the moment. The problem is + that the rpc request shouldn't really be executed until all the + data needed for it is received. This currently assumes that each + SMBwrite or SMBwriteX contains all the data needed for an rpc + request. JRA. ****************************************************************************/ -ssize_t write_pipe(pipes_struct *p, char *data, size_t n) + +ssize_t write_to_pipe(pipes_struct *p, char *data, size_t n) { DEBUG(6,("write_pipe: %x", p->pnum)); + DEBUG(6,("name: %s open: %s len: %d", - p->name, BOOLSTR(p->open), n)); + p->name, BOOLSTR(p->open), (int)n)); dump_data(50, data, n); - return rpc_to_smb(p, data, n) ? ((ssize_t)n) : -1; + return rpc_command(p, data, (int)n) ? ((ssize_t)n) : -1; } /**************************************************************************** - reads data from a pipe. + Replyies to a request to read data from a pipe. - headers are interspersed with the data at regular intervals. by the time + Headers are interspersed with the data at PDU intervals. By the time this function is called, the start of the data could possibly have been read by an SMBtrans (file_offset != 0). - calling create_rpc_reply() here is a fudge. the data should already + Calling create_rpc_reply() here is a hack. The data should already have been prepared into arrays of headers + data stream sections. ****************************************************************************/ -int read_pipe(pipes_struct *p, char *data, uint32 pos, int n) + +int read_from_pipe(pipes_struct *p, char *data, int n) { - int num = 0; - int pdu_len = 0; - uint32 hdr_num = 0; - int pdu_data_sent; /* amount of current pdu already sent */ - int data_pos; /* entire rpc data sent - no headers, no auth verifiers */ - int this_pdu_data_pos; - - DEBUG(6,("read_pipe: %x name: %s open: %s pos: %d len: %d", - p->pnum, p->name, BOOLSTR(p->open), - pos, n)); - - if (!p || !p->open) - { - DEBUG(6,("pipe not open\n")); + uint32 pdu_remaining = 0; + int data_returned = 0; + + if (!p || !p->open) { + DEBUG(0,("read_from_pipe: pipe not open\n")); return -1; } + DEBUG(6,("read_from_pipe: %x", p->pnum)); - if (p->rsmb_pdu.data == NULL || p->rsmb_pdu.data->data == NULL || - p->rsmb_pdu.data->data_used == 0) - { - return 0; + DEBUG(6,("name: %s len: %d\n", p->name, n)); + + /* + * We cannot return more than one PDU length per + * read request. + */ + + if(n > MAX_PDU_FRAG_LEN) { + DEBUG(0,("read_from_pipe: loo large read (%d) requested on pipe %s. We can \ +only service %d sized reads.\n", n, p->name, MAX_PDU_FRAG_LEN )); + return -1; } - DEBUG(6,("read_pipe: p: %p file_offset: %d file_pos: %d\n", - p, p->file_offset, n)); + /* + * Determine if there is still data to send in the + * pipe PDU buffer. Always send this first. Never + * send more than is left in the current PDU. The + * client should send a new read request for a new + * PDU. + */ - /* the read request starts from where the SMBtrans2 left off. */ - data_pos = p->file_offset - p->hdr_offsets; - pdu_data_sent = p->file_offset - p->prev_pdu_file_offset; - this_pdu_data_pos = (pdu_data_sent == 0) ? 0 : (pdu_data_sent - 0x18); + if((pdu_remaining = p->current_pdu_len - p->current_pdu_sent) > 0) { + data_returned = MIN(n, pdu_remaining); - if (!IS_BITS_SET_ALL(p->l->hdr.flags, RPC_FLG_LAST)) - { - /* intermediate fragment - possibility of another header */ - - DEBUG(5,("read_pipe: frag_len: %d data_pos: %d pdu_data_sent: %d\n", - p->l->hdr.frag_len, data_pos, pdu_data_sent)); - - if (pdu_data_sent == 0) - { - DEBUG(6,("read_pipe: next fragment header\n")); - - /* this is subtracted from the total data bytes, later */ - hdr_num = 0x18; - p->hdr_offsets += 0x18; - data_pos -= 0x18; - - /* create and copy in a new header. */ - create_rpc_reply(p->l, data_pos); - } - } - - pdu_len = mem_buf_len(p->rsmb_pdu.data); - num = pdu_len - this_pdu_data_pos; - - DEBUG(6,("read_pipe: pdu_len: %d num: %d n: %d\n", pdu_len, num, n)); - - if (num > n) num = n; - if (num <= 0) - { - DEBUG(5,("read_pipe: 0 or -ve data length\n")); - return 0; - } + DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, current_pdu_sent = %u \ +returning %d bytes.\n", p->name, (unsigned int)p->current_pdu_len, + (unsigned int)p->current_pdu_sent, (int)data_returned)); - if (num < hdr_num) - { - DEBUG(5,("read_pipe: warning - data read only part of a header\n")); + memcpy( data, &p->current_pdu[p->current_pdu_sent], (size_t)data_returned); + p->current_pdu_sent += (uint32)data_returned; + return data_returned; } - mem_buf_copy(data, p->rsmb_pdu.data, pdu_data_sent, num); - - p->file_offset += num; - pdu_data_sent += num; - - if (hdr_num == 0x18 && num == 0x18) - { - DEBUG(6,("read_pipe: just header read\n")); + /* + * At this point p->current_pdu_len == p->current_pdu_sent (which + * may of course be zero if this is the first return fragment. + */ + + DEBUG(10,("read_from_pipe: %s: data_sent_length = %u, prs_offset(&p->rdata) = %u.\n", + p->name, (unsigned int)p->data_sent_length, (unsigned int)prs_offset(&p->rdata) )); + + if(p->data_sent_length >= prs_offset(&p->rdata)) { + /* + * We have sent all possible data. Return 0. + */ + return 0; } - if (pdu_data_sent == p->l->hdr.frag_len) - { - DEBUG(6,("read_pipe: next fragment expected\n")); - p->prev_pdu_file_offset = p->file_offset; + /* + * We need to create a new PDU from the data left in p->rdata. + * Create the header/data/footers. This also sets up the fields + * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length + * and stores the outgoing PDU in p->current_pdu. + */ + + if(!create_next_pdu(p)) { + DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", + p->name)); + return -1; } - return num; -} + data_returned = MIN(n, p->current_pdu_len); + memcpy( data, p->current_pdu, (size_t)data_returned); + p->current_pdu_sent += (uint32)data_returned; + return data_returned; +} /**************************************************************************** - wait device state on a pipe. exactly what this is for is unknown... + Wait device state on a pipe. Exactly what this is for is unknown... ****************************************************************************/ + BOOL wait_rpc_pipe_hnd_state(pipes_struct *p, uint16 priority) { - if (p == NULL) return False; + if (p == NULL) + return False; - if (p->open) - { - DEBUG(3,("%s Setting pipe wait state priority=%x on pipe (name=%s)\n", - timestring(), priority, p->name)); + if (p->open) { + DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n", + priority, p->name)); p->priority = priority; return True; } - DEBUG(3,("%s Error setting pipe wait state priority=%x (name=%s)\n", - timestring(), priority, p->name)); + DEBUG(3,("wait_rpc_pipe_hnd_state: Error setting pipe wait state priority=%x (name=%s)\n", + priority, p->name)); return False; } /**************************************************************************** - set device state on a pipe. exactly what this is for is unknown... + Set device state on a pipe. Exactly what this is for is unknown... ****************************************************************************/ + BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state) { - if (p == NULL) return False; + if (p == NULL) + return False; if (p->open) { - DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s)\n", - timestring(), device_state, p->name)); + DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n", + device_state, p->name)); p->device_state = device_state; return True; } - DEBUG(3,("%s Error setting pipe device state=%x (name=%s)\n", - timestring(), device_state, p->name)); + DEBUG(3,("set_rpc_pipe_hnd_state: Error setting pipe device state=%x (name=%s)\n", + device_state, p->name)); return False; } /**************************************************************************** - close an rpc pipe + Close an rpc pipe. ****************************************************************************/ + BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) { if (!p) { @@ -385,8 +363,7 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) return False; } - mem_buf_free(&(p->smb_pdu .data)); - mem_buf_free(&(p->rsmb_pdu.data)); + prs_mem_free(&p->rdata); bitmap_clear(bmap, p->pnum - pipe_handle_offset); @@ -397,50 +374,31 @@ BOOL close_rpc_pipe_hnd(pipes_struct *p, connection_struct *conn) DLIST_REMOVE(Pipes, p); - if (p->m != NULL) - { - DEBUG(4,("closed msrpc redirect: ")); - if (msrpc_use_del(p->m->pipe_name, &p->m->usr, False, NULL)) - { - DEBUG(4,("OK\n")); - } - else - { - DEBUG(4,("FAILED\n")); - } - } - - if (p->l != NULL) - { - DEBUG(4,("closed msrpc local: OK\n")); - - mem_free_data(p->l->rdata .data); - rpcsrv_free_temp(p->l); - - free(p->l); - } - ZERO_STRUCTP(p); + free(p); return True; } /**************************************************************************** - close an rpc pipe + Find an rpc pipe given a pipe handle in a buffer and an offset. ****************************************************************************/ + pipes_struct *get_rpc_pipe_p(char *buf, int where) { int pnum = SVAL(buf,where); - if (chain_p) return chain_p; + if (chain_p) + return chain_p; return get_rpc_pipe(pnum); } /**************************************************************************** - close an rpc pipe + Find an rpc pipe given a pipe handle. ****************************************************************************/ + pipes_struct *get_rpc_pipe(int pnum) { pipes_struct *p; @@ -448,15 +406,11 @@ pipes_struct *get_rpc_pipe(int pnum) DEBUG(4,("search for pipe pnum=%x\n", pnum)); for (p=Pipes;p;p=p->next) - { DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", p->name, p->pnum, pipes_open)); - } - for (p=Pipes;p;p=p->next) - { - if (p->pnum == pnum) - { + for (p=Pipes;p;p=p->next) { + if (p->pnum == pnum) { chain_p = p; return p; } @@ -464,4 +418,3 @@ pipes_struct *get_rpc_pipe(int pnum) return NULL; } - |