move default option so that b44 defaults to y on brcm-2.6
[openwrt.git] / package / samba / patches / 200-security.patch
1 diff -ur samba-2.0.10/source/include/smb.h samba-2.0.10-security/source/include/smb.h
2 --- samba-2.0.10/source/include/smb.h   2001-06-23 12:52:20.000000000 +0400
3 +++ samba-2.0.10-security/source/include/smb.h  2005-05-21 21:51:17.206995728 +0400
4 @@ -256,6 +256,7 @@
5  #define ERRlock 33 /* Lock request conflicts with existing lock */
6  #define ERRunsup 50 /* Request unsupported, returned by Win 95, RJS 20Jun98 */
7  #define ERRfilexists 80 /* File in operation already exists */
8 +#define ERRinvalidparam 87
9  #define ERRcannotopen 110 /* Cannot open the file specified */
10  #define ERRunknownlevel 124
11  #define ERRrename 183
12 @@ -1893,4 +1894,7 @@
13  
14  #define SAFE_NETBIOS_CHARS ". -_"
15  
16 +#ifndef SAFE_FREE
17 +#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
18 +#endif
19  #endif /* _SMB_H */
20 diff -ur samba-2.0.10/source/include/version.h samba-2.0.10-security/source/include/version.h
21 --- samba-2.0.10/source/include/version.h       2001-06-23 17:23:59.000000000 +0400
22 +++ samba-2.0.10-security/source/include/version.h      2005-05-21 21:51:17.227992536 +0400
23 @@ -1 +1 @@
24 -#define VERSION "2.0.10"
25 +#define VERSION "2.0.10-security-rollup"
26 diff -ur samba-2.0.10/source/smbd/filename.c samba-2.0.10-security/source/smbd/filename.c
27 --- samba-2.0.10/source/smbd/filename.c 2000-03-17 01:59:44.000000000 +0300
28 +++ samba-2.0.10-security/source/smbd/filename.c        2005-05-21 21:51:17.403965784 +0400
29 @@ -172,7 +172,7 @@
30     * StrnCpy always null terminates.
31     */
32  
33 -  StrnCpy(orig_name, full_orig_name, namelen);
34 +  StrnCpy(orig_name, full_orig_name, MIN(namelen, sizeof(orig_name)-1));
35    if(!case_sensitive)
36      strupper( orig_name );
37  
38 diff -ur samba-2.0.10/source/smbd/ipc.c samba-2.0.10-security/source/smbd/ipc.c
39 --- samba-2.0.10/source/smbd/ipc.c      2000-03-30 02:20:06.000000000 +0400
40 +++ samba-2.0.10-security/source/smbd/ipc.c     2005-05-21 21:51:17.269986152 +0400
41 @@ -3550,18 +3550,18 @@
42         uint16 *setup=NULL;
43         int outsize = 0;
44         uint16 vuid = SVAL(inbuf,smb_uid);
45 -       int tpscnt = SVAL(inbuf,smb_vwv0);
46 -       int tdscnt = SVAL(inbuf,smb_vwv1);
47 -       int mprcnt = SVAL(inbuf,smb_vwv2);
48 -       int mdrcnt = SVAL(inbuf,smb_vwv3);
49 -       int msrcnt = CVAL(inbuf,smb_vwv4);
50 +       unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
51 +       unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
52 +       unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
53 +       unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
54 +       unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
55         BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
56         BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
57 -       int pscnt = SVAL(inbuf,smb_vwv9);
58 -       int psoff = SVAL(inbuf,smb_vwv10);
59 -       int dscnt = SVAL(inbuf,smb_vwv11);
60 -       int dsoff = SVAL(inbuf,smb_vwv12);
61 -       int suwcnt = CVAL(inbuf,smb_vwv13);
62 +       unsigned int pscnt = SVAL(inbuf,smb_vwv9);
63 +       unsigned int psoff = SVAL(inbuf,smb_vwv10);
64 +       unsigned int dscnt = SVAL(inbuf,smb_vwv11);
65 +       unsigned int dsoff = SVAL(inbuf,smb_vwv12);
66 +       unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
67  
68         memset(name, '\0',sizeof(name));
69         fstrcpy(name,smb_buf(inbuf));
70 @@ -3572,31 +3572,48 @@
71    
72         if (tdscnt)  {
73                 if((data = (char *)malloc(tdscnt)) == NULL) {
74 -                       DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
75 +                       DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
76                         return(ERROR(ERRDOS,ERRnomem));
77                 } 
78 +               if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
79 +                       goto bad_param;
80 +               if (smb_base(inbuf)+dsoff+dscnt > inbuf + size)
81 +                       goto bad_param;
82 +
83                 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
84         }
85  
86         if (tpscnt) {
87                 if((params = (char *)malloc(tpscnt)) == NULL) {
88 -                       DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
89 +                       DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
90 +                       SAFE_FREE(data);
91                         return(ERROR(ERRDOS,ERRnomem));
92                 } 
93 +               if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
94 +                       goto bad_param;
95 +               if (smb_base(inbuf)+psoff+pscnt > inbuf + size)
96 +                       goto bad_param;
97 +
98                 memcpy(params,smb_base(inbuf)+psoff,pscnt);
99         }
100  
101         if (suwcnt) {
102                 int i;
103                 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
104 -          DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
105 -                 return(ERROR(ERRDOS,ERRnomem));
106 -        } 
107 +                       DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
108 +                       SAFE_FREE(data);
109 +                       SAFE_FREE(params);
110 +                       return(ERROR(ERRDOS,ERRnomem));
111 +               } 
112 +               if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
113 +                       goto bad_param;
114 +               if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
115 +                       goto bad_param;
116 +
117                 for (i=0;i<suwcnt;i++)
118                         setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
119         }
120  
121 -
122         if (pscnt < tpscnt || dscnt < tdscnt) {
123                 /* We need to send an interim response then receive the rest
124                    of the parameter/data bytes */
125 @@ -3608,7 +3625,7 @@
126         /* receive the rest of the trans packet */
127         while (pscnt < tpscnt || dscnt < tdscnt) {
128                 BOOL ret;
129 -               int pcnt,poff,dcnt,doff,pdisp,ddisp;
130 +               unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
131        
132                 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
133  
134 @@ -3619,19 +3636,19 @@
135                                 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
136                                          (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
137                         }
138 -                       if (params)
139 -                               free(params);
140 -                       if (data)
141 -                               free(data);
142 -                       if (setup)
143 -                               free(setup);
144 +                       SAFE_FREE(params);
145 +                       SAFE_FREE(data);
146 +                       SAFE_FREE(setup);
147                         return(ERROR(ERRSRV,ERRerror));
148                 }
149  
150                 show_msg(inbuf);
151        
152 -               tpscnt = SVAL(inbuf,smb_vwv0);
153 -               tdscnt = SVAL(inbuf,smb_vwv1);
154 +               /* Revise total_params and total_data in case they have changed downwards */
155 +               if (SVAL(inbuf,smb_vwv0) < tpscnt)
156 +                       tpscnt = SVAL(inbuf,smb_vwv0);
157 +               if (SVAL(inbuf,smb_vwv1) < tdscnt)
158 +                       tdscnt = SVAL(inbuf,smb_vwv1);
159  
160                 pcnt = SVAL(inbuf,smb_vwv2);
161                 poff = SVAL(inbuf,smb_vwv3);
162 @@ -3644,17 +3661,36 @@
163                 pscnt += pcnt;
164                 dscnt += dcnt;
165                 
166 -               if (dscnt > tdscnt || pscnt > tpscnt) {
167 -                       exit_server("invalid trans parameters\n");
168 -               }
169 +               if (dscnt > tdscnt || pscnt > tpscnt)
170 +                       goto bad_param;
171                 
172 -               if (pcnt)
173 +               if (pcnt) {
174 +                       if (pdisp+pcnt >= tpscnt)
175 +                               goto bad_param;
176 +                       if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
177 +                               goto bad_param;
178 +                       if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize)
179 +                               goto bad_param;
180 +                       if (params + pdisp < params)
181 +                               goto bad_param;
182 +
183                         memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
184 -               if (dcnt)
185 +               }
186 +
187 +               if (dcnt) {
188 +                       if (ddisp+dcnt >= tdscnt)
189 +                               goto bad_param;
190 +                       if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
191 +                               goto bad_param;
192 +                       if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize)
193 +                               goto bad_param;
194 +                       if (data + ddisp < data)
195 +                               goto bad_param;
196 +
197                         memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
198 +               }
199         }
200 -       
201 -       
202 +
203         DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
204                  name,tdscnt,tpscnt,suwcnt));
205         
206 @@ -3694,4 +3730,12 @@
207                 return(ERROR(ERRSRV,ERRnosupport));
208         
209         return(outsize);
210 +
211 +  bad_param:
212 +
213 +       DEBUG(0,("reply_trans: invalid trans parameters\n"));
214 +       SAFE_FREE(data);
215 +       SAFE_FREE(params);
216 +       SAFE_FREE(setup);
217 +       return(ERROR(ERRSRV,ERRerror));
218  }
219 diff -ur samba-2.0.10/source/smbd/nttrans.c samba-2.0.10-security/source/smbd/nttrans.c
220 --- samba-2.0.10/source/smbd/nttrans.c  2000-04-24 21:27:30.000000000 +0400
221 +++ samba-2.0.10-security/source/smbd/nttrans.c 2005-05-21 21:51:17.314979312 +0400
222 @@ -2575,11 +2575,14 @@
223      params = (char *)malloc(total_parameter_count);
224    if (total_data_count > 0)
225      data = (char *)malloc(total_data_count);
226
227 +
228    if ((total_parameter_count && !params)  || (total_data_count && !data) ||
229        (setup_count && !setup)) {
230 +    SAFE_FREE(setup);
231 +    SAFE_FREE(params);
232 +    SAFE_FREE(data);
233      DEBUG(0,("reply_nttrans : Out of memory\n"));
234 -    return(ERROR(ERRDOS,ERRnomem));
235 +    return ERROR(ERRDOS,ERRnomem);
236    }
237  
238    /* Copy the param and data bytes sent with this request into
239 @@ -2588,64 +2591,112 @@
240    num_data_sofar = data_count;
241  
242    if (parameter_count > total_parameter_count || data_count > total_data_count)
243 -    exit_server("reply_nttrans: invalid sizes in packet.\n");
244 +    goto bad_param;
245  
246    if(setup) {
247 -    memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
248      DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
249 -    dump_data(10, setup, setup_count);
250 +    if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
251 +       (smb_nt_SetupStart + setup_count < setup_count))
252 +      goto bad_param;
253 +    if (smb_nt_SetupStart + setup_count > length)
254 +      goto bad_param;
255 +    
256 +    memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
257    }
258    if(params) {
259 -    memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
260      DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
261 -    dump_data(10, params, parameter_count);
262 +    if ((parameter_offset + parameter_count < parameter_offset) ||
263 +       (parameter_offset + parameter_count < parameter_count))
264 +      goto bad_param;
265 +    if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)
266 +      goto bad_param;
267 +    
268 +    memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
269    }
270    if(data) {
271 -    memcpy( data, smb_base(inbuf) + data_offset, data_count);
272      DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
273 -    dump_data(10, data, data_count);
274 +    if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count))
275 +      goto bad_param;
276 +    if (smb_base(inbuf) + data_offset + data_count > inbuf + length)
277 +      goto bad_param;
278 +    
279 +    memcpy( data, smb_base(inbuf) + data_offset, data_count);
280 +
281    }
282  
283    if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
284      /* We need to send an interim response then receive the rest
285         of the parameter/data bytes */
286      outsize = set_message(outbuf,0,0,True);
287 -    send_smb(Client,outbuf);
288 +    if (!send_smb(Client,outbuf))
289 +      exit_server("reply_nttrans: send_smb failed.");
290  
291      while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
292        BOOL ret;
293 -
294 +      uint32 parameter_displacement;
295 +      uint32 data_displacement;
296 +      
297        ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
298 -
299 +      
300        if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
301 -        outsize = set_message(outbuf,0,0,True);
302 -        if(ret) {
303 -               DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
304 -        } else {
305 -               DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
306 -                        (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
307 +       outsize = set_message(outbuf,0,0,True);
308 +       if(ret) {
309 +         DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
310 +       } else {
311 +         DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
312 +                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
313         }
314 -        if(params)
315 -          free(params);
316 -        if(data)
317 -          free(data);
318 -        if(setup)
319 -          free(setup);
320 -        return(ERROR(ERRSRV,ERRerror));
321 +       goto bad_param;
322        }
323        
324        /* Revise total_params and total_data in case they have changed downwards */
325 -      total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
326 -      total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
327 -      num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
328 -      num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
329 -      if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
330 -        exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
331 -
332 -      memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)], 
333 -              smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
334 -      memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
335 -              smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
336 +      if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count)
337 +       total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
338 +      if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count)
339 +       total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
340 +      
341 +      parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
342 +      parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
343 +      parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
344 +      num_params_sofar += parameter_count;
345 +      
346 +      data_count = IVAL(inbuf, smb_nts_DataCount);
347 +      data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
348 +      data_offset = IVAL(inbuf, smb_nts_DataOffset);
349 +      num_data_sofar += data_count;
350 +
351 +      if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
352 +       DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
353 +       goto bad_param;
354 +      }
355 +
356 +      if (parameter_count) {
357 +       if (parameter_displacement + parameter_count >= total_parameter_count)
358 +         goto bad_param;
359 +       if ((parameter_displacement + parameter_count < parameter_displacement) ||
360 +           (parameter_displacement + parameter_count < parameter_count))
361 +         goto bad_param;
362 +       if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize)
363 +         goto bad_param;
364 +       if (params + parameter_displacement < params)
365 +         goto bad_param;
366 +       
367 +       memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
368 +      }
369 +      
370 +      if (data_count) {
371 +       if (data_displacement + data_count >= total_data_count)
372 +         goto bad_param;
373 +       if ((data_displacement + data_count < data_displacement) ||
374 +           (data_displacement + data_count < data_count))
375 +         goto bad_param;
376 +       if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize)
377 +         goto bad_param;
378 +       if (data + data_displacement < data)
379 +         goto bad_param;
380 +       
381 +       memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
382 +      }
383      }
384    }
385  
386 @@ -2714,4 +2765,10 @@
387    return outsize; /* If a correct response was needed the call_nt_transact_xxxx 
388                      calls have already sent it. If outsize != -1 then it is
389                      returning an error packet. */
390 + bad_param:
391 +
392 +  SAFE_FREE(params);
393 +  SAFE_FREE(data);
394 +  SAFE_FREE(setup);
395 +  return ERROR(ERRDOS,ERRinvalidparam);
396  }
397 diff -ur samba-2.0.10/source/smbd/password.c samba-2.0.10-security/source/smbd/password.c
398 --- samba-2.0.10/source/smbd/password.c 2000-03-17 01:59:48.000000000 +0300
399 +++ samba-2.0.10-security/source/smbd/password.c        2005-05-21 21:51:17.336975968 +0400
400 @@ -770,7 +770,7 @@
401        if (!ok && lp_username(snum)) {
402         char *auser;
403         pstring user_list;
404 -       StrnCpy(user_list,lp_username(snum),sizeof(pstring));
405 +       StrnCpy(user_list,lp_username(snum),sizeof(pstring)-1);
406  
407         pstring_sub(user_list,"%S",lp_servicename(snum));
408           
409 diff -ur samba-2.0.10/source/smbd/reply.c samba-2.0.10-security/source/smbd/reply.c
410 --- samba-2.0.10/source/smbd/reply.c    2001-06-23 12:51:24.000000000 +0400
411 +++ samba-2.0.10-security/source/smbd/reply.c   2005-05-21 21:51:17.378969584 +0400
412 @@ -1413,6 +1413,9 @@
413  
414          for (i=numentries;(i<maxentries) && !finished;i++)
415          {
416 +         /* check to make sure we have room in the buffer */
417 +         if ( ((PTR_DIFF(p, outbuf))+DIR_STRUCT_SIZE) > BUFFER_SIZE )
418 +               break;
419            finished = 
420              !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
421            if (!finished)
422 @@ -3122,6 +3125,9 @@
423      
424  
425                 for (i=first;i<first+num_to_get;i++) {
426 +                       /* check to make sure we have room in the buffer */
427 +                       if ( (PTR_DIFF(p, outbuf)+28) > BUFFER_SIZE )
428 +                               break;
429                         put_dos_date2(p,0,queue[i].time);
430                         CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
431                         SSVAL(p,5,printjob_encode(SNUM(conn), 
432 diff -ur samba-2.0.10/source/smbd/trans2.c samba-2.0.10-security/source/smbd/trans2.c
433 --- samba-2.0.10/source/smbd/trans2.c   2000-04-24 21:27:31.000000000 +0400
434 +++ samba-2.0.10-security/source/smbd/trans2.c  2005-05-21 21:51:17.402965936 +0400
435 @@ -201,7 +201,6 @@
436    int16 open_ofun = SVAL(params,12);
437    int32 open_size = IVAL(params,14);
438    char *pname = &params[28];
439 -  int16 namelen = strlen(pname)+1;
440  
441    pstring fname;
442    mode_t unixmode;
443 @@ -213,7 +212,7 @@
444    BOOL bad_path = False;
445    files_struct *fsp;
446  
447 -  StrnCpy(fname,pname,namelen);
448 +  pstrcpy(fname,pname);
449  
450    DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
451            fname,open_mode, open_attr, open_ofun, open_size));
452 @@ -2185,7 +2184,7 @@
453         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
454         unsigned int tran_call = SVAL(inbuf, smb_setup0);
455         char *params = NULL, *data = NULL;
456 -       int num_params, num_params_sofar, num_data, num_data_sofar;
457 +       unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
458  
459         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
460                 /* Queue this open message as we are the process of an
461 @@ -2203,8 +2202,9 @@
462         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
463            is so as a sanity check */
464         if (suwcnt != 1) {
465 -               DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
466 -               return(ERROR(ERRSRV,ERRerror));
467 +               DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
468 +               DEBUG(2,("Transaction is %d\n",tran_call));
469 +               ERROR(ERRDOS,ERRinvalidparam);
470         }
471      
472         /* Allocate the space for the maximum needed parameters and data */
473 @@ -2215,11 +2215,9 @@
474    
475         if ((total_params && !params)  || (total_data && !data)) {
476                 DEBUG(2,("Out of memory in reply_trans2\n"));
477 -        if(params)
478 -          free(params);
479 -        if(data)
480 -          free(data); 
481 -               return(ERROR(ERRDOS,ERRnomem));
482 +               SAFE_FREE(params);
483 +               SAFE_FREE(data); 
484 +               return ERROR(ERRDOS,ERRnomem);
485         }
486  
487         /* Copy the param and data bytes sent with this request into
488 @@ -2230,20 +2228,37 @@
489         if (num_params > total_params || num_data > total_data)
490                 exit_server("invalid params in reply_trans2");
491  
492 -       if(params)
493 -               memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
494 -       if(data)
495 -               memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
496 +       if(params) {
497 +               unsigned int psoff = SVAL(inbuf, smb_psoff);
498 +               if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
499 +                       goto bad_param;
500 +               if (smb_base(inbuf) + psoff + num_params > inbuf + length)
501 +                       goto bad_param;
502 +               memcpy( params, smb_base(inbuf) + psoff, num_params);
503 +       }
504 +       if(data) {
505 +               unsigned int dsoff = SVAL(inbuf, smb_dsoff);
506 +               if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
507 +                       goto bad_param;
508 +               if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
509 +                       goto bad_param;
510 +               memcpy( data, smb_base(inbuf) + dsoff, num_data);
511 +       }
512  
513         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
514                 /* We need to send an interim response then receive the rest
515                    of the parameter/data bytes */
516                 outsize = set_message(outbuf,0,0,True);
517 -               send_smb(Client,outbuf);
518 +               if (!send_smb(Client,outbuf))
519 +                       exit_server("reply_trans2: send_smb failed.");
520  
521                 while (num_data_sofar < total_data || 
522                        num_params_sofar < total_params) {
523                         BOOL ret;
524 +                       unsigned int param_disp;
525 +                       unsigned int param_off;
526 +                       unsigned int data_disp;
527 +                       unsigned int data_off;
528  
529                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
530                         
531 @@ -2255,26 +2270,55 @@
532                                 else
533                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
534                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
535 -                               if(params)
536 -                                       free(params);
537 -                               if(data)
538 -                                       free(data);
539 -                               return(ERROR(ERRSRV,ERRerror));
540 +                               goto bad_param;
541                         }
542        
543                         /* Revise total_params and total_data in case
544                             they have changed downwards */
545 -                       total_params = SVAL(inbuf, smb_tpscnt);
546 -                       total_data = SVAL(inbuf, smb_tdscnt);
547 -                       num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
548 -                       num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
549 +                       if (SVAL(inbuf, smb_tpscnt) < total_params)
550 +                               total_params = SVAL(inbuf, smb_tpscnt);
551 +                       if (SVAL(inbuf, smb_tdscnt) < total_data)
552 +                               total_data = SVAL(inbuf, smb_tdscnt);
553 +
554 +                       num_params = SVAL(inbuf,smb_spscnt);
555 +                       param_off = SVAL(inbuf, smb_spsoff);
556 +                       param_disp = SVAL(inbuf, smb_spsdisp);
557 +                       num_params_sofar += num_params;
558 +
559 +                       num_data = SVAL(inbuf, smb_sdscnt);
560 +                       data_off = SVAL(inbuf, smb_sdsoff);
561 +                       data_disp = SVAL(inbuf, smb_sdsdisp);
562 +                       num_data_sofar += num_data;
563 +
564                         if (num_params_sofar > total_params || num_data_sofar > total_data)
565 -                               exit_server("data overflow in trans2");
566 +                               goto bad_param;
567                         
568 -                       memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
569 -                               smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
570 -                       memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
571 -                               smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
572 +                       if (num_params) {
573 +                               if (param_disp + num_params >= total_params)
574 +                                       goto bad_param;
575 +                               if ((param_disp + num_params < param_disp) ||
576 +                                               (param_disp + num_params < num_params))
577 +                                       goto bad_param;
578 +                               if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
579 +                                       goto bad_param;
580 +                               if (params + param_disp < params)
581 +                                       goto bad_param;
582 +
583 +                               memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
584 +                       }
585 +                       if (num_data) {
586 +                               if (data_disp + num_data >= total_data)
587 +                                       goto bad_param;
588 +                               if ((data_disp + num_data < data_disp) ||
589 +                                               (data_disp + num_data < num_data))
590 +                                       goto bad_param;
591 +                               if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
592 +                                       goto bad_param;
593 +                               if (data + data_disp < data)
594 +                                       goto bad_param;
595 +
596 +                               memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
597 +                       }
598                 }
599         }
600         
601 @@ -2367,4 +2411,10 @@
602         return outsize; /* If a correct response was needed the
603                            call_trans2xxx calls have already sent
604                            it. If outsize != -1 then it is returning */
605 +
606 +  bad_param:
607 +
608 +       SAFE_FREE(params);
609 +       SAFE_FREE(data);
610 +       return (ERROR(ERRDOS,ERRinvalidparam));
611  }