r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[tprouty/samba.git] / source / smbd / ipc.c
index 85e28f5d17279ba2c4fcf0da040fdec56e95ac03..9fcd39b5002caa932a0ebbcd3163ec055fa6d42f 100644 (file)
@@ -96,7 +96,7 @@ void send_trans_reply(char *outbuf,
        align = ((this_lparam)%4);
 
        if (buffer_too_large) {
-               ERROR_NT(STATUS_BUFFER_OVERFLOW);
+               ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
        }
 
        set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
@@ -165,7 +165,7 @@ void send_trans_reply(char *outbuf,
 static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p)
 {
        BOOL is_data_outstanding;
-       char *rdata = malloc(p->max_trans_reply);
+       char *rdata = SMB_MALLOC(p->max_trans_reply);
        int data_len;
 
        if(rdata == NULL) {
@@ -281,11 +281,19 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
        subcommand = ((int)setup[0]) & 0xFFFF;
 
        if(!(p = get_rpc_pipe(pnum))) {
+               if (subcommand == TRANSACT_WAITNAMEDPIPEHANDLESTATE) {
+                       /* Win9x does this call with a unicode pipe name, not a pnum. */
+                       /* Just return success for now... */
+                       DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
+                       send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
+                       return -1;
+               }
+
                DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
                return api_no_reply(outbuf, mdrcnt);
        }
 
-       DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
+       DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", subcommand, p->name, pnum));
 
        /* record maximum data length that can be transmitted in an SMBtrans */
        p->max_trans_reply = mdrcnt;
@@ -381,29 +389,31 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                goto bad_param;
   
        if (tdscnt)  {
-               if((data = (char *)malloc(tdscnt)) == NULL) {
+               if((data = (char *)SMB_MALLOC(tdscnt)) == NULL) {
                        DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
                        END_PROFILE(SMBtrans);
                        return(ERROR_DOS(ERRDOS,ERRnomem));
                } 
                if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
                        goto bad_param;
-               if (smb_base(inbuf)+dsoff+dscnt > inbuf + size)
+               if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
+                               (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
                        goto bad_param;
 
                memcpy(data,smb_base(inbuf)+dsoff,dscnt);
        }
 
        if (tpscnt) {
-               if((params = (char *)malloc(tpscnt)) == NULL) {
+               if((params = (char *)SMB_MALLOC(tpscnt)) == NULL) {
                        DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
                        SAFE_FREE(data);
                        END_PROFILE(SMBtrans);
                        return(ERROR_DOS(ERRDOS,ERRnomem));
                } 
                if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
-                        goto bad_param;
-               if (smb_base(inbuf)+psoff+pscnt > inbuf + size)
+                       goto bad_param;
+               if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
+                               (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
                        goto bad_param;
 
                memcpy(params,smb_base(inbuf)+psoff,pscnt);
@@ -411,7 +421,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
        if (suwcnt) {
                unsigned int i;
-               if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
+               if((setup = SMB_MALLOC_ARRAY(uint16,suwcnt)) == NULL) {
                        DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
                        SAFE_FREE(data);
                        SAFE_FREE(params);
@@ -428,11 +438,14 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
 
 
+       srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
        if (pscnt < tpscnt || dscnt < tdscnt) {
                /* We need to send an interim response then receive the rest
                   of the parameter/data bytes */
                outsize = set_message(outbuf,0,0,True);
                show_msg(outbuf);
+               srv_signing_trans_stop();
                if (!send_smb(smbd_server_fd(),outbuf))
                        exit_server("reply_trans: send_smb failed.");
        }
@@ -444,6 +457,13 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
       
                ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
+               /*
+                * The sequence number for the trans reply is always
+                * based on the last secondary received.
+                */
+
+               srv_signing_trans_start(SVAL(inbuf,smb_mid));
+
                if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
                        if(ret) {
                                DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
@@ -455,6 +475,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                        SAFE_FREE(data);
                        SAFE_FREE(setup);
                        END_PROFILE(SMBtrans);
+                       srv_signing_trans_stop();
                        return(ERROR_DOS(ERRSRV,ERRerror));
                }
 
@@ -481,11 +502,14 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                        goto bad_param;
                
                if (pcnt) {
-                       if (pdisp+pcnt >= tpscnt)
+                       if (pdisp+pcnt > tpscnt)
                                goto bad_param;
                        if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
-                                goto bad_param;
-                       if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize)
+                               goto bad_param;
+                       if (pdisp > tpscnt)
+                               goto bad_param;
+                       if ((smb_base(inbuf) + poff + pcnt >= inbuf + bufsize) ||
+                                       (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
                                goto bad_param;
                        if (params + pdisp < params)
                                goto bad_param;
@@ -494,11 +518,14 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                }
 
                if (dcnt) {
-                       if (ddisp+dcnt >= tdscnt)
+                       if (ddisp+dcnt > tdscnt)
                                goto bad_param;
                        if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
                                goto bad_param;
-                       if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize)
+                       if (ddisp > tdscnt)
+                               goto bad_param;
+                       if ((smb_base(inbuf) + doff + dcnt >= inbuf + bufsize) ||
+                                       (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
                                goto bad_param;
                        if (data + ddisp < data)
                                goto bad_param;
@@ -506,11 +533,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                        memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
                }
        }
-       
-       
+
        DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n",
                 name,tdscnt,tpscnt,suwcnt));
-       
+
        /*
         * WinCE wierdness....
         */
@@ -542,6 +568,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        SAFE_FREE(params);
        SAFE_FREE(setup);
        
+       srv_signing_trans_stop();
+
        if (close_on_completion)
                close_cnum(conn,vuid);
 
@@ -561,6 +589,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 
   bad_param:
 
+       srv_signing_trans_stop();
        DEBUG(0,("reply_trans: invalid trans parameters\n"));
        SAFE_FREE(data);
        SAFE_FREE(params);