diff options
Diffstat (limited to 'source3/smbd/ipc.c')
-rw-r--r-- | source3/smbd/ipc.c | 669 |
1 files changed, 460 insertions, 209 deletions
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 048dab8b3e..bbeeb21e96 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -27,6 +27,7 @@ */ #include "includes.h" +#include "nterr.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -131,79 +132,128 @@ static BOOL prefix_ok(char *str,char *prefix) return(strncmp(str,prefix,strlen(prefix)) == 0); } +/******************************************************************* + copies parameters and data, as needed, into the smb buffer + + *both* the data and params sections should be aligned. this + is fudged in the rpc pipes by + at present, only the data section is. this may be a possible + cause of some of the ipc problems being experienced. lkcl26dec97 + + ******************************************************************/ +static void copy_trans_params_and_data(char *outbuf, int align, + struct mem_buf *rparam, struct mem_buf *rdata, + int param_offset, int data_offset, + int param_len, int data_len) +{ + char *copy_into = smb_buf(outbuf); + + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", + param_offset, param_offset + param_len, + data_offset , data_offset + data_len)); + + if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len); + copy_into += param_len + align; + if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len); +} /**************************************************************************** send a trans reply ****************************************************************************/ -static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup) +static void send_trans_reply(char *outbuf, + struct mem_buf *rdata, + struct mem_buf *rparam, + uint16 *setup, int lsetup, int max_data_ret) { - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - int align; + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + int align; + + int ldata = rdata ? mem_buf_len(rdata ) : 0; + int lparam = rparam ? mem_buf_len(rparam) : 0; - this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); + BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False; + + if (buffer_too_large) + { + DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret)); + ldata = max_data_ret; + } + + this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING - /* if you don't want Net Monitor to decode your packets, do this!!! */ - align = ((this_lparam+1)%4); + /* if you don't want Net Monitor to decode your packets, do this!!! */ + align = ((this_lparam+1)%4); #else - align = (this_lparam%4); + align = (this_lparam%4); #endif - set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - if (this_lparam) - memcpy(smb_buf(outbuf),param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata); - - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,lsetup); - for (i=0;i<lsetup;i++) - SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam)); + set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - align = (this_lparam%4); + if (buffer_too_large) + { + /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ + SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); + } - set_message(outbuf,10,this_ldata+this_lparam+align,False); - if (this_lparam) - memcpy(smb_buf(outbuf),param+tot_param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata); + copy_trans_params_and_data(outbuf, align, + rparam , rdata, + tot_param , tot_data, + this_lparam, this_ldata); + + SSVAL(outbuf,smb_vwv0,lparam); + SSVAL(outbuf,smb_vwv1,ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,lsetup); + + for (i=0;i<lsetup;i++) + { + SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]); + } - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data); - SSVAL(outbuf,smb_vwv9,0); + show_msg(outbuf); + send_smb(Client,outbuf); - show_msg(outbuf); - send_smb(Client,outbuf); + tot_data = this_ldata; + tot_param = this_lparam; - tot_data += this_ldata; - tot_param += this_lparam; - } + while (tot_data < ldata || tot_param < lparam) + { + this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */ + this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam)); + + align = (this_lparam%4); + + set_message(outbuf,10,this_ldata+this_lparam+align,False); + + copy_trans_params_and_data(outbuf, align, + rparam , rdata, + tot_param , tot_data, + this_lparam, this_ldata); + + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv5,tot_param); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,tot_data); + SSVAL(outbuf,smb_vwv9,0); + + show_msg(outbuf); + send_smb(Client,outbuf); + + tot_data += this_ldata; + tot_param += this_lparam; + } } struct pack_desc { @@ -1252,6 +1302,39 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, return(True); } +/**************************************************************************** + command 0x34 - suspected of being a "Lookup Names" stub api + ****************************************************************************/ +static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + int counted=0; + int missed=0; + + DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", + str1, str2, p, uLevel, buf_len)); + + if (!prefix_ok(str1,"zWrLeh")) return False; + + *rdata_len = 0; + *rdata = NULL; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + SSVAL(*rparam,0,0x08AC); /* informational warning message */ + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); + + return(True); +} /**************************************************************************** get info about a share @@ -2185,8 +2268,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, char *p2; /* get NIS home of a previously validated user - simeon */ + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); - DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2236,7 +2322,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); } @@ -2292,7 +2378,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ @@ -2920,175 +3006,331 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } - -struct +struct api_cmd { - char * name; char * pipe_clnt_name; -#ifdef NTDOMAIN char * pipe_srv_name; -#endif - int subcommand; - BOOL (*fn) (); -} api_fd_commands [] = - { -#ifdef NTDOMAIN - { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, - { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP }, - { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, - { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP }, - { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, - { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#else - { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, - { NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#endif - }; + BOOL (*fn) (pipes_struct *, prs_struct *); +}; -/**************************************************************************** - handle remote api calls delivered to a named pipe already opened. - ****************************************************************************/ -static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +static struct api_cmd api_fd_commands[] = { - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; + { "lsarpc", "lsass", api_ntlsa_rpc }, + { "samr", "lsass", api_samr_rpc }, + { "srvsvc", "ntsvcs", api_srvsvc_rpc }, + { "wkssvc", "ntsvcs", api_wkssvc_rpc }, + { "NETLOGON", "lsass", api_netlog_rpc }, + { "winreg", "winreg", api_reg_rpc }, + { NULL, NULL, NULL } +}; - BOOL reply = False; - BOOL bind_req = False; - BOOL set_nphs = False; +static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) +{ + BOOL ntlmssp_auth = False; + fstring ack_pipe_name; + int i = 0; - int i; - int fd; - int subcommand; - char *pipe_name; - - DEBUG(5,("api_fd_reply\n")); - /* First find out the name of this file. */ - if (suwcnt != 2) - { - DEBUG(0,("Unexpected named pipe transaction.\n")); - return(-1); - } - - /* Get the file handle and hence the file name. */ - fd = setup[1]; - subcommand = setup[0]; - pipe_name = get_rpc_pipe_hnd_name(fd); + DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); - if (pipe_name == NULL) - { - DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd)); - } + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + api_fd_commands[i].pipe_clnt_name, + api_fd_commands[i].pipe_srv_name)); + fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name); + break; + } + } - DEBUG(3,("Got API command %d on pipe %s (fd %x)", - subcommand, pipe_name, fd)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); - - for (i = 0; api_fd_commands[i].name; i++) - { - if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n", api_fd_commands[i].name)); - break; - } - } - - rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - -#ifdef NTDOMAIN - /* RPC Pipe command 0x26. */ - if (data != NULL && api_fd_commands[i].subcommand == 0x26) - { - RPC_HDR hdr; + if (api_fd_commands[i].fn == NULL) return False; - /* process the rpc header */ - char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0); - - /* bind request received */ - if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND)))) - { - RPC_HDR_RB hdr_rb; + /* decode the bind request */ + smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0); - /* decode the bind request */ - char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0); + if (pd->offset == 0) return False; - if ((bind_req = (p != NULL))) - { - RPC_HDR_BA hdr_ba; - fstring ack_pipe_name; + if (p->hdr.auth_len != 0) + { + /* decode the authentication verifier */ + smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0); - /* name has to be \PIPE\xxxxx */ - strcpy(ack_pipe_name, "\\PIPE\\"); - strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name); + if (pd->offset == 0) return False; - /* make a bind acknowledgement */ - make_rpc_hdr_ba(&hdr_ba, - hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &(hdr_rb.transfer)); + /* ignore the version number for now */ + ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP"); + } - p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0); + /* name has to be \PIPE\xxxxx */ + strcpy(ack_pipe_name, "\\PIPE\\"); + strcat(ack_pipe_name, p->pipe_srv_name); - rdata_len = PTR_DIFF(p, rdata); + DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len); + prs_init(&(p->rdata), 1024, 4, 0, False); + prs_init(&(p->rhdr ), 0x10, 4, 0, False); + prs_init(&(p->rauth), 1024, 4, 0, False); - p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0); - - reply = (p != NULL); - } - } - } -#endif + /***/ + /*** do the bind ack first ***/ + /***/ - /* Set Named Pipe Handle state */ - if (subcommand == 0x1) - { - set_nphs = True; - reply = api_LsarpcSNPHS(fd, cnum, params); - } + make_rpc_hdr_ba(&p->hdr_ba, + p->hdr_rb.bba.max_tsize, + p->hdr_rb.bba.max_rsize, + p->hdr_rb.bba.assoc_gid, + ack_pipe_name, + 0x1, 0x0, 0x0, + &(p->hdr_rb.transfer)); - if (!bind_req && !set_nphs) - { - DEBUG(10,("calling api_fd_command\n")); + smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0); + mem_realloc_data(p->rdata.data, p->rdata.offset); - reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - DEBUG(10,("called api_fd_command\n")); - } + /***/ + /*** now the authentication ***/ + /***/ - if (rdata_len > mdrcnt || rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* if we get False back then it's actually unsupported */ - if (!reply) - { - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata ) free(rdata ); - if (rparam) free(rparam); - - return(-1); + if (ntlmssp_auth) + { + uint8 data[16]; + bzero(data, sizeof(data)); /* first 8 bytes are non-zero */ + + make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp, + 0x0a, 0x06, 0, + "NTLMSSP", 2, + 0x00000000, 0x0000b2b3, 0x000082b1, + data); + smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0); + mem_realloc_data(p->rauth.data, p->rauth.offset); + } + + /***/ + /*** then do the header, now we know the length ***/ + /***/ + + make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + p->rdata.offset + p->rauth.offset, + p->rauth.offset); + + smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); + mem_realloc_data(p->rhdr.data, p->rdata.offset); + + /***/ + /*** link rpc header, bind acknowledgment and authentication responses ***/ + /***/ + + p->rhdr.data->offset.start = 0; + p->rhdr.data->offset.end = p->rhdr.offset; + p->rhdr.data->next = p->rdata.data; + + if (ntlmssp_auth) + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = p->rauth.data; + + p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset; + p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset; + p->rauth.data->next = NULL; + } + else + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = NULL; + } + + return True; } +static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd) +{ + int i = 0; + + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name)); + return api_fd_commands[i].fn(p, pd); + } + } + return False; +} +static BOOL api_dce_rpc_command(char *outbuf, + pipes_struct *p, + prs_struct *pd) +{ + BOOL reply = False; + if (pd->data == NULL) return False; + + /* process the rpc header */ + smb_io_rpc_hdr("", &p->hdr, pd, 0); + + if (pd->offset == 0) return False; + + switch (p->hdr.pkt_type) + { + case RPC_BIND : + { + reply = api_pipe_bind_req(p, pd); + break; + } + case RPC_REQUEST: + { + reply = api_pipe_request (p, pd); + break; + } + } + + if (reply) + { + /* now send the reply */ + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len); + + if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len) + { + /* all of data was sent: no need to wait for SMBreadX calls */ + mem_free_data(p->rhdr .data); + mem_free_data(p->rdata.data); + } + } + + return reply; +} + +/**************************************************************************** + SetNamedPipeHandleState +****************************************************************************/ +static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) +{ + uint16 id; + + if (!param) return False; + + id = param[0] + (param[1] << 8); + DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id)); + + if (set_rpc_pipe_hnd_state(p, id)) + { + /* now send the reply */ + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len); + + return True; + } + return False; +} + + +/**************************************************************************** + when no reply is generated, indicate unsupported. + ****************************************************************************/ +static BOOL api_no_reply(char *outbuf, int max_rdata_len) +{ + struct mem_buf rparam; + + mem_init(&rparam, 0); + mem_alloc_data(&rparam, 4); + + rparam.offset.start = 0; + rparam.offset.end = 4; + + /* unsupported */ + SSVAL(rparam.data,0,NERR_notsupported); + SSVAL(rparam.data,2,0); /* converter word */ + + DEBUG(3,("Unsupported API fd command\n")); + + /* now send the reply */ + send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len); + + mem_free_data(&rparam); + + return(-1); +} + +/**************************************************************************** + handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ +static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + BOOL reply = False; + + int pnum; + 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; + + /* First find out the name of this file. */ + if (suwcnt != 2) + { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } + + /* Get the file handle and hence the file name. */ + pnum = setup[1]; + subcommand = setup[0]; + get_rpc_pipe(pnum, &p); + + if (p != NULL) + { + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", + subcommand, p->name, pnum)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); + + /* record maximum data length that can be transmitted in an SMBtrans */ + p->max_rdata_len = mdrcnt; + + switch (subcommand) + { + case 0x26: + { + /* dce/rpc command */ + reply = api_dce_rpc_command(outbuf, p, &pd); + break; + } + case 0x01: + { + /* Set Named Pipe Handle state */ + reply = api_SNPHS(outbuf, p, params); + break; + } + } + } + else + { + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + } + + if (!reply) + { + return api_no_reply(outbuf, mdrcnt); + } + return -1; +} /**************************************************************************** the buffer was too small @@ -3145,6 +3387,7 @@ struct {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, + {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0}, {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, @@ -3177,6 +3420,8 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command = SVAL(params,0); + struct mem_buf rdata_buf; + struct mem_buf rparam_buf; char *rdata = NULL; char *rparam = NULL; int rdata_len = 0; @@ -3216,14 +3461,20 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, &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; /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); - if (rdata) - free(rdata); - if (rparam) - free(rparam); + if (rdata ) free(rdata); + if (rparam) free(rparam); return(-1); } |