summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/blocking.c2
-rw-r--r--source3/smbd/change_trust_pw.c5
-rw-r--r--source3/smbd/chgpasswd.c113
-rw-r--r--source3/smbd/fileio.c22
-rw-r--r--source3/smbd/filename.c4
-rw-r--r--source3/smbd/files.c28
-rw-r--r--source3/smbd/lanman.c131
-rw-r--r--source3/smbd/mangle_hash2.c49
-rw-r--r--source3/smbd/message.c2
-rw-r--r--source3/smbd/notify.c2
-rw-r--r--source3/smbd/nttrans.c189
-rw-r--r--source3/smbd/open.c13
-rw-r--r--source3/smbd/password.c5
-rw-r--r--source3/smbd/process.c17
-rw-r--r--source3/smbd/reply.c307
-rw-r--r--source3/smbd/sec_ctx.c2
-rw-r--r--source3/smbd/server.c2
-rw-r--r--source3/smbd/service.c9
-rw-r--r--source3/smbd/sesssetup.c22
-rw-r--r--source3/smbd/statcache.c15
-rw-r--r--source3/smbd/trans2.c253
-rw-r--r--source3/smbd/uid.c465
-rw-r--r--source3/smbd/utmp.c10
-rw-r--r--source3/smbd/vfs-wrap.c66
-rw-r--r--source3/smbd/vfs.c6
25 files changed, 914 insertions, 825 deletions
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index fed3a51b88..8fa2a6494e 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -148,7 +148,7 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout,
blr->fsp->fnum, blr->fsp->fsp_name ));
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(inbuf,smb_mid), True);
return True;
}
diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c
index 2eff77b1f7..80c9fcb258 100644
--- a/source3/smbd/change_trust_pw.c
+++ b/source3/smbd/change_trust_pw.c
@@ -35,6 +35,9 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
fstring dc_name;
struct cli_state *cli;
+ DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n",
+ domain));
+
if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
/* Use the PDC *only* for this */
@@ -92,6 +95,8 @@ failed:
DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n",
timestring(False), domain));
}
+ else
+ DEBUG(5,("change_trust_account_password: sucess!\n"));
return nt_status;
}
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index 6bc8626d81..d99570ff7c 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -259,7 +259,7 @@ static int expect(int master, char *issue, char *expected)
/* Eat leading/trailing whitespace before match. */
pstring str;
pstrcpy( str, buffer);
- trim_string( str, " ", " ");
+ trim_char( str, ' ', ' ');
if ((match = (unix_wild_match(expected, str) == 0)))
timeout = 200;
@@ -333,19 +333,14 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass,
int wstat;
BOOL chstat = False;
- if (pass == NULL)
- {
- DEBUG(0,
- ("chat_with_program: user doesn't exist in the UNIX password database.\n"));
+ if (pass == NULL) {
+ DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n"));
return False;
}
/* allocate a pseudo-terminal device */
- if ((master = findpty(&slavedev)) < 0)
- {
- DEBUG(3,
- ("Cannot Allocate pty for password change: %s\n",
- pass->pw_name));
+ if ((master = findpty(&slavedev)) < 0) {
+ DEBUG(3, ("Cannot Allocate pty for password change: %s\n", pass->pw_name));
return (False);
}
@@ -356,39 +351,29 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass,
CatchChildLeaveStatus();
- if ((pid = sys_fork()) < 0)
- {
- DEBUG(3,
- ("Cannot fork() child for password change: %s\n",
- pass->pw_name));
+ if ((pid = sys_fork()) < 0) {
+ DEBUG(3, ("Cannot fork() child for password change: %s\n", pass->pw_name));
close(master);
CatchChild();
return (False);
}
/* we now have a pty */
- if (pid > 0)
- { /* This is the parent process */
- if ((chstat = talktochild(master, chatsequence)) == False)
- {
- DEBUG(3,
- ("Child failed to change password: %s\n",
- pass->pw_name));
+ if (pid > 0) { /* This is the parent process */
+ if ((chstat = talktochild(master, chatsequence)) == False) {
+ DEBUG(3, ("Child failed to change password: %s\n", pass->pw_name));
kill(pid, SIGKILL); /* be sure to end this process */
}
- while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0)
- {
- if (errno == EINTR)
- {
+ while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
+ if (errno == EINTR) {
errno = 0;
continue;
}
break;
}
- if (wpid < 0)
- {
+ if (wpid < 0) {
DEBUG(3, ("The process is no longer waiting!\n\n"));
close(master);
CatchChild();
@@ -402,29 +387,21 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass,
close(master);
- if (pid != wpid)
- {
- DEBUG(3,
- ("We were waiting for the wrong process ID\n"));
+ if (pid != wpid) {
+ DEBUG(3, ("We were waiting for the wrong process ID\n"));
return (False);
}
- if (WIFEXITED(wstat) == 0)
- {
- DEBUG(3,
- ("The process exited while we were waiting\n"));
+ if (WIFEXITED(wstat) == 0) {
+ DEBUG(3, ("The process exited while we were waiting\n"));
return (False);
}
- if (WEXITSTATUS(wstat) != 0)
- {
- DEBUG(3,
- ("The status of the process exiting was %d\n",
+ if (WEXITSTATUS(wstat) != 0) {
+ DEBUG(3, ("The status of the process exiting was %d\n",
wstat));
return (False);
}
- }
- else
- {
+ } else {
/* CHILD */
/*
@@ -438,12 +415,9 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass,
if (as_root)
become_root();
- DEBUG(3,
- ("Dochild for user %s (uid=%d,gid=%d)\n", pass->pw_name,
- (int)getuid(), (int)getgid()));
- chstat =
- dochild(master, slavedev, pass, passwordprogram,
- as_root);
+ DEBUG(3, ("Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name,
+ (int)getuid(), (int)getgid(), BOOLSTR(as_root) ));
+ chstat = dochild(master, slavedev, pass, passwordprogram, as_root);
if (as_root)
unbecome_root();
@@ -452,20 +426,16 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass,
* The child should never return from dochild() ....
*/
- DEBUG(0,
- ("chat_with_program: Error: dochild() returned %d\n",
- chstat));
+ DEBUG(0, ("chat_with_program: Error: dochild() returned %d\n", chstat));
exit(1);
}
if (chstat)
- DEBUG(3,
- ("Password change %ssuccessful for user %s\n",
+ DEBUG(3, ("Password change %ssuccessful for user %s\n",
(chstat ? "" : "un"), pass->pw_name));
return (chstat);
}
-
BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root)
{
pstring passwordprogram;
@@ -489,7 +459,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
oldpass = "";
}
- DEBUG(3, ("Password change for user: %s\n", name));
+ DEBUG(3, ("Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name));
#if DEBUG_PASSWORD
DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass));
@@ -519,8 +489,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
len = strlen(oldpass);
for (i = 0; i < len; i++) {
if (iscntrl((int)oldpass[i])) {
- DEBUG(0,
- ("chat_with_program: oldpass contains control characters (disallowed).\n"));
+ DEBUG(0, ("chat_with_program: oldpass contains control characters (disallowed).\n"));
return False;
}
}
@@ -528,8 +497,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
len = strlen(newpass);
for (i = 0; i < len; i++) {
if (iscntrl((int)newpass[i])) {
- DEBUG(0,
- ("chat_with_program: newpass contains control characters (disallowed).\n"));
+ DEBUG(0, ("chat_with_program: newpass contains control characters (disallowed).\n"));
return False;
}
}
@@ -556,11 +524,8 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
/* A non-PAM password change just doen't make sense without a valid local user */
- if (pass == NULL)
- {
- DEBUG(0,
- ("chgpasswd: user %s doesn't exist in the UNIX password database.\n",
- name));
+ if (pass == NULL) {
+ DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name));
return False;
}
@@ -746,7 +711,6 @@ NTSTATUS pass_oem_change(char *user,
uchar * ntdata, uchar * nthash)
{
fstring new_passwd;
- const char *unix_user;
SAM_ACCOUNT *sampass = NULL;
NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash,
&sampass, new_passwd, sizeof(new_passwd));
@@ -754,20 +718,9 @@ NTSTATUS pass_oem_change(char *user,
if (!NT_STATUS_IS_OK(nt_status))
return nt_status;
- /*
- * At this point we have the new case-sensitive plaintext
- * password in the fstring new_passwd. If we wanted to synchronise
- * with UNIX passwords we would call a UNIX password changing
- * function here. However it would have to be done as root
- * as the plaintext of the old users password is not
- * available. JRA.
- */
-
- unix_user = pdb_get_username(sampass);
-
/* We've already checked the old password here.... */
become_root();
- nt_status = change_oem_password(sampass, NULL, new_passwd);
+ nt_status = change_oem_password(sampass, NULL, new_passwd, True);
unbecome_root();
memset(new_passwd, 0, sizeof(new_passwd));
@@ -949,7 +902,7 @@ static NTSTATUS check_oem_password(const char *user,
is correct before calling. JRA.
************************************************************/
-NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd)
+NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
{
BOOL ret;
uint32 min_len;
@@ -993,7 +946,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
*/
if(lp_unix_password_sync() &&
- !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, False)) {
+ !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) {
return NT_STATUS_ACCESS_DENIED;
}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 6be5f6af7d..6cf7014846 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -87,8 +87,11 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
* Serve from write cache if we can.
*/
- if(read_from_write_cache(fsp, data, pos, n))
+ if(read_from_write_cache(fsp, data, pos, n)) {
+ fsp->pos = pos + n;
+ fsp->position_information = fsp->pos;
return n;
+ }
flush_write_cache(fsp, READ_FLUSH);
@@ -123,6 +126,9 @@ tryagain:
DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
+ fsp->pos += ret;
+ fsp->position_information = fsp->pos;
+
return(ret);
}
@@ -145,6 +151,16 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_
DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
+ if (ret != -1) {
+ fsp->pos += ret;
+
+/* Yes - this is correct - writes don't update this. JRA. */
+/* Found by Samba4 tests. */
+#if 0
+ fsp->position_information = fsp->pos;
+#endif
+ }
+
return ret;
}
@@ -244,7 +260,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
if(!wcp) {
DO_PROFILE_INC(writecache_direct_writes);
total_written = real_write_file(fsp, data, pos, n);
- if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size))
+ if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size))
fsp->size = (SMB_BIG_UINT)(pos + total_written);
return total_written;
}
@@ -252,6 +268,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n",
fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
+ fsp->pos = pos + n;
+
/*
* If we have active cache and it isn't contiguous then we flush.
* NOTE: There is a small problem with running out of disk ....
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index ad107f9c3e..643e315c06 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -125,7 +125,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
* also trim trailing /'s.
*/
- trim_string(name,"/","/");
+ trim_char(name,'/','/');
/*
* If we trimmed down to a single '\0' character
@@ -164,7 +164,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
return(True);
start = name;
- while (strncmp(start,"./",2) == 0)
+ while (start[0] == '.' && start[1] == '/')
start += 2;
pstrcpy(orig_path, name);
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index f0fd6b7a73..1fe6f250e5 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -143,6 +143,22 @@ void file_close_conn(connection_struct *conn)
}
/****************************************************************************
+ Close all open files for a pid.
+****************************************************************************/
+
+void file_close_pid(uint16 smbpid)
+{
+ files_struct *fsp, *next;
+
+ for (fsp=Files;fsp;fsp=next) {
+ next = fsp->next;
+ if (fsp->file_pid == smbpid) {
+ close_file(fsp,False);
+ }
+ }
+}
+
+/****************************************************************************
Initialise file structures.
****************************************************************************/
@@ -200,6 +216,18 @@ void file_close_user(int vuid)
}
}
+void file_dump_open_table(void)
+{
+ int count=0;
+ files_struct *fsp;
+
+ for (fsp=Files;fsp;fsp=fsp->next,count++) {
+ DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
+ count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id,
+ (unsigned int)fsp->dev, (double)fsp->inode ));
+ }
+}
+
/****************************************************************************
Find a fsp given a file descriptor.
****************************************************************************/
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index a5f7a7b2ea..b27ccc23ef 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -1706,13 +1706,24 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
int uLevel = SVAL(p,0);
const char *level_string;
int count=0;
+ SAM_ACCOUNT *sampw = NULL;
+ BOOL ret = False;
+ DOM_GID *gids = NULL;
+ int num_groups = 0;
+ int i;
+ fstring grp_domain;
+ fstring grp_name;
+ enum SID_NAME_USE grp_type;
+ DOM_SID sid, dom_sid;
*rparam_len = 8;
*rparam = REALLOC(*rparam,*rparam_len);
/* check it's a supported varient */
- if (!strcmp(str1,"zWrLeh"))
+
+ if ( strcmp(str1,"zWrLeh") != 0 )
return False;
+
switch( uLevel ) {
case 0:
level_string = "B21";
@@ -1732,18 +1743,59 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
p = *rdata;
- /* XXXX we need a real SAM database some day */
- pstrcpy(p,"Users"); p += 21; count++;
- pstrcpy(p,"Domain Users"); p += 21; count++;
- pstrcpy(p,"Guests"); p += 21; count++;
- pstrcpy(p,"Domain Guests"); p += 21; count++;
+ /* Lookup the user information; This should only be one of
+ our accounts (not remote domains) */
+
+ pdb_init_sam( &sampw );
+
+ become_root(); /* ROOT BLOCK */
+
+ if ( !pdb_getsampwnam(sampw, UserName) )
+ goto out;
+
+ /* this next set of code is horribly inefficient, but since
+ it is rarely called, I'm going to leave it like this since
+ it easier to follow --jerry */
+
+ /* get the list of group SIDs */
+
+ if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
+ DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
+ goto out;
+ }
+ /* convert to names (we don't support universal groups so the domain
+ can only be ours) */
+
+ sid_copy( &dom_sid, get_global_sam_sid() );
+ for (i=0; i<num_groups; i++) {
+
+ /* make the DOM_GID into a DOM_SID and then lookup
+ the name */
+
+ sid_copy( &sid, &dom_sid );
+ sid_append_rid( &sid, gids[i].g_rid );
+
+ if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
+ pstrcpy(p, grp_name);
+ p += 21;
+ count++;
+ }
+ }
+
*rdata_len = PTR_DIFF(p,*rdata);
SSVAL(*rparam,4,count); /* is this right?? */
SSVAL(*rparam,6,count); /* is this right?? */
- return(True);
+ ret = True;
+
+out:
+ unbecome_root(); /* END ROOT BLOCK */
+
+ pdb_free_sam( &sampw );
+
+ return ret;
}
/*******************************************************************
@@ -1932,7 +1984,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
become_root();
- if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) {
+ if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
SSVAL(*rparam,0,NERR_Success);
}
unbecome_root();
@@ -1957,7 +2009,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
become_root();
- if (change_lanman_password(hnd,pass2)) {
+ if (change_lanman_password(hnd,(uchar *)pass2)) {
SSVAL(*rparam,0,NERR_Success);
}
unbecome_root();
@@ -1980,47 +2032,46 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- fstring user;
- char *p = param + 2;
- *rparam_len = 2;
- *rparam = REALLOC(*rparam,*rparam_len);
+ fstring user;
+ char *p = param + 2;
+ *rparam_len = 2;
+ *rparam = REALLOC(*rparam,*rparam_len);
- *rdata_len = 0;
+ *rdata_len = 0;
- SSVAL(*rparam,0,NERR_badpass);
+ SSVAL(*rparam,0,NERR_badpass);
- /*
- * Check the parameter definition is correct.
- */
- if(!strequal(param + 2, "zsT")) {
- DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
- return False;
- }
- p = skip_string(p, 1);
+ /*
+ * Check the parameter definition is correct.
+ */
- if(!strequal(p, "B516B16")) {
- DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
- return False;
- }
- p = skip_string(p,1);
+ if(!strequal(param + 2, "zsT")) {
+ DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
+ return False;
+ }
+ p = skip_string(p, 1);
- p += pull_ascii_fstring(user,p);
+ if(!strequal(p, "B516B16")) {
+ DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
+ return False;
+ }
+ p = skip_string(p,1);
+ p += pull_ascii_fstring(user,p);
- DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
+ DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
+ /*
+ * Pass the user through the NT -> unix user mapping
+ * function.
+ */
- (void)map_username(user);
+ (void)map_username(user);
- if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)))
- {
- SSVAL(*rparam,0,NERR_Success);
- }
+ if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
+ SSVAL(*rparam,0,NERR_Success);
+ }
- return(True);
+ return(True);
}
/****************************************************************************
diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c
index cdce28e1bd..9cd0438d51 100644
--- a/source3/smbd/mangle_hash2.c
+++ b/source3/smbd/mangle_hash2.c
@@ -201,22 +201,24 @@ static const char *cache_lookup(u32 hash)
In this algorithm, mangled names use only pure ascii characters (no
multi-byte) so we can avoid doing a UCS2 conversion
*/
-static BOOL is_mangled_component(const char *name)
+static BOOL is_mangled_component(const char *name, size_t len)
{
- unsigned int len, i;
+ unsigned int i;
- M_DEBUG(10,("is_mangled_component %s ?\n", name));
+ M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
/* check the length */
- len = strlen(name);
- if (len > 12 || len < 8) return False;
+ if (len > 12 || len < 8)
+ return False;
/* the best distinguishing characteristic is the ~ */
- if (name[6] != '~') return False;
+ if (name[6] != '~')
+ return False;
/* check extension */
if (len > 8) {
- if (name[8] != '.') return False;
+ if (name[8] != '.')
+ return False;
for (i=9; name[i]; i++) {
if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
return False;
@@ -241,7 +243,7 @@ static BOOL is_mangled_component(const char *name)
}
}
- M_DEBUG(10,("is_mangled %s -> yes\n", name));
+ M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
return True;
}
@@ -267,16 +269,13 @@ static BOOL is_mangled(const char *name)
M_DEBUG(10,("is_mangled %s ?\n", name));
for (s=name; (p=strchr(s, '/')); s=p+1) {
- char *component = strndup(s, PTR_DIFF(p, s));
- if (is_mangled_component(component)) {
- free(component);
+ if (is_mangled_component(s, PTR_DIFF(p, s))) {
return True;
}
- free(component);
}
/* and the last part ... */
- return is_mangled_component(s);
+ return is_mangled_component(s,strlen(s));
}
@@ -305,7 +304,8 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
the result we need in this case. Using strlen_m would not
only be slower, it would be incorrect */
len = strlen(name);
- if (len > 12) return False;
+ if (len > 12)
+ return False;
/* find the '.'. Note that once again we use the non-multibyte
function */
@@ -449,6 +449,27 @@ static BOOL is_legal_name(const char *name)
size_t numdots = 0;
while (*name) {
+ if (((unsigned int)name[0]) > 128 && (name[1] != 0)) {
+ /* Possible start of mb character. */
+ char mbc[2];
+ /*
+ * We know the following will return 2 bytes. What
+ * we need to know was if errno was set.
+ * Note that if CH_UNIX is utf8 a string may be 3
+ * bytes, but this is ok as mb utf8 characters don't
+ * contain embedded ascii bytes. We are really checking
+ * for mb UNIX asian characters like Japanese (SJIS) here.
+ * JRA.
+ */
+ errno = 0;
+ convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2);
+ if (!errno) {
+ /* Was a good mb string. */
+ name += 2;
+ continue;
+ }
+ }
+
if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) {
return False;
}
diff --git a/source3/smbd/message.c b/source3/smbd/message.c
index 233848d2d6..88f833e468 100644
--- a/source3/smbd/message.c
+++ b/source3/smbd/message.c
@@ -64,7 +64,7 @@ static void msg_deliver(void)
* Incoming message is in DOS codepage format. Convert to UNIX.
*/
- if ((len = convert_string_allocate(CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) {
+ if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) {
DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n"));
for (i = 0; i < msgpos;) {
if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') {
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 9adf827c79..ca6f2b783f 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn,
DLIST_ADD(change_notify_list, cnbp);
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(inbuf,smb_mid));
+ srv_defer_sign_response(SVAL(inbuf,smb_mid), True);
return True;
}
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 3ffa6efa77..f8bd3ae15f 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -762,9 +762,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
restore_case_semantics(file_attributes);
if(!fsp) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBntcreateX);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
/*
@@ -838,16 +837,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if(!fsp) {
restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBntcreateX);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBntcreateX);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
}
}
@@ -1279,8 +1276,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if(!fsp) {
restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
@@ -1312,13 +1308,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if(!fsp) {
restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
}
@@ -1724,7 +1718,11 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
char **ppparams, uint32 parameter_count,
char **ppdata, uint32 data_count)
{
- unsigned fnum, control;
+ uint32 function;
+ uint16 fidnum;
+ files_struct *fsp;
+ uint8 isFSctl;
+ uint8 compfilter;
static BOOL logged_message;
char *pdata = *ppdata;
@@ -1733,19 +1731,26 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
- fnum = SVAL(*ppsetup, 4);
- control = IVAL(*ppsetup, 0);
+ function = IVAL(*ppsetup, 0);
+ fidnum = SVAL(*ppsetup, 4);
+ isFSctl = CVAL(*ppsetup, 6);
+ compfilter = CVAL(*ppsetup, 7);
+
+ DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n",
+ function, fidnum, isFSctl, compfilter));
- DEBUG(10,("call_nt_transact_ioctl: fnum=%d control=0x%08x\n",
- fnum, control));
+ fsp=file_fsp(*ppsetup, 4);
+ /* this check is done in each implemented function case for now
+ because I don't want to break anything... --metze
+ FSP_BELONGS_CONN(fsp,conn);*/
- switch (control) {
+ switch (function) {
case FSCTL_SET_SPARSE:
/* pretend this succeeded - tho strictly we should
mark the file sparse (if the local fs supports it)
so we can know if we need to pre-allocate or not */
- DEBUG(10,("FSCTL_SET_SPARSE: fnum=%d control=0x%08x\n",fnum,control));
+ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
@@ -1754,7 +1759,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
but works ok like this --metze
*/
- DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control));
+ DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
@@ -1763,7 +1768,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
* --metze
*/
- DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control));
+ DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
return -1;
@@ -1772,10 +1777,125 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
* --metze
*/
- DEBUG(10,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control));
+ DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
return -1;
+ case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
+ {
+ /*
+ * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
+ * and return their volume names. If max_data_count is 16, then it is just
+ * asking for the number of volumes and length of the combined names.
+ *
+ * pdata is the data allocated by our caller, but that uses
+ * total_data_count (which is 0 in our case) rather than max_data_count.
+ * Allocate the correct amount and return the pointer to let
+ * it be deallocated when we return.
+ */
+ uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
+ SHADOW_COPY_DATA *shadow_data = NULL;
+ TALLOC_CTX *shadow_mem_ctx = NULL;
+ BOOL labels = False;
+ uint32 labels_data_count = 0;
+ uint32 i;
+ char *cur_pdata;
+
+ FSP_BELONGS_CONN(fsp,conn);
+
+ if (max_data_count < 16) {
+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
+ max_data_count));
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (max_data_count > 16) {
+ labels = True;
+ }
+
+ shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA");
+ if (shadow_mem_ctx == NULL) {
+ DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n"));
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA));
+ if (shadow_data == NULL) {
+ DEBUG(0,("talloc_zero() failed!\n"));
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ shadow_data->mem_ctx = shadow_mem_ctx;
+
+ /*
+ * Call the VFS routine to actually do the work.
+ */
+ if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
+ talloc_destroy(shadow_data->mem_ctx);
+ if (errno == ENOSYS) {
+ DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
+ conn->connectpath));
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ } else {
+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
+ conn->connectpath));
+ return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ }
+ }
+
+ labels_data_count = (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))+2;
+
+ if (!labels) {
+ data_count = 16;
+ } else {
+ data_count = 12+labels_data_count+4;
+ }
+
+ if (max_data_count<data_count) {
+ DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
+ max_data_count,data_count));
+ talloc_destroy(shadow_data->mem_ctx);
+ return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+ }
+
+ pdata = nttrans_realloc(ppdata, data_count);
+ if (pdata == NULL) {
+ talloc_destroy(shadow_data->mem_ctx);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ cur_pdata = pdata;
+
+ /* num_volumes 4 bytes */
+ SIVAL(pdata,0,shadow_data->num_volumes);
+
+ if (labels) {
+ /* num_labels 4 bytes */
+ SIVAL(pdata,4,shadow_data->num_volumes);
+ }
+
+ /* needed_data_count 4 bytes */
+ SIVAL(pdata,8,labels_data_count);
+
+ cur_pdata+=12;
+
+ DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
+ shadow_data->num_volumes,fsp->fsp_name));
+ if (labels && shadow_data->labels) {
+ for (i=0;i<shadow_data->num_volumes;i++) {
+ srvstr_push(outbuf, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE);
+ cur_pdata+=2*sizeof(SHADOW_COPY_LABEL);
+ DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
+ }
+ }
+
+ talloc_destroy(shadow_data->mem_ctx);
+
+ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count);
+
+ return -1;
+ }
+
case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */
{
/* pretend this succeeded -
@@ -1783,24 +1903,24 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
* we have to send back a list with all files owned by this SID
*
* but I have to check that --metze
- */
-
+ */
DOM_SID sid;
uid_t uid;
- size_t sid_len=SID_MAX_SIZE;
-
- DEBUG(10,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control));
+ size_t sid_len = MIN(data_count-4,SID_MAX_SIZE);
- /* this is not the length of the sid :-( so unknown 4 bytes */
- /*sid_len = IVAL(pdata,0);
- DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/
+ DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum));
+
+ FSP_BELONGS_CONN(fsp,conn);
+
+ /* unknown 4 bytes: this is not the length of the sid :-( */
+ /*unknown = IVAL(pdata,0);*/
sid_parse(pdata+4,sid_len,&sid);
- DEBUGADD(10,("SID: %s\n",sid_string_static(&sid)));
+ DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid)));
if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) {
- DEBUG(0,("sid_to_uid: failed, sid[%s]\n",
- sid_string_static(&sid)));
+ DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%u]\n",
+ sid_string_static(&sid),sid_len));
uid = (-1);
}
@@ -1813,6 +1933,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
* for each file
*
* but I don't know how to deal with the paged results
+ * (maybe we can hang the result anywhere in the fsp struct)
*
* we don't send all files at once
* and at the next we should *not* start from the beginning,
@@ -1829,7 +1950,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
if (!logged_message) {
logged_message = True; /* Only print this once... */
DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n",
- control));
+ function));
}
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 5f49640aa4..71af23aaf9 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -23,6 +23,7 @@
extern userdom_struct current_user_info;
extern uint16 global_oplock_port;
+extern uint16 global_smbpid;
extern BOOL global_client_failed_oplock_break;
/****************************************************************************
@@ -226,8 +227,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
fsp->inode = psbuf->st_ino;
fsp->dev = psbuf->st_dev;
fsp->vuid = current_user.vuid;
+ fsp->file_pid = global_smbpid;
fsp->size = psbuf->st_size;
- fsp->pos = -1;
fsp->can_lock = True;
fsp->can_read = ((flags & O_WRONLY)==0);
fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
@@ -626,6 +627,12 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \
dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode));
+ /* Ensure the reply for the open uses the correct sequence number. */
+ /* This isn't a real deferred packet as it's response will also increment
+ * the sequence.
+ */
+ srv_defer_sign_response(get_current_mid(), False);
+
/* Oplock break - unlock to request it. */
unlock_share_entry(conn, dev, inode);
@@ -1356,7 +1363,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->dev = psbuf->st_dev;
fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->pos = -1;
+ fsp->file_pid = global_smbpid;
fsp->can_lock = True;
fsp->can_read = False;
fsp->can_write = False;
@@ -1419,7 +1426,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->dev = (SMB_DEV_T)0;
fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->pos = -1;
+ fsp->file_pid = global_smbpid;
fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index b988f2ec74..32c24b3d67 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -28,6 +28,9 @@ static user_struct *validated_users;
static int next_vuid = VUID_OFFSET;
static int num_validated_vuids;
+extern userdom_struct current_user_info;
+
+
/****************************************************************************
Check if a uid has been validated, and return an pointer to the user_struct
if it has. NULL if not. vuid is biased by an offset. This allows us to
@@ -296,7 +299,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
if (ret && lp_valid_users(snum)) {
str_list_copy(&valid, lp_valid_users(snum));
- if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) {
+ if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) {
ret = user_in_list(user, (const char **)valid, groups, n_groups);
}
}
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dce1c4bc03..3c15cd1833 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -48,6 +48,15 @@ BOOL global_machine_password_needs_changing = False;
extern int max_send;
/****************************************************************************
+ Function to return the current request mid from Inbuffer.
+****************************************************************************/
+
+uint16 get_current_mid(void)
+{
+ return SVAL(InBuffer,smb_mid);
+}
+
+/****************************************************************************
structure to hold a linked list of queued messages.
for processing.
****************************************************************************/
@@ -88,7 +97,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
ubi_slAddTail( list_head, msg);
/* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(SVAL(buf,smb_mid));
+ srv_defer_sign_response(SVAL(buf,smb_mid), True);
return True;
}
@@ -710,7 +719,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
if(session_tag != UID_FIELD_INVALID)
vuser = get_valid_user_struct(session_tag);
if(vuser != NULL)
- current_user_info = vuser->user;
+ set_current_user_info(&vuser->user);
}
/* does this protocol need to be run as root? */
@@ -1256,8 +1265,10 @@ void smbd_process(void)
if ((InBuffer == NULL) || (OutBuffer == NULL))
return;
+#if defined(DEVELOPER)
clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
+#endif
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
@@ -1286,7 +1297,9 @@ void smbd_process(void)
num_smbs = 0; /* Reset smb counter. */
}
+#if defined(DEVELOPER)
clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
+#endif
while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 71312295f4..6ac4cffddb 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -39,6 +39,21 @@ unsigned int smb_echo_count = 0;
extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
+ Ensure we check the path in the same way as W2K.
+****************************************************************************/
+
+static NTSTATUS check_path_syntax(const char *name)
+{
+ while (*name == '\\')
+ name++;
+ if (strequal(name, "."))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ else if (strequal(name, ".."))
+ return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Reply to a special message.
****************************************************************************/
@@ -333,7 +348,6 @@ int reply_ioctl(connection_struct *conn,
uint32 ioctl_code = (device << 16) + function;
int replysize, outsize;
char *p;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBioctl);
DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
@@ -356,6 +370,11 @@ int reply_ioctl(connection_struct *conn,
switch (ioctl_code) {
case IOCTL_QUERY_JOB_INFO:
{
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ if (!fsp) {
+ END_PROFILE(SMBioctl);
+ return(UNIXERROR(ERRDOS,ERRbadfid));
+ }
SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
@@ -379,10 +398,16 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
BOOL ok = False;
BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
+
START_PROFILE(SMBchkpth);
srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+ status = check_path_syntax(name);
+ if (!NT_STATUS_IS_OK(status))
+ return ERROR_NT(status);
+
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
unix_convert(name,conn,0,&bad_path,&sbuf);
@@ -401,8 +426,21 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
one at a time - if a component fails it expects
ERRbadpath, not ERRbadfile.
*/
- if(errno == ENOENT)
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ if(errno == ENOENT) {
+ /*
+ * Windows returns different error codes if
+ * the parent directory is valid but not the
+ * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
+ * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
+ * if the path is invalid.
+ */
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ } else {
+ return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ }
+ } else if (errno == ENOTDIR)
+ return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
return(UNIXERROR(ERRDOS,ERRbadpath));
}
@@ -463,9 +501,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
if (!ok) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBgetatr);
- return(UNIXERROR(ERRDOS,ERRbadfile));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
}
outsize = set_message(outbuf,10,0,True);
@@ -510,20 +547,24 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
mode = SVAL(inbuf,smb_vwv0);
mtime = make_unix_date3(inbuf+smb_vwv1);
- if (VALID_STAT_OF_DIR(sbuf))
- mode |= aDIR;
- else
- mode &= ~aDIR;
+ if (mode != FILE_ATTRIBUTE_NORMAL) {
+ if (VALID_STAT_OF_DIR(sbuf))
+ mode |= aDIR;
+ else
+ mode &= ~aDIR;
+
+ if (check_name(fname,conn))
+ ok = (file_chmod(conn,fname,mode,NULL) == 0);
+ } else {
+ ok = True;
+ }
- if (check_name(fname,conn))
- ok = (file_chmod(conn,fname,mode,NULL) == 0);
if (ok)
ok = set_filetime(conn,fname,mtime);
if (!ok) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBsetatr);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,0,0,True);
@@ -684,9 +725,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
if (dptr_num < 0) {
if(dptr_num == -2) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBsearch);
- return (UNIXERROR(ERRDOS,ERRnofids));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
}
END_PROFILE(SMBsearch);
return ERROR_DOS(ERRDOS,ERRnofids);
@@ -732,21 +772,23 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SearchEmpty:
- if (numentries == 0 || !ok) {
- SCVAL(outbuf,smb_rcls,ERRDOS);
- SSVAL(outbuf,smb_err,ERRnofiles);
- dptr_close(&dptr_num);
- }
-
/* If we were called as SMBffirst with smb_search_id == NULL
and no entries were found then return error and close dirptr
(X/Open spec) */
if(ok && expect_close && numentries == 0 && status_len == 0) {
- SCVAL(outbuf,smb_rcls,ERRDOS);
- SSVAL(outbuf,smb_err,ERRnofiles);
+ if (Protocol < PROTOCOL_NT1) {
+ SCVAL(outbuf,smb_rcls,ERRDOS);
+ SSVAL(outbuf,smb_err,ERRnofiles);
+ }
/* Also close the dptr - we know it's gone */
dptr_close(&dptr_num);
+ } else if (numentries == 0 || !ok) {
+ if (Protocol < PROTOCOL_NT1) {
+ SCVAL(outbuf,smb_rcls,ERRDOS);
+ SSVAL(outbuf,smb_err,ERRnofiles);
+ }
+ dptr_close(&dptr_num);
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
@@ -851,9 +893,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unixmode, oplock_request,&rmode,NULL);
if (!fsp) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBopen);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
size = sbuf.st_size;
@@ -939,9 +980,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
oplock_request, &rmode,&smb_action);
if (!fsp) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBopenX);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
size = sbuf.st_size;
@@ -1063,9 +1103,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
ofun, unixmode, oplock_request, NULL, NULL);
if (!fsp) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBcreate);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,1,0,True);
@@ -1132,9 +1171,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
close(tmpfd);
if (!fsp) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBctemp);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,1,0,True);
@@ -1215,6 +1253,9 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
int access_mode;
files_struct *fsp;
+ DEBUG(10,("can_delete: %s, dirtype = %d\n",
+ fname, dirtype ));
+
if (!CAN_WRITE(conn))
return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -1222,14 +1263,21 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
fmode = dos_mode(conn,fname,&sbuf);
+
+ /* Can't delete a directory. */
if (fmode & aDIR)
return NT_STATUS_FILE_IS_A_DIRECTORY;
+#if 0 /* JRATEST */
+ else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
+ return NT_STATUS_OBJECT_NAME_INVALID;
+#endif /* JRATEST */
+
if (!lp_delete_readonly(SNUM(conn))) {
if (fmode & aRONLY)
return NT_STATUS_CANNOT_DELETE;
}
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
- return NT_STATUS_CANNOT_DELETE;
+ return NT_STATUS_NO_SUCH_FILE;
/* We need a better way to return NT status codes from open... */
unix_ERR_class = 0;
@@ -1329,7 +1377,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
*/
if (dirptr) {
- error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ error = NT_STATUS_NO_SUCH_FILE;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
@@ -1377,6 +1425,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+ status = check_path_syntax(name);
+ if (!NT_STATUS_IS_OK(status))
+ return ERROR_NT(status);
+
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
DEBUG(3,("reply_unlink : %s\n",name));
@@ -2262,39 +2314,25 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
switch (mode) {
case 0:
umode = SEEK_SET;
+ res = startpos;
break;
case 1:
umode = SEEK_CUR;
+ res = fsp->pos + startpos;
break;
case 2:
umode = SEEK_END;
break;
default:
umode = SEEK_SET;
+ res = startpos;
break;
}
- if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
- /*
- * Check for the special case where a seek before the start
- * of the file sets the offset to zero. Added in the CIFS spec,
- * section 4.2.7.
- */
-
- if(errno == EINVAL) {
- SMB_OFF_T current_pos = startpos;
-
- if(umode == SEEK_CUR) {
-
- if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
- END_PROFILE(SMBlseek);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- current_pos += startpos;
-
- } else if (umode == SEEK_END) {
-
+ if (umode == SEEK_END) {
+ if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+ if(errno == EINVAL) {
+ SMB_OFF_T current_pos = startpos;
SMB_STRUCT_STAT sbuf;
if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
@@ -2303,10 +2341,9 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
}
current_pos += sbuf.st_size;
+ if(current_pos < 0)
+ res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
}
-
- if(current_pos < 0)
- res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
}
if(res == -1) {
@@ -2334,10 +2371,12 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
int outsize = set_message(outbuf,0,0,True);
+ uint16 fnum = SVAL(inbuf,smb_vwv0);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBflush);
- CHECK_FSP(fsp,conn);
+ if (fnum != 0xFFFF)
+ CHECK_FSP(fsp,conn);
if (!fsp) {
file_sync_all(conn);
@@ -2359,6 +2398,9 @@ int reply_exit(connection_struct *conn,
{
int outsize;
START_PROFILE(SMBexit);
+
+ file_close_pid(SVAL(inbuf,smb_pid));
+
outsize = set_message(outbuf,0,0,True);
DEBUG(3,("exit\n"));
@@ -2704,7 +2746,7 @@ int reply_printclose(connection_struct *conn,
if (!CAN_PRINT(conn)) {
END_PROFILE(SMBsplclose);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
+ return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
DEBUG(3,("printclose fd=%d fnum=%d\n",
@@ -2849,7 +2891,17 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
if (ret == -1) {
- NTSTATUS nterr = set_bad_path_error(errno, bad_path);
+ NTSTATUS nterr = NT_STATUS_OK;
+ if(errno == ENOENT) {
+ unix_ERR_class = ERRDOS;
+ if (bad_path) {
+ unix_ERR_code = ERRbadpath;
+ nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else {
+ unix_ERR_code = ERRbadfile;
+ nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ }
if (!NT_STATUS_IS_OK(nterr))
return nterr;
return map_nt_error_from_unix(errno);
@@ -3044,9 +3096,8 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
if (!ok) {
- set_bad_path_error(errno, bad_path);
END_PROFILE(SMBrmdir);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
}
outsize = set_message(outbuf,0,0,True);
@@ -3130,6 +3181,130 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
}
/****************************************************************************
+ Ensure open files have their names updates.
+****************************************************************************/
+
+static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
+{
+ files_struct *fsp;
+ BOOL did_rename = False;
+
+ for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
+ DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
+ fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fsp_name, newname ));
+ string_set(&fsp->fsp_name, newname);
+ did_rename = True;
+ }
+
+ if (!did_rename)
+ DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
+ (unsigned int)dev, (double)inode, newname ));
+}
+
+/****************************************************************************
+ Rename an open file - given an fsp.
+****************************************************************************/
+
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
+{
+ SMB_STRUCT_STAT sbuf;
+ BOOL bad_path = False;
+ pstring newname_last_component;
+ NTSTATUS error = NT_STATUS_OK;
+ BOOL dest_exists;
+
+ ZERO_STRUCT(sbuf);
+ unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
+
+ /* Ensure newname contains a '/' */
+ if(strrchr_m(newname,'/') == 0) {
+ pstring tmpstr;
+
+ pstrcpy(tmpstr, "./");
+ pstrcat(tmpstr, newname);
+ pstrcpy(newname, tmpstr);
+ }
+
+ /*
+ * Check for special case with case preserving and not
+ * case sensitive. If the old last component differs from the original
+ * last component only by case, then we should allow
+ * the rename (user is trying to change the case of the
+ * filename).
+ */
+
+ if((case_sensitive == False) && (case_preserve == True) &&
+ strequal(newname, fsp->fsp_name)) {
+ char *p;
+ pstring newname_modified_last_component;
+
+ /*
+ * Get the last component of the modified name.
+ * Note that we guarantee that newname contains a '/'
+ * character above.
+ */
+ p = strrchr_m(newname,'/');
+ pstrcpy(newname_modified_last_component,p+1);
+
+ if(strcsequal(newname_modified_last_component,
+ newname_last_component) == False) {
+ /*
+ * Replace the modified last component with
+ * the original.
+ */
+ pstrcpy(p+1, newname_last_component);
+ }
+ }
+
+ /*
+ * If the src and dest names are identical - including case,
+ * don't do the rename, just return success.
+ */
+
+ if (strcsequal(fsp->fsp_name, newname)) {
+ DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
+ newname));
+ return NT_STATUS_OK;
+ }
+
+ dest_exists = vfs_object_exist(conn,newname,NULL);
+
+ if(!replace_if_exists && dest_exists) {
+ DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
+ fsp->fsp_name,newname));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ error = can_rename(newname,conn,&sbuf);
+
+ if (dest_exists && !NT_STATUS_IS_OK(error)) {
+ DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ nt_errstr(error), fsp->fsp_name,newname));
+ if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
+ error = NT_STATUS_ACCESS_DENIED;
+ return error;
+ }
+
+ if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
+ DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
+ fsp->fsp_name,newname));
+ rename_open_files(conn, fsp->dev, fsp->inode, newname);
+ return NT_STATUS_OK;
+ }
+
+ if (errno == ENOTDIR || errno == EISDIR)
+ error = NT_STATUS_OBJECT_NAME_COLLISION;
+ else
+ error = map_nt_error_from_unix(errno);
+
+ DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
+ nt_errstr(error), fsp->fsp_name,newname));
+
+ return error;
+}
+
+/****************************************************************************
The guts of the rename command, split out so it may be called by the NT SMB
code.
****************************************************************************/
@@ -3150,6 +3325,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
*directory = *mask = 0;
+ ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(sbuf2);
rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
@@ -3290,6 +3467,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
*/
if (strcsequal(directory, newname)) {
+ rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
return NT_STATUS_OK;
}
@@ -3303,6 +3481,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
directory,newname));
+ rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
return NT_STATUS_OK;
}
@@ -3367,8 +3546,10 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
continue;
}
- if (!SMB_VFS_RENAME(conn,fname,destname))
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
count++;
+ }
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
}
CloseDir(dirptr);
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index 411ece5249..8a85792ead 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -199,7 +199,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid)
/* Call initgroups() to get user groups */
- if (initgroups(user,gid) == -1) {
+ if (winbind_initgroups(user,gid) == -1) {
DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) ));
if (getuid() == 0) {
if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) {
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 453ff54e4b..8b890549ea 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -744,7 +744,7 @@ void build_options(BOOL screen);
reopen_logs();
- DEBUG(0,( "smbd version %s started.\n", VERSION));
+ DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING));
DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n"));
DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index c2855487a5..70126b9e7f 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -273,7 +273,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group
str_list_copy(&list, lp_readlist(conn->service));
if (list) {
- if (!str_list_substitute(list, "%S", service)) {
+ if ( !str_list_sub_basic(list, current_user_info.smb_name) ) {
DEBUG(0, ("ERROR: read list substitution failed\n"));
}
if (user_in_list(conn->user, (const char **)list, groups, n_groups))
@@ -283,7 +283,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group
str_list_copy(&list, lp_writelist(conn->service));
if (list) {
- if (!str_list_substitute(list, "%S", service)) {
+ if ( !str_list_sub_basic(list, current_user_info.smb_name) ) {
DEBUG(0, ("ERROR: write list substitution failed\n"));
}
if (user_in_list(conn->user, (const char **)list, groups, n_groups))
@@ -642,6 +642,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
return NULL;
}
}
+
+#ifdef WITH_FAKE_KASERVER
+ afs_login(user);
+#endif
#if CHECK_PATH_ON_TCONX
/* win2000 does not check the permissions on the directory
@@ -691,6 +695,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
+ dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
dbgtext( "initially as user %s ", user );
dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 88b442215d..427caa3ba1 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p)
char *start = p;
fstring lanman;
- fstr_sprintf( lanman, "Samba %s", VERSION );
+ fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
@@ -149,7 +149,6 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB auth_data;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
- ADS_STRUCT *ads;
uint8 session_key[16];
uint8 tok_id[2];
BOOL foreign = False;
@@ -165,18 +164,12 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- ads = ads_init_simple();
+ ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key);
- if (!ads) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
+ data_blob_free(&ticket);
- ads->auth.realm = strdup(lp_realm());
-
- ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(1,("Failed to verify incoming ticket!\n"));
- ads_destroy(&ads);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -187,16 +180,17 @@ static int reply_spnego_kerberos(connection_struct *conn,
p = strchr_m(client, '@');
if (!p) {
DEBUG(3,("Doesn't look like a valid principal\n"));
- ads_destroy(&ads);
data_blob_free(&ap_rep);
+ SAFE_FREE(client);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
*p = 0;
- if (strcasecmp(p+1, ads->auth.realm) != 0) {
+ if (strcasecmp(p+1, lp_realm()) != 0) {
DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
if (!lp_allow_trusted_domains()) {
data_blob_free(&ap_rep);
+ SAFE_FREE(client);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
foreign = True;
@@ -213,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
user = smb_xstrdup(client);
}
- ads_destroy(&ads);
+ SAFE_FREE(client);
/* setup the string used by %U */
sub_set_smb_name(user);
@@ -223,7 +217,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (!pw) {
DEBUG(1,("Username %s is invalid on this system\n",user));
data_blob_free(&ap_rep);
- return ERROR_NT(NT_STATUS_NO_SUCH_USER);
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c
index fbebdb240f..948173687d 100644
--- a/source3/smbd/statcache.c
+++ b/source3/smbd/statcache.c
@@ -66,11 +66,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
return;
/*
- * Don't cache trivial valid directory entries.
+ * Don't cache trivial valid directory entries such as . and ..
*/
- if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) ||
- (strcmp(full_orig_name, "..") == 0))
+ if((*full_orig_name == '\0') || (full_orig_name[0] == '.' &&
+ ((full_orig_name[1] == '\0') ||
+ (full_orig_name[1] == '.' && full_orig_name[1] == '\0'))))
return;
/*
@@ -216,10 +217,10 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
/*
* Don't lookup trivial valid directory entries.
*/
- if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) {
- DO_PROFILE_INC(statcache_misses);
+ if((*name == '\0') || (name[0] == '.' &&
+ ((name[1] == '\0') ||
+ (name[1] == '.' && name[1] == '\0'))))
return False;
- }
if (case_sensitive) {
chk_name = strdup(name);
@@ -247,6 +248,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
while (1) {
hash_elem = hash_lookup(&stat_cache, chk_name);
if(hash_elem == NULL) {
+ DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name ));
/*
* Didn't find it - remove last component for next try.
*/
@@ -276,6 +278,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
}
} else {
scp = (stat_cache_entry *)(hash_elem->value);
+ DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path ));
DO_PROFILE_INC(statcache_hits);
if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 86906fa5be..033e76a33e 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
SMB transaction2 handling
- Copyright (C) Jeremy Allison 1994-2001
+ Copyright (C) Jeremy Allison 1994-2003
Copyright (C) Stefan (metze) Metzmacher 2003
Extensively modified by Andrew Tridgell, 1995
@@ -261,8 +261,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn)) {
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
unixmode = unix_mode(conn,open_attr | aARCH, fname);
@@ -271,8 +270,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
oplock_request, &rmode,&smb_action);
if (!fsp) {
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
size = get_file_size(sbuf);
@@ -441,9 +439,9 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps
}
/****************************************************************************
-checks for SMB_TIME_NO_CHANGE and if not found
-calls interpret_long_date
+ Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
****************************************************************************/
+
time_t interpret_long_unix_date(char *p)
{
DEBUG(1,("interpret_long_unix_date\n"));
@@ -763,6 +761,70 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
p = pdata + len;
break;
+ case SMB_FIND_FILE_LEVEL_261:
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date(p,cdate); p += 8;
+ put_long_date(p,adate); p += 8;
+ put_long_date(p,mdate); p += 8;
+ put_long_date(p,mdate); p += 8;
+ SOFF_T(p,0,file_size);
+ SOFF_T(p,8,allocation_size);
+ p += 16;
+ SIVAL(p,0,nt_extmode);
+ p += 4;
+ len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII);
+ SIVAL(p, 0, len);
+ memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */
+ p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
+
+ case SMB_FIND_FILE_LEVEL_262:
+ was_8_3 = mangle_is_8_3(fname, True);
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date(p,cdate); p += 8;
+ put_long_date(p,adate); p += 8;
+ put_long_date(p,mdate); p += 8;
+ put_long_date(p,mdate); p += 8;
+ SOFF_T(p,0,file_size);
+ SOFF_T(p,8,allocation_size);
+ p += 16;
+ SIVAL(p,0,nt_extmode); p += 4;
+ q = p; p += 4;
+ SIVAL(p,0,0); p += 4;
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
+ memset(p,'\0',26);
+ if (!was_8_3) {
+ pstring mangled_name;
+ pstrcpy(mangled_name, fname);
+ mangle_map(mangled_name,True,True,SNUM(conn));
+ mangled_name[12] = 0;
+ len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
+ SSVAL(p, 0, len);
+ } else {
+ SSVAL(p,0,0);
+ *(p+2) = 0;
+ }
+ p += 2 + 24;
+ memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */
+ p += 10;
+ len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
+ SIVAL(q,0,len);
+ p += len;
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
+ p = pdata + len;
+ break;
+
/* CIFS UNIX Extension. */
case SMB_FIND_FILE_UNIX:
@@ -895,6 +957,8 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
case SMB_FIND_FILE_NAMES_INFO:
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ case SMB_FIND_FILE_LEVEL_261:
+ case SMB_FIND_FILE_LEVEL_262:
break;
case SMB_FIND_FILE_UNIX:
if (!lp_unix_extensions())
@@ -910,8 +974,7 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
unix_convert(directory,conn,0,&bad_path,&sbuf);
if(!check_name(directory,conn)) {
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
p = strrchr_m(directory,'/');
@@ -1365,7 +1428,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
* the called hostname and the service name.
*/
SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) );
- len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0);
+ len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
SCVAL(pdata,l2_vol_cch,len);
data_len = l2_vol_szVolLabel + len;
DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
@@ -1716,14 +1779,22 @@ static int call_trans2setfsinfo(connection_struct *conn,
* Utility function to set bad path error.
****************************************************************************/
-NTSTATUS set_bad_path_error(int err, BOOL bad_path)
+int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
{
- if((err == ENOENT) && bad_path) {
+ DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
+ err, (int)bad_path ));
+
+ if(err == ENOENT) {
unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ if (bad_path) {
+ unix_ERR_code = ERRbadpath;
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ } else {
+ unix_ERR_code = ERRbadfile;
+ return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ }
}
- return NT_STATUS_OK;
+ return UNIXERROR(def_class,def_code);
}
/****************************************************************************
@@ -1778,8 +1849,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
} else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
@@ -1792,21 +1862,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
delete_pending = fsp->directory_delete_on_close;
@@ -1821,9 +1888,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRbadfid));
}
- if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
-
+ pos = fsp->position_information;
delete_pending = fsp->delete_on_close;
}
} else {
@@ -1842,29 +1907,26 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
}
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
return ERROR_DOS(ERRDOS,ERRunknownlevel);
- DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n",
- fname,info_level,tran_call,total_data));
+ DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
+ fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
p = strrchr_m(fname,'/');
if (!p)
@@ -1873,6 +1935,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
base_name = p+1;
mode = dos_mode(conn,fname,&sbuf);
+ if (!mode)
+ mode = FILE_ATTRIBUTE_NORMAL;
+
fullpathname = fname;
file_size = get_file_size(sbuf);
allocation_size = get_allocation_size(fsp,&sbuf);
@@ -1985,7 +2050,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
data_size = 24;
SOFF_T(pdata,0,allocation_size);
SOFF_T(pdata,8,file_size);
- SIVAL(pdata,16,sbuf.st_nlink);
+ if (delete_pending & sbuf.st_nlink)
+ SIVAL(pdata,16,sbuf.st_nlink - 1);
+ else
+ SIVAL(pdata,16,sbuf.st_nlink);
SCVAL(pdata,20,0);
SCVAL(pdata,21,(mode&aDIR)?1:0);
break;
@@ -2043,7 +2111,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
pdata += 40;
SOFF_T(pdata,0,allocation_size);
SOFF_T(pdata,8,file_size);
- SIVAL(pdata,16,sbuf.st_nlink);
+ if (delete_pending && sbuf.st_nlink)
+ SIVAL(pdata,16,sbuf.st_nlink - 1);
+ else
+ SIVAL(pdata,16,sbuf.st_nlink);
SCVAL(pdata,20,delete_pending);
SCVAL(pdata,21,(mode&aDIR)?1:0);
pdata += 24;
@@ -2415,8 +2486,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
} else if (fsp && fsp->print_file) {
/*
@@ -2455,8 +2525,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
unix_convert(fname,conn,0,&bad_path,&sbuf);
if(!check_name(fname, conn)) {
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
/*
@@ -2465,8 +2534,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRbadpath));
+ return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
}
}
@@ -2479,8 +2547,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if (VALID_STAT(sbuf))
unixmode = sbuf.st_mode;
- DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n",
- tran_call,fname,info_level,total_data));
+ DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
+ tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
/* Realloc the parameter and data sizes */
params = Realloc(*pparams,2);
@@ -2507,18 +2575,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
switch (info_level) {
case SMB_INFO_STANDARD:
{
- if (total_data < l1_cbFile+4)
+ if (total_data < 12)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
/* access time */
tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
-
/* write time */
tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
-
- dosmode = SVAL(pdata,l1_attrFile);
- size = IVAL(pdata,l1_cbFile);
-
break;
}
@@ -2677,14 +2740,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_FILE_DISPOSITION_INFORMATION:
case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
{
- BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
+ BOOL delete_on_close;
NTSTATUS status;
if (total_data < 1)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+ delete_on_close = (CVAL(pdata,0) ? True : False);
+
+ /* Just ignore this set on a path. */
if (tran_call != TRANSACT2_SETFILEINFO)
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ break;
if (fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadfid));
@@ -2702,6 +2768,27 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
break;
}
+ case SMB_FILE_POSITION_INFORMATION:
+ {
+ SMB_BIG_UINT position_information;
+
+ if (total_data < 8)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ position_information = (SMB_BIG_UINT)IVAL(pdata,0);
+#ifdef LARGE_SMB_OFF_T
+ position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
+#else /* LARGE_SMB_OFF_T */
+ if (IVAL(pdata,4) != 0) /* more than 32 bits? */
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+#endif /* LARGE_SMB_OFF_T */
+ DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
+ fname, (double)position_information ));
+ if (fsp)
+ fsp->position_information = position_information;
+ break;
+ }
+
/*
* CIFS UNIX extensions.
*/
@@ -2881,6 +2968,55 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
return(-1);
}
+ case SMB_FILE_RENAME_INFORMATION:
+ {
+ BOOL overwrite;
+ uint32 root_fid;
+ uint32 len;
+ pstring newname;
+ pstring base_name;
+ char *p;
+ NTSTATUS status;
+
+ if (total_data < 12)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ overwrite = (CVAL(pdata,0) ? True : False);
+ root_fid = IVAL(pdata,4);
+ len = IVAL(pdata,8);
+ srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0);
+
+ /* Check the new name has no '\' characters. */
+ if (strchr_m(newname, '\\') || strchr_m(newname, '/'))
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+
+ RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+
+ /* Create the base directory. */
+ pstrcpy(base_name, fname);
+ p = strrchr_m(base_name, '/');
+ if (p)
+ *p = '\0';
+ /* Append the new name. */
+ pstrcat(base_name, "/");
+ pstrcat(base_name, newname);
+
+ if (fsp) {
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
+ fsp->fnum, fsp->fsp_name, base_name ));
+ status = rename_internals_fsp(conn, fsp, base_name, overwrite);
+ } else {
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
+ fname, newname ));
+ status = rename_internals(conn, fname, base_name, overwrite);
+ }
+ if (!NT_STATUS_IS_OK(status))
+ return ERROR_NT(status);
+ process_pending_change_notify_queue((time_t)0);
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ return(-1);
+ }
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
}
@@ -2896,10 +3032,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
DEBUG(6,("size: %.0f ", (double)size));
- if (S_ISDIR(sbuf.st_mode))
- dosmode |= aDIR;
- else
- dosmode &= ~aDIR;
+ if (dosmode) {
+ if (S_ISDIR(sbuf.st_mode))
+ dosmode |= aDIR;
+ else
+ dosmode &= ~aDIR;
+ }
DEBUG(6,("dosmode: %x\n" , dosmode));
@@ -3030,8 +3168,7 @@ static int call_trans2mkdir(connection_struct *conn,
if(ret < 0) {
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
/* Realloc the parameter and data sizes */
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 8d3e7cd9be..7979ffe854 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -370,7 +370,7 @@ BOOL unbecome_user(void)
}
/*****************************************************************
- Convert the suplimentary SIDs returned in a netlogon into UNIX
+ Convert the supplementary SIDs returned in a netlogon into UNIX
group gid_t's. Add to the total group array.
*****************************************************************/
@@ -437,467 +437,4 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER
*pptok = new_tok;
}
-/*****************************************************************
- *THE CANONICAL* convert name to SID function.
- Tries local lookup first - for local domains - then uses winbind.
-*****************************************************************/
-
-BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
- fstring sid;
- BOOL local_lookup = False;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /* If we are looking up a domain user, make sure it is
- for the local machine only */
-
- if (strequal(global_myname(), domain)) {
- local_lookup = True;
- } else if (lp_server_role() == ROLE_DOMAIN_PDC ||
- lp_server_role() == ROLE_DOMAIN_BDC) {
- if (strequal(domain, lp_workgroup())) {
- local_lookup = True;
- }
- }
-
- if (local_lookup) {
- if (local_lookup_name(name, psid, name_type)) {
- DEBUG(10,
- ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
- domain, name, sid_to_string(sid,psid),
- sid_type_lookup(*name_type), (unsigned int)*name_type));
- return True;
- }
- } else {
- /* Remote */
- if (winbind_lookup_name(domain, name, psid, name_type)) {
-
- DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
- domain, name, sid_to_string(sid, psid),
- (unsigned int)*name_type));
- return True;
- }
- }
-
- DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n",
- local_lookup ? "local" : "winbind", domain, name));
-
- return False;
-}
-
-/*****************************************************************
- *THE CANONICAL* convert SID to name function.
- Tries local lookup first - for local sids, then tries winbind.
-*****************************************************************/
-
-BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
-{
- if (!name_type)
- return False;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /* Check if this is our own sid. This should perhaps be done by
- winbind? For the moment handle it here. */
-
- if (sid->num_auths == 5) {
- DOM_SID tmp_sid;
- uint32 rid;
-
- sid_copy(&tmp_sid, sid);
- sid_split_rid(&tmp_sid, &rid);
-
- if (sid_equal(get_global_sam_sid(), &tmp_sid)) {
-
- return map_domain_sid_to_name(&tmp_sid, dom_name) &&
- local_lookup_sid(sid, name, name_type);
- }
- }
-
- if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
- fstring sid_str;
- DOM_SID tmp_sid;
- uint32 rid;
-
- DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
-
- sid_copy(&tmp_sid, sid);
- sid_split_rid(&tmp_sid, &rid);
- return map_domain_sid_to_name(&tmp_sid, dom_name) &&
- lookup_known_rid(&tmp_sid, rid, name, name_type);
- }
- return True;
-}
-
-
-/*****************************************************************
- Id mapping cache. This is to avoid Winbind mappings already
- seen by smbd to be queried too frequently, keeping winbindd
- busy, and blocking smbd while winbindd is busy with other
- stuff. Written by Michael Steffens <michael.steffens@hp.com>,
- modified to use linked lists by jra.
-*****************************************************************/
-
-#define MAX_UID_SID_CACHE_SIZE 100
-#define TURNOVER_UID_SID_CACHE_SIZE 10
-#define MAX_GID_SID_CACHE_SIZE 100
-#define TURNOVER_GID_SID_CACHE_SIZE 10
-
-static size_t n_uid_sid_cache = 0;
-static size_t n_gid_sid_cache = 0;
-
-static struct uid_sid_cache {
- struct uid_sid_cache *next, *prev;
- uid_t uid;
- DOM_SID sid;
- enum SID_NAME_USE sidtype;
-} *uid_sid_cache_head;
-
-static struct gid_sid_cache {
- struct gid_sid_cache *next, *prev;
- gid_t gid;
- DOM_SID sid;
- enum SID_NAME_USE sidtype;
-} *gid_sid_cache_head;
-
-/*****************************************************************
- Find a SID given a uid.
-*****************************************************************/
-
-static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid)
-{
- struct uid_sid_cache *pc;
-
- for (pc = uid_sid_cache_head; pc; pc = pc->next) {
- if (pc->uid == uid) {
- fstring sid;
- *psid = pc->sid;
- DEBUG(3,("fetch sid from uid cache %u -> %s\n",
- (unsigned int)uid, sid_to_string(sid, psid)));
- DLIST_PROMOTE(uid_sid_cache_head, pc);
- return True;
- }
- }
- return False;
-}
-
-/*****************************************************************
- Find a uid given a SID.
-*****************************************************************/
-
-static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
-{
- struct uid_sid_cache *pc;
-
- for (pc = uid_sid_cache_head; pc; pc = pc->next) {
- if (sid_compare(&pc->sid, psid) == 0) {
- fstring sid;
- *puid = pc->uid;
- DEBUG(3,("fetch uid from cache %u -> %s\n",
- (unsigned int)*puid, sid_to_string(sid, psid)));
- DLIST_PROMOTE(uid_sid_cache_head, pc);
- return True;
- }
- }
- return False;
-}
-
-/*****************************************************************
- Store uid to SID mapping in cache.
-*****************************************************************/
-
-static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
-{
- struct uid_sid_cache *pc;
-
- if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) {
- /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */
- struct uid_sid_cache *pc_next;
- size_t i;
-
- for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next)
- ;
- for(; pc; pc = pc_next) {
- pc_next = pc->next;
- DLIST_REMOVE(uid_sid_cache_head,pc);
- SAFE_FREE(pc);
- n_uid_sid_cache--;
- }
- }
-
- pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache));
- if (!pc)
- return;
- pc->uid = uid;
- sid_copy(&pc->sid, psid);
- DLIST_ADD(uid_sid_cache_head, pc);
- n_uid_sid_cache++;
-}
-
-/*****************************************************************
- Find a SID given a gid.
-*****************************************************************/
-
-static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid)
-{
- struct gid_sid_cache *pc;
-
- for (pc = gid_sid_cache_head; pc; pc = pc->next) {
- if (pc->gid == gid) {
- fstring sid;
- *psid = pc->sid;
- DEBUG(3,("fetch sid from gid cache %u -> %s\n",
- (unsigned int)gid, sid_to_string(sid, psid)));
- DLIST_PROMOTE(gid_sid_cache_head, pc);
- return True;
- }
- }
- return False;
-}
-
-/*****************************************************************
- Find a gid given a SID.
-*****************************************************************/
-
-static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
-{
- struct gid_sid_cache *pc;
-
- for (pc = gid_sid_cache_head; pc; pc = pc->next) {
- if (sid_compare(&pc->sid, psid) == 0) {
- fstring sid;
- *pgid = pc->gid;
- DEBUG(3,("fetch uid from cache %u -> %s\n",
- (unsigned int)*pgid, sid_to_string(sid, psid)));
- DLIST_PROMOTE(gid_sid_cache_head, pc);
- return True;
- }
- }
- return False;
-}
-
-/*****************************************************************
- Store gid to SID mapping in cache.
-*****************************************************************/
-static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
-{
- struct gid_sid_cache *pc;
-
- if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) {
- /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */
- struct gid_sid_cache *pc_next;
- size_t i;
-
- for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next)
- ;
- for(; pc; pc = pc_next) {
- pc_next = pc->next;
- DLIST_REMOVE(gid_sid_cache_head,pc);
- SAFE_FREE(pc);
- n_gid_sid_cache--;
- }
- }
-
- pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache));
- if (!pc)
- return;
- pc->gid = gid;
- sid_copy(&pc->sid, psid);
- DLIST_ADD(gid_sid_cache_head, pc);
- n_gid_sid_cache++;
-}
-
-/*****************************************************************
- *THE CANONICAL* convert uid_t to SID function.
-*****************************************************************/
-
-NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
-{
- uid_t low, high;
- fstring sid;
-
- ZERO_STRUCTP(psid);
-
- if (fetch_sid_from_uid_cache(psid, uid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-
- if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) {
- if (winbind_uid_to_sid(psid, uid)) {
-
- DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
- (unsigned int)uid, sid_to_string(sid, psid)));
-
- if (psid)
- store_uid_sid_cache(psid, uid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
- }
-
- if (!local_uid_to_sid(psid, uid)) {
- DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid)));
-
- store_uid_sid_cache(psid, uid);
- return NT_STATUS_OK;
-}
-
-/*****************************************************************
- *THE CANONICAL* convert gid_t to SID function.
-*****************************************************************/
-
-NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
-{
- gid_t low, high;
- fstring sid;
-
- ZERO_STRUCTP(psid);
-
- if (fetch_sid_from_gid_cache(psid, gid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-
- if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) {
- if (winbind_gid_to_sid(psid, gid)) {
-
- DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
- (unsigned int)gid, sid_to_string(sid, psid)));
-
- if (psid)
- store_gid_sid_cache(psid, gid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
- }
-
- if (!local_gid_to_sid(psid, gid)) {
- DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
-
- store_gid_sid_cache(psid, gid);
- return NT_STATUS_OK;
-}
-
-/*****************************************************************
- *THE CANONICAL* convert SID to uid function.
-*****************************************************************/
-
-NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
-{
- fstring dom_name, name, sid_str;
- enum SID_NAME_USE name_type;
-
- if (fetch_uid_from_cache(puid, psid))
- return NT_STATUS_OK;
-
- /* if this is our SID then go straight to a local lookup */
-
- if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
- DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
- sid_string_static(psid) ));
-
- if ( local_sid_to_uid(puid, psid, &name_type) )
- goto success;
-
- DEBUG(10,("sid_to_uid: local lookup failed\n"));
-
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* If it is not our local domain, only hope is winbindd */
-
- if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) {
- DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
- sid_string_static(psid) ));
-
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* If winbindd does know the SID, ensure this is a user */
-
- if (name_type != SID_NAME_USER) {
- DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
- (unsigned int)name_type ));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* get the uid. Has to work or else we are dead in the water */
-
- if ( !winbind_sid_to_uid(puid, psid) ) {
- DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
- sid_to_string(sid_str, psid) ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
-success:
- DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid),
- (unsigned int)*puid ));
-
- store_uid_sid_cache(psid, *puid);
-
- return NT_STATUS_OK;
-}
-/*****************************************************************
- *THE CANONICAL* convert SID to gid function.
- Group mapping is used for gids that maps to Wellknown SIDs
-*****************************************************************/
-
-NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
-{
- fstring dom_name, name, sid_str;
- enum SID_NAME_USE name_type;
-
- if (fetch_gid_from_cache(pgid, psid))
- return NT_STATUS_OK;
-
- /*
- * First we must look up the name and decide if this is a group sid.
- * Group mapping can deal with foreign SIDs
- */
-
- if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
- DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
- sid_to_string(sid_str, psid) ));
-
- if ( local_sid_to_gid(pgid, psid, &name_type) )
- goto success;
-
- DEBUG(10,("sid_to_gid: no one knows this SID\n"));
-
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- /* winbindd knows it; Ensure this is a group sid */
-
- if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
- DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
- (unsigned int)name_type ));
-
- /* winbindd is running and knows about this SID. Just the wrong type.
- Don't fallback to a local lookup here */
-
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* winbindd knows it and it is a type of group; sid_to_gid must succeed
- or we are dead in the water */
-
- if ( !winbind_sid_to_gid(pgid, psid) ) {
- DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n",
- sid_to_string(sid_str, psid) ));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
-success:
- DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid),
- (unsigned int)*pgid ));
-
- store_gid_sid_cache(psid, *pgid);
-
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c
index 6ff2f586ba..a521d0113d 100644
--- a/source3/smbd/utmp.c
+++ b/source3/smbd/utmp.c
@@ -217,13 +217,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau
/* For w-files, first look for explicit "wtmp dir" */
if (uw_name[0] == 'w') {
pstrcpy(dirname,lp_wtmpdir());
- trim_string(dirname,"","/");
+ trim_char(dirname,'\0','/');
}
/* For u-files and non-explicit w-dir, look for "utmp dir" */
if (dirname == 0 || strlen(dirname) == 0) {
pstrcpy(dirname,lp_utmpdir());
- trim_string(dirname,"","/");
+ trim_char(dirname,'\0','/');
}
/* If explicit directory above, use it */
@@ -283,8 +283,12 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim)
* man page appears not to specify (hints non-NULL)
* A correspondent suggest at least ut_name should be NULL
*/
+#if defined(HAVE_UT_UT_NAME)
memset((char *)&u->ut_name, '\0', sizeof(u->ut_name));
+#endif
+#if defined(HAVE_UT_UT_HOST)
memset((char *)&u->ut_host, '\0', sizeof(u->ut_host));
+#endif
}
/* Stolen from logwtmp function in libutil.
* May be more locking/blocking is needed?
@@ -406,7 +410,9 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim)
else
ux.ut_syslen = 0;
#endif
+#if defined(HAVE_UT_UT_HOST)
utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host));
+#endif
uw_pathname(uname, "utmpx", ux_pathname);
uw_pathname(wname, "wtmpx", wx_pathname);
diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c
index 8d44a1a0fa..a76a7a6abd 100644
--- a/source3/smbd/vfs-wrap.c
+++ b/source3/smbd/vfs-wrap.c
@@ -49,6 +49,42 @@ SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *con
result = sys_disk_free(path, small_query, bsize, dfree, dsize);
return result;
}
+
+int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+ int result;
+
+ START_PROFILE(syscall_get_quota);
+ result = sys_get_quota(conn->connectpath, qtype, id, qt);
+ END_PROFILE(syscall_get_quota);
+ return result;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
+{
+#ifdef HAVE_SYS_QUOTAS
+ int result;
+
+ START_PROFILE(syscall_set_quota);
+ result = sys_set_quota(conn->connectpath, qtype, id, qt);
+ END_PROFILE(syscall_set_quota);
+ return result;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels)
+{
+ errno = ENOSYS;
+ return -1; /* Not implemented. */
+}
/* Directory operations */
@@ -756,36 +792,6 @@ int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct
return sys_acl_free_qualifier(qualifier, tagtype);
}
-int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
- int result;
-
- START_PROFILE(syscall_get_quota);
- result = sys_get_quota(conn->connectpath, qtype, id, qt);
- END_PROFILE(syscall_get_quota);
- return result;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
-{
-#ifdef HAVE_SYS_QUOTAS
- int result;
-
- START_PROFILE(syscall_set_quota);
- result = sys_set_quota(conn->connectpath, qtype, id, qt);
- END_PROFILE(syscall_set_quota);
- return result;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
/****************************************************************
Extended attribute operations.
*****************************************************************/
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 5f3abe7efe..753db4cece 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -56,6 +56,7 @@ static struct vfs_ops default_vfs = {
vfswrap_disk_free,
vfswrap_get_quota,
vfswrap_set_quota,
+ vfswrap_get_shadow_copy_data,
/* Directory operations */
@@ -140,7 +141,6 @@ static struct vfs_ops default_vfs = {
vfswrap_setxattr,
vfswrap_lsetxattr,
vfswrap_fsetxattr
-
}
};
@@ -233,10 +233,10 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
if (p) {
*p = 0;
module_param = p+1;
- trim_string(module_param, " ", " ");
+ trim_char(module_param, ' ', ' ');
}
- trim_string(module_name, " ", " ");
+ trim_char(module_name, ' ', ' ');
/* First, try to load the module with the new module system */
if((entry = vfs_find_backend_entry(module_name)) ||