r5165: BUG 2295: always use get_local_machine_name() rather than digging in the glova...
[Samba/gebeck_regimport.git] / source3 / smbd / ipc.c
blobe3f6521fba86f407c8763861f2e4da0f44284825
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 extern int max_send;
32 #define NERR_notsupported 50
34 extern int smb_read_error;
36 /*******************************************************************
37 copies parameters and data, as needed, into the smb buffer
39 *both* the data and params sections should be aligned. this
40 is fudged in the rpc pipes by
41 at present, only the data section is. this may be a possible
42 cause of some of the ipc problems being experienced. lkcl26dec97
44 ******************************************************************/
46 static void copy_trans_params_and_data(char *outbuf, int align,
47 char *rparam, int param_offset, int param_len,
48 char *rdata, int data_offset, int data_len)
50 char *copy_into = smb_buf(outbuf)+1;
52 if(param_len < 0)
53 param_len = 0;
55 if(data_len < 0)
56 data_len = 0;
58 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
59 param_offset, param_offset + param_len,
60 data_offset , data_offset + data_len));
62 if (param_len)
63 memcpy(copy_into, &rparam[param_offset], param_len);
65 copy_into += param_len + align;
67 if (data_len )
68 memcpy(copy_into, &rdata[data_offset], data_len);
71 /****************************************************************************
72 Send a trans reply.
73 ****************************************************************************/
75 void send_trans_reply(char *outbuf,
76 char *rparam, int rparam_len,
77 char *rdata, int rdata_len,
78 BOOL buffer_too_large)
80 int this_ldata,this_lparam;
81 int tot_data_sent = 0;
82 int tot_param_sent = 0;
83 int align;
85 int ldata = rdata ? rdata_len : 0;
86 int lparam = rparam ? rparam_len : 0;
88 if (buffer_too_large)
89 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
91 this_lparam = MIN(lparam,max_send - 500); /* hack */
92 this_ldata = MIN(ldata,max_send - (500+this_lparam));
94 align = ((this_lparam)%4);
96 if (buffer_too_large) {
97 ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
100 set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
102 copy_trans_params_and_data(outbuf, align,
103 rparam, tot_param_sent, this_lparam,
104 rdata, tot_data_sent, this_ldata);
106 SSVAL(outbuf,smb_vwv0,lparam);
107 SSVAL(outbuf,smb_vwv1,ldata);
108 SSVAL(outbuf,smb_vwv3,this_lparam);
109 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
110 SSVAL(outbuf,smb_vwv5,0);
111 SSVAL(outbuf,smb_vwv6,this_ldata);
112 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
113 SSVAL(outbuf,smb_vwv8,0);
114 SSVAL(outbuf,smb_vwv9,0);
116 show_msg(outbuf);
117 if (!send_smb(smbd_server_fd(),outbuf))
118 exit_server("send_trans_reply: send_smb failed.");
120 tot_data_sent = this_ldata;
121 tot_param_sent = this_lparam;
123 while (tot_data_sent < ldata || tot_param_sent < lparam)
125 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
126 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
128 if(this_lparam < 0)
129 this_lparam = 0;
131 if(this_ldata < 0)
132 this_ldata = 0;
134 align = (this_lparam%4);
136 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
138 copy_trans_params_and_data(outbuf, align,
139 rparam, tot_param_sent, this_lparam,
140 rdata, tot_data_sent, this_ldata);
142 SSVAL(outbuf,smb_vwv3,this_lparam);
143 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
144 SSVAL(outbuf,smb_vwv5,tot_param_sent);
145 SSVAL(outbuf,smb_vwv6,this_ldata);
146 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
147 SSVAL(outbuf,smb_vwv8,tot_data_sent);
148 SSVAL(outbuf,smb_vwv9,0);
150 show_msg(outbuf);
151 if (!send_smb(smbd_server_fd(),outbuf))
152 exit_server("send_trans_reply: send_smb failed.");
154 tot_data_sent += this_ldata;
155 tot_param_sent += this_lparam;
159 /****************************************************************************
160 Start the first part of an RPC reply which began with an SMBtrans request.
161 ****************************************************************************/
163 static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p)
165 BOOL is_data_outstanding;
166 char *rdata = SMB_MALLOC(p->max_trans_reply);
167 int data_len;
169 if(rdata == NULL) {
170 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
171 return False;
174 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply,
175 &is_data_outstanding)) < 0) {
176 SAFE_FREE(rdata);
177 return False;
180 send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
182 SAFE_FREE(rdata);
183 return True;
186 /****************************************************************************
187 WaitNamedPipeHandleState
188 ****************************************************************************/
190 static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
192 uint16 priority;
194 if (!param || param_len < 2)
195 return False;
197 priority = SVAL(param,0);
198 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
200 if (wait_rpc_pipe_hnd_state(p, priority)) {
201 /* now send the reply */
202 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
203 return True;
205 return False;
209 /****************************************************************************
210 SetNamedPipeHandleState
211 ****************************************************************************/
213 static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
215 uint16 id;
217 if (!param || param_len < 2)
218 return False;
220 id = SVAL(param,0);
221 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
223 if (set_rpc_pipe_hnd_state(p, id)) {
224 /* now send the reply */
225 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
226 return True;
228 return False;
232 /****************************************************************************
233 When no reply is generated, indicate unsupported.
234 ****************************************************************************/
236 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
238 char rparam[4];
240 /* unsupported */
241 SSVAL(rparam,0,NERR_notsupported);
242 SSVAL(rparam,2,0); /* converter word */
244 DEBUG(3,("Unsupported API fd command\n"));
246 /* now send the reply */
247 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
249 return -1;
252 /****************************************************************************
253 Handle remote api calls delivered to a named pipe already opened.
254 ****************************************************************************/
256 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
257 uint16 *setup,char *data,char *params,
258 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
260 BOOL reply = False;
261 smb_np_struct *p = NULL;
262 int pnum;
263 int subcommand;
265 DEBUG(5,("api_fd_reply\n"));
267 /* First find out the name of this file. */
268 if (suwcnt != 2) {
269 DEBUG(0,("Unexpected named pipe transaction.\n"));
270 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
273 /* Get the file handle and hence the file name. */
275 * NB. The setup array has already been transformed
276 * via SVAL and so is in gost byte order.
278 pnum = ((int)setup[1]) & 0xFFFF;
279 subcommand = ((int)setup[0]) & 0xFFFF;
281 if(!(p = get_rpc_pipe(pnum))) {
282 if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) {
283 /* Win9x does this call with a unicode pipe name, not a pnum. */
284 /* Just return success for now... */
285 DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
286 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
287 return -1;
290 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
291 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
294 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum));
296 /* record maximum data length that can be transmitted in an SMBtrans */
297 p->max_trans_reply = mdrcnt;
299 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
301 switch (subcommand) {
302 case TRANSACT_DCERPCCMD:
303 /* dce/rpc command */
304 reply = write_to_pipe(p, data, tdscnt);
305 if (reply)
306 reply = api_rpc_trans_reply(outbuf, p);
307 break;
308 case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
309 /* Wait Named Pipe Handle state */
310 reply = api_WNPHS(outbuf, p, params, tpscnt);
311 break;
312 case TRANSACT_SETNAMEDPIPEHANDLESTATE:
313 /* Set Named Pipe Handle state */
314 reply = api_SNPHS(outbuf, p, params, tpscnt);
315 break;
316 default:
317 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
320 if (!reply)
321 return api_no_reply(outbuf, mdrcnt);
323 return -1;
326 /****************************************************************************
327 handle named pipe commands
328 ****************************************************************************/
329 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
330 uint16 *setup,char *data,char *params,
331 int suwcnt,int tdscnt,int tpscnt,
332 int msrcnt,int mdrcnt,int mprcnt)
334 DEBUG(3,("named pipe command on <%s> name\n", name));
336 if (strequal(name,"LANMAN"))
337 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
339 if (strequal(name,"WKSSVC") ||
340 strequal(name,"SRVSVC") ||
341 strequal(name,"WINREG") ||
342 strequal(name,"SAMR") ||
343 strequal(name,"LSARPC"))
345 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
346 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
349 if (strlen(name) < 1)
350 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
352 if (setup)
353 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
355 return 0;
359 /****************************************************************************
360 Reply to a SMBtrans.
361 ****************************************************************************/
363 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
365 fstring name;
366 int name_offset = 0;
367 char *data=NULL,*params=NULL;
368 uint16 *setup=NULL;
369 int outsize = 0;
370 uint16 vuid = SVAL(inbuf,smb_uid);
371 unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
372 unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
373 unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
374 unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
375 unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
376 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
377 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
378 unsigned int pscnt = SVAL(inbuf,smb_vwv9);
379 unsigned int psoff = SVAL(inbuf,smb_vwv10);
380 unsigned int dscnt = SVAL(inbuf,smb_vwv11);
381 unsigned int dsoff = SVAL(inbuf,smb_vwv12);
382 unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
383 fstring local_machine_name;
384 START_PROFILE(SMBtrans);
386 memset(name, '\0',sizeof(name));
387 srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE);
389 if (dscnt > tdscnt || pscnt > tpscnt)
390 goto bad_param;
392 if (tdscnt) {
393 if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) {
394 DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
395 END_PROFILE(SMBtrans);
396 return(ERROR_DOS(ERRDOS,ERRnomem));
398 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
399 goto bad_param;
400 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
401 (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
402 goto bad_param;
404 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
407 if (tpscnt) {
408 if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) {
409 DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
410 SAFE_FREE(data);
411 END_PROFILE(SMBtrans);
412 return(ERROR_DOS(ERRDOS,ERRnomem));
414 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
415 goto bad_param;
416 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
417 (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
418 goto bad_param;
420 memcpy(params,smb_base(inbuf)+psoff,pscnt);
423 if (suwcnt) {
424 unsigned int i;
425 if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) {
426 DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
427 SAFE_FREE(data);
428 SAFE_FREE(params);
429 END_PROFILE(SMBtrans);
430 return(ERROR_DOS(ERRDOS,ERRnomem));
432 if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
433 goto bad_param;
434 if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
435 goto bad_param;
437 for (i=0;i<suwcnt;i++)
438 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
442 srv_signing_trans_start(SVAL(inbuf,smb_mid));
444 if (pscnt < tpscnt || dscnt < tdscnt) {
445 /* We need to send an interim response then receive the rest
446 of the parameter/data bytes */
447 outsize = set_message(outbuf,0,0,True);
448 show_msg(outbuf);
449 srv_signing_trans_stop();
450 if (!send_smb(smbd_server_fd(),outbuf))
451 exit_server("reply_trans: send_smb failed.");
454 /* receive the rest of the trans packet */
455 while (pscnt < tpscnt || dscnt < tdscnt) {
456 BOOL ret;
457 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
459 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
462 * The sequence number for the trans reply is always
463 * based on the last secondary received.
466 srv_signing_trans_start(SVAL(inbuf,smb_mid));
468 if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
469 if(ret) {
470 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
471 } else {
472 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
473 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
475 SAFE_FREE(params);
476 SAFE_FREE(data);
477 SAFE_FREE(setup);
478 END_PROFILE(SMBtrans);
479 srv_signing_trans_stop();
480 return(ERROR_DOS(ERRSRV,ERRerror));
483 show_msg(inbuf);
485 /* Revise total_params and total_data in case they have changed downwards */
486 if (SVAL(inbuf,smb_vwv0) < tpscnt)
487 tpscnt = SVAL(inbuf,smb_vwv0);
488 if (SVAL(inbuf,smb_vwv1) < tdscnt)
489 tdscnt = SVAL(inbuf,smb_vwv1);
491 pcnt = SVAL(inbuf,smb_vwv2);
492 poff = SVAL(inbuf,smb_vwv3);
493 pdisp = SVAL(inbuf,smb_vwv4);
495 dcnt = SVAL(inbuf,smb_vwv5);
496 doff = SVAL(inbuf,smb_vwv6);
497 ddisp = SVAL(inbuf,smb_vwv7);
499 pscnt += pcnt;
500 dscnt += dcnt;
502 if (dscnt > tdscnt || pscnt > tpscnt)
503 goto bad_param;
505 if (pcnt) {
506 if (pdisp+pcnt > tpscnt)
507 goto bad_param;
508 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
509 goto bad_param;
510 if (pdisp > tpscnt)
511 goto bad_param;
512 if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) ||
513 (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
514 goto bad_param;
515 if (params + pdisp < params)
516 goto bad_param;
518 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
521 if (dcnt) {
522 if (ddisp+dcnt > tdscnt)
523 goto bad_param;
524 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
525 goto bad_param;
526 if (ddisp > tdscnt)
527 goto bad_param;
528 if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) ||
529 (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
530 goto bad_param;
531 if (data + ddisp < data)
532 goto bad_param;
534 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
538 DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
539 name,tdscnt,tpscnt,suwcnt));
542 * WinCE wierdness....
545 fstrcpy( local_machine_name, get_local_machine_name() );
547 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine_name, strlen(local_machine_name)) == 0) &&
548 (name[strlen(local_machine_name)+1] == '\\'))
549 name_offset = strlen(local_machine_name)+1;
551 if (strnequal(&name[name_offset], "\\PIPE", strlen("\\PIPE"))) {
552 name_offset += strlen("\\PIPE");
554 /* Win9x weirdness. When talking to a unicode server Win9x
555 only sends \PIPE instead of \PIPE\ */
557 if (name[name_offset] == '\\')
558 name_offset++;
560 DEBUG(5,("calling named_pipe\n"));
561 outsize = named_pipe(conn,vuid,outbuf,
562 name+name_offset,setup,data,params,
563 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
564 } else {
565 DEBUG(3,("invalid pipe name\n"));
566 outsize = 0;
570 SAFE_FREE(data);
571 SAFE_FREE(params);
572 SAFE_FREE(setup);
574 srv_signing_trans_stop();
576 if (close_on_completion)
577 close_cnum(conn,vuid);
579 if (one_way) {
580 END_PROFILE(SMBtrans);
581 return(-1);
584 if (outsize == 0) {
585 END_PROFILE(SMBtrans);
586 return(ERROR_DOS(ERRSRV,ERRnosupport));
589 END_PROFILE(SMBtrans);
590 return(outsize);
593 bad_param:
595 srv_signing_trans_stop();
596 DEBUG(0,("reply_trans: invalid trans parameters\n"));
597 SAFE_FREE(data);
598 SAFE_FREE(params);
599 SAFE_FREE(setup);
600 END_PROFILE(SMBtrans);
601 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);