summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/ipc.c12
-rw-r--r--source/smbd/lanman.c924
-rw-r--r--source/smbd/msdfs.c76
-rw-r--r--source/smbd/nttrans.c103
-rw-r--r--source/smbd/quotas.c56
-rw-r--r--source/smbd/reply.c23
-rw-r--r--source/smbd/service.c22
-rw-r--r--source/smbd/sesssetup.c5
-rw-r--r--source/smbd/trans2.c61
-rw-r--r--source/smbd/vfs.c2
10 files changed, 909 insertions, 375 deletions
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index ca128d29d9c..6e5ff9f0359 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -478,8 +478,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_data) {
/* Can't use talloc here, the core routines do realloc on the
- * params and data. */
- state->data = (char *)SMB_MALLOC(state->total_data);
+ * params and data. Out of paranoia, 100 bytes too many. */
+ state->data = (char *)SMB_MALLOC(state->total_data+100);
if (state->data == NULL) {
DEBUG(0,("reply_trans: data malloc fail for %u "
"bytes !\n", (unsigned int)state->total_data));
@@ -487,6 +487,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
END_PROFILE(SMBtrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
+ /* null-terminate the slack space */
+ memset(&state->data[state->total_data], 0, 100);
if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
goto bad_param;
if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
@@ -498,8 +500,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
if (state->total_param) {
/* Can't use talloc here, the core routines do realloc on the
- * params and data. */
- state->param = (char *)SMB_MALLOC(state->total_param);
+ * params and data. Out of paranoia, 100 bytes too many */
+ state->param = (char *)SMB_MALLOC(state->total_param+100);
if (state->param == NULL) {
DEBUG(0,("reply_trans: param malloc fail for %u "
"bytes !\n", (unsigned int)state->total_param));
@@ -508,6 +510,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
END_PROFILE(SMBtrans);
return(ERROR_DOS(ERRDOS,ERRnomem));
}
+ /* null-terminate the slack space */
+ memset(&state->param[state->total_param], 0, 100);
if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
goto bad_param;
if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index 8ecc965c0d3..79aea8544f2 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
Inter-process communication and named pipe handling
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 2007.
SMB Version handling
Copyright (C) John H Terpstra 1995-1998
@@ -50,10 +51,13 @@ extern userdom_struct current_user_info;
#define SHPWLEN 8 /* share password length */
-static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data,
- int mdrcnt, int mprcnt,
- char **rdata, char **rparam,
- int *rdata_len, int *rparam_len);
+static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt, int mprcnt,
+ char **rdata, char **rparam,
+ int *rdata_len, int *rparam_len);
+
static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
int mdrcnt, int mprcnt,
char **rdata, char **rparam,
@@ -437,12 +441,18 @@ static int check_printq_info(struct pack_desc* desc,
desc->subformat = "z";
break;
default:
+ DEBUG(0,("check_printq_info: invalid level %d\n",
+ uLevel ));
return False;
}
- if (strcmp(desc->format,id1) != 0) {
+ if (id1 == NULL || strcmp(desc->format,id1) != 0) {
+ DEBUG(0,("check_printq_info: invalid format %s\n",
+ id1 ? id1 : "<NULL>" ));
return False;
}
- if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
+ if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
+ DEBUG(0,("check_printq_info: invalid subformat %s\n",
+ id2 ? id2 : "<NULL>" ));
return False;
}
return True;
@@ -585,7 +595,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
lp_servicename(snum)));
goto err;
}
-
+
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
"Windows 4.0", 0)) )
{
@@ -597,17 +607,17 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
-
+
PACKI(desc, "W", 0x0400); /* don't know */
PACKS(desc, "z", driver.info_3->name); /* long printer name */
PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
-
+
fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
standard_sub_basic( "", "", location, sizeof(location)-1 );
PACKS(desc,"z", location); /* share to retrieve files */
-
+
PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
@@ -627,12 +637,12 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
}
-
+
/* sanity check */
if ( i != count )
DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
count, i));
-
+
DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
desc->errcode=NERR_Success;
@@ -645,7 +655,7 @@ err:
done:
if ( printer )
free_a_printer( &printer, 2 );
-
+
if ( driver.info_3 )
free_a_printer_driver( driver, 3 );
}
@@ -743,7 +753,7 @@ static int get_printerdrivernumber(int snum)
lp_servicename(snum)));
goto done;
}
-
+
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
"Windows 4.0", 0)) )
{
@@ -751,7 +761,7 @@ static int get_printerdrivernumber(int snum)
printer->info_2->drivername));
goto done;
}
-
+
/* count the number of files */
while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
result++;
@@ -759,39 +769,47 @@ static int get_printerdrivernumber(int snum)
done:
if ( printer )
free_a_printer( &printer, 2 );
-
+
if ( driver.info_3 )
free_a_printer_driver( driver, 3 );
-
+
return result;
}
-static BOOL api_DosPrintQGetInfo(connection_struct *conn,
- uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
char *QueueName = p;
unsigned int uLevel;
int count=0;
int snum;
- char* str3;
+ char *str3;
struct pack_desc desc;
print_queue_struct *queue=NULL;
print_status_struct status;
char* tmpdata=NULL;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
memset((char *)&status,'\0',sizeof(status));
memset((char *)&desc,'\0',sizeof(desc));
-
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
- str3 = p + 4;
-
+
+ p = skip_string(param,tpscnt,p);
+ if (!p) {
+ return False;
+ }
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ str3 = get_safe_str_ptr(param,tpscnt,p,4);
+ /* str3 may be null here and is checked in check_printq_info(). */
+
/* remove any trailing username */
if ((p = strchr_m(QueueName,'%')))
*p = 0;
@@ -883,16 +901,18 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
View list of all print jobs on all queues.
****************************************************************************/
-static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
- int mdrcnt, int mprcnt,
- char **rdata, char** rparam,
- int *rdata_len, int *rparam_len)
+static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt, int mprcnt,
+ char **rdata, char** rparam,
+ int *rdata_len, int *rparam_len)
{
- char *param_format = param+2;
- char *output_format1 = skip_string(param_format,1);
- char *p = skip_string(output_format1,1);
- unsigned int uLevel = SVAL(p,0);
- char *output_format2 = p + 4;
+ char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
+ char *output_format1 = skip_string(param,tpscnt,param_format);
+ char *p = skip_string(param,tpscnt,output_format1);
+ unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
int services = lp_numservices();
int i, n;
struct pack_desc desc;
@@ -901,6 +921,10 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
int *subcntarr = NULL;
int queuecnt = 0, subcnt = 0, succnt = 0;
+ if (!param_format || !output_format1 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
@@ -1252,16 +1276,18 @@ static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
extracted from lists saved by nmbd on the local host.
****************************************************************************/
-static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
- int mdrcnt, int mprcnt, char **rdata,
- char **rparam, int *rdata_len, int *rparam_len)
+static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt, int mprcnt, char **rdata,
+ char **rparam, int *rdata_len, int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
- uint32 servertype = IVAL(p,4);
+ char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
+ int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
+ uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
char *p2;
int data_len, fixed_len, string_len;
int f_len = 0, s_len = 0;
@@ -1272,6 +1298,10 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
BOOL domain_request;
BOOL local_request;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
/* If someone sets all the bits they don't really mean to set
DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
known servers. */
@@ -1307,6 +1337,9 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
if (strcmp(str1, "WrLehDz") == 0) {
+ if (skip_string(param,tpscnt,p) == NULL) {
+ return False;
+ }
pull_ascii_fstring(domain, p);
} else {
fstrcpy(domain, lp_workgroup());
@@ -1399,18 +1432,24 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
command 0x34 - suspected of being a "Lookup Names" stub api
****************************************************************************/
-static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
- int mdrcnt, int mprcnt, char **rdata,
- char **rparam, int *rdata_len, int *rparam_len)
+static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt, int mprcnt, char **rdata,
+ char **rparam, int *rdata_len, int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
int counted=0;
int missed=0;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
str1, str2, p, uLevel, buf_len));
@@ -1582,18 +1621,25 @@ static int fill_share_info(connection_struct *conn, int snum, int uLevel,
return len;
}
-static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *netname = skip_string(str2,1);
- char *p = skip_string(netname,1);
- int uLevel = SVAL(p,0);
- int snum = find_service(netname);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *netname = skip_string(param,tpscnt,str2);
+ char *p = skip_string(param,tpscnt,netname);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ int snum;
+ if (!str1 || !str2 || !netname || !p) {
+ return False;
+ }
+
+ snum = find_service(netname);
if (snum < 0) {
return False;
}
@@ -1638,22 +1684,21 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
Share names longer than 12 bytes must be skipped.
****************************************************************************/
-static BOOL api_RNetShareEnum( connection_struct *conn,
- uint16 vuid,
- char *param,
- char *data,
- int mdrcnt,
- int mprcnt,
- char **rdata,
- char **rparam,
- int *rdata_len,
- int *rparam_len )
+static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,
+ int mprcnt,
+ char **rdata,
+ char **rparam,
+ int *rdata_len,
+ int *rparam_len )
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- int buf_len = SVAL(p,2);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
char *p2;
int count = 0;
int total=0,counted=0;
@@ -1662,6 +1707,10 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
int data_len, fixed_len, string_len;
int f_len = 0, s_len = 0;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
if (!prefix_ok(str1,"WrLeh")) {
return False;
}
@@ -1742,15 +1791,17 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
Add a share
****************************************************************************/
-static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
fstring sharename;
fstring comment;
pstring pathname;
@@ -1759,6 +1810,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
int snum;
int res = ERRunsup;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
/* check it's a supported varient */
if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
return False;
@@ -1770,6 +1825,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
return False;
}
+ /* Do we have a string ? */
+ if (skip_string(data,mdrcnt,data) == NULL) {
+ return False;
+ }
pull_ascii_fstring(sharename,data);
snum = find_service(sharename);
if (snum >= 0) { /* already exists */
@@ -1777,6 +1836,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
goto error_exit;
}
+ if (mdrcnt < 28) {
+ return False;
+ }
+
/* only support disk share adds */
if (SVAL(data,14)!=STYPE_DISKTREE) {
return False;
@@ -1788,6 +1851,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
goto error_exit;
}
+ /* Do we have a string ? */
+ if (skip_string(data,mdrcnt,data+offset) == NULL) {
+ return False;
+ }
pull_ascii_fstring(comment, offset? (data+offset) : "");
offset = IVAL(data, 26);
@@ -1797,6 +1864,10 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
goto error_exit;
}
+ /* Do we have a string ? */
+ if (skip_string(data,mdrcnt,data+offset) == NULL) {
+ return False;
+ }
pull_ascii_pstring(pathname, offset? (data+offset) : "");
string_replace(sharename, '"', ' ');
@@ -1857,23 +1928,29 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
view list of groups available
****************************************************************************/
-static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
int i;
int errflags=0;
int resume_context, cli_buf_size;
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
struct pdb_search *search;
struct samr_displayentry *entries;
int num_entries;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
if (strcmp(str1,"WrLeh") != 0) {
return False;
}
@@ -1900,8 +1977,8 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
return False;
}
- resume_context = SVAL(p,0);
- cli_buf_size=SVAL(p+2,0);
+ resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
+ cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
"%d\n", resume_context, cli_buf_size));
@@ -1957,16 +2034,18 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
Get groups that a user is a member of.
******************************************************************/
-static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *UserName = skip_string(str2,1);
- char *p = skip_string(UserName,1);
- int uLevel = SVAL(p,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *UserName = skip_string(param,tpscnt,str2);
+ char *p = skip_string(param,tpscnt,UserName);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
const char *level_string;
int count=0;
struct samu *sampw = NULL;
@@ -1980,6 +2059,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
enum lsa_SidType type;
TALLOC_CTX *mem_ctx;
+ if (!str1 || !str2 || !UserName || !p) {
+ return False;
+ }
+
*rparam_len = 8;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
if (!*rparam) {
@@ -2090,10 +2173,12 @@ done:
Get all users.
******************************************************************/
-static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
int count_sent=0;
int num_users=0;
@@ -2102,9 +2187,13 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
struct pdb_search *search;
struct samr_displayentry *users;
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
if (strcmp(str1,"WrLeh") != 0)
return False;
@@ -2116,8 +2205,8 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
* h -> return parameter total number of users
*/
- resume_context = SVAL(p,0);
- cli_buf_size=SVAL(p+2,0);
+ resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
+ cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
resume_context, cli_buf_size));
@@ -2188,10 +2277,12 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
Get the time of day info.
****************************************************************************/
-static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
struct tm *t;
time_t unixdate = time(NULL);
@@ -2244,21 +2335,46 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
Set the user password.
*****************************************************************************/
-static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *p = skip_string(param+2,2);
+ char *np = get_safe_str_ptr(param,tpscnt,param,2);
+ char *p = NULL;
fstring user;
fstring pass1,pass2;
+ /* Skip 2 strings. */
+ p = skip_string(param,tpscnt,np);
+ p = skip_string(param,tpscnt,p);
+
+ if (!np || !p) {
+ return False;
+ }
+
+ /* Do we have a string ? */
+ if (skip_string(param,tpscnt,p) == NULL) {
+ return False;
+ }
pull_ascii_fstring(user,p);
- p = skip_string(p,1);
+ p = skip_string(param,tpscnt,p);
+ if (!p) {
+ return False;
+ }
memset(pass1,'\0',sizeof(pass1));
memset(pass2,'\0',sizeof(pass2));
+ /*
+ * We use 31 here not 32 as we're checking
+ * the last byte we want to access is safe.
+ */
+ if (!is_offset_safe(param,tpscnt,p,31)) {
+ return False;
+ }
memcpy(pass1,p,16);
memcpy(pass2,p+16,16);
@@ -2330,19 +2446,24 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
Set the user password (SamOEM version - gets plaintext).
****************************************************************************/
-static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
fstring user;
- char *p = param + 2;
+ char *p = get_safe_str_ptr(param,tpscnt,param,2);
*rparam_len = 2;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
if (!*rparam) {
return False;
}
+ if (!p) {
+ return False;
+ }
*rdata_len = 0;
SSVAL(*rparam,0,NERR_badpass);
@@ -2351,17 +2472,35 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
* Check the parameter definition is correct.
*/
- if(!strequal(param + 2, "zsT")) {
- DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
+ /* Do we have a string ? */
+ if (skip_string(param,tpscnt,p) == 0) {
+ return False;
+ }
+ if(!strequal(p, "zsT")) {
+ DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
+ return False;
+ }
+ p = skip_string(param, tpscnt, p);
+ if (!p) {
return False;
}
- p = skip_string(p, 1);
+ /* Do we have a string ? */
+ if (skip_string(param,tpscnt,p) == 0) {
+ return False;
+ }
if(!strequal(p, "B516B16")) {
DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
return False;
}
- p = skip_string(p,1);
+ p = skip_string(param,tpscnt,p);
+ if (!p) {
+ return False;
+ }
+ /* Do we have a string ? */
+ if (skip_string(param,tpscnt,p) == 0) {
+ return False;
+ }
p += pull_ascii_fstring(user,p);
DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
@@ -2385,21 +2524,33 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
Form: <W> <>
****************************************************************************/
-static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- int function = SVAL(param,0);
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ int function = get_safe_SVAL(param,tpscnt,param,0,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
uint32 jobid;
int snum;
fstring sharename;
int errcode;
WERROR werr = WERR_OK;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+ /*
+ * We use 1 here not 2 as we're checking
+ * the last byte we want to access is safe.
+ */
+ if (!is_offset_safe(param,tpscnt,p,1)) {
+ return False;
+ }
if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
return False;
@@ -2456,19 +2607,25 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
Purge a print queue - or pause or resume it.
****************************************************************************/
-static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- int function = SVAL(param,0);
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *QueueName = skip_string(str2,1);
+ int function = get_safe_SVAL(param,tpscnt,param,0,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *QueueName = skip_string(param,tpscnt,str2);
int errcode = NERR_notsupported;
int snum;
WERROR werr = WERR_OK;
+ if (!str1 || !str2 || !QueueName) {
+ return False;
+ }
+
/* check it's a supported varient */
if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
return(False);
@@ -2480,6 +2637,9 @@ static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param
}
*rdata_len = 0;
+ if (skip_string(param,tpscnt,QueueName) == NULL) {
+ return False;
+ }
snum = print_queue_snum(QueueName);
if (snum == -1) {
@@ -2526,27 +2686,46 @@ static int check_printjob_info(struct pack_desc* desc,
case 2: desc->format = "WWzWWDDzz"; break;
case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
- default: return False;
+ default:
+ DEBUG(0,("check_printjob_info: invalid level %d\n",
+ uLevel ));
+ return False;
+ }
+ if (id == NULL || strcmp(desc->format,id) != 0) {
+ DEBUG(0,("check_printjob_info: invalid format %s\n",
+ id ? id : "<NULL>" ));
+ return False;
}
- if (strcmp(desc->format,id) != 0) return False;
return True;
}
-static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
struct pack_desc desc;
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
uint32 jobid;
fstring sharename;
- int uLevel = SVAL(p,2);
- int function = SVAL(p,4);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
+ int function = get_safe_SVAL(param,tpscnt,p,4,-1);
int place, errcode;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+ /*
+ * We use 1 here not 2 as we're checking
+ * the last byte we want to access is safe.
+ */
+ if (!is_offset_safe(param,tpscnt,p,1)) {
+ return False;
+ }
if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
return False;
*rparam_len = 4;
@@ -2608,18 +2787,24 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
Get info about the server.
****************************************************************************/
-static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
char *p2;
int struct_len;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
/* check it's a supported varient */
@@ -2714,7 +2899,10 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
current_user_info.domain,
comment, sizeof(comment));
StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
}
}
@@ -2740,16 +2928,22 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
Get info about the server.
****************************************************************************/
-static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
char *p2;
- int level = SVAL(p,0);
+ int level = get_safe_SVAL(param,tpscnt,p,0,-1);
+
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
DEBUG(4,("NetWkstaGetInfo level %d\n",level));
@@ -2774,23 +2968,35 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVAL(*rparam,2,0); /* converter word */
p = *rdata;
- p2 = p + 22;
+ p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
pstrcpy(p2,get_local_machine_name());
strupper_m(p2);
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
pstrcpy(p2,current_user_info.smb_name);
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
pstrcpy(p2,lp_workgroup());
strupper_m(p2);
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
p += 4;
SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
@@ -2799,12 +3005,18 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
SIVAL(p,0,PTR_DIFF(p2,*rdata));
pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
pstrcpy(p2,"");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
p += 4;
*rdata_len = PTR_DIFF(p2,*rdata);
@@ -2984,16 +3196,18 @@ There is no auxiliary data in the response.
#define AF_OP_ACCOUNTS 3
-static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *UserName = skip_string(str2,1);
- char *p = skip_string(UserName,1);
- int uLevel = SVAL(p,0);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *UserName = skip_string(param,tpscnt,str2);
+ char *p = skip_string(param,tpscnt,UserName);
+ int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
char *p2;
const char *level_string;
@@ -3006,6 +3220,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
vuser->user.unix_name));
}
+ if (!str1 || !str2 || !UserName || !p) {
+ return False;
+ }
+
*rparam_len = 6;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
if (!*rparam) {
@@ -3041,7 +3259,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVAL(*rparam,2,0); /* converter word */
p = *rdata;
- p2 = p + usri11_end;
+ p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
+ if (!p2) {
+ return False;
+ }
memset(p,0,21);
fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
@@ -3054,16 +3275,25 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
if (uLevel >= 10) {
SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
pstrcpy(p2,"Comment");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
pstrcpy(p2,"UserComment");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
/* EEK! the cifsrap.txt doesn't have this in!!!! */
SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
}
if (uLevel == 11) {
@@ -3073,22 +3303,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SIVALS(p,usri11_password_age,-1); /* password age */
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
pstrcpy(p2,"");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,usri11_last_logon,0); /* last logon */
SIVAL(p,usri11_last_logoff,0); /* last logoff */
SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
SSVALS(p,usri11_num_logons,-1); /* num logons */
SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
pstrcpy(p2,"\\\\*");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SSVAL(p,usri11_country_code,0); /* country code */
SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
pstrcpy(p2,"");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVALS(p,usri11_max_storage,-1); /* max storage */
SSVAL(p,usri11_units_per_week,168); /* units per week */
@@ -3097,7 +3339,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
/* a simple way to get logon hours at all times. */
memset(p2,0xff,21);
SCVAL(p2,21,0); /* fix zero termination */
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SSVAL(p,usri11_code_page,0); /* code page */
}
@@ -3109,22 +3354,34 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
*p2++ = 0;
SSVAL(p,52,0); /* flags */
SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
if (uLevel == 2) {
SIVAL(p,60,0); /* auth_flags */
SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,68,0); /* urs_comment */
SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
pstrcpy(p2,"");
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SIVAL(p,76,0); /* workstations */
SIVAL(p,80,0); /* last_logon */
SIVAL(p,84,0); /* last_logoff */
@@ -3143,7 +3400,10 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
standard_sub_basic("", "", tmp, sizeof(tmp));
pstrcpy(p2, tmp);
}
- p2 = skip_string(p2,1);
+ p2 = skip_string(*rdata,*rdata_len,p2);
+ if (!p2) {
+ return False;
+ }
SSVAL(p,110,49); /* country_code */
SSVAL(p,112,860); /* code page */
}
@@ -3156,14 +3416,16 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
return(True);
}
-static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
struct pack_desc desc;
char* name;
@@ -3171,13 +3433,20 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
Don't depend on vuser being non-null !!. JRA */
user_struct *vuser = get_valid_user_struct(vuid);
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
if(vuser != NULL) {
DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
vuser->user.unix_name));
}
- uLevel = SVAL(p,0);
- name = p + 2;
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
+ name = get_safe_str_ptr(param,tpscnt,p,2);
+ if (!name) {
+ return False;
+ }
memset((char *)&desc,'\0',sizeof(desc));
@@ -3250,16 +3519,25 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
api_WAccessGetUserPerms
****************************************************************************/
-static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *user = skip_string(str2,1);
- char *resource = skip_string(user,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *user = skip_string(param,tpscnt,str2);
+ char *resource = skip_string(param,tpscnt,user);
+ if (!str1 || !str2 || !user || !resource) {
+ return False;
+ }
+
+ if (skip_string(param,tpscnt,resource) == NULL) {
+ return False;
+ }
DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
/* check it's a supported varient */
@@ -3286,14 +3564,16 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p
api_WPrintJobEnumerate
****************************************************************************/
-static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
int count;
int i;
@@ -3305,7 +3585,11 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
print_status_struct status;
char *tmpdata=NULL;
- uLevel = SVAL(p,2);
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
+ uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
memset((char *)&desc,'\0',sizeof(desc));
memset((char *)&status,'\0',sizeof(status));
@@ -3379,15 +3663,17 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
return True;
}
-static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
- char* name = p;
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
+ char *name = p;
int uLevel;
int count;
int i, succnt=0;
@@ -3396,11 +3682,18 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
print_queue_struct *queue=NULL;
print_status_struct status;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
memset((char *)&status,'\0',sizeof(status));
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
+ p = skip_string(param,tpscnt,p);
+ if (!p) {
+ return False;
+ }
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
@@ -3479,9 +3772,13 @@ static int check_printdest_info(struct pack_desc* desc,
desc->format = "zzzWWzzzWW";
break;
default:
+ DEBUG(0,("check_printdest_info: invalid level %d\n",
+ uLevel));
return False;
}
- if (strcmp(desc->format,id) != 0) {
+ if (id == NULL || strcmp(desc->format,id) != 0) {
+ DEBUG(0,("check_printdest_info: invalid string %s\n",
+ id ? id : "<NULL>" ));
return False;
}
return True;
@@ -3523,24 +3820,33 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
}
}
-static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
char* PrinterName = p;
int uLevel;
struct pack_desc desc;
int snum;
char *tmpdata=NULL;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
- p = skip_string(p,1);
- uLevel = SVAL(p,0);
+ p = skip_string(param,tpscnt,p);
+ if (!p) {
+ return False;
+ }
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
@@ -3594,23 +3900,29 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
return True;
}
-static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
int queuecnt;
int i, n, succnt=0;
struct pack_desc desc;
int services = lp_numservices();
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
@@ -3669,21 +3981,27 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
return True;
}
-static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
int succnt;
struct pack_desc desc;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
@@ -3726,21 +4044,26 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
return True;
}
-static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
+static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
int succnt;
struct pack_desc desc;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
@@ -3784,21 +4107,27 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
return True;
}
-static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
int succnt;
struct pack_desc desc;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
@@ -3843,27 +4172,33 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
return True;
}
-
/****************************************************************************
List open sessions
****************************************************************************/
-static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+
+static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
+ char *str2 = skip_string(param,tpscnt,str1);
+ char *p = skip_string(param,tpscnt,str2);
int uLevel;
struct pack_desc desc;
struct sessionid *session_list;
int i, num_sessions;
+ if (!str1 || !str2 || !p) {
+ return False;
+ }
+
memset((char *)&desc,'\0',sizeof(desc));
- uLevel = SVAL(p,0);
+ uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
@@ -3950,10 +4285,12 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char
The request is not supported.
****************************************************************************/
-static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
- int mdrcnt, int mprcnt,
- char **rdata, char **rparam,
- int *rdata_len, int *rparam_len)
+static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
+ char *param, int tpscnt,
+ char *data, int tdscnt,
+ int mdrcnt, int mprcnt,
+ char **rdata, char **rparam,
+ int *rdata_len, int *rparam_len)
{
*rparam_len = 4;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
@@ -3974,7 +4311,9 @@ static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, c
static const struct {
const char *name;
int id;
- BOOL (*fn)(connection_struct *,uint16,char *,char *,
+ BOOL (*fn)(connection_struct *, uint16,
+ char *, int,
+ char *, int,
int,int,char **,char **,int *,int *);
BOOL auth_user; /* Deny anonymous access? */
} api_commands[] = {
@@ -4029,6 +4368,8 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
int api_command;
char *rdata = NULL;
char *rparam = NULL;
+ const char *name1 = NULL;
+ const char *name2 = NULL;
int rdata_len = 0;
int rparam_len = 0;
BOOL reply=False;
@@ -4039,12 +4380,25 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
return 0;
}
+ if (tpscnt < 2) {
+ return 0;
+ }
api_command = SVAL(params,0);
+ /* Is there a string at position params+2 ? */
+ if (skip_string(params,tpscnt,params+2)) {
+ name1 = params + 2;
+ } else {
+ name1 = "";
+ }
+ name2 = skip_string(params,tpscnt,params+2);
+ if (!name2) {
+ name2 = "";
+ }
DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
api_command,
- params+2,
- skip_string(params+2,1),
+ name1,
+ name2,
tdscnt,tpscnt,mdrcnt,mprcnt));
for (i=0;api_commands[i].name;i++) {
@@ -4081,7 +4435,11 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
return -1;
}
- reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
+ reply = api_commands[i].fn(conn,
+ vuid,
+ params,tpscnt, /* params + length */
+ data,tdscnt, /* data + length */
+ mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
@@ -4092,7 +4450,7 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
/* if we get False back then it's actually unsupported */
if (!reply) {
- reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
+ reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
}
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index 284061331bf..6fa81ddc29b 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -170,7 +170,7 @@ static NTSTATUS parse_dfs_path(const char *pathname,
Note this CHANGES CWD !!!! JRA.
*********************************************************/
-static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path)
+static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char *path)
{
pstring connpath;
@@ -183,12 +183,12 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa
if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) {
DEBUG(0,("talloc_init(connection_struct) failed!\n"));
- return False;
+ return NT_STATUS_NO_MEMORY;
}
if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) {
DEBUG(0, ("TALLOC failed\n"));
- return False;
+ return NT_STATUS_NO_MEMORY;
}
conn->params->service = snum;
@@ -196,9 +196,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa
set_conn_connectpath(conn, connpath);
if (!smbd_vfs_init(conn)) {
+ NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n"));
conn_free_internal(conn);
- return False;
+ return status;
}
/*
@@ -208,13 +209,14 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa
*/
if (vfs_ChDir(conn,conn->connectpath) != 0) {
+ NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n",
conn->connectpath, strerror(errno) ));
conn_free_internal(conn);
- return False;
+ return status;
}
- return True;
+ return NT_STATUS_OK;
}
/**********************************************************************
@@ -249,6 +251,10 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx,
pstrcpy(temp,target);
prot = strtok(temp,":");
+ if (!prot) {
+ DEBUG(0,("parse_msdfs_symlink: invalid path !\n"));
+ return False;
+ }
/* parse out the alternate paths */
while((count<MAX_REFERRAL_COUNT) &&
@@ -538,7 +544,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn,
Return a self referral.
**********************************************************************/
-static BOOL self_ref(TALLOC_CTX *ctx,
+static NTSTATUS self_ref(TALLOC_CTX *ctx,
const char *dfs_path,
struct junction_map *jucn,
int *consumedcntp,
@@ -551,7 +557,7 @@ static BOOL self_ref(TALLOC_CTX *ctx,
jucn->referral_count = 1;
if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
DEBUG(0,("self_ref: talloc failed for referral\n"));
- return False;
+ return NT_STATUS_NO_MEMORY;
}
pstrcpy(ref->alternate_path,dfs_path);
@@ -559,7 +565,7 @@ static BOOL self_ref(TALLOC_CTX *ctx,
ref->ttl = REFERRAL_TTL;
jucn->referral_list = ref;
*consumedcntp = strlen(dfs_path);
- return True;
+ return NT_STATUS_OK;
}
/**********************************************************************
@@ -567,7 +573,7 @@ static BOOL self_ref(TALLOC_CTX *ctx,
junction_map structure.
**********************************************************************/
-BOOL get_referred_path(TALLOC_CTX *ctx,
+NTSTATUS get_referred_path(TALLOC_CTX *ctx,
const char *dfs_path,
struct junction_map *jucn,
int *consumedcntp,
@@ -579,8 +585,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
pstring conn_path;
pstring targetpath;
int snum;
- NTSTATUS status;
- BOOL ret = False;
+ NTSTATUS status = NT_STATUS_NOT_FOUND;
BOOL dummy;
ZERO_STRUCT(conns);
@@ -589,14 +594,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
status = parse_dfs_path(dfs_path, False, &dp, &dummy);
if (!NT_STATUS_IS_OK(status)) {
- return False;
+ return status;
}
/* Verify hostname in path */
if (!is_myname_or_ipaddr(dp.hostname)) {
DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n",
dp.hostname, dfs_path));
- return False;
+ return NT_STATUS_NOT_FOUND;
}
fstrcpy(jucn->service_name, dp.servicename);
@@ -606,14 +611,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
snum = lp_servicenumber(jucn->service_name);
if(snum < 0) {
if ((snum = find_service(jucn->service_name)) < 0) {
- return False;
+ return NT_STATUS_NOT_FOUND;
}
}
if (!lp_msdfs_root(snum)) {
DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n",
dp.servicename, dfs_path));
- goto out;
+ return NT_STATUS_NOT_FOUND;
}
/*
@@ -642,7 +647,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
jucn->referral_count = 1;
if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
DEBUG(0, ("malloc failed for referral\n"));
- goto out;
+ return NT_STATUS_NO_MEMORY;
}
pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum));
@@ -653,13 +658,13 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
ref->ttl = REFERRAL_TTL;
jucn->referral_list = ref;
*consumedcntp = strlen(dfs_path);
- ret = True;
- goto out;
+ return NT_STATUS_OK;
}
pstrcpy(conn_path, lp_pathname(snum));
- if (!create_conn_struct(conn, snum, conn_path)) {
- return False;
+ status = create_conn_struct(conn, snum, conn_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* If this is a DFS path dfs_lookup should return
@@ -671,7 +676,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
DEBUG(3,("get_referred_path: No valid referrals for path %s\n",
dfs_path));
- goto out;
+ conn_free_internal(conn);
+ return status;
}
/* We know this is a valid dfs link. Parse the targetpath. */
@@ -680,15 +686,12 @@ BOOL get_referred_path(TALLOC_CTX *ctx,
&jucn->referral_count)) {
DEBUG(3,("get_referred_path: failed to parse symlink "
"target %s\n", targetpath ));
- goto out;
+ conn_free_internal(conn);
+ return NT_STATUS_NOT_FOUND;
}
- ret = True;
-
-out:
-
conn_free_internal(conn);
- return ret;
+ return NT_STATUS_OK;
}
static int setup_ver2_dfs_referral(const char *pathname,
@@ -886,7 +889,7 @@ static int setup_ver3_dfs_referral(const char *pathname,
int setup_dfs_referral(connection_struct *orig_conn,
const char *dfs_path,
int max_referral_level,
- char **ppdata)
+ char **ppdata, NTSTATUS *pstatus)
{
struct junction_map junction;
int consumedcnt = 0;
@@ -897,6 +900,7 @@ int setup_dfs_referral(connection_struct *orig_conn,
TALLOC_CTX *ctx;
if (!(ctx=talloc_init("setup_dfs_referral"))) {
+ *pstatus = NT_STATUS_NO_MEMORY;
return -1;
}
@@ -905,6 +909,7 @@ int setup_dfs_referral(connection_struct *orig_conn,
/* get the junction entry */
if (!dfs_path) {
talloc_destroy(ctx);
+ *pstatus = NT_STATUS_NOT_FOUND;
return -1;
}
@@ -920,7 +925,8 @@ int setup_dfs_referral(connection_struct *orig_conn,
}
/* The following call can change cwd. */
- if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) {
+ *pstatus = get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral);
+ if (!NT_STATUS_IS_OK(*pstatus)) {
vfs_ChDir(orig_conn,orig_conn->connectpath);
talloc_destroy(ctx);
return -1;
@@ -961,6 +967,7 @@ int setup_dfs_referral(connection_struct *orig_conn,
default:
DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level));
talloc_destroy(ctx);
+ *pstatus = NT_STATUS_INVALID_LEVEL;
return -1;
}
@@ -970,6 +977,7 @@ int setup_dfs_referral(connection_struct *orig_conn,
}
talloc_destroy(ctx);
+ *pstatus = NT_STATUS_OK;
return reply_size;
}
@@ -1037,7 +1045,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn,
safe_strcat(path, jucn->volume_name, max_pathlen-1);
pstrcpy(conn_path, lp_pathname(snum));
- if (!create_conn_struct(conn_out, snum, conn_path)) {
+ if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) {
return False;
}
@@ -1156,7 +1164,7 @@ static int form_junctions(TALLOC_CTX *ctx,
* Fake up a connection struct for the VFS layer.
*/
- if (!create_conn_struct(&conn, snum, connect_path)) {
+ if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) {
return 0;
}
@@ -1252,7 +1260,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na
{
NTSTATUS status = NT_STATUS_OK;
BOOL dummy;
- if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+ if (dfs_pathnames) {
status = dfs_redirect(conn, name, False, &dummy);
}
return status;
@@ -1268,7 +1276,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na
NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard)
{
NTSTATUS status = NT_STATUS_OK;
- if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+ if (dfs_pathnames) {
status = dfs_redirect(conn, name, True, ppath_contains_wcard);
}
return status;
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 2a49e1f4a64..fe2cb05bf3e 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -374,6 +374,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
int ret;
int pnum = -1;
char *p = NULL;
+ uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
@@ -385,7 +386,17 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
* Deal with pipe return.
*/
- set_message(outbuf,34,0,True);
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ /* This is very strange. We
+ * return 50 words, but only set
+ * the wcnt to 42 ? It's definately
+ * what happens on the wire....
+ */
+ set_message(outbuf,50,0,True);
+ SCVAL(outbuf,smb_wct,42);
+ } else {
+ set_message(outbuf,34,0,True);
+ }
p = outbuf + smb_vwv2;
p++;
@@ -400,6 +411,18 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
/* Device state. */
SSVAL(p,2, 0x5FF); /* ? */
+ p += 4;
+
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ p += 26;
+ SIVAL(p,0,FILE_GENERIC_ALL);
+ /*
+ * For pipes W2K3 seems to return
+ * 0x12019B next.
+ * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
+ */
+ SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
+ }
DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
@@ -847,13 +870,18 @@ int reply_ntcreate_and_X(connection_struct *conn,
extended_oplock_granted = True;
}
-#if 0
- /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */
- set_message(outbuf,42,0,True);
-#else
- set_message(outbuf,34,0,True);
-#endif
-
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ /* This is very strange. We
+ * return 50 words, but only set
+ * the wcnt to 42 ? It's definately
+ * what happens on the wire....
+ */
+ set_message(outbuf,50,0,True);
+ SCVAL(outbuf,smb_wct,42);
+ } else {
+ set_message(outbuf,34,0,True);
+ }
+
p = outbuf + smb_vwv2;
/*
@@ -914,6 +942,17 @@ int reply_ntcreate_and_X(connection_struct *conn,
p += 4;
SCVAL(p,0,fsp->is_directory ? 1 : 0);
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ uint32 perms = 0;
+ p += 26;
+ if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) {
+ perms = FILE_GENERIC_ALL;
+ } else {
+ perms = FILE_GENERIC_READ|FILE_EXECUTE;
+ }
+ SIVAL(p,0,perms);
+ }
+
DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
result = chain_reply(inbuf,outbuf,length,bufsize);
@@ -936,6 +975,8 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
int pnum = -1;
char *p = NULL;
NTSTATUS status;
+ size_t param_len;
+ uint32 flags;
/*
* Ensure minimum number of parameters sent.
@@ -946,6 +987,8 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
+ flags = IVAL(params,0);
+
srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
@@ -956,7 +999,13 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
}
/* Realloc the size of parameters and data we will return */
- params = nttrans_realloc(ppparams, 69);
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ /* Extended response is 32 more byyes. */
+ param_len = 101;
+ } else {
+ param_len = 69;
+ }
+ params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
return ERROR_DOS(ERRDOS,ERRnomem);
}
@@ -977,11 +1026,23 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
/* Device state. */
SSVAL(p,2, 0x5FF); /* ? */
+ p += 4;
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ p += 26;
+ SIVAL(p,0,FILE_GENERIC_ALL);
+ /*
+ * For pipes W2K3 seems to return
+ * 0x12019B next.
+ * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
+ */
+ SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
+ }
+
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
return -1;
}
@@ -1126,6 +1187,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
TALLOC_CTX *ctx = NULL;
char *pdata = NULL;
NTSTATUS status;
+ size_t param_len;
DEBUG(5,("call_nt_transact_create\n"));
@@ -1496,7 +1558,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
/* Realloc the size of parameters and data we will return */
- params = nttrans_realloc(ppparams, 69);
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ /* Extended response is 32 more byyes. */
+ param_len = 101;
+ } else {
+ param_len = 69;
+ }
+ params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
return ERROR_DOS(ERRDOS,ERRnomem);
}
@@ -1555,10 +1623,21 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
p += 4;
SCVAL(p,0,fsp->is_directory ? 1 : 0);
+ if (flags & EXTENDED_RESPONSE_REQUIRED) {
+ uint32 perms = 0;
+ p += 26;
+ if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) {
+ perms = FILE_GENERIC_ALL;
+ } else {
+ perms = FILE_GENERIC_READ|FILE_EXECUTE;
+ }
+ SIVAL(p,0,perms);
+ }
+
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
return -1;
}
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index bb88957731f..ddfcb8e0f86 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -238,7 +238,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if (!found)
return(False);
- become_root_uid_only();
+ become_root();
if (strcmp(mnt->mnt_type, "xfs")==0) {
r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
@@ -251,7 +251,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
}
- unbecome_root_uid_only();
+ unbecome_root();
/* Use softlimit to determine disk space, except when it has been exceeded */
*bsize = D.bsize;
@@ -655,20 +655,20 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
if ( ! found )
return(False) ;
- become_root_uid_only();
+ become_root();
#if defined(SUNOS5)
if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
BOOL retval;
DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
- unbecome_root_uid_only();
+ unbecome();
return retval;
}
DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
if((file=sys_open(name, O_RDONLY,0))<0) {
- unbecome_root_uid_only();
+ unbecome_root();
return(False);
}
command.op = Q_GETQUOTA;
@@ -681,7 +681,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif
- unbecome_root_uid_only();
+ unbecome_root();
if (ret < 0) {
DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
@@ -841,7 +841,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
euser_id=geteuid();
- become_root_uid_only();
+ become_root();
/* Use softlimit to determine disk space, except when it has been exceeded */
@@ -851,7 +851,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
{
r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
- unbecome_root_uid_only();
+ unbecome_root();
if (r==-1)
return(False);
@@ -882,7 +882,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
{
r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
- unbecome_root_uid_only();
+ unbecome_root();
if (r==-1)
{
@@ -916,7 +916,7 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
}
else
{
- unbecome_root_uid_only();
+ unbecome_root();
return(False);
}
@@ -936,6 +936,10 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
#define dqb_curfiles dqb_curinodes
#define dqb_fhardlimit dqb_ihardlimit
#define dqb_fsoftlimit dqb_isoftlimit
+#ifdef _AIXVERSION_530
+#include <sys/statfs.h>
+#include <sys/vmount.h>
+#endif /* AIX 5.3 */
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
#include <sys/quota.h>
#include <devnm.h>
@@ -1180,13 +1184,13 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
return False;
#endif
- become_root_uid_only();
+ become_root();
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
BOOL retval;
retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
- unbecome_root_uid_only();
+ unbecome_root();
return retval;
}
#endif
@@ -1200,16 +1204,42 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
}
- unbecome_root_uid_only();
+ unbecome_root();
}
#elif defined(AIX)
/* AIX has both USER and GROUP quotas:
Get the USER quota (ohnielse@fysik.dtu.dk) */
+#ifdef _AIXVERSION_530
+ {
+ struct statfs statbuf;
+ quota64_t user_quota;
+ if (statfs(path,&statbuf) != 0)
+ return False;
+ if(statbuf.f_vfstype == MNT_J2)
+ {
+ /* For some reason we need to be root for jfs2 */
+ become_root();
+ r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
+ unbecome_root();
+ /* Copy results to old struct to let the following code work as before */
+ D.dqb_curblocks = user_quota.bused;
+ D.dqb_bsoftlimit = user_quota.bsoft;
+ D.dqb_bhardlimit = user_quota.bhard;
+ }
+ else if(statbuf.f_vfstype == MNT_JFS)
+ {
+#endif /* AIX 5.3 */
save_re_uid();
if (set_re_uid() != 0)
return False;
r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
restore_re_uid();
+#ifdef _AIXVERSION_530
+ }
+ else
+ r = 1; /* Fail for other FS-types */
+ }
+#endif /* AIX 5.3 */
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 14b16e1ae23..98d72ba742b 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -451,6 +451,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *p, *q;
+ uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
START_PROFILE(SMBtconX);
@@ -521,7 +522,27 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
/* NT sets the fstype of IPC$ to the null string */
const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
- set_message(outbuf,3,0,True);
+ if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
+ /* Return permissions. */
+ uint32 perm1 = 0;
+ uint32 perm2 = 0;
+
+ set_message(outbuf,7,0,True);
+
+ if (IS_IPC(conn)) {
+ perm1 = FILE_ALL_ACCESS;
+ perm2 = FILE_ALL_ACCESS;
+ } else {
+ perm1 = CAN_WRITE(conn) ?
+ SHARE_ALL_ACCESS :
+ SHARE_READ_ONLY;
+ }
+
+ SIVAL(outbuf, smb_vwv3, perm1);
+ SIVAL(outbuf, smb_vwv5, perm2);
+ } else {
+ set_message(outbuf,3,0,True);
+ }
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
diff --git a/source/smbd/service.c b/source/smbd/service.c
index b38a4c869c8..bfe9649ea4a 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -814,10 +814,28 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*/
{
+ BOOL can_write = False;
NT_USER_TOKEN *token = conn->nt_user_token ?
- conn->nt_user_token : vuser->nt_user_token;
+ conn->nt_user_token :
+ (vuser ? vuser->nt_user_token : NULL);
+
+ /*
+ * I don't believe this can happen. But the
+ * logic above is convoluted enough to confuse
+ * automated checkers, so be sure. JRA.
+ */
+
+ if (token == NULL) {
+ DEBUG(0,("make_connection: connection to %s "
+ "denied due to missing "
+ "NT token.\n",
+ lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
- BOOL can_write = share_access_check(token,
+ can_write = share_access_check(token,
lp_servicename(snum),
FILE_WRITE_DATA);
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index ff1b2821cca..05a5962056c 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -1060,6 +1060,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
native_os, native_lanman, primary_domain));
if ( ra_type == RA_WIN2K ) {
+ /* Vista sets neither the OS or lanman strings */
+
+ if ( !strlen(native_os) && !strlen(native_lanman) )
+ set_remote_arch(RA_VISTA);
+
/* Windows 2003 doesn't set the native lanman string,
but does set primary domain which is a bug I think */
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index deb5db1bafe..5efad04b550 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -1601,13 +1601,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
p = store_file_unix_basic(conn, p,
NULL, &sbuf);
+ len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
} else {
DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
p = store_file_unix_basic_info2(conn, p,
NULL, &sbuf);
+ nameptr = p;
+ p += 4;
+ len = srvstr_push(outbuf, p, fname, -1, 0);
+ SIVAL(nameptr, 0, len);
}
- len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
p += len;
SIVAL(p,0,0); /* Ensure any padding is null. */
@@ -5295,17 +5299,20 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
SIVAL(pdata,4,info); /* Was directory created. */
switch (info_level_return) {
- case SMB_QUERY_FILE_UNIX_BASIC:
- SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,10,0); /* Padding. */
- store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
- case SMB_QUERY_FILE_UNIX_INFO2:
- SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
- SSVAL(pdata,10,0); /* Padding. */
- store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
- default:
- SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,10,0); /* Padding. */
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ break;
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ break;
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* Padding. */
+ break;
}
return status;
@@ -5479,17 +5486,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
SIVAL(pdata,4,info); /* Was file created etc. */
switch (info_level_return) {
- case SMB_QUERY_FILE_UNIX_BASIC:
- SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,10,0); /* padding. */
- store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
- case SMB_QUERY_FILE_UNIX_INFO2:
- SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
- SSVAL(pdata,10,0); /* padding. */
- store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
- default:
- SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,10,0); /* padding. */
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ break;
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ break;
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* padding. */
+ break;
}
return NT_STATUS_OK;
}
@@ -6153,6 +6163,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
pstring pathname;
int reply_size = 0;
int max_referral_level;
+ NTSTATUS status = NT_STATUS_OK;
DEBUG(10,("call_trans2getdfsreferral\n"));
@@ -6166,8 +6177,8 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
return ERROR_DOS(ERRDOS,ERRbadfunc);
srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
- if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
- return UNIXERROR(ERRDOS,ERRbadfile);
+ if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
+ return ERROR_NT(status);
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 82ea602187c..0803ffb7e70 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -174,7 +174,7 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
/* If this operation was already made opaque by different module, it
- * will be overridded here.
+ * will be overridden here.
*/
DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op);