summaryrefslogtreecommitdiff
path: root/source3/smbd/ipc.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
committerJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
commitfdeea341ed1bae670382e45eb731db1b5838ad21 (patch)
treebdbc5138a9340bdbd5c12cee243e6acfb2e64daf /source3/smbd/ipc.c
parent4c6230afd2f144322c07c7e4c46147d3e5d2ddde (diff)
downloadsamba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.gz
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.bz2
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.zip
"For I have laboured mightily on Luke's code, and hath broken
all I saw" - the book of Jeremy, chapter 1 :-). So here is the mega-merge of the NTDOM branch server code. It doesn't include the new client side pieces, we'll look at that later. This should give the same functionality, server wise, as the NTDOM branch does, only merged into the main branch. Any fixes to domain controler functionality should be added to the main branch, not the NTDOM branch. This code compiles without warnings on gcc2.8, but will need further testing before we are sure all the working functionality of the NTDOM server branch has been correctly carried over. I hereby declare the server side of the NTDOM branch dead (and all who sail in her :-). Jeremy. (This used to be commit 118ba4d77a33248e762a2cf843fb7cbc906ee6e7)
Diffstat (limited to 'source3/smbd/ipc.c')
-rw-r--r--source3/smbd/ipc.c669
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);
}