source: trunk/samba/source/smbd/ipc.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 20.7 KB
Line 
1/*
2   Unix SMB/CIFS implementation.
3   Inter-process communication and named pipe handling
4   Copyright (C) Andrew Tridgell 1992-1998
5
6   SMB Version handling
7   Copyright (C) John H Terpstra 1995-1998
8   
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.
13   
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.
18   
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.
22   */
23/*
24   This file handles the named pipe and mailslot calls
25   in the SMBtrans protocol
26   */
27
28#include "includes.h"
29
30extern int max_send;
31
32#define NERR_notsupported 50
33
34extern int smb_read_error;
35
36/*******************************************************************
37 copies parameters and data, as needed, into the smb buffer
38
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
43
44 ******************************************************************/
45
46static 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)
49{
50        char *copy_into = smb_buf(outbuf)+1;
51
52        if(param_len < 0)
53                param_len = 0;
54
55        if(data_len < 0)
56                data_len = 0;
57
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));
61
62        if (param_len)
63                memcpy(copy_into, &rparam[param_offset], param_len);
64
65        copy_into += param_len + align;
66
67        if (data_len )
68                memcpy(copy_into, &rdata[data_offset], data_len);
69}
70
71/****************************************************************************
72 Send a trans reply.
73 ****************************************************************************/
74
75void send_trans_reply(char *outbuf,
76                                char *rparam, int rparam_len,
77                                char *rdata, int rdata_len,
78                                BOOL buffer_too_large)
79{
80        int this_ldata,this_lparam;
81        int tot_data_sent = 0;
82        int tot_param_sent = 0;
83        int align;
84
85        int ldata  = rdata  ? rdata_len : 0;
86        int lparam = rparam ? rparam_len : 0;
87
88        if (buffer_too_large)
89                DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
90
91        this_lparam = MIN(lparam,max_send - 500); /* hack */
92        this_ldata  = MIN(ldata,max_send - (500+this_lparam));
93
94        align = ((this_lparam)%4);
95
96        if (buffer_too_large) {
97                ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
98        }
99
100        set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
101
102        copy_trans_params_and_data(outbuf, align,
103                                                                rparam, tot_param_sent, this_lparam,
104                                                                rdata, tot_data_sent, this_ldata);
105
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);
115
116        show_msg(outbuf);
117        if (!send_smb(smbd_server_fd(),outbuf))
118                exit_server_cleanly("send_trans_reply: send_smb failed.");
119
120        tot_data_sent = this_ldata;
121        tot_param_sent = this_lparam;
122
123        while (tot_data_sent < ldata || tot_param_sent < lparam)
124        {
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));
127
128                if(this_lparam < 0)
129                        this_lparam = 0;
130
131                if(this_ldata < 0)
132                        this_ldata = 0;
133
134                align = (this_lparam%4);
135
136                set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
137
138                copy_trans_params_and_data(outbuf, align,
139                                           rparam, tot_param_sent, this_lparam,
140                                           rdata, tot_data_sent, this_ldata);
141               
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);
149
150                show_msg(outbuf);
151                if (!send_smb(smbd_server_fd(),outbuf))
152                        exit_server_cleanly("send_trans_reply: send_smb failed.");
153
154                tot_data_sent  += this_ldata;
155                tot_param_sent += this_lparam;
156        }
157}
158
159/****************************************************************************
160 Start the first part of an RPC reply which began with an SMBtrans request.
161****************************************************************************/
162
163static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p)
164{
165        BOOL is_data_outstanding;
166        char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
167        int data_len;
168
169        if(rdata == NULL) {
170                DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
171                return False;
172        }
173
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;
178        }
179
180        send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
181
182        SAFE_FREE(rdata);
183        return True;
184}
185
186/****************************************************************************
187 WaitNamedPipeHandleState
188****************************************************************************/
189
190static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
191{
192        uint16 priority;
193
194        if (!param || param_len < 2)
195                return False;
196
197        priority = SVAL(param,0);
198        DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
199
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;
204        }
205        return False;
206}
207
208
209/****************************************************************************
210 SetNamedPipeHandleState
211****************************************************************************/
212
213static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
214{
215        uint16 id;
216
217        if (!param || param_len < 2)
218                return False;
219
220        id = SVAL(param,0);
221        DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
222
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;
227        }
228        return False;
229}
230
231
232/****************************************************************************
233 When no reply is generated, indicate unsupported.
234 ****************************************************************************/
235
236static BOOL api_no_reply(char *outbuf, int max_rdata_len)
237{
238        char rparam[4];
239
240        /* unsupported */
241        SSVAL(rparam,0,NERR_notsupported);
242        SSVAL(rparam,2,0); /* converter word */
243
244        DEBUG(3,("Unsupported API fd command\n"));
245
246        /* now send the reply */
247        send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
248
249        return -1;
250}
251
252/****************************************************************************
253 Handle remote api calls delivered to a named pipe already opened.
254 ****************************************************************************/
255
256static 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)
259{
260        BOOL reply = False;
261        smb_np_struct *p = NULL;
262        int pnum;
263        int subcommand;
264
265        DEBUG(5,("api_fd_reply\n"));
266
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);
271        }
272
273        /* Get the file handle and hence the file name. */
274        /*
275         * NB. The setup array has already been transformed
276         * via SVAL and so is in gost byte order.
277         */
278        pnum = ((int)setup[1]) & 0xFFFF;
279        subcommand = ((int)setup[0]) & 0xFFFF;
280
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;
288                }
289
290                DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
291                return ERROR_NT(NT_STATUS_INVALID_HANDLE);
292        }
293
294        if (vuid != p->vuid) {
295                DEBUG(1, ("Got pipe request (pnum %x) using invalid VUID %d, "
296                          "expected %d\n", pnum, vuid, p->vuid));
297                return ERROR_NT(NT_STATUS_INVALID_HANDLE);
298        }
299
300        DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum));
301
302        /* record maximum data length that can be transmitted in an SMBtrans */
303        p->max_trans_reply = mdrcnt;
304
305        DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
306
307        switch (subcommand) {
308        case TRANSACT_DCERPCCMD:
309                /* dce/rpc command */
310                reply = write_to_pipe(p, data, tdscnt);
311                if (reply)
312                        reply = api_rpc_trans_reply(outbuf, p);
313                break;
314        case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
315                /* Wait Named Pipe Handle state */
316                reply = api_WNPHS(outbuf, p, params, tpscnt);
317                break;
318        case TRANSACT_SETNAMEDPIPEHANDLESTATE:
319                /* Set Named Pipe Handle state */
320                reply = api_SNPHS(outbuf, p, params, tpscnt);
321                break;
322        default:
323                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
324        }
325
326        if (!reply)
327                return api_no_reply(outbuf, mdrcnt);
328
329        return -1;
330}
331
332/****************************************************************************
333  handle named pipe commands
334  ****************************************************************************/
335static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
336                      uint16 *setup,char *data,char *params,
337                      int suwcnt,int tdscnt,int tpscnt,
338                      int msrcnt,int mdrcnt,int mprcnt)
339{
340        DEBUG(3,("named pipe command on <%s> name\n", name));
341
342        if (strequal(name,"LANMAN"))
343                return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
344
345        if (strequal(name,"WKSSVC") ||
346            strequal(name,"SRVSVC") ||
347            strequal(name,"WINREG") ||
348            strequal(name,"SAMR") ||
349            strequal(name,"LSARPC"))
350        {
351                DEBUG(4,("named pipe command from Win95 (wow!)\n"));
352                return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
353        }
354
355        if (strlen(name) < 1)
356                return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
357
358        if (setup)
359                DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
360
361        return 0;
362}
363
364static NTSTATUS handle_trans(connection_struct *conn,
365                             struct trans_state *state,
366                             char *outbuf, int *outsize)
367{
368        char *local_machine_name;
369        int name_offset = 0;
370
371        DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
372                 state->name,(unsigned int)state->total_data,(unsigned int)state->total_param,
373                 (unsigned int)state->setup_count));
374
375        /*
376         * WinCE wierdness....
377         */
378
379        local_machine_name = talloc_asprintf(state, "\\%s\\",
380                                             get_local_machine_name());
381
382        if (local_machine_name == NULL) {
383                return NT_STATUS_NO_MEMORY;
384        }
385
386        if (strnequal(state->name, local_machine_name,
387                      strlen(local_machine_name))) {
388                name_offset = strlen(local_machine_name)-1;
389        }
390
391        if (!strnequal(&state->name[name_offset], "\\PIPE",
392                       strlen("\\PIPE"))) {
393                return NT_STATUS_NOT_SUPPORTED;
394        }
395       
396        name_offset += strlen("\\PIPE");
397
398        /* Win9x weirdness.  When talking to a unicode server Win9x
399           only sends \PIPE instead of \PIPE\ */
400
401        if (state->name[name_offset] == '\\')
402                name_offset++;
403
404        DEBUG(5,("calling named_pipe\n"));
405        *outsize = named_pipe(conn, state->vuid, outbuf,
406                              state->name+name_offset,
407                              state->setup,state->data,
408                              state->param,
409                              state->setup_count,state->total_data,
410                              state->total_param,
411                              state->max_setup_return,
412                              state->max_data_return,
413                              state->max_param_return);
414
415        if (*outsize == 0) {
416                return NT_STATUS_NOT_SUPPORTED;
417        }
418
419        if (state->close_on_completion)
420                close_cnum(conn,state->vuid);
421
422        return NT_STATUS_OK;
423}
424
425/****************************************************************************
426 Reply to a SMBtrans.
427 ****************************************************************************/
428
429int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
430                int size, int bufsize)
431{
432        int outsize = 0;
433        unsigned int dsoff = SVAL(inbuf, smb_dsoff);
434        unsigned int dscnt = SVAL(inbuf, smb_dscnt);
435        unsigned int psoff = SVAL(inbuf, smb_psoff);
436        unsigned int pscnt = SVAL(inbuf, smb_pscnt);
437        struct trans_state *state;
438        NTSTATUS result;
439
440        START_PROFILE(SMBtrans);
441
442        result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
443        if (!NT_STATUS_IS_OK(result)) {
444                DEBUG(2, ("Got invalid trans request: %s\n",
445                          nt_errstr(result)));
446                END_PROFILE(SMBtrans);
447                return ERROR_NT(result);
448        }
449
450        if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
451                DEBUG(0, ("talloc failed\n"));
452                END_PROFILE(SMBtrans);
453                return ERROR_NT(NT_STATUS_NO_MEMORY);
454        }
455
456        state->cmd = SMBtrans;
457
458        state->mid = SVAL(inbuf, smb_mid);
459        state->vuid = SVAL(inbuf, smb_uid);
460        state->setup_count = CVAL(inbuf, smb_suwcnt);
461        state->setup = NULL;
462        state->total_param = SVAL(inbuf, smb_tpscnt);
463        state->param = NULL;
464        state->total_data = SVAL(inbuf, smb_tdscnt);
465        state->data = NULL;
466        state->max_param_return = SVAL(inbuf, smb_mprcnt);
467        state->max_data_return = SVAL(inbuf, smb_mdrcnt);
468        state->max_setup_return = CVAL(inbuf, smb_msrcnt);
469        state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
470        state->one_way = BITSETW(inbuf+smb_vwv5,1);
471
472        memset(state->name, '\0',sizeof(state->name));
473        srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
474                        sizeof(state->name), STR_TERMINATE);
475       
476        if ((dscnt > state->total_data) || (pscnt > state->total_param))
477                goto bad_param;
478
479        if (state->total_data)  {
480                /* Can't use talloc here, the core routines do realloc on the
481                 * params and data. Out of paranoia, 100 bytes too many. */
482                state->data = (char *)SMB_MALLOC(state->total_data+100);
483                if (state->data == NULL) {
484                        DEBUG(0,("reply_trans: data malloc fail for %u "
485                                 "bytes !\n", (unsigned int)state->total_data));
486                        TALLOC_FREE(state);
487                        END_PROFILE(SMBtrans);
488                        return(ERROR_DOS(ERRDOS,ERRnomem));
489                } 
490                /* null-terminate the slack space */
491                memset(&state->data[state->total_data], 0, 100);
492                if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
493                        goto bad_param;
494                if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
495                    (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
496                        goto bad_param;
497
498                memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
499        }
500
501        if (state->total_param) {
502                /* Can't use talloc here, the core routines do realloc on the
503                 * params and data. Out of paranoia, 100 bytes too many */
504                state->param = (char *)SMB_MALLOC(state->total_param+100);
505                if (state->param == NULL) {
506                        DEBUG(0,("reply_trans: param malloc fail for %u "
507                                 "bytes !\n", (unsigned int)state->total_param));
508                        SAFE_FREE(state->data);
509                        TALLOC_FREE(state);
510                        END_PROFILE(SMBtrans);
511                        return(ERROR_DOS(ERRDOS,ERRnomem));
512                } 
513                /* null-terminate the slack space */
514                memset(&state->param[state->total_param], 0, 100);
515                if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
516                        goto bad_param;
517                if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
518                    (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
519                        goto bad_param;
520
521                memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
522        }
523
524        state->received_data  = dscnt;
525        state->received_param = pscnt;
526
527        if (state->setup_count) {
528                unsigned int i;
529                if((state->setup = TALLOC_ARRAY(
530                            state, uint16, state->setup_count)) == NULL) {
531                        DEBUG(0,("reply_trans: setup malloc fail for %u "
532                                 "bytes !\n", (unsigned int)
533                                 (state->setup_count * sizeof(uint16))));
534                        TALLOC_FREE(state);
535                        END_PROFILE(SMBtrans);
536                        return(ERROR_DOS(ERRDOS,ERRnomem));
537                } 
538                if (inbuf+smb_vwv14+(state->setup_count*SIZEOFWORD) >
539                    inbuf + size)
540                        goto bad_param;
541                if ((smb_vwv14+(state->setup_count*SIZEOFWORD) < smb_vwv14) ||
542                    (smb_vwv14+(state->setup_count*SIZEOFWORD) <
543                     (state->setup_count*SIZEOFWORD)))
544                        goto bad_param;
545
546                for (i=0;i<state->setup_count;i++)
547                        state->setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
548        }
549
550        state->received_param = pscnt;
551
552        if ((state->received_param == state->total_param) &&
553            (state->received_data == state->total_data)) {
554
555                result = handle_trans(conn, state, outbuf, &outsize);
556
557                SAFE_FREE(state->data);
558                SAFE_FREE(state->param);
559                TALLOC_FREE(state);
560
561                if (!NT_STATUS_IS_OK(result)) {
562                        END_PROFILE(SMBtrans);
563                        return ERROR_NT(result);
564                }
565
566                if (outsize == 0) {
567                        END_PROFILE(SMBtrans);
568                        return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
569                }
570
571                END_PROFILE(SMBtrans);
572                return outsize;
573        }
574
575        DLIST_ADD(conn->pending_trans, state);
576
577        /* We need to send an interim response then receive the rest
578           of the parameter/data bytes */
579        outsize = set_message(outbuf,0,0,True);
580        show_msg(outbuf);
581        END_PROFILE(SMBtrans);
582        return outsize;
583
584  bad_param:
585
586        DEBUG(0,("reply_trans: invalid trans parameters\n"));
587        SAFE_FREE(state->data);
588        SAFE_FREE(state->param);
589        TALLOC_FREE(state);
590        END_PROFILE(SMBtrans);
591        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
592}
593
594/****************************************************************************
595 Reply to a secondary SMBtrans.
596 ****************************************************************************/
597
598int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
599                 int size, int bufsize)
600{
601        int outsize = 0;
602        unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
603        struct trans_state *state;
604        NTSTATUS result;
605
606        START_PROFILE(SMBtranss);
607
608        show_msg(inbuf);
609
610        for (state = conn->pending_trans; state != NULL;
611             state = state->next) {
612                if (state->mid == SVAL(inbuf,smb_mid)) {
613                        break;
614                }
615        }
616
617        if ((state == NULL) || (state->cmd != SMBtrans)) {
618                END_PROFILE(SMBtranss);
619                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
620        }
621
622        /* Revise total_params and total_data in case they have changed
623         * downwards */
624
625        if (SVAL(inbuf, smb_vwv0) < state->total_param)
626                state->total_param = SVAL(inbuf,smb_vwv0);
627        if (SVAL(inbuf, smb_vwv1) < state->total_data)
628                state->total_data = SVAL(inbuf,smb_vwv1);
629
630        pcnt = SVAL(inbuf, smb_spscnt);
631        poff = SVAL(inbuf, smb_spsoff);
632        pdisp = SVAL(inbuf, smb_spsdisp);
633
634        dcnt = SVAL(inbuf, smb_sdscnt);
635        doff = SVAL(inbuf, smb_sdsoff);
636        ddisp = SVAL(inbuf, smb_sdsdisp);
637
638        state->received_param += pcnt;
639        state->received_data += dcnt;
640               
641        if ((state->received_data > state->total_data) ||
642            (state->received_param > state->total_param))
643                goto bad_param;
644               
645        if (pcnt) {
646                if (pdisp+pcnt > state->total_param)
647                        goto bad_param;
648                if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
649                        goto bad_param;
650                if (pdisp > state->total_param)
651                        goto bad_param;
652                if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
653                    (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
654                        goto bad_param;
655                if (state->param + pdisp < state->param)
656                        goto bad_param;
657
658                memcpy(state->param+pdisp,smb_base(inbuf)+poff,
659                       pcnt);
660        }
661
662        if (dcnt) {
663                if (ddisp+dcnt > state->total_data)
664                        goto bad_param;
665                if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
666                        goto bad_param;
667                if (ddisp > state->total_data)
668                        goto bad_param;
669                if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
670                    (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
671                        goto bad_param;
672                if (state->data + ddisp < state->data)
673                        goto bad_param;
674
675                memcpy(state->data+ddisp, smb_base(inbuf)+doff,
676                       dcnt);     
677        }
678
679        if ((state->received_param < state->total_param) ||
680            (state->received_data < state->total_data)) {
681                END_PROFILE(SMBtranss);
682                return -1;
683        }
684
685        /* construct_reply_common has done us the favor to pre-fill the
686         * command field with SMBtranss which is wrong :-)
687         */
688        SCVAL(outbuf,smb_com,SMBtrans);
689
690        result = handle_trans(conn, state, outbuf, &outsize);
691
692        DLIST_REMOVE(conn->pending_trans, state);
693        SAFE_FREE(state->data);
694        SAFE_FREE(state->param);
695        TALLOC_FREE(state);
696
697        if ((outsize == 0) || !NT_STATUS_IS_OK(result)) {
698                END_PROFILE(SMBtranss);
699                return(ERROR_DOS(ERRSRV,ERRnosupport));
700        }
701       
702        END_PROFILE(SMBtranss);
703        return(outsize);
704
705  bad_param:
706
707        DEBUG(0,("reply_transs: invalid trans parameters\n"));
708        DLIST_REMOVE(conn->pending_trans, state);
709        SAFE_FREE(state->data);
710        SAFE_FREE(state->param);
711        TALLOC_FREE(state);
712        END_PROFILE(SMBtranss);
713        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
714}
Note: See TracBrowser for help on using the repository browser.