summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/reply.c65
-rw-r--r--source3/smbd/sec_ctx.c2
-rw-r--r--source3/smbd/uid.c50
-rw-r--r--source3/smbd/vfs.c97
4 files changed, 141 insertions, 73 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index fa8aa11277..0b3b5bbe27 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1882,14 +1882,13 @@ static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
}
/****************************************************************************
- Reply to a unlink
+ The guts of the unlink command, split out so it may be called by the NT SMB
+ code.
****************************************************************************/
-int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+int unlink_internals(connection_struct *conn, char *inbuf,char *outbuf,
+ int dirtype, char *name)
{
- int outsize = 0;
- pstring name;
- int dirtype;
pstring directory;
pstring mask;
char *p;
@@ -1900,18 +1899,9 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
BOOL bad_path = False;
BOOL rc = True;
SMB_STRUCT_STAT sbuf;
- START_PROFILE(SMBunlink);
*directory = *mask = 0;
- dirtype = SVAL(inbuf,smb_vwv0);
-
- pstrcpy(name,smb_buf(inbuf) + 1);
-
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
-
- DEBUG(3,("reply_unlink : %s\n",name));
-
rc = unix_convert(name,conn,0,&bad_path,&sbuf);
p = strrchr(name,'/');
@@ -1975,29 +1965,58 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
if (!can_delete(fname,conn,dirtype)) continue;
if (!vfs_unlink(conn,fname)) count++;
- DEBUG(3,("reply_unlink : doing unlink on %s\n",fname));
+ DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
CloseDir(dirptr);
}
}
if (count == 0) {
- if (exists) {
- END_PROFILE(SMBunlink);
+ if (exists)
return(ERROR(ERRDOS,error));
- } else
- {
- if((errno == ENOENT) && bad_path)
- {
+ else {
+ if((errno == ENOENT) && bad_path) {
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
- END_PROFILE(SMBunlink);
return(UNIXERROR(ERRDOS,error));
}
}
+ return 0;
+}
+
+/****************************************************************************
+ Reply to a unlink
+****************************************************************************/
+
+int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+{
+ int outsize = 0;
+ pstring name;
+ int dirtype;
+ START_PROFILE(SMBunlink);
+
+ dirtype = SVAL(inbuf,smb_vwv0);
+
+ pstrcpy(name,smb_buf(inbuf) + 1);
+
+ RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+
+ DEBUG(3,("reply_unlink : %s\n",name));
+
+ outsize = unlink_internals(conn, inbuf, outbuf, dirtype, name);
+ if(outsize == 0) {
+
+ /*
+ * Win2k needs a changenotify request response before it will
+ * update after a rename..
+ */
+
+ process_pending_change_notify_queue((time_t)0);
+
outsize = set_message(outbuf,0,0,True);
+ }
END_PROFILE(SMBunlink);
return(outsize);
@@ -3589,7 +3608,6 @@ static BOOL can_rename(char *fname,connection_struct *conn)
if (conn->vfs_ops.lstat(conn,dos_to_unix(fname,False),&sbuf) != 0) return(False);
if (!check_file_sharing(conn,fname,True)) return(False);
-
return(True);
}
@@ -3718,6 +3736,7 @@ int rename_internals(connection_struct *conn,
* file with the same name so don't check for
* vfs_file_exist().
*/
+
if(resolve_wildcards(directory,newname) &&
can_rename(directory,conn) &&
!conn->vfs_ops.rename(conn,zdirectory,
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index ef446ed759..f3adcfce8f 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -221,7 +221,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/uid.c b/source3/smbd/uid.c
index d82edcbfae..008765cde1 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -243,8 +243,8 @@ BOOL unbecome_authenticated_pipe_user(pipes_struct *p)
return pop_sec_ctx();
}
-
/* Temporarily become a root user. Must match with unbecome_root(). */
+
void become_root(void)
{
push_sec_ctx();
@@ -267,25 +267,49 @@ BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
{
extern pstring global_myname;
fstring sid;
+ char *sep = lp_winbind_separator();
if (!winbind_lookup_name(name, psid, name_type)) {
BOOL ret;
- DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name ));
+ DEBUG(10, ("lookup_name: winbind lookup for %s failed - trying local\n", name));
+
+ /* If we are looking up a domain user, make sure it is
+ for the local machine only */
+
+ if (strchr(name, sep[0]) || strchr(name, '\\')) {
+ fstring domain, username;
+
+ split_domain_name(name, domain, username);
+
+ if (strcasecmp(global_myname, domain) != 0) {
+ DEBUG(5, ("domain %s is not local\n", domain));
+ return False;
+ }
+
+ ret = local_lookup_name(domain, username, psid,
+ name_type);
+ } else {
+
+ ret = local_lookup_name(global_myname, name, psid,
+ name_type);
+ }
+
+ if (ret) {
+ DEBUG(10,
+ ("lookup_name: (local) %s -> SID %s (type %u)\n",
+ name, sid_to_string(sid,psid),
+ (unsigned int)*name_type ));
+ } else {
+ DEBUG(10,("lookup name: (local) %s failed.\n", name));
+ }
- ret = local_lookup_name(global_myname, name, psid, name_type);
- if (ret)
- DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n",
- name, sid_to_string(sid,psid),
- (unsigned int)*name_type ));
- else
- DEBUG(10,("lookup name : (local) %s failed.\n",
- name ));
return ret;
}
- DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n",
- name, sid_to_string(sid,psid), (unsigned int)*name_type ));
+ DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n",
+ name, sid_to_string(sid, psid),
+ (unsigned int)*name_type));
return True;
}
@@ -300,7 +324,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE
return False;
/* Check if this is our own sid. This should perhaps be done by
- winbind? For the moment handle it here. */
+ winbind? For the moment handle it here. */
if (sid->num_auths == 5) {
DOM_SID tmp_sid;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 99c8e26fa8..77b42361ed 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1,19 +1,19 @@
-/*
+/*
Unix SMB/Netbios implementation.
Version 1.9.
VFS initialisation and support functions
Copyright (C) Tim Potter 1999
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -36,7 +36,7 @@ struct vfs_syminfo {
struct vfs_ops default_vfs_ops = {
- /* Disk operations */
+ /* Disk operations */
vfswrap_dummy_connect,
vfswrap_dummy_disconnect,
@@ -112,7 +112,7 @@ BOOL vfs_init_custom(connection_struct *conn)
init_fptr = (struct vfs_ops *(*)(int *))dlsym(conn->dl_handle, "vfs_init");
if (init_fptr == NULL) {
- DEBUG(0, ("No vfs_init() symbol found in %s\n",
+ DEBUG(0, ("No vfs_init() symbol found in %s\n",
lp_vfsobj(SNUM(conn))));
return False;
}
@@ -132,10 +132,10 @@ BOOL vfs_init_custom(connection_struct *conn)
/* Fill in unused operations with default (disk based) ones.
There's probably a neater way to do this then a whole bunch of
- if statements. */
+ if statements. */
memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops));
-
+
if (conn->vfs_ops.connect == NULL) {
conn->vfs_ops.connect = default_vfs_ops.connect;
}
@@ -179,47 +179,47 @@ BOOL vfs_init_custom(connection_struct *conn)
if (conn->vfs_ops.read == NULL) {
conn->vfs_ops.read = default_vfs_ops.read;
}
-
+
if (conn->vfs_ops.write == NULL) {
conn->vfs_ops.write = default_vfs_ops.write;
}
-
+
if (conn->vfs_ops.lseek == NULL) {
conn->vfs_ops.lseek = default_vfs_ops.lseek;
}
-
+
if (conn->vfs_ops.rename == NULL) {
conn->vfs_ops.rename = default_vfs_ops.rename;
}
-
+
if (conn->vfs_ops.fsync == NULL) {
conn->vfs_ops.fsync = default_vfs_ops.fsync;
}
-
+
if (conn->vfs_ops.stat == NULL) {
conn->vfs_ops.stat = default_vfs_ops.stat;
}
-
+
if (conn->vfs_ops.fstat == NULL) {
conn->vfs_ops.fstat = default_vfs_ops.fstat;
}
-
+
if (conn->vfs_ops.lstat == NULL) {
conn->vfs_ops.lstat = default_vfs_ops.lstat;
}
-
+
if (conn->vfs_ops.unlink == NULL) {
conn->vfs_ops.unlink = default_vfs_ops.unlink;
}
-
+
if (conn->vfs_ops.chmod == NULL) {
conn->vfs_ops.chmod = default_vfs_ops.chmod;
}
-
+
if (conn->vfs_ops.chown == NULL) {
conn->vfs_ops.chown = default_vfs_ops.chown;
}
-
+
if (conn->vfs_ops.chdir == NULL) {
conn->vfs_ops.chdir = default_vfs_ops.chdir;
}
@@ -227,15 +227,15 @@ BOOL vfs_init_custom(connection_struct *conn)
if (conn->vfs_ops.getwd == NULL) {
conn->vfs_ops.getwd = default_vfs_ops.getwd;
}
-
+
if (conn->vfs_ops.utime == NULL) {
conn->vfs_ops.utime = default_vfs_ops.utime;
}
-
+
if (conn->vfs_ops.ftruncate == NULL) {
conn->vfs_ops.ftruncate = default_vfs_ops.ftruncate;
}
-
+
if (conn->vfs_ops.lock == NULL) {
conn->vfs_ops.lock = default_vfs_ops.lock;
}
@@ -255,7 +255,7 @@ BOOL vfs_init_custom(connection_struct *conn)
if (conn->vfs_ops.set_nt_acl == NULL) {
conn->vfs_ops.set_nt_acl = default_vfs_ops.set_nt_acl;
}
-
+
return True;
}
#endif
@@ -272,7 +272,7 @@ BOOL vfs_directory_exist(connection_struct *conn, char *dname, SMB_STRUCT_STAT *
if (!st)
st = &st2;
- if (vfs_stat(conn,dname,st) != 0)
+ if (vfs_stat(conn,dname,st) != 0)
return(False);
ret = S_ISDIR(st->st_mode);
@@ -294,7 +294,7 @@ int vfs_mkdir(connection_struct *conn, char *fname, mode_t mode)
pstrcpy(name,dos_to_unix(fname,False)); /* paranoia copy */
if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) {
- /*
+ /*
* Check if high bits should have been set,
* then (if bits are missing): add them.
* Consider bits automagically set by UNIX, i.e. SGID bit from parent dir.
@@ -331,14 +331,39 @@ BOOL vfs_file_exist(connection_struct *conn,char *fname,SMB_STRUCT_STAT *sbuf)
sbuf = &st;
ZERO_STRUCTP(sbuf);
-
- if (vfs_stat(conn,fname,sbuf) != 0)
+
+ if (vfs_stat(conn,fname,sbuf) != 0)
return(False);
return(S_ISREG(sbuf->st_mode));
}
/****************************************************************************
+ Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
+****************************************************************************/
+
+ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
+{
+ size_t total=0;
+
+ while (total < byte_count)
+ {
+ ssize_t ret = fsp->conn->vfs_ops.read(fsp, fsp->fd, buf + total,
+ byte_count - total);
+
+ if (ret == 0) return total;
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
+}
+
+/****************************************************************************
Write data to a fd on the vfs.
****************************************************************************/
@@ -363,11 +388,11 @@ ssize_t vfs_write_data(files_struct *fsp,char *buffer,size_t N)
Transfer some data between two file_struct's.
****************************************************************************/
-SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
+SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
int out_fd, files_struct *out_fsp,
SMB_OFF_T n, char *header, int headlen, int align)
{
- static char *buf=NULL;
+ static char *buf=NULL;
static int size=0;
char *buf1,*abuf;
SMB_OFF_T total = 0;
@@ -425,7 +450,7 @@ SMB_OFF_T vfs_transfer_file(int in_fd, files_struct *in_fsp,
}
if (s > ret) {
- ret += in_fsp ?
+ ret += in_fsp ?
in_fsp->conn->vfs_ops.read(in_fsp,in_fsp->fd,buf1+ret,s-ret) : read(in_fd,buf1+ret,s-ret);
}
@@ -459,7 +484,7 @@ char *vfs_readdirname(connection_struct *conn, void *p)
if (!p)
return(NULL);
-
+
ptr = (struct dirent *)conn->vfs_ops.readdir(conn,p);
if (!ptr)
return(NULL);
@@ -497,7 +522,7 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr)
{
struct vfs_options *new_option, **options = (struct vfs_options **)ptr;
int i;
-
+
/* Create new vfs option */
new_option = (struct vfs_options *)malloc(sizeof(*new_option));
@@ -508,7 +533,7 @@ static BOOL handle_vfs_option(char *pszParmValue, char **ptr)
ZERO_STRUCTP(new_option);
/* Get name and value */
-
+
new_option->name = strtok(pszParmValue, "=");
if (new_option->name == NULL) {
@@ -714,7 +739,7 @@ char *vfs_GetWd(connection_struct *conn, char *path)
}
/*******************************************************************
- Reduce a file name, removing .. elements and checking that
+ Reduce a file name, removing .. elements and checking that
it is below dir in the heirachy. This uses vfs_GetWd() and so must be run
on the system that has the referenced file system.
Widelinks are allowed if widelinks is true.
@@ -749,7 +774,7 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks)
return(True);
}
-
+
DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
/* remove any double slashes */
@@ -810,7 +835,7 @@ BOOL reduce_name(connection_struct *conn, char *s,char *dir,BOOL widelinks)
}
{
- size_t l = strlen(dir2);
+ size_t l = strlen(dir2);
if (dir2[l-1] == '/')
l--;