Openwrt/openwrt/package/samba/patches/200-security.patch

607 lines
21 KiB
Diff
Raw Normal View History

diff -ruN samba-2.0.10.orig/source/include/smb.h samba-2.0.10/source/include/smb.h
--- samba-2.0.10.orig/source/include/smb.h 2006-03-06 22:25:08.000000000 +0100
+++ samba-2.0.10/source/include/smb.h 2006-03-06 22:25:53.000000000 +0100
@@ -272,6 +272,7 @@
2005-08-22 07:11:48 +00:00
#define ERRlock 33 /* Lock request conflicts with existing lock */
#define ERRunsup 50 /* Request unsupported, returned by Win 95, RJS 20Jun98 */
#define ERRfilexists 80 /* File in operation already exists */
+#define ERRinvalidparam 87
#define ERRcannotopen 110 /* Cannot open the file specified */
#define ERRunknownlevel 124
#define ERRrename 183
@@ -1911,4 +1912,7 @@
2005-08-22 07:11:48 +00:00
#define SAFE_NETBIOS_CHARS ". -_"
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0)
+#endif
#endif /* _SMB_H */
diff -ruN samba-2.0.10.orig/source/include/version.h samba-2.0.10/source/include/version.h
--- samba-2.0.10.orig/source/include/version.h 2001-06-23 15:23:59.000000000 +0200
+++ samba-2.0.10/source/include/version.h 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -1 +1 @@
-#define VERSION "2.0.10"
+#define VERSION "2.0.10-security-rollup"
diff -ruN samba-2.0.10.orig/source/smbd/filename.c samba-2.0.10/source/smbd/filename.c
--- samba-2.0.10.orig/source/smbd/filename.c 2000-03-16 23:59:44.000000000 +0100
+++ samba-2.0.10/source/smbd/filename.c 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -172,7 +172,7 @@
* StrnCpy always null terminates.
*/
- StrnCpy(orig_name, full_orig_name, namelen);
+ StrnCpy(orig_name, full_orig_name, MIN(namelen, sizeof(orig_name)-1));
if(!case_sensitive)
strupper( orig_name );
diff -ruN samba-2.0.10.orig/source/smbd/ipc.c samba-2.0.10/source/smbd/ipc.c
--- samba-2.0.10.orig/source/smbd/ipc.c 2006-03-06 22:25:08.000000000 +0100
+++ samba-2.0.10/source/smbd/ipc.c 2006-03-06 22:25:53.000000000 +0100
@@ -3556,18 +3556,18 @@
2005-08-22 07:11:48 +00:00
uint16 *setup=NULL;
int outsize = 0;
uint16 vuid = SVAL(inbuf,smb_uid);
- int tpscnt = SVAL(inbuf,smb_vwv0);
- int tdscnt = SVAL(inbuf,smb_vwv1);
- int mprcnt = SVAL(inbuf,smb_vwv2);
- int mdrcnt = SVAL(inbuf,smb_vwv3);
- int msrcnt = CVAL(inbuf,smb_vwv4);
+ unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
+ unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
+ unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
+ unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
+ unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
- int pscnt = SVAL(inbuf,smb_vwv9);
- int psoff = SVAL(inbuf,smb_vwv10);
- int dscnt = SVAL(inbuf,smb_vwv11);
- int dsoff = SVAL(inbuf,smb_vwv12);
- int suwcnt = CVAL(inbuf,smb_vwv13);
+ unsigned int pscnt = SVAL(inbuf,smb_vwv9);
+ unsigned int psoff = SVAL(inbuf,smb_vwv10);
+ unsigned int dscnt = SVAL(inbuf,smb_vwv11);
+ unsigned int dsoff = SVAL(inbuf,smb_vwv12);
+ unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
memset(name, '\0',sizeof(name));
fstrcpy(name,smb_buf(inbuf));
@@ -3578,26 +3578,44 @@
2005-08-22 07:11:48 +00:00
if (tdscnt) {
if((data = (char *)malloc(tdscnt)) == NULL) {
- DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
+ DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
return(ERROR(ERRDOS,ERRnomem));
}
+ if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
+ goto bad_param;
+ if (smb_base(inbuf)+dsoff+dscnt > inbuf + size)
+ goto bad_param;
+
memcpy(data,smb_base(inbuf)+dsoff,dscnt);
}
if (tpscnt) {
if((params = (char *)malloc(tpscnt)) == NULL) {
- DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
+ DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
+ SAFE_FREE(data);
return(ERROR(ERRDOS,ERRnomem));
}
+ if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
+ goto bad_param;
+ if (smb_base(inbuf)+psoff+pscnt > inbuf + size)
+ goto bad_param;
+
memcpy(params,smb_base(inbuf)+psoff,pscnt);
}
if (suwcnt) {
int i;
if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
- DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
- return(ERROR(ERRDOS,ERRnomem));
- }
+ DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
+ SAFE_FREE(data);
+ SAFE_FREE(params);
+ return(ERROR(ERRDOS,ERRnomem));
+ }
+ if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
+ goto bad_param;
+ if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
+ goto bad_param;
+
for (i=0;i<suwcnt;i++)
setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
}
@@ -3614,7 +3632,7 @@
2005-08-22 07:11:48 +00:00
/* receive the rest of the trans packet */
while (pscnt < tpscnt || dscnt < tdscnt) {
BOOL ret;
- int pcnt,poff,dcnt,doff,pdisp,ddisp;
+ unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
@@ -3625,19 +3643,19 @@
2005-08-22 07:11:48 +00:00
DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
(smb_read_error == READ_ERROR) ? "error" : "timeout" ));
}
- if (params)
- free(params);
- if (data)
- free(data);
- if (setup)
- free(setup);
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ SAFE_FREE(setup);
return(ERROR(ERRSRV,ERRerror));
}
show_msg(inbuf);
- tpscnt = SVAL(inbuf,smb_vwv0);
- tdscnt = SVAL(inbuf,smb_vwv1);
+ /* Revise total_params and total_data in case they have changed downwards */
+ if (SVAL(inbuf,smb_vwv0) < tpscnt)
+ tpscnt = SVAL(inbuf,smb_vwv0);
+ if (SVAL(inbuf,smb_vwv1) < tdscnt)
+ tdscnt = SVAL(inbuf,smb_vwv1);
pcnt = SVAL(inbuf,smb_vwv2);
poff = SVAL(inbuf,smb_vwv3);
@@ -3650,17 +3668,36 @@
2005-08-22 07:11:48 +00:00
pscnt += pcnt;
dscnt += dcnt;
- if (dscnt > tdscnt || pscnt > tpscnt) {
- exit_server("invalid trans parameters\n");
- }
+ if (dscnt > tdscnt || pscnt > tpscnt)
+ goto bad_param;
- if (pcnt)
+ if (pcnt) {
+ 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 (params + pdisp < params)
+ goto bad_param;
+
memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
- if (dcnt)
+ }
+
+ if (dcnt) {
+ 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)
+ goto bad_param;
+ if (data + ddisp < data)
+ goto bad_param;
+
memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
+ }
}
-
-
+
DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
name,tdscnt,tpscnt,suwcnt));
@@ -3700,4 +3737,12 @@
2005-08-22 07:11:48 +00:00
return(ERROR(ERRSRV,ERRnosupport));
return(outsize);
+
+ bad_param:
+
+ DEBUG(0,("reply_trans: invalid trans parameters\n"));
+ SAFE_FREE(data);
+ SAFE_FREE(params);
+ SAFE_FREE(setup);
+ return(ERROR(ERRSRV,ERRerror));
}
diff -ruN samba-2.0.10.orig/source/smbd/nttrans.c samba-2.0.10/source/smbd/nttrans.c
--- samba-2.0.10.orig/source/smbd/nttrans.c 2000-04-24 19:27:30.000000000 +0200
+++ samba-2.0.10/source/smbd/nttrans.c 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -2575,11 +2575,14 @@
params = (char *)malloc(total_parameter_count);
if (total_data_count > 0)
data = (char *)malloc(total_data_count);
-
+
if ((total_parameter_count && !params) || (total_data_count && !data) ||
(setup_count && !setup)) {
+ SAFE_FREE(setup);
+ SAFE_FREE(params);
+ SAFE_FREE(data);
DEBUG(0,("reply_nttrans : Out of memory\n"));
- return(ERROR(ERRDOS,ERRnomem));
+ return ERROR(ERRDOS,ERRnomem);
}
/* Copy the param and data bytes sent with this request into
@@ -2588,64 +2591,112 @@
num_data_sofar = data_count;
if (parameter_count > total_parameter_count || data_count > total_data_count)
- exit_server("reply_nttrans: invalid sizes in packet.\n");
+ goto bad_param;
if(setup) {
- memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
- dump_data(10, setup, setup_count);
+ if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
+ (smb_nt_SetupStart + setup_count < setup_count))
+ goto bad_param;
+ if (smb_nt_SetupStart + setup_count > length)
+ goto bad_param;
+
+ memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
}
if(params) {
- memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
- dump_data(10, params, parameter_count);
+ if ((parameter_offset + parameter_count < parameter_offset) ||
+ (parameter_offset + parameter_count < parameter_count))
+ goto bad_param;
+ if (smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)
+ goto bad_param;
+
+ memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
}
if(data) {
- memcpy( data, smb_base(inbuf) + data_offset, data_count);
DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
- dump_data(10, data, data_count);
+ if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count))
+ goto bad_param;
+ if (smb_base(inbuf) + data_offset + data_count > inbuf + length)
+ goto bad_param;
+
+ memcpy( data, smb_base(inbuf) + data_offset, data_count);
+
}
if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
- send_smb(Client,outbuf);
+ if (!send_smb(Client,outbuf))
+ exit_server("reply_nttrans: send_smb failed.");
while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
BOOL ret;
-
+ uint32 parameter_displacement;
+ uint32 data_displacement;
+
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
-
+
if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
- outsize = set_message(outbuf,0,0,True);
- if(ret) {
- DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
- } else {
- DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
+ outsize = set_message(outbuf,0,0,True);
+ if(ret) {
+ DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
+ } else {
+ DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
+ (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
}
- if(params)
- free(params);
- if(data)
- free(data);
- if(setup)
- free(setup);
- return(ERROR(ERRSRV,ERRerror));
+ goto bad_param;
}
/* Revise total_params and total_data in case they have changed downwards */
- total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
- total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
- num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
- num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
- if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
- exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
-
- memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)],
- smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
- memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
- smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
+ if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count)
+ total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
+ if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count)
+ total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
+
+ parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
+ parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
+ parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
+ num_params_sofar += parameter_count;
+
+ data_count = IVAL(inbuf, smb_nts_DataCount);
+ data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
+ data_offset = IVAL(inbuf, smb_nts_DataOffset);
+ num_data_sofar += data_count;
+
+ if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
+ DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
+ goto bad_param;
+ }
+
+ if (parameter_count) {
+ if (parameter_displacement + parameter_count >= total_parameter_count)
+ goto bad_param;
+ if ((parameter_displacement + parameter_count < parameter_displacement) ||
+ (parameter_displacement + parameter_count < parameter_count))
+ goto bad_param;
+ if (smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize)
+ goto bad_param;
+ if (params + parameter_displacement < params)
+ goto bad_param;
+
+ memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
+ }
+
+ if (data_count) {
+ if (data_displacement + data_count >= total_data_count)
+ goto bad_param;
+ if ((data_displacement + data_count < data_displacement) ||
+ (data_displacement + data_count < data_count))
+ goto bad_param;
+ if (smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize)
+ goto bad_param;
+ if (data + data_displacement < data)
+ goto bad_param;
+
+ memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
+ }
}
}
@@ -2714,4 +2765,10 @@
return outsize; /* If a correct response was needed the call_nt_transact_xxxx
calls have already sent it. If outsize != -1 then it is
returning an error packet. */
+ bad_param:
+
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ SAFE_FREE(setup);
+ return ERROR(ERRDOS,ERRinvalidparam);
}
diff -ruN samba-2.0.10.orig/source/smbd/password.c samba-2.0.10/source/smbd/password.c
--- samba-2.0.10.orig/source/smbd/password.c 2006-03-06 22:25:08.000000000 +0100
+++ samba-2.0.10/source/smbd/password.c 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -770,7 +770,7 @@
if (!ok && lp_username(snum)) {
char *auser;
pstring user_list;
- StrnCpy(user_list,lp_username(snum),sizeof(pstring));
+ StrnCpy(user_list,lp_username(snum),sizeof(pstring)-1);
pstring_sub(user_list,"%S",lp_servicename(snum));
diff -ruN samba-2.0.10.orig/source/smbd/reply.c samba-2.0.10/source/smbd/reply.c
--- samba-2.0.10.orig/source/smbd/reply.c 2006-03-06 22:25:08.000000000 +0100
+++ samba-2.0.10/source/smbd/reply.c 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -1413,6 +1413,9 @@
for (i=numentries;(i<maxentries) && !finished;i++)
{
+ /* check to make sure we have room in the buffer */
+ if ( ((PTR_DIFF(p, outbuf))+DIR_STRUCT_SIZE) > BUFFER_SIZE )
+ break;
finished =
!get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
if (!finished)
@@ -3122,6 +3125,9 @@
for (i=first;i<first+num_to_get;i++) {
+ /* check to make sure we have room in the buffer */
+ if ( (PTR_DIFF(p, outbuf)+28) > BUFFER_SIZE )
+ break;
put_dos_date2(p,0,queue[i].time);
CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
SSVAL(p,5,printjob_encode(SNUM(conn),
diff -ruN samba-2.0.10.orig/source/smbd/trans2.c samba-2.0.10/source/smbd/trans2.c
--- samba-2.0.10.orig/source/smbd/trans2.c 2000-04-24 19:27:31.000000000 +0200
+++ samba-2.0.10/source/smbd/trans2.c 2006-03-06 22:25:53.000000000 +0100
2005-08-22 07:11:48 +00:00
@@ -201,7 +201,6 @@
int16 open_ofun = SVAL(params,12);
int32 open_size = IVAL(params,14);
char *pname = &params[28];
- int16 namelen = strlen(pname)+1;
pstring fname;
mode_t unixmode;
@@ -213,7 +212,7 @@
BOOL bad_path = False;
files_struct *fsp;
- StrnCpy(fname,pname,namelen);
+ pstrcpy(fname,pname);
DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
fname,open_mode, open_attr, open_ofun, open_size));
@@ -2185,7 +2184,7 @@
unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
unsigned int tran_call = SVAL(inbuf, smb_setup0);
char *params = NULL, *data = NULL;
- int num_params, num_params_sofar, num_data, num_data_sofar;
+ unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
/* Queue this open message as we are the process of an
@@ -2203,8 +2202,9 @@
/* All trans2 messages we handle have smb_sucnt == 1 - ensure this
is so as a sanity check */
if (suwcnt != 1) {
- DEBUG(2,("Invalid smb_sucnt in trans2 call\n"));
- return(ERROR(ERRSRV,ERRerror));
+ DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
+ DEBUG(2,("Transaction is %d\n",tran_call));
+ ERROR(ERRDOS,ERRinvalidparam);
}
/* Allocate the space for the maximum needed parameters and data */
@@ -2215,11 +2215,9 @@
if ((total_params && !params) || (total_data && !data)) {
DEBUG(2,("Out of memory in reply_trans2\n"));
- if(params)
- free(params);
- if(data)
- free(data);
- return(ERROR(ERRDOS,ERRnomem));
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ return ERROR(ERRDOS,ERRnomem);
}
/* Copy the param and data bytes sent with this request into
@@ -2230,20 +2228,37 @@
if (num_params > total_params || num_data > total_data)
exit_server("invalid params in reply_trans2");
- if(params)
- memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
- if(data)
- memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
+ if(params) {
+ unsigned int psoff = SVAL(inbuf, smb_psoff);
+ if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
+ goto bad_param;
+ if (smb_base(inbuf) + psoff + num_params > inbuf + length)
+ goto bad_param;
+ memcpy( params, smb_base(inbuf) + psoff, num_params);
+ }
+ if(data) {
+ unsigned int dsoff = SVAL(inbuf, smb_dsoff);
+ if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
+ goto bad_param;
+ if (smb_base(inbuf) + dsoff + num_data > inbuf + length)
+ goto bad_param;
+ memcpy( data, smb_base(inbuf) + dsoff, num_data);
+ }
if(num_data_sofar < total_data || num_params_sofar < total_params) {
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
outsize = set_message(outbuf,0,0,True);
- send_smb(Client,outbuf);
+ if (!send_smb(Client,outbuf))
+ exit_server("reply_trans2: send_smb failed.");
while (num_data_sofar < total_data ||
num_params_sofar < total_params) {
BOOL ret;
+ unsigned int param_disp;
+ unsigned int param_off;
+ unsigned int data_disp;
+ unsigned int data_off;
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
@@ -2255,26 +2270,55 @@
else
DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
(smb_read_error == READ_ERROR) ? "error" : "timeout" ));
- if(params)
- free(params);
- if(data)
- free(data);
- return(ERROR(ERRSRV,ERRerror));
+ goto bad_param;
}
/* Revise total_params and total_data in case
they have changed downwards */
- total_params = SVAL(inbuf, smb_tpscnt);
- total_data = SVAL(inbuf, smb_tdscnt);
- num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
- num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
+ if (SVAL(inbuf, smb_tpscnt) < total_params)
+ total_params = SVAL(inbuf, smb_tpscnt);
+ if (SVAL(inbuf, smb_tdscnt) < total_data)
+ total_data = SVAL(inbuf, smb_tdscnt);
+
+ num_params = SVAL(inbuf,smb_spscnt);
+ param_off = SVAL(inbuf, smb_spsoff);
+ param_disp = SVAL(inbuf, smb_spsdisp);
+ num_params_sofar += num_params;
+
+ num_data = SVAL(inbuf, smb_sdscnt);
+ data_off = SVAL(inbuf, smb_sdsoff);
+ data_disp = SVAL(inbuf, smb_sdsdisp);
+ num_data_sofar += num_data;
+
if (num_params_sofar > total_params || num_data_sofar > total_data)
- exit_server("data overflow in trans2");
+ goto bad_param;
- memcpy( &params[ SVAL(inbuf, smb_spsdisp)],
- smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
- memcpy( &data[SVAL(inbuf, smb_sdsdisp)],
- smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data);
+ if (num_params) {
+ if (param_disp + num_params >= total_params)
+ goto bad_param;
+ if ((param_disp + num_params < param_disp) ||
+ (param_disp + num_params < num_params))
+ goto bad_param;
+ if (smb_base(inbuf) + param_off + num_params >= inbuf + bufsize)
+ goto bad_param;
+ if (params + param_disp < params)
+ goto bad_param;
+
+ memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
+ }
+ if (num_data) {
+ if (data_disp + num_data >= total_data)
+ goto bad_param;
+ if ((data_disp + num_data < data_disp) ||
+ (data_disp + num_data < num_data))
+ goto bad_param;
+ if (smb_base(inbuf) + data_off + num_data >= inbuf + bufsize)
+ goto bad_param;
+ if (data + data_disp < data)
+ goto bad_param;
+
+ memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
+ }
}
}
@@ -2367,4 +2411,10 @@
return outsize; /* If a correct response was needed the
call_trans2xxx calls have already sent
it. If outsize != -1 then it is returning */
+
+ bad_param:
+
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ return (ERROR(ERRDOS,ERRinvalidparam));
}