summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/build_options.c28
-rw-r--r--source3/smbd/change_trust_pw.c10
-rw-r--r--source3/smbd/chgpasswd.c4
-rw-r--r--source3/smbd/conn.c2
-rw-r--r--source3/smbd/dir.c156
-rw-r--r--source3/smbd/fileio.c779
-rw-r--r--source3/smbd/filename.c760
-rw-r--r--source3/smbd/groupname.c5
-rw-r--r--source3/smbd/ipc.c2
-rw-r--r--source3/smbd/lanman.c424
-rw-r--r--source3/smbd/mangle.c21
-rw-r--r--source3/smbd/mangle_hash.c534
-rw-r--r--source3/smbd/mangle_hash2.c110
-rw-r--r--source3/smbd/mangle_map.c4
-rw-r--r--source3/smbd/message.c10
-rw-r--r--source3/smbd/negprot.c380
-rw-r--r--source3/smbd/notify_kernel.c109
-rw-r--r--source3/smbd/nttrans.c568
-rw-r--r--source3/smbd/open.c18
-rw-r--r--source3/smbd/oplock.c79
-rw-r--r--source3/smbd/oplock_irix.c30
-rw-r--r--source3/smbd/oplock_linux.c57
-rw-r--r--source3/smbd/password.c182
-rw-r--r--source3/smbd/pipes.c2
-rw-r--r--source3/smbd/posix_acls.c180
-rw-r--r--source3/smbd/process.c65
-rw-r--r--source3/smbd/reply.c93
-rw-r--r--source3/smbd/sec_ctx.c39
-rw-r--r--source3/smbd/server.c23
-rw-r--r--source3/smbd/service.c393
-rw-r--r--source3/smbd/session.c52
-rw-r--r--source3/smbd/sesssetup.c88
-rw-r--r--source3/smbd/srvstr.c9
-rw-r--r--source3/smbd/trans2.c2623
-rw-r--r--source3/smbd/uid.c15
-rw-r--r--source3/smbd/vfs-wrap.c4
-rw-r--r--source3/smbd/vfs.c8
37 files changed, 4406 insertions, 3460 deletions
diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c
index 1d18f534b1..f52c53dda5 100644
--- a/source3/smbd/build_options.c
+++ b/source3/smbd/build_options.c
@@ -89,6 +89,12 @@ void build_options(BOOL screen)
#ifdef HAVE_KRB5
output(screen," HAVE_KRB5");
#endif
+#ifdef HAVE_GSSAPI
+ output(screen," HAVE_GSSAPI");
+#endif
+#ifdef HAVE_LDAP
+ output(screen," HAVE_LDAP");
+#endif
#ifdef WITH_AUTOMOUNT
output(screen," WITH_AUTOMOUNT\n");
#endif
@@ -101,9 +107,6 @@ void build_options(BOOL screen)
#ifdef WITH_TDB_SAM
output(screen," WITH_TDB_SAM\n");
#endif
-#ifdef WITH_LDAP_SAM
- output(screen," WITH_LDAP_SAM\n");
-#endif
#ifdef WITH_SMBPASSWD_SAM
output(screen," WITH_SMBPASSWD_SAM\n");
#endif
@@ -113,12 +116,6 @@ void build_options(BOOL screen)
#ifdef WITH_NISPLUS_HOME
output(screen," WITH_NISPLUS_HOME\n");
#endif
-#ifdef WITH_SSL
- output(screen," WITH_SSL\n");
-#endif
-#ifdef SSL_DIR
- output(screen," SSL_DIR: %s\n",SSL_DIR);
-#endif
#ifdef WITH_SYSLOG
output(screen," WITH_SYSLOG\n");
#endif
@@ -220,8 +217,17 @@ void build_options(BOOL screen)
#ifdef HAVE_CUPS_LANGUAGE_H
output(screen," HAVE_CUPS_LANGUAGE_H\n");
#endif
-#ifdef HAVE_LIBDL
- output(screen," HAVE_LIBDL\n");
+#ifdef HAVE_DLOPEN
+ output(screen," HAVE_DLOPEN\n");
+#endif
+#ifdef HAVE_DLCLOSE
+ output(screen," HAVE_DLCLOSE\n");
+#endif
+#ifdef HAVE_DLSYM
+ output(screen," HAVE_DLSYM\n");
+#endif
+#ifdef HAVE_DLERROR
+ output(screen," HAVE_DLERROR\n");
#endif
#ifdef HAVE_UNIXSOCKET
output(screen," HAVE_UNIXSOCKET\n");
diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c
index 0d80d5718f..0c468699b4 100644
--- a/source3/smbd/change_trust_pw.c
+++ b/source3/smbd/change_trust_pw.c
@@ -35,7 +35,6 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine,
{
struct cli_state *cli;
DOM_SID domain_sid;
- struct in_addr dest_ip;
NTSTATUS nt_status;
/*
@@ -43,17 +42,12 @@ static NTSTATUS modify_trust_password( char *domain, char *remote_machine,
*/
if (!secrets_fetch_domain_sid(domain, &domain_sid)) {
- DEBUG(0, ("domain_client_validate: unable to fetch domain sid.\n"));
+ DEBUG(0, ("modify_trust_password: unable to fetch domain sid.\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- if(!resolve_name( remote_machine, &dest_ip, 0x20)) {
- DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname, remote_machine,
- &dest_ip, 0,
+ NULL, 0,
"IPC$", "IPC",
"", "",
"", 0))) {
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index eed535cf11..68871deb90 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -472,6 +472,10 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
struct passwd *pass;
+ if (!name) {
+ DEBUG(1, ("NULL username specfied to chgpasswd()!\n"));
+ }
+
DEBUG(3, ("Password change for user: %s\n", name));
#if DEBUG_PASSWORD
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index f552d4a224..c0aa447016 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -166,7 +166,7 @@ void conn_free(connection_struct *conn)
if (conn->dl_handle != NULL) {
/* Close dlopen() handle */
- dlclose(conn->dl_handle);
+ sys_dlclose(conn->dl_handle);
}
DLIST_REMOVE(Connections, conn);
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index f56e0e9ef0..7dd425ef8a 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -558,6 +558,12 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di
return True;
}
+static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask)
+{
+ mangle_map(filename,True,False,SNUM(conn));
+ return mask_match(filename,mask,False);
+}
+
/****************************************************************************
Get an 8.3 directory entry.
****************************************************************************/
@@ -603,8 +609,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,
*/
if ((strcmp(mask,"*.*") == 0) ||
mask_match(filename,mask,False) ||
- (mangle_map(filename,True,False,SNUM(conn)) &&
- mask_match(filename,mask,False)))
+ mangle_mask_match(conn,filename,mask))
{
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
continue;
@@ -680,7 +685,15 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
ZERO_STRUCT(ste);
- /* if we can't stat it does not show it */
+ /*
+ * If user is a member of the Admin group
+ * we never hide files from them.
+ */
+
+ if (conn->admin_user)
+ return True;
+
+ /* If we can't stat it does not show it */
if (vfs_stat(conn, name, &ste) != 0)
return False;
@@ -714,73 +727,80 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
{
- Dir *dirp;
- char *n;
- DIR *p = conn->vfs_ops.opendir(conn,name);
- int used=0;
-
- if (!p) return(NULL);
- dirp = (Dir *)malloc(sizeof(Dir));
- if (!dirp) {
- DEBUG(0,("Out of memory in OpenDir\n"));
- conn->vfs_ops.closedir(conn,p);
- return(NULL);
- }
- dirp->pos = dirp->numentries = dirp->mallocsize = 0;
- dirp->data = dirp->current = NULL;
-
- while (True)
- {
- int l;
-
- if (used == 0) {
- n = ".";
- } else if (used == 2) {
- n = "..";
- } else {
- n = vfs_readdirname(conn, p);
- if (n == NULL)
- break;
- if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0))
- continue;
- }
-
- l = strlen(n)+1;
-
- /* If it's a vetoed file, pretend it doesn't even exist */
- if (use_veto && conn && IS_VETO_PATH(conn, n)) continue;
-
- /* Honour _hide unreadable_ option */
- if (conn && lp_hideunreadable(SNUM(conn))) {
- char *entry;
- int ret=0;
+ Dir *dirp;
+ char *n;
+ DIR *p = conn->vfs_ops.opendir(conn,name);
+ int used=0;
+
+ if (!p)
+ return(NULL);
+ dirp = (Dir *)malloc(sizeof(Dir));
+ if (!dirp) {
+ DEBUG(0,("Out of memory in OpenDir\n"));
+ conn->vfs_ops.closedir(conn,p);
+ return(NULL);
+ }
+ dirp->pos = dirp->numentries = dirp->mallocsize = 0;
+ dirp->data = dirp->current = NULL;
+
+ while (True) {
+ int l;
+ BOOL normal_entry = True;
+
+ if (used == 0) {
+ n = ".";
+ normal_entry = False;
+ } else if (used == 2) {
+ n = "..";
+ normal_entry = False;
+ } else {
+ n = vfs_readdirname(conn, p);
+ if (n == NULL)
+ break;
+ if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0))
+ continue;
+ normal_entry = True;
+ }
+
+ l = strlen(n)+1;
+
+ /* If it's a vetoed file, pretend it doesn't even exist */
+ if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n))
+ continue;
+
+ /* Honour _hide unreadable_ option */
+ if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
+ char *entry;
+ int ret=0;
- if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = user_can_read_file(conn, entry);
- SAFE_FREE(entry);
- }
- if (!ret) continue;
- }
-
- if (used + l > dirp->mallocsize) {
- int s = MAX(used+l,used+2000);
- char *r;
- r = (char *)Realloc(dirp->data,s);
- if (!r) {
- DEBUG(0,("Out of memory in OpenDir\n"));
- break;
- }
- dirp->data = r;
- dirp->mallocsize = s;
- dirp->current = dirp->data;
- }
- pstrcpy(dirp->data+used,n);
- used += l;
- dirp->numentries++;
- }
+ if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
+ ret = user_can_read_file(conn, entry);
+ SAFE_FREE(entry);
+ }
+ if (!ret)
+ continue;
+ }
+
+ if (used + l > dirp->mallocsize) {
+ int s = MAX(used+l,used+2000);
+ char *r;
+ r = (char *)Realloc(dirp->data,s);
+ if (!r) {
+ DEBUG(0,("Out of memory in OpenDir\n"));
+ break;
+ }
+ dirp->data = r;
+ dirp->mallocsize = s;
+ dirp->current = dirp->data;
+ }
+
+ pstrcpy(dirp->data+used,n);
+ used += l;
+ dirp->numentries++;
+ }
- conn->vfs_ops.closedir(conn,p);
- return((void *)dirp);
+ conn->vfs_ops.closedir(conn,p);
+ return((void *)dirp);
}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index addbcb0b3c..710ba396d8 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -1,7 +1,9 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
read/write to a files_struct
Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 2000-2002. - write cache.
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
@@ -23,31 +25,32 @@
static BOOL setup_write_cache(files_struct *, SMB_OFF_T);
/****************************************************************************
-seek a file. Try to avoid the seek if possible
+ Seek a file. Try to avoid the seek if possible.
****************************************************************************/
-SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos)
+static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos)
{
- SMB_OFF_T offset = 0;
- SMB_OFF_T seek_ret;
+ SMB_OFF_T offset = 0;
+ SMB_OFF_T seek_ret;
- if (fsp->print_file && lp_postscript(fsp->conn->service))
- offset = 3;
+ if (fsp->print_file && lp_postscript(fsp->conn->service))
+ offset = 3;
- seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET);
+ seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos+offset,SEEK_SET);
- if(seek_ret == -1) {
- DEBUG(0,("seek_file: sys_lseek failed. Error was %s\n", strerror(errno) ));
- fsp->pos = -1;
- return -1;
- }
+ if(seek_ret == -1) {
+ DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n",
+ fsp->fsp_name, strerror(errno) ));
+ fsp->pos = -1;
+ return -1;
+ }
- fsp->pos = seek_ret - offset;
+ fsp->pos = seek_ret - offset;
- DEBUG(10,("seek_file: requested pos = %.0f, new pos = %.0f\n",
- (double)(pos+offset), (double)fsp->pos ));
+ DEBUG(10,("seek_file (%s): requested pos = %.0f, new pos = %.0f\n",
+ fsp->fsp_name, (double)(pos+offset), (double)fsp->pos ));
- return(fsp->pos);
+ return(fsp->pos);
}
/****************************************************************************
@@ -55,25 +58,25 @@ SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos)
****************************************************************************/
-BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
+static BOOL read_from_write_cache(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
{
- write_cache *wcp = fsp->wcp;
+ write_cache *wcp = fsp->wcp;
- if(!wcp)
- return False;
+ if(!wcp)
+ return False;
- if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size)
- return False;
+ if(n > wcp->data_size || pos < wcp->offset || pos + n > wcp->offset + wcp->data_size)
+ return False;
- memcpy(data, wcp->data + (pos - wcp->offset), n);
+ memcpy(data, wcp->data + (pos - wcp->offset), n);
- DO_PROFILE_INC(writecache_read_hits);
+ DO_PROFILE_INC(writecache_read_hits);
- return True;
+ return True;
}
/****************************************************************************
-read from a file
+ Read from a file.
****************************************************************************/
ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
@@ -121,6 +124,9 @@ tryagain:
ret += readret;
}
+ DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
+ fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
+
return(ret);
}
@@ -133,10 +139,17 @@ static unsigned int allocated_write_caches;
static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_t n)
{
- if ((pos != -1) && (seek_file(fsp,pos) == -1))
- return -1;
+ ssize_t ret;
+
+ if ((pos != -1) && (seek_file(fsp,pos) == -1))
+ return -1;
+
+ ret = vfs_write_data(fsp,data,n);
+
+ DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
+ fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
- return vfs_write_data(fsp,data,n);
+ return ret;
}
/****************************************************************************
@@ -145,367 +158,365 @@ write to a file
ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
{
- write_cache *wcp = fsp->wcp;
- ssize_t total_written = 0;
- int write_path = -1;
-
- if (fsp->print_file) {
- return print_job_write(fsp->print_jobid, data, n);
- }
-
- if (!fsp->can_write) {
- errno = EPERM;
- return(0);
- }
-
- if (!fsp->modified) {
- SMB_STRUCT_STAT st;
- fsp->modified = True;
-
- if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) {
- int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
- fsp->size = st.st_size;
- if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) {
- file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
- }
-
- /*
- * If this is the first write and we have an exclusive oplock then setup
- * the write cache.
- */
-
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) {
- setup_write_cache(fsp, st.st_size);
- wcp = fsp->wcp;
- }
- }
- }
+ write_cache *wcp = fsp->wcp;
+ ssize_t total_written = 0;
+ int write_path = -1;
+
+ if (fsp->print_file)
+ return print_job_write(fsp->print_jobid, data, n);
+
+ if (!fsp->can_write) {
+ errno = EPERM;
+ return(0);
+ }
+
+ if (!fsp->modified) {
+ SMB_STRUCT_STAT st;
+ fsp->modified = True;
+
+ if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) {
+ int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
+ fsp->size = st.st_size;
+ if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode))
+ file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
+
+ /*
+ * If this is the first write and we have an exclusive oplock then setup
+ * the write cache.
+ */
+
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) {
+ setup_write_cache(fsp, st.st_size);
+ wcp = fsp->wcp;
+ }
+ }
+ }
#ifdef WITH_PROFILE
- DO_PROFILE_INC(writecache_total_writes);
- if (!fsp->oplock_type) {
- DO_PROFILE_INC(writecache_non_oplock_writes);
- }
+ DO_PROFILE_INC(writecache_total_writes);
+ if (!fsp->oplock_type) {
+ DO_PROFILE_INC(writecache_non_oplock_writes);
+ }
#endif
- /*
- * If this file is level II oplocked then we need
- * to grab the shared memory lock and inform all
- * other files with a level II lock that they need
- * to flush their read caches. We keep the lock over
- * the shared memory area whilst doing this.
- */
+ /*
+ * If this file is level II oplocked then we need
+ * to grab the shared memory lock and inform all
+ * other files with a level II lock that they need
+ * to flush their read caches. We keep the lock over
+ * the shared memory area whilst doing this.
+ */
- release_level_2_oplocks_on_change(fsp);
+ release_level_2_oplocks_on_change(fsp);
#ifdef WITH_PROFILE
- if (profile_p && profile_p->writecache_total_writes % 500 == 0) {
- DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \
+ if (profile_p && profile_p->writecache_total_writes % 500 == 0) {
+ DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \
nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
- profile_p->writecache_init_writes,
- profile_p->writecache_abutted_writes,
- profile_p->writecache_total_writes,
- profile_p->writecache_non_oplock_writes,
- profile_p->writecache_allocated_write_caches,
- profile_p->writecache_num_write_caches,
- profile_p->writecache_direct_writes,
- profile_p->writecache_num_perfect_writes,
- profile_p->writecache_read_hits ));
-
- DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n",
- profile_p->writecache_flushed_writes[SEEK_FLUSH],
- profile_p->writecache_flushed_writes[READ_FLUSH],
- profile_p->writecache_flushed_writes[WRITE_FLUSH],
- profile_p->writecache_flushed_writes[READRAW_FLUSH],
- profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH],
- profile_p->writecache_flushed_writes[CLOSE_FLUSH],
- profile_p->writecache_flushed_writes[SYNC_FLUSH] ));
- }
+ profile_p->writecache_init_writes,
+ profile_p->writecache_abutted_writes,
+ profile_p->writecache_total_writes,
+ profile_p->writecache_non_oplock_writes,
+ profile_p->writecache_allocated_write_caches,
+ profile_p->writecache_num_write_caches,
+ profile_p->writecache_direct_writes,
+ profile_p->writecache_num_perfect_writes,
+ profile_p->writecache_read_hits ));
+
+ DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n",
+ profile_p->writecache_flushed_writes[SEEK_FLUSH],
+ profile_p->writecache_flushed_writes[READ_FLUSH],
+ profile_p->writecache_flushed_writes[WRITE_FLUSH],
+ profile_p->writecache_flushed_writes[READRAW_FLUSH],
+ profile_p->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH],
+ profile_p->writecache_flushed_writes[CLOSE_FLUSH],
+ profile_p->writecache_flushed_writes[SYNC_FLUSH] ));
+ }
#endif
- if(!wcp) {
- DO_PROFILE_INC(writecache_direct_writes);
- total_written = real_write_file(fsp, data, pos, n);
- if ((total_written != -1) && (pos + total_written > fsp->size))
- fsp->size = pos + total_written;
- return total_written;
- }
+ if(!wcp) {
+ DO_PROFILE_INC(writecache_direct_writes);
+ total_written = real_write_file(fsp, data, pos, n);
+ if ((total_written != -1) && (pos + total_written > fsp->size))
+ fsp->size = pos + total_written;
+ return total_written;
+ }
- DEBUG(9,("write_file(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n",
- fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
+ 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));
- /*
- * If we have active cache and it isn't contiguous then we flush.
- * NOTE: There is a small problem with running out of disk ....
- */
+ /*
+ * If we have active cache and it isn't contiguous then we flush.
+ * NOTE: There is a small problem with running out of disk ....
+ */
- if (wcp->data_size) {
+ if (wcp->data_size) {
- BOOL cache_flush_needed = False;
+ BOOL cache_flush_needed = False;
- if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) {
+ if ((pos >= wcp->offset) && (pos <= wcp->offset + wcp->data_size)) {
- /*
- * Start of write overlaps or abutts the existing data.
- */
+ /*
+ * Start of write overlaps or abutts the existing data.
+ */
- size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n);
+ size_t data_used = MIN((wcp->alloc_size - (pos - wcp->offset)), n);
- memcpy(wcp->data + (pos - wcp->offset), data, data_used);
+ memcpy(wcp->data + (pos - wcp->offset), data, data_used);
- /*
- * Update the current buffer size with the new data.
- */
+ /*
+ * Update the current buffer size with the new data.
+ */
- if(pos + data_used > wcp->offset + wcp->data_size)
- wcp->data_size = pos + data_used - wcp->offset;
+ if(pos + data_used > wcp->offset + wcp->data_size)
+ wcp->data_size = pos + data_used - wcp->offset;
- /*
- * Update the file size if changed.
- */
+ /*
+ * Update the file size if changed.
+ */
- if (wcp->offset + wcp->data_size > wcp->file_size)
- fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
+ if (wcp->offset + wcp->data_size > wcp->file_size)
+ fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
- /*
- * If we used all the data then
- * return here.
- */
+ /*
+ * If we used all the data then
+ * return here.
+ */
- if(n == data_used)
- return n;
- else
- cache_flush_needed = True;
+ if(n == data_used)
+ return n;
+ else
+ cache_flush_needed = True;
- /*
- * Move the start of data forward by the amount used,
- * cut down the amount left by the same amount.
- */
+ /*
+ * Move the start of data forward by the amount used,
+ * cut down the amount left by the same amount.
+ */
- data += data_used;
- pos += data_used;
- n -= data_used;
+ data += data_used;
+ pos += data_used;
+ n -= data_used;
- DO_PROFILE_INC(writecache_abutted_writes);
- total_written = data_used;
+ DO_PROFILE_INC(writecache_abutted_writes);
+ total_written = data_used;
- write_path = 1;
+ write_path = 1;
- } else if ((pos < wcp->offset) && (pos + n > wcp->offset) &&
- (pos + n <= wcp->offset + wcp->alloc_size)) {
+ } else if ((pos < wcp->offset) && (pos + n > wcp->offset) &&
+ (pos + n <= wcp->offset + wcp->alloc_size)) {
- /*
- * End of write overlaps the existing data.
- */
+ /*
+ * End of write overlaps the existing data.
+ */
- size_t data_used = pos + n - wcp->offset;
+ size_t data_used = pos + n - wcp->offset;
- memcpy(wcp->data, data + n - data_used, data_used);
+ memcpy(wcp->data, data + n - data_used, data_used);
- /*
- * Update the current buffer size with the new data.
- */
+ /*
+ * Update the current buffer size with the new data.
+ */
- if(pos + n > wcp->offset + wcp->data_size)
- wcp->data_size = pos + n - wcp->offset;
+ if(pos + n > wcp->offset + wcp->data_size)
+ wcp->data_size = pos + n - wcp->offset;
- /*
- * Update the file size if changed.
- */
+ /*
+ * Update the file size if changed.
+ */
- if (wcp->offset + wcp->data_size > wcp->file_size)
- fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
+ if (wcp->offset + wcp->data_size > wcp->file_size)
+ fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
- /*
- * We don't need to move the start of data, but we
- * cut down the amount left by the amount used.
- */
+ /*
+ * We don't need to move the start of data, but we
+ * cut down the amount left by the amount used.
+ */
- n -= data_used;
+ n -= data_used;
- /*
- * We cannot have used all the data here.
- */
+ /*
+ * We cannot have used all the data here.
+ */
- cache_flush_needed = True;
+ cache_flush_needed = True;
- DO_PROFILE_INC(writecache_abutted_writes);
- total_written = data_used;
+ DO_PROFILE_INC(writecache_abutted_writes);
+ total_written = data_used;
- write_path = 2;
+ write_path = 2;
- } else if ( (pos >= wcp->file_size) &&
- (wcp->offset + wcp->data_size == wcp->file_size) &&
- (pos > wcp->offset + wcp->data_size) &&
- (pos < wcp->offset + wcp->alloc_size) ) {
+ } else if ( (pos >= wcp->file_size) &&
+ (wcp->offset + wcp->data_size == wcp->file_size) &&
+ (pos > wcp->offset + wcp->data_size) &&
+ (pos < wcp->offset + wcp->alloc_size) ) {
- /*
- * Non-contiguous write part of which fits within
- * the cache buffer and is extending the file
- * and the cache contents reflect the current
- * data up to the current end of the file.
- */
+ /*
+ * Non-contiguous write part of which fits within
+ * the cache buffer and is extending the file
+ * and the cache contents reflect the current
+ * data up to the current end of the file.
+ */
- size_t data_used;
+ size_t data_used;
- if(pos + n <= wcp->offset + wcp->alloc_size)
- data_used = n;
- else
- data_used = wcp->offset + wcp->alloc_size - pos;
+ if(pos + n <= wcp->offset + wcp->alloc_size)
+ data_used = n;
+ else
+ data_used = wcp->offset + wcp->alloc_size - pos;
- /*
- * Fill in the non-continuous area with zeros.
- */
+ /*
+ * Fill in the non-continuous area with zeros.
+ */
- memset(wcp->data + wcp->data_size, '\0',
- pos - (wcp->offset + wcp->data_size) );
+ memset(wcp->data + wcp->data_size, '\0',
+ pos - (wcp->offset + wcp->data_size) );
- memcpy(wcp->data + (pos - wcp->offset), data, data_used);
+ memcpy(wcp->data + (pos - wcp->offset), data, data_used);
- /*
- * Update the current buffer size with the new data.
- */
+ /*
+ * Update the current buffer size with the new data.
+ */
- if(pos + data_used > wcp->offset + wcp->data_size)
- wcp->data_size = pos + data_used - wcp->offset;
+ if(pos + data_used > wcp->offset + wcp->data_size)
+ wcp->data_size = pos + data_used - wcp->offset;
- /*
- * Update the file size if changed.
- */
+ /*
+ * Update the file size if changed.
+ */
- if (wcp->offset + wcp->data_size > wcp->file_size)
- fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
+ if (wcp->offset + wcp->data_size > wcp->file_size)
+ fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
- /*
- * If we used all the data then
- * return here.
- */
+ /*
+ * If we used all the data then
+ * return here.
+ */
- if(n == data_used)
- return n;
- else
- cache_flush_needed = True;
+ if(n == data_used)
+ return n;
+ else
+ cache_flush_needed = True;
- /*
- * Move the start of data forward by the amount used,
- * cut down the amount left by the same amount.
- */
+ /*
+ * Move the start of data forward by the amount used,
+ * cut down the amount left by the same amount.
+ */
- data += data_used;
- pos += data_used;
- n -= data_used;
+ data += data_used;
+ pos += data_used;
+ n -= data_used;
- DO_PROFILE_INC(writecache_abutted_writes);
- total_written = data_used;
+ DO_PROFILE_INC(writecache_abutted_writes);
+ total_written = data_used;
- write_path = 3;
+ write_path = 3;
- } else {
+ } else {
- /*
- * Write is bigger than buffer, or there is no overlap on the
- * low or high ends.
- */
+ /*
+ * Write is bigger than buffer, or there is no overlap on the
+ * low or high ends.
+ */
- DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \
+ DEBUG(9,("write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \
len = %u\n",fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size ));
- /*
- * Update the file size if needed.
- */
+ /*
+ * Update the file size if needed.
+ */
- if(pos + n > wcp->file_size)
- fsp->size = wcp->file_size = pos + n;
+ if(pos + n > wcp->file_size)
+ fsp->size = wcp->file_size = pos + n;
- /*
- * If write would fit in the cache, and is larger than
- * the data already in the cache, flush the cache and
- * preferentially copy the data new data into it. Otherwise
- * just write the data directly.
- */
+ /*
+ * If write would fit in the cache, and is larger than
+ * the data already in the cache, flush the cache and
+ * preferentially copy the data new data into it. Otherwise
+ * just write the data directly.
+ */
- if ( n <= wcp->alloc_size && n > wcp->data_size) {
- cache_flush_needed = True;
- } else {
- ssize_t ret = real_write_file(fsp, data, pos, n);
+ if ( n <= wcp->alloc_size && n > wcp->data_size) {
+ cache_flush_needed = True;
+ } else {
+ ssize_t ret = real_write_file(fsp, data, pos, n);
- DO_PROFILE_INC(writecache_direct_writes);
- if (ret == -1)
- return ret;
+ DO_PROFILE_INC(writecache_direct_writes);
+ if (ret == -1)
+ return ret;
- if (pos + ret > wcp->file_size)
- fsp->size = wcp->file_size = pos + ret;
+ if (pos + ret > wcp->file_size)
+ fsp->size = wcp->file_size = pos + ret;
- return ret;
- }
+ return ret;
+ }
- write_path = 4;
+ write_path = 4;
- }
+ }
- if(wcp->data_size > wcp->file_size)
- fsp->size = wcp->file_size = wcp->data_size;
+ if(wcp->data_size > wcp->file_size)
+ fsp->size = wcp->file_size = wcp->data_size;
- if (cache_flush_needed) {
- DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \
+ if (cache_flush_needed) {
+ DEBUG(3,("WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \
n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
- write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n,
- (double)wcp->offset, (unsigned int)wcp->data_size ));
+ write_path, fsp->fd, (double)wcp->file_size, (double)pos, (unsigned int)n,
+ (double)wcp->offset, (unsigned int)wcp->data_size ));
- flush_write_cache(fsp, WRITE_FLUSH);
- }
- }
+ flush_write_cache(fsp, WRITE_FLUSH);
+ }
+ }
- /*
- * If the write request is bigger than the cache
- * size, write it all out.
- */
+ /*
+ * If the write request is bigger than the cache
+ * size, write it all out.
+ */
- if (n > wcp->alloc_size ) {
- ssize_t ret = real_write_file(fsp, data, pos, n);
- if (ret == -1)
- return -1;
+ if (n > wcp->alloc_size ) {
+ ssize_t ret = real_write_file(fsp, data, pos, n);
+ if (ret == -1)
+ return -1;
- if (pos + ret > wcp->file_size)
- fsp->size = wcp->file_size = pos + n;
+ if (pos + ret > wcp->file_size)
+ fsp->size = wcp->file_size = pos + n;
- DO_PROFILE_INC(writecache_direct_writes);
- return total_written + n;
- }
+ DO_PROFILE_INC(writecache_direct_writes);
+ return total_written + n;
+ }
- /*
- * If there's any data left, cache it.
- */
+ /*
+ * If there's any data left, cache it.
+ */
- if (n) {
+ if (n) {
#ifdef WITH_PROFILE
- if (wcp->data_size) {
- DO_PROFILE_INC(writecache_abutted_writes);
- } else {
- DO_PROFILE_INC(writecache_init_writes);
- }
+ if (wcp->data_size) {
+ DO_PROFILE_INC(writecache_abutted_writes);
+ } else {
+ DO_PROFILE_INC(writecache_init_writes);
+ }
#endif
- memcpy(wcp->data+wcp->data_size, data, n);
- if (wcp->data_size == 0) {
- wcp->offset = pos;
- DO_PROFILE_INC(writecache_num_write_caches);
- }
- wcp->data_size += n;
-
- /*
- * Update the file size if changed.
- */
-
- if (wcp->offset + wcp->data_size > wcp->file_size)
- fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
- DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n",
- (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n));
-
- total_written += n;
- return total_written; /* .... that's a write :) */
- }
+ memcpy(wcp->data+wcp->data_size, data, n);
+ if (wcp->data_size == 0) {
+ wcp->offset = pos;
+ DO_PROFILE_INC(writecache_num_write_caches);
+ }
+ wcp->data_size += n;
+
+ /*
+ * Update the file size if changed.
+ */
+
+ if (wcp->offset + wcp->data_size > wcp->file_size)
+ fsp->size = wcp->file_size = wcp->offset + wcp->data_size;
+ DEBUG(9,("wcp->offset = %.0f wcp->data_size = %u cache return %u\n",
+ (double)wcp->offset, (unsigned int)wcp->data_size, (unsigned int)n));
+
+ total_written += n;
+ return total_written; /* .... that's a write :) */
+ }
- return total_written;
+ return total_written;
}
/****************************************************************************
@@ -514,24 +525,23 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n",
void delete_write_cache(files_struct *fsp)
{
- write_cache *wcp;
-
- if(!fsp)
- return;
+ write_cache *wcp;
- if(!(wcp = fsp->wcp))
- return;
+ if(!fsp)
+ return;
- DO_PROFILE_DEC(writecache_allocated_write_caches);
- allocated_write_caches--;
+ if(!(wcp = fsp->wcp))
+ return;
- SMB_ASSERT(wcp->data_size == 0);
+ DO_PROFILE_DEC(writecache_allocated_write_caches);
+ allocated_write_caches--;
- SAFE_FREE(wcp->data);
- SAFE_FREE(fsp->wcp);
+ SMB_ASSERT(wcp->data_size == 0);
- DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name ));
+ SAFE_FREE(wcp->data);
+ SAFE_FREE(fsp->wcp);
+ DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name ));
}
/****************************************************************************
@@ -540,41 +550,41 @@ void delete_write_cache(files_struct *fsp)
static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size)
{
- ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn));
- write_cache *wcp;
-
- if (allocated_write_caches >= MAX_WRITE_CACHES)
- return False;
-
- if(alloc_size == 0 || fsp->wcp)
- return False;
-
- if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) {
- DEBUG(0,("setup_write_cache: malloc fail.\n"));
- return False;
- }
-
- wcp->file_size = file_size;
- wcp->offset = 0;
- wcp->alloc_size = alloc_size;
- wcp->data_size = 0;
- if((wcp->data = malloc(wcp->alloc_size)) == NULL) {
- DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n",
- (unsigned int)wcp->alloc_size ));
- SAFE_FREE(wcp);
- return False;
- }
-
- memset(wcp->data, '\0', wcp->alloc_size );
-
- fsp->wcp = wcp;
- DO_PROFILE_INC(writecache_allocated_write_caches);
- allocated_write_caches++;
-
- DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n",
+ ssize_t alloc_size = lp_write_cache_size(SNUM(fsp->conn));
+ write_cache *wcp;
+
+ if (allocated_write_caches >= MAX_WRITE_CACHES)
+ return False;
+
+ if(alloc_size == 0 || fsp->wcp)
+ return False;
+
+ if((wcp = (write_cache *)malloc(sizeof(write_cache))) == NULL) {
+ DEBUG(0,("setup_write_cache: malloc fail.\n"));
+ return False;
+ }
+
+ wcp->file_size = file_size;
+ wcp->offset = 0;
+ wcp->alloc_size = alloc_size;
+ wcp->data_size = 0;
+ if((wcp->data = malloc(wcp->alloc_size)) == NULL) {
+ DEBUG(0,("setup_write_cache: malloc fail for buffer size %u.\n",
+ (unsigned int)wcp->alloc_size ));
+ SAFE_FREE(wcp);
+ return False;
+ }
+
+ memset(wcp->data, '\0', wcp->alloc_size );
+
+ fsp->wcp = wcp;
+ DO_PROFILE_INC(writecache_allocated_write_caches);
+ allocated_write_caches++;
+
+ DEBUG(10,("setup_write_cache: File %s allocated write cache size %u\n",
fsp->fsp_name, wcp->alloc_size ));
- return True;
+ return True;
}
/****************************************************************************
@@ -583,17 +593,17 @@ static BOOL setup_write_cache(files_struct *fsp, SMB_OFF_T file_size)
void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size)
{
- fsp->size = file_size;
- if(fsp->wcp) {
- /* The cache *must* have been flushed before we do this. */
- if (fsp->wcp->data_size != 0) {
- pstring msg;
- slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \
+ fsp->size = file_size;
+ if(fsp->wcp) {
+ /* The cache *must* have been flushed before we do this. */
+ if (fsp->wcp->data_size != 0) {
+ pstring msg;
+ slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \
on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size );
- smb_panic(msg);
- }
- fsp->wcp->file_size = file_size;
- }
+ smb_panic(msg);
+ }
+ fsp->wcp->file_size = file_size;
+ }
}
/*******************************************************************
@@ -602,36 +612,36 @@ on file %s with write cache size = %u\n", fsp->fsp_name, fsp->wcp->data_size );
ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason)
{
- write_cache *wcp = fsp->wcp;
- size_t data_size;
- ssize_t ret;
+ write_cache *wcp = fsp->wcp;
+ size_t data_size;
+ ssize_t ret;
- if(!wcp || !wcp->data_size)
- return 0;
+ if(!wcp || !wcp->data_size)
+ return 0;
- data_size = wcp->data_size;
- wcp->data_size = 0;
+ data_size = wcp->data_size;
+ wcp->data_size = 0;
- DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]);
+ DO_PROFILE_DEC_INC(writecache_num_write_caches,writecache_flushed_writes[reason]);
- DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n",
- fsp->fd, (double)wcp->offset, (unsigned int)data_size));
+ DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n",
+ fsp->fd, (double)wcp->offset, (unsigned int)data_size));
#ifdef WITH_PROFILE
- if(data_size == wcp->alloc_size)
- DO_PROFILE_INC(writecache_num_perfect_writes);
+ if(data_size == wcp->alloc_size)
+ DO_PROFILE_INC(writecache_num_perfect_writes);
#endif
- ret = real_write_file(fsp, wcp->data, wcp->offset, data_size);
+ ret = real_write_file(fsp, wcp->data, wcp->offset, data_size);
- /*
- * Ensure file size if kept up to date if write extends file.
- */
+ /*
+ * Ensure file size if kept up to date if write extends file.
+ */
- if ((ret != -1) && (wcp->offset + ret > wcp->file_size))
- wcp->file_size = wcp->offset + ret;
+ if ((ret != -1) && (wcp->offset + ret > wcp->file_size))
+ wcp->file_size = wcp->offset + ret;
- return ret;
+ return ret;
}
/*******************************************************************
@@ -640,12 +650,13 @@ sync a file
void sync_file(connection_struct *conn, files_struct *fsp)
{
- if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) {
- flush_write_cache(fsp, SYNC_FLUSH);
- conn->vfs_ops.fsync(fsp,fsp->fd);
- }
+ if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) {
+ flush_write_cache(fsp, SYNC_FLUSH);
+ conn->vfs_ops.fsync(fsp,fsp->fd);
+ }
}
+
/************************************************************
Perform a stat whether a valid fd or not.
************************************************************/
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index cb6a6d31a4..e5f9b7a0ae 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -38,54 +38,29 @@ static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL d
Check if two filenames are equal.
This needs to be careful about whether we are case sensitive.
****************************************************************************/
+
static BOOL fname_equal(char *name1, char *name2)
{
- int l1 = strlen(name1);
- int l2 = strlen(name2);
-
- /* handle filenames ending in a single dot */
- if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
- {
- BOOL ret;
- name1[l1-1] = 0;
- ret = fname_equal(name1,name2);
- name1[l1-1] = '.';
- return(ret);
- }
-
- if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
- {
- BOOL ret;
- name2[l2-1] = 0;
- ret = fname_equal(name1,name2);
- name2[l2-1] = '.';
- return(ret);
- }
-
- /* now normal filename handling */
- if (case_sensitive)
- return(strcmp(name1,name2) == 0);
-
- return(strequal(name1,name2));
-}
+ /* Normal filename handling */
+ if (case_sensitive)
+ return(strcmp(name1,name2) == 0);
+ return(strequal(name1,name2));
+}
/****************************************************************************
Mangle the 2nd name and check if it is then equal to the first name.
****************************************************************************/
-static BOOL mangled_equal(char *name1, char *name2, int snum)
+
+static BOOL mangled_equal(char *name1, const char *name2, int snum)
{
pstring tmpname;
- if (mangle_is_8_3(name2, True)) {
- return False;
- }
pstrcpy(tmpname, name2);
- return mangle_map(tmpname, True, False, snum) &&
- strequal(name1, tmpname);
+ mangle_map(tmpname, True, False, snum);
+ return strequal(name1, tmpname);
}
-
/****************************************************************************
This routine is called to convert names from the dos namespace to unix
namespace. It needs to handle any case conversions, mangling, format
@@ -116,388 +91,391 @@ for nlinks = 0, which can never be true for any file).
BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_component,
BOOL *bad_path, SMB_STRUCT_STAT *pst)
{
- SMB_STRUCT_STAT st;
- char *start, *end;
- pstring dirpath;
- pstring orig_path;
- BOOL component_was_mangled = False;
- BOOL name_has_wildcard = False;
-
- ZERO_STRUCTP(pst);
-
- *dirpath = 0;
- *bad_path = False;
- if(saved_last_component)
- *saved_last_component = 0;
-
- if (conn->printer) {
- /* we don't ever use the filenames on a printer share as a
- filename - so don't convert them */
- return True;
- }
-
- DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
-
- /*
- * Convert to basic unix format - removing \ chars and cleaning it up.
- */
-
- unix_format(name);
- unix_clean_name(name);
-
- /*
- * Names must be relative to the root of the service - trim any leading /.
- * also trim trailing /'s.
- */
-
- trim_string(name,"/","/");
-
- /*
- * If we trimmed down to a single '\0' character
- * then we should use the "." directory to avoid
- * searching the cache, but not if we are in a
- * printing share.
- */
-
- if (!*name) {
- name[0] = '.';
- name[1] = '\0';
- }
-
- /*
- * Ensure saved_last_component is valid even if file exists.
- */
-
- if(saved_last_component) {
- end = strrchr_m(name, '/');
- if(end)
- pstrcpy(saved_last_component, end + 1);
- else
- pstrcpy(saved_last_component, name);
- }
-
- if (!case_sensitive &&
- (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve)))
- strnorm(name);
-
- /*
- * If we trimmed down to a single '\0' character
- * then we will be using the "." directory.
- * As we know this is valid we can return true here.
- */
-
- if(!*name)
- return(True);
-
- start = name;
- while (strncmp(start,"./",2) == 0)
- start += 2;
-
- pstrcpy(orig_path, name);
-
- if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
- *pst = st;
- return True;
- }
-
- /*
- * stat the name - if it exists then we are all done!
- */
-
-/* ZZZ: stat1 */ if (vfs_stat(conn,name,&st) == 0) {
- stat_cache_add(orig_path, name);
- DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
- *pst = st;
- return(True);
- }
-
- DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
- name, dirpath, start));
-
- /*
- * A special case - if we don't have any mangling chars and are case
- * sensitive then searching won't help.
- */
-
- if (case_sensitive && !mangle_is_mangled(name) &&
- !lp_strip_dot() && !use_mangled_map)
- return(False);
-
- name_has_wildcard = ms_has_wild(start);
-
- /*
- * is_mangled() was changed to look at an entire pathname, not
- * just a component. JRA.
- */
-
- if (mangle_is_mangled(start))
- component_was_mangled = True;
-
- /*
- * Now we need to recursively match the name against the real
- * directory structure.
- */
-
- /*
- * Match each part of the path name separately, trying the names
- * as is first, then trying to scan the directory for matching names.
- */
-
- for (; start ; start = (end?end+1:(char *)NULL)) {
- /*
- * Pinpoint the end of this section of the filename.
- */
- end = strchr_m(start, '/');
-
- /*
- * Chop the name at this point.
- */
- if (end)
- *end = 0;
-
- if(saved_last_component != 0)
- pstrcpy(saved_last_component, end ? end + 1 : start);
-
- /*
- * Check if the name exists up to this point.
- */
-
- if (vfs_stat(conn,name, &st) == 0) {
- /*
- * It exists. it must either be a directory or this must be
- * the last part of the path for it to be OK.
- */
- if (end && !(st.st_mode & S_IFDIR)) {
- /*
- * An intermediate part of the name isn't a directory.
- */
- DEBUG(5,("Not a dir %s\n",start));
- *end = '/';
- return(False);
- }
-
- } else {
- pstring rest;
-
- /* Stat failed - ensure we don't use it. */
- ZERO_STRUCT(st);
- *rest = 0;
-
- /*
- * Remember the rest of the pathname so it can be restored
- * later.
- */
-
- if (end)
- pstrcpy(rest,end+1);
-
- /*
- * Try to find this part of the path in the directory.
- */
-
- if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) {
- if (end) {
- /*
- * An intermediate part of the name can't be found.
- */
- DEBUG(5,("Intermediate not found %s\n",start));
- *end = '/';
-
- /*
- * We need to return the fact that the intermediate
- * name resolution failed. This is used to return an
- * error of ERRbadpath rather than ERRbadfile. Some
- * Windows applications depend on the difference between
- * these two errors.
- */
- *bad_path = True;
- return(False);
- }
+ SMB_STRUCT_STAT st;
+ char *start, *end;
+ pstring dirpath;
+ pstring orig_path;
+ BOOL component_was_mangled = False;
+ BOOL name_has_wildcard = False;
+
+ ZERO_STRUCTP(pst);
+
+ *dirpath = 0;
+ *bad_path = False;
+ if(saved_last_component)
+ *saved_last_component = 0;
+
+ if (conn->printer) {
+ /* we don't ever use the filenames on a printer share as a
+ filename - so don't convert them */
+ return True;
+ }
+
+ DEBUG(5, ("unix_convert called on file \"%s\"\n", name));
+
+ /*
+ * Convert to basic unix format - removing \ chars and cleaning it up.
+ */
+
+ unix_format(name);
+ unix_clean_name(name);
+
+ /*
+ * Names must be relative to the root of the service - trim any leading /.
+ * also trim trailing /'s.
+ */
+
+ trim_string(name,"/","/");
+
+ /*
+ * If we trimmed down to a single '\0' character
+ * then we should use the "." directory to avoid
+ * searching the cache, but not if we are in a
+ * printing share.
+ */
+
+ if (!*name) {
+ name[0] = '.';
+ name[1] = '\0';
+ }
+
+ /*
+ * Ensure saved_last_component is valid even if file exists.
+ */
+
+ if(saved_last_component) {
+ end = strrchr_m(name, '/');
+ if(end)
+ pstrcpy(saved_last_component, end + 1);
+ else
+ pstrcpy(saved_last_component, name);
+ }
+
+ if (!case_sensitive && (!case_preserve || (mangle_is_8_3(name, False) && !short_case_preserve)))
+ strnorm(name);
+
+ /*
+ * If we trimmed down to a single '\0' character
+ * then we will be using the "." directory.
+ * As we know this is valid we can return true here.
+ */
+
+ if(!*name)
+ return(True);
+
+ start = name;
+ while (strncmp(start,"./",2) == 0)
+ start += 2;
+
+ pstrcpy(orig_path, name);
+
+ if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
+ *pst = st;
+ return True;
+ }
+
+ /*
+ * stat the name - if it exists then we are all done!
+ */
+
+ if (vfs_stat(conn,name,&st) == 0) {
+ stat_cache_add(orig_path, name);
+ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+ *pst = st;
+ return(True);
+ }
+
+ DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));
+
+ /*
+ * A special case - if we don't have any mangling chars and are case
+ * sensitive then searching won't help.
+ */
+
+ if (case_sensitive && !mangle_is_mangled(name) && !use_mangled_map)
+ return(False);
+
+ name_has_wildcard = ms_has_wild(start);
+
+ /*
+ * is_mangled() was changed to look at an entire pathname, not
+ * just a component. JRA.
+ */
+
+ if (mangle_is_mangled(start))
+ component_was_mangled = True;
+
+ /*
+ * Now we need to recursively match the name against the real
+ * directory structure.
+ */
+
+ /*
+ * Match each part of the path name separately, trying the names
+ * as is first, then trying to scan the directory for matching names.
+ */
+
+ for (; start ; start = (end?end+1:(char *)NULL)) {
+ /*
+ * Pinpoint the end of this section of the filename.
+ */
+ end = strchr_m(start, '/');
+
+ /*
+ * Chop the name at this point.
+ */
+ if (end)
+ *end = 0;
+
+ if(saved_last_component != 0)
+ pstrcpy(saved_last_component, end ? end + 1 : start);
+
+ /*
+ * Check if the name exists up to this point.
+ */
+
+ if (vfs_stat(conn,name, &st) == 0) {
+ /*
+ * It exists. it must either be a directory or this must be
+ * the last part of the path for it to be OK.
+ */
+ if (end && !(st.st_mode & S_IFDIR)) {
+ /*
+ * An intermediate part of the name isn't a directory.
+ */
+ DEBUG(5,("Not a dir %s\n",start));
+ *end = '/';
+ return(False);
+ }
+
+ } else {
+ pstring rest;
+
+ /* Stat failed - ensure we don't use it. */
+ ZERO_STRUCT(st);
+ *rest = 0;
+
+ /*
+ * Remember the rest of the pathname so it can be restored
+ * later.
+ */
+
+ if (end)
+ pstrcpy(rest,end+1);
+
+ /*
+ * Try to find this part of the path in the directory.
+ */
+
+ if (ms_has_wild(start) || !scan_directory(dirpath, start, conn, end?True:False)) {
+ if (end) {
+ /*
+ * An intermediate part of the name can't be found.
+ */
+ DEBUG(5,("Intermediate not found %s\n",start));
+ *end = '/';
+
+ /*
+ * We need to return the fact that the intermediate
+ * name resolution failed. This is used to return an
+ * error of ERRbadpath rather than ERRbadfile. Some
+ * Windows applications depend on the difference between
+ * these two errors.
+ */
+ *bad_path = True;
+ return(False);
+ }
- /*
- * Just the last part of the name doesn't exist.
- * We may need to strupper() or strlower() it in case
- * this conversion is being used for file creation
- * purposes. If the filename is of mixed case then
- * don't normalise it.
- */
-
- if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))
- strnorm(start);
-
- /*
- * check on the mangled stack to see if we can recover the
- * base of the filename.
- */
-
- if (mangle_is_mangled(start)) {
- mangle_check_cache( start );
- }
-
- DEBUG(5,("New file %s\n",start));
- return(True);
- }
-
- /*
- * Restore the rest of the string. If the string was mangled the size
- * may have changed.
- */
- if (end) {
- end = start + strlen(start);
- pstrcat(start,"/");
- pstrcat(start,rest);
- *end = '\0';
- }
- } /* end else */
-
- /*
- * Add to the dirpath that we have resolved so far.
- */
- if (*dirpath)
- pstrcat(dirpath,"/");
-
- pstrcat(dirpath,start);
-
- /*
- * Don't cache a name with mangled or wildcard components
- * as this can change the size.
- */
-
- if(!component_was_mangled && !name_has_wildcard)
- stat_cache_add(orig_path, dirpath);
-
- /*
- * Restore the / that we wiped out earlier.
- */
- if (end)
- *end = '/';
- }
+ /*
+ * Just the last part of the name doesn't exist.
+ * We may need to strupper() or strlower() it in case
+ * this conversion is being used for file creation
+ * purposes. If the filename is of mixed case then
+ * don't normalise it.
+ */
+
+ if (!case_preserve && (!strhasupper(start) || !strhaslower(start)))
+ strnorm(start);
+
+ /*
+ * check on the mangled stack to see if we can recover the
+ * base of the filename.
+ */
+
+ if (mangle_is_mangled(start)) {
+ mangle_check_cache( start );
+ }
+
+ DEBUG(5,("New file %s\n",start));
+ return(True);
+ }
+
+ /*
+ * Restore the rest of the string. If the string was mangled the size
+ * may have changed.
+ */
+ if (end) {
+ end = start + strlen(start);
+ pstrcat(start,"/");
+ pstrcat(start,rest);
+ *end = '\0';
+ }
+ } /* end else */
+
+ /*
+ * Add to the dirpath that we have resolved so far.
+ */
+ if (*dirpath)
+ pstrcat(dirpath,"/");
+
+ pstrcat(dirpath,start);
+
+ /*
+ * Don't cache a name with mangled or wildcard components
+ * as this can change the size.
+ */
+
+ if(!component_was_mangled && !name_has_wildcard)
+ stat_cache_add(orig_path, dirpath);
+
+ /*
+ * Restore the / that we wiped out earlier.
+ */
+ if (end)
+ *end = '/';
+ }
- /*
- * Don't cache a name with mangled or wildcard components
- * as this can change the size.
- */
+ /*
+ * Don't cache a name with mangled or wildcard components
+ * as this can change the size.
+ */
- if(!component_was_mangled && !name_has_wildcard)
- stat_cache_add(orig_path, name);
+ if(!component_was_mangled && !name_has_wildcard)
+ stat_cache_add(orig_path, name);
- /*
- * If we ended up resolving the entire path then return a valid
- * stat struct if we got one.
- */
+ /*
+ * If we ended up resolving the entire path then return a valid
+ * stat struct if we got one.
+ */
- if (VALID_STAT(st) && (strlen(orig_path) == strlen(name)))
- *pst = st;
+ if (VALID_STAT(st) && (strlen(orig_path) == strlen(name)))
+ *pst = st;
- /*
- * The name has been resolved.
- */
+ /*
+ * The name has been resolved.
+ */
- DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
- return(True);
+ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+ return(True);
}
-
/****************************************************************************
-check a filename - possibly caling reducename
-
-This is called by every routine before it allows an operation on a filename.
-It does any final confirmation necessary to ensure that the filename is
-a valid one for the user to access.
+ Check a filename - possibly caling reducename.
+ This is called by every routine before it allows an operation on a filename.
+ It does any final confirmation necessary to ensure that the filename is
+ a valid one for the user to access.
****************************************************************************/
+
BOOL check_name(char *name,connection_struct *conn)
{
- BOOL ret;
+ BOOL ret;
- errno = 0;
+ errno = 0;
- if (IS_VETO_PATH(conn, name)) {
- DEBUG(5,("file path name %s vetoed\n",name));
- return(0);
- }
+ if (IS_VETO_PATH(conn, name)) {
+ if(strcmp(name, ".") && strcmp(name, "..")) {
+ DEBUG(5,("file path name %s vetoed\n",name));
+ return(0);
+ }
+ }
- ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn)));
+ ret = reduce_name(conn,name,conn->connectpath,lp_widelinks(SNUM(conn)));
- /* Check if we are allowing users to follow symlinks */
- /* Patch from David Clerc <David.Clerc@cui.unige.ch>
- University of Geneva */
+ /* Check if we are allowing users to follow symlinks */
+ /* Patch from David Clerc <David.Clerc@cui.unige.ch>
+ University of Geneva */
#ifdef S_ISLNK
- if (!lp_symlinks(SNUM(conn))) {
- SMB_STRUCT_STAT statbuf;
- if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) &&
- (S_ISLNK(statbuf.st_mode)) ) {
- DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
- ret=0;
- }
- }
+ if (!lp_symlinks(SNUM(conn))) {
+ SMB_STRUCT_STAT statbuf;
+ if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) &&
+ (S_ISLNK(statbuf.st_mode)) ) {
+ DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
+ ret=0;
+ }
+ }
#endif
- if (!ret)
- DEBUG(5,("check_name on %s failed\n",name));
+ if (!ret)
+ DEBUG(5,("check_name on %s failed\n",name));
- return(ret);
+ return(ret);
}
-
/****************************************************************************
-scan a directory to find a filename, matching without case sensitivity
-
-If the name looks like a mangled name then try via the mangling functions
+ Scan a directory to find a filename, matching without case sensitivity.
+ If the name looks like a mangled name then try via the mangling functions
****************************************************************************/
+
static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache)
{
- void *cur_dir;
- char *dname;
- BOOL mangled;
- pstring name2;
-
- mangled = mangle_is_mangled(name);
-
- /* handle null paths */
- if (*path == 0)
- path = ".";
-
- if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
- pstrcpy(name, dname);
- return(True);
- }
-
- /*
- * The incoming name can be mangled, and if we de-mangle it
- * here it will not compare correctly against the filename (name2)
- * read from the directory and then mangled by the mangle_map()
- * call. We need to mangle both names or neither.
- * (JRA).
- */
- if (mangled)
- mangled = !mangle_check_cache( name );
-
- /* open the directory */
- if (!(cur_dir = OpenDir(conn, path, True))) {
- DEBUG(3,("scan dir didn't open dir [%s]\n",path));
- return(False);
- }
-
- /* now scan for matching names */
- while ((dname = ReadDirName(cur_dir))) {
- if (*dname == '.' && (strequal(dname,".") || strequal(dname,"..")))
- continue;
-
- pstrcpy(name2,dname);
- if (!mangle_map(name2,False,True,SNUM(conn)))
- continue;
-
- if ((mangled && mangled_equal(name,name2,SNUM(conn))) || fname_equal(name, dname)) {
- /* we've found the file, change it's name and return */
- if (docache)
- DirCacheAdd(path,name,dname,SNUM(conn));
- pstrcpy(name, dname);
- CloseDir(cur_dir);
- return(True);
- }
- }
-
- CloseDir(cur_dir);
- return(False);
+ void *cur_dir;
+ char *dname;
+ BOOL mangled;
+
+ mangled = mangle_is_mangled(name);
+
+ /* handle null paths */
+ if (*path == 0)
+ path = ".";
+
+ if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
+ pstrcpy(name, dname);
+ return(True);
+ }
+
+ /*
+ * The incoming name can be mangled, and if we de-mangle it
+ * here it will not compare correctly against the filename (name2)
+ * read from the directory and then mangled by the mangle_map()
+ * call. We need to mangle both names or neither.
+ * (JRA).
+ */
+ if (mangled)
+ mangled = !mangle_check_cache( name );
+
+ /* open the directory */
+ if (!(cur_dir = OpenDir(conn, path, True))) {
+ DEBUG(3,("scan dir didn't open dir [%s]\n",path));
+ return(False);
+ }
+
+ /* now scan for matching names */
+ while ((dname = ReadDirName(cur_dir))) {
+ if (*dname == '.' && (strequal(dname,".") || strequal(dname,"..")))
+ continue;
+
+ /*
+ * At this point dname is the unmangled name.
+ * name is either mangled or not, depending on the state of the "mangled"
+ * variable. JRA.
+ */
+
+ /*
+ * Check mangled name against mangled name, or unmangled name
+ * against unmangled name.
+ */
+
+ if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname)) {
+ /* we've found the file, change it's name and return */
+ if (docache)
+ DirCacheAdd(path,name,dname,SNUM(conn));
+ pstrcpy(name, dname);
+ CloseDir(cur_dir);
+ return(True);
+ }
+ }
+
+ CloseDir(cur_dir);
+ return(False);
}
diff --git a/source3/smbd/groupname.c b/source3/smbd/groupname.c
index 812488571a..5147ae4b95 100644
--- a/source3/smbd/groupname.c
+++ b/source3/smbd/groupname.c
@@ -21,7 +21,6 @@
#ifdef USING_GROUPNAME_MAP
#include "includes.h"
-extern DOM_SID global_sam_sid;
/**************************************************************************
Groupname map functionality. The code loads a groupname map file and
@@ -160,7 +159,7 @@ Error was %s.\n", unixname, strerror(errno) ));
* It's not a well known name, convert the UNIX gid_t
* to a rid within this domain SID.
*/
- tmp_sid = global_sam_sid;
+ sid_copy(&tmp_sid,get_global_sam_sid());
tmp_sid.sub_auths[tmp_sid.num_auths++] =
pdb_gid_to_group_rid(gid);
}
@@ -228,7 +227,7 @@ void map_gid_to_sid( gid_t gid, DOM_SID *psid)
* If there's no map, convert the UNIX gid_t
* to a rid within this domain SID.
*/
- *psid = global_sam_sid;
+ sid_copy(psid,get_global_sam_sid());
psid->sub_auths[psid->num_auths++] = pdb_gid_to_group_rid(gid);
return;
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index c2f3b7b2f0..91b221968f 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -375,7 +375,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
START_PROFILE(SMBtrans);
memset(name, '\0',sizeof(name));
- srvstr_pull(inbuf, name, smb_buf(inbuf), sizeof(name), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, name, smb_buf(inbuf), sizeof(name), STR_TERMINATE);
if (dscnt > tdscnt || pscnt > tpscnt) {
exit_server("invalid trans parameters");
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 666bbb5f61..217bb6a613 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -71,7 +71,7 @@ static int CopyExpanded(connection_struct *conn,
StrnCpy(buf,src,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf);
+ standard_sub_conn(conn,buf,sizeof(buf));
l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
(*dst) += l;
(*n) -= l;
@@ -94,7 +94,7 @@ static int StrlenExpanded(connection_struct *conn, int snum, char* s)
if (!s) return(0);
StrnCpy(buf,s,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf);
+ standard_sub_conn(conn,buf,sizeof(buf));
return strlen(buf) + 1;
}
@@ -104,7 +104,7 @@ static char* Expand(connection_struct *conn, int snum, char* s)
if (!s) return(NULL);
StrnCpy(buf,s,sizeof(buf)/2);
pstring_sub(buf,"%S",lp_servicename(snum));
- standard_sub_conn(conn,buf);
+ standard_sub_conn(conn,buf,sizeof(buf));
return &buf[0];
}
@@ -1670,7 +1670,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
fstring comment;
pstring pathname;
char *command, *cmdname;
- uint offset;
+ unsigned int offset;
int snum;
int res = ERRunsup;
@@ -1754,82 +1754,104 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
+ int i;
+ int errflags=0;
+ int resume_context, cli_buf_size;
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
- int uLevel = SVAL(p,0);
- char *p2;
- int count=0;
- if (!prefix_ok(str1,"WrLeh")) return False;
-
- /* check it's a supported variant */
- switch( uLevel )
- {
- case 0:
- p2 = "B21";
- break;
- default:
- return False;
+ GROUP_MAP *group_list;
+ int num_entries;
+
+ if (strcmp(str1,"WrLeh") != 0)
+ return False;
+
+ /* parameters
+ * W-> resume context (number of users to skip)
+ * r -> return parameter pointer to receive buffer
+ * L -> length of receive buffer
+ * e -> return parameter number of entries
+ * h -> return parameter total number of users
+ */
+ if (strcmp("B21",str2) != 0)
+ return False;
+
+ /* get list of domain groups SID_DOMAIN_GRP=2 */
+ if(!enum_group_mapping(2 , &group_list, &num_entries, False, False)) {
+ DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
+ return False;
}
- if (strcmp(p2,str2) != 0) return False;
+ resume_context = SVAL(p,0);
+ cli_buf_size=SVAL(p+2,0);
+ DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
- *rdata_len = mdrcnt + 1024;
+ *rdata_len = cli_buf_size;
*rdata = REALLOC(*rdata,*rdata_len);
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
-
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++;
+ for(i=resume_context; i<num_entries; i++) {
+ char* name=group_list[i].nt_name;
+ if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
+ /* truncate the name at 21 chars. */
+ memcpy(p, name, 21);
+ DEBUG(10,("adding entry %d group %s\n", i, p));
+ p += 21;
+ } else {
+ /* set overflow error */
+ DEBUG(3,("overflow on entry %d group %s\n", i, name));
+ errflags=234;
+ break;
+ }
+ }
*rdata_len = PTR_DIFF(p,*rdata);
*rparam_len = 8;
*rparam = REALLOC(*rparam,*rparam_len);
- SSVAL(*rparam,4,count); /* is this right?? */
- SSVAL(*rparam,6,count); /* is this right?? */
-
- DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
+ SSVAL(*rparam, 0, errflags);
+ SSVAL(*rparam, 2, 0); /* converter word */
+ SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
+ SSVAL(*rparam, 6, num_entries); /* is this right?? */
return(True);
}
-/****************************************************************************
- view list of groups available
- ****************************************************************************/
-static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
+/*******************************************************************
+ get groups that a user is a member of
+ ******************************************************************/
+static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
char *str1 = param+2;
char *str2 = skip_string(str1,1);
- char *p = skip_string(str2,1);
+ char *UserName = skip_string(str2,1);
+ char *p = skip_string(UserName,1);
int uLevel = SVAL(p,0);
char *p2;
int count=0;
- if (!prefix_ok(str1,"WrLeh")) return False;
+ *rparam_len = 8;
+ *rparam = REALLOC(*rparam,*rparam_len);
- /* check it's a supported variant */
- switch( uLevel )
- {
- case 0:
- p2 = "B21";
+ /* check it's a supported varient */
+ if (!strcmp(str1,"zWrLeh"))
+ return False;
+ switch( uLevel ) {
+ case 0:
+ p2 = "B21";
break;
- default:
+ default:
return False;
}
- if (strcmp(p2,str2) != 0) return False;
+ if (strcmp(p2,str2) != 0)
+ return False;
*rdata_len = mdrcnt + 1024;
*rdata = REALLOC(*rdata,*rdata_len);
@@ -1847,15 +1869,101 @@ static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,ch
*rdata_len = PTR_DIFF(p,*rdata);
+ SSVAL(*rparam,4,count); /* is this right?? */
+ SSVAL(*rparam,6,count); /* is this right?? */
+
+ return(True);
+}
+
+/*******************************************************************
+ get all users
+ ******************************************************************/
+static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
+{
+ SAM_ACCOUNT *pwd=NULL;
+ int count_sent=0;
+ int count_total=0;
+ int errflags=0;
+ int resume_context, cli_buf_size;
+
+ char *str1 = param+2;
+ char *str2 = skip_string(str1,1);
+ char *p = skip_string(str2,1);
+
+ if (strcmp(str1,"WrLeh") != 0)
+ return False;
+ /* parameters
+ * W-> resume context (number of users to skip)
+ * r -> return parameter pointer to receive buffer
+ * L -> length of receive buffer
+ * e -> return parameter number of entries
+ * h -> return parameter total number of users
+ */
+
+ resume_context = SVAL(p,0);
+ cli_buf_size=SVAL(p+2,0);
+ DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
+
*rparam_len = 8;
*rparam = REALLOC(*rparam,*rparam_len);
- SSVAL(*rparam,4,count); /* is this right?? */
- SSVAL(*rparam,6,count); /* is this right?? */
+ /* check it's a supported varient */
+ if (strcmp("B21",str2) != 0)
+ return False;
- DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
+ *rdata_len = cli_buf_size;
+ *rdata = REALLOC(*rdata,*rdata_len);
- return(True);
+ p = *rdata;
+
+ /* to get user list enumerations for NetUserEnum in B21 format */
+ pdb_init_sam(&pwd);
+
+ /* Open the passgrp file - not for update. */
+ become_root();
+ if(!pdb_setsampwent(False)) {
+ DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
+ unbecome_root();
+ return False;
+ }
+ errflags=NERR_Success;
+
+ while ( pdb_getsampwent(pwd) ) {
+ const char *name=pdb_get_username(pwd);
+ if ((name) && (*(name+strlen(name)-1)!='$')) {
+ count_total++;
+ if(count_total>=resume_context) {
+ if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
+ pstrcpy(p,name);
+ DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
+ p += 21;
+ count_sent++;
+ } else {
+ /* set overflow error */
+ DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
+ errflags=234;
+ break;
+ }
+ }
+ }
+ } ;
+
+ pdb_endsampwent();
+ unbecome_root();
+
+ pdb_free_sam(&pwd);
+
+ *rdata_len = PTR_DIFF(p,*rdata);
+
+ SSVAL(*rparam,0,errflags);
+ SSVAL(*rparam,2,0); /* converter word */
+ SSVAL(*rparam,4,count_sent); /* is this right?? */
+ SSVAL(*rparam,6,count_total); /* is this right?? */
+
+ return True;
}
@@ -2343,7 +2451,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
SIVAL(p,6,0);
} else {
SIVAL(p,6,PTR_DIFF(p2,*rdata));
- standard_sub_conn(conn,comment);
+ standard_sub_conn(conn,comment,sizeof(comment));
StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
p2 = skip_string(p2,1);
}
@@ -2685,8 +2793,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
SIVALS(p,usri11_password_age,-1); /* password age */
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
- pstrcpy(p2, lp_logon_home());
- standard_sub_conn(conn, p2);
+ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
p2 = skip_string(p2,1);
SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
pstrcpy(p2,"");
@@ -2722,15 +2829,13 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVAL(p,42,
conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
- pstrcpy(p2,lp_logon_home());
- standard_sub_conn(conn, p2);
+ pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
p2 = skip_string(p2,1);
SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
*p2++ = 0;
SSVAL(p,52,0); /* flags */
SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
- pstrcpy(p2,lp_logon_script());
- standard_sub_conn( conn, p2 );
+ pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
p2 = skip_string(p2,1);
if (uLevel == 2)
{
@@ -2755,7 +2860,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVALS(p,104,-1); /* num_logons */
SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
pstrcpy(p2,"\\\\%L");
- standard_sub_conn(conn, p2);
+ standard_sub_conn(conn, p2,0);
p2 = skip_string(p2,1);
SSVAL(p,110,49); /* country_code */
SSVAL(p,112,860); /* code page */
@@ -2769,56 +2874,6 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
return(True);
}
-/*******************************************************************
- get groups that a user is a member of
- ******************************************************************/
-static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
-{
- char *str1 = param+2;
- char *str2 = skip_string(str1,1);
- char *UserName = skip_string(str2,1);
- char *p = skip_string(UserName,1);
- int uLevel = SVAL(p,0);
- char *p2;
- int count=0;
-
- *rparam_len = 8;
- *rparam = REALLOC(*rparam,*rparam_len);
-
- /* check it's a supported varient */
- if (strcmp(str1,"zWrLeh") != 0) return False;
- switch( uLevel ) {
- case 0: p2 = "B21"; break;
- default: return False;
- }
- if (strcmp(p2,str2) != 0) return False;
-
- *rdata_len = mdrcnt + 1024;
- *rdata = REALLOC(*rdata,*rdata_len);
-
- SSVAL(*rparam,0,NERR_Success);
- SSVAL(*rparam,2,0); /* converter word */
-
- 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++;
-
- *rdata_len = PTR_DIFF(p,*rdata);
-
- SSVAL(*rparam,4,count); /* is this right?? */
- SSVAL(*rparam,6,count); /* is this right?? */
-
- return(True);
-}
-
-
static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
@@ -2830,6 +2885,12 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
int uLevel;
struct pack_desc desc;
char* name;
+ /* With share level security vuid will always be zero.
+ Don't depend on vuser being non-null !!. JRA */
+ user_struct *vuser = get_valid_user_struct(vuid);
+ if(vuser != NULL)
+ DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
+ vuser->user.unix_name));
uLevel = SVAL(p,0);
name = p + 2;
@@ -2873,15 +2934,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
}
PACKS(&desc,"z",global_myworkgroup);/* domain */
-/* JHT - By calling lp_logon_script() and standard_sub() we have */
-/* made sure all macros are fully substituted and available */
- {
- pstring logon_script;
- pstrcpy(logon_script,lp_logon_script());
- standard_sub_conn( conn, logon_script );
- PACKS(&desc,"z", logon_script); /* script path */
- }
-/* End of JHT mods */
+ PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
PACKI(&desc,"D",0x00000000); /* reserved */
}
@@ -3030,7 +3083,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
- /* check it's a supported varient */
+ /* check it's a supported variant */
if (strcmp(str1,"zWrLeh") != 0) return False;
if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
if (!check_printjob_info(&desc,uLevel,str2)) return False;
@@ -3383,38 +3436,6 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
return(True);
}
-struct session_info {
- char machine[31];
- char username[24];
- char clitype[24];
- int opens;
- int time;
-};
-
-struct sessions_info {
- int count;
- struct session_info *session_list;
-};
-
-static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
-{
- struct sessions_info *sinfo = state;
- struct session_info *curinfo = NULL;
- struct sessionid *sessid = (struct sessionid *) dbuf.dptr;
-
- sinfo->count += 1;
- sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info));
-
- curinfo = &(sinfo->session_list[sinfo->count - 1]);
-
- safe_strcpy(curinfo->machine, sessid->remote_machine,
- sizeof(curinfo->machine));
- safe_strcpy(curinfo->username, uidtoname(sessid->uid),
- sizeof(curinfo->username));
- DEBUG(7,("gather_sessioninfo session from %s@%s\n",
- curinfo->username, curinfo->machine));
- return 0;
-}
/****************************************************************************
List open sessions
@@ -3430,8 +3451,8 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
char *p = skip_string(str2,1);
int uLevel;
struct pack_desc desc;
- struct sessions_info sinfo;
- int i;
+ struct sessionid *session_list;
+ int i, num_sessions;
memset((char *)&desc,'\0',sizeof(desc));
@@ -3445,26 +3466,20 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
- sinfo.count = 0;
- sinfo.session_list = NULL;
-
- if (!session_traverse(gather_sessioninfo, &sinfo)) {
- DEBUG(4,("RNetSessionEnum session_traverse failed\n"));
- return False;
- }
+ num_sessions = list_sessions(&session_list);
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
memset((char *)&desc,'\0',sizeof(desc));
desc.base = *rdata;
desc.buflen = mdrcnt;
desc.format = str2;
- if (!init_package(&desc,sinfo.count,0)) {
+ if (!init_package(&desc,num_sessions,0)) {
return False;
}
- for(i=0; i<sinfo.count; i++) {
- PACKS(&desc, "z", sinfo.session_list[i].machine);
- PACKS(&desc, "z", sinfo.session_list[i].username);
+ for(i=0; i<num_sessions; i++) {
+ PACKS(&desc, "z", session_list[i].remote_machine);
+ PACKS(&desc, "z", session_list[i].username);
PACKI(&desc, "W", 1); /* num conns */
PACKI(&desc, "W", 0); /* num opens */
PACKI(&desc, "W", 1); /* num users */
@@ -3480,7 +3495,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
*rparam = REALLOC(*rparam,*rparam_len);
SSVALS(*rparam,0,desc.errcode);
SSVAL(*rparam,2,0); /* converter */
- SSVAL(*rparam,4,sinfo.count); /* count */
+ SSVAL(*rparam,4,num_sessions); /* count */
DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
return True;
@@ -3540,43 +3555,47 @@ struct
int id;
BOOL (*fn)(connection_struct *,uint16,char *,char *,
int,int,char **,char **,int *,int *);
- int flags;
+ BOOL auth_user; /* Deny anonymous access? */
} api_commands[] = {
- {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum,0},
- {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo,0},
- {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd,0},
- {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum,0},
- {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo,0},
- {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum,0},
- {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers,0},
- {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum,0},
- {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo,0},
- {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups,0},
- {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo,0},
- {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum,0},
- {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo,0},
- {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl,0},
- {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl,0},
- {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate,0},
- {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo,0},
- {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel,0},
- {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel,0},
- {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel,0},
- {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum,0},
- {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo,0},
- {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD,0},
- {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl,0},
- {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum,0},
- {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms,0},
- {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword,0},
- {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon,0},
- {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo,0},
- {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum,0},
- {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum,0},
- {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum,0},
- {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword,0},
- {NULL, -1, api_Unsupported,0}};
-
+ {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
+ {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
+ {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
+ {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
+ {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
+ {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
+ {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
+ {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
+ {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
+ {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
+ {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
+ {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
+ {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
+ {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
+ {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
+ {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
+ {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
+ {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
+ {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
+ {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
+ {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
+ {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
+ {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
+ {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
+ {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
+ {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
+ {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
+ {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
+ {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
+ {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
+ {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
+ {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
+ {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
+ {NULL, -1, api_Unsupported}};
+
+/* The following RAP calls are not implemented by Samba:
+
+ RAP_WFileEnum2 - anon not OK
+*/
/****************************************************************************
Handle remote api calls
@@ -3613,6 +3632,15 @@ int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *
}
}
+ /* Check whether this api call can be done anonymously */
+
+ if (api_commands[i].auth_user && lp_restrict_anonymous()) {
+ user_struct *user = get_valid_user_struct(vuid);
+
+ if (!user || user->guest)
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ }
+
rdata = (char *)malloc(1024);
if (rdata)
memset(rdata,'\0',1024);
diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c
index 20b2b419cf..392e48afc1 100644
--- a/source3/smbd/mangle.c
+++ b/source3/smbd/mangle.c
@@ -29,6 +29,7 @@ static struct {
} mangle_backends[] = {
{ "hash", mangle_hash_init },
{ "hash2", mangle_hash2_init },
+ /*{ "tdb", mangle_tdb_init }, */
{ NULL, NULL }
};
@@ -40,11 +41,12 @@ static void mangle_init(void)
int i;
char *method;
- if (mangle_fns) return;
+ if (mangle_fns)
+ return;
method = lp_mangling_method();
- /* find the first mangling method that manages to initialise and
+ /* find the first mangling method that manages to initialise and
matches the "mangling method" parameter */
for (i=0; mangle_backends[i].name && !mangle_fns; i++) {
if (!method || !*method || strcmp(method, mangle_backends[i].name) == 0) {
@@ -82,7 +84,12 @@ BOOL mangle_is_mangled(const char *s)
*/
BOOL mangle_is_8_3(const char *fname, BOOL check_case)
{
- return mangle_fns->is_8_3(fname, check_case);
+ return mangle_fns->is_8_3(fname, check_case, False);
+}
+
+BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case)
+{
+ return mangle_fns->is_8_3(fname, check_case, True);
}
/*
@@ -99,7 +106,8 @@ BOOL mangle_check_cache(char *s)
/*
map a long filename to a 8.3 name.
*/
-BOOL mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum)
+
+void mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum)
{
/* name mangling can be disabled for speed, in which case
we just truncate the string */
@@ -107,11 +115,10 @@ BOOL mangle_map(char *OutName, BOOL need83, BOOL cache83, int snum)
if (need83) {
string_truncate(OutName, 12);
}
- return True;
+ return;
}
/* invoke the inane "mangled map" code */
mangle_map_filename(OutName, snum);
-
- return mangle_fns->name_map(OutName, need83, cache83);
+ mangle_fns->name_map(OutName, need83, cache83);
}
diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c
index f38c2ae2c4..1d4697474c 100644
--- a/source3/smbd/mangle_hash.c
+++ b/source3/smbd/mangle_hash.c
@@ -127,9 +127,8 @@ static BOOL ct_initialized = False;
static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
static BOOL mc_initialized = False;
-#define MANGLED_CACHE_MAX_ENTRIES 0
-#define MANGLED_CACHE_MAX_MEMORY 16384
-
+#define MANGLED_CACHE_MAX_ENTRIES 1024
+#define MANGLED_CACHE_MAX_MEMORY 0
/* -------------------------------------------------------------------------- **
* External Variables...
@@ -140,16 +139,19 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
/* -------------------------------------------------------------------- */
-static NTSTATUS has_valid_chars(const smb_ucs2_t *s)
+static NTSTATUS has_valid_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
{
- if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
+ if (!s || !*s)
+ return NT_STATUS_INVALID_PARAMETER;
/* CHECK: this should not be necessary if the ms wild chars
are not valid in valid.dat --- simo */
- if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
+ if (!allow_wildcards && ms_has_wild_w(s))
+ return NT_STATUS_UNSUCCESSFUL;
while (*s) {
- if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
+ if(!isvalid83_w(*s))
+ return NT_STATUS_UNSUCCESSFUL;
s++;
}
@@ -159,7 +161,9 @@ static NTSTATUS has_valid_chars(const smb_ucs2_t *s)
/* return False if something fail and
* return 2 alloced unicode strings that contain prefix and extension
*/
-static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension)
+
+static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix,
+ smb_ucs2_t **extension, BOOL allow_wildcards)
{
size_t ext_len;
smb_ucs2_t *p;
@@ -169,12 +173,10 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr
if (!*prefix) {
return NT_STATUS_NO_MEMORY;
}
- if ((p = strrchr_w(*prefix, UCS2_CHAR('.'))))
- {
+ if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) {
ext_len = strlen_w(p+1);
if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
- (NT_STATUS_IS_OK(has_valid_chars(p+1)))) /* check extension */
- {
+ (NT_STATUS_IS_OK(has_valid_chars(p+1,allow_wildcards)))) /* check extension */ {
*p = 0;
*extension = strdup_w(p+1);
if (!*extension) {
@@ -197,20 +199,34 @@ static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **pr
*
* ************************************************************************** **
*/
-static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
+
+static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards)
{
smb_ucs2_t *str, *p;
NTSTATUS ret = NT_STATUS_OK;
- if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
+ if (!fname || !*fname)
+ return NT_STATUS_INVALID_PARAMETER;
- if (*fname == UCS2_CHAR('.')) return NT_STATUS_UNSUCCESSFUL;
+ /* . and .. are valid names. */
+ if (strcmp_wa(fname, ".")==0 || strcmp_wa(fname, "..")==0)
+ return NT_STATUS_OK;
+
+ /* Name cannot start with '.' */
+ if (*fname == UCS2_CHAR('.'))
+ return NT_STATUS_UNSUCCESSFUL;
- ret = has_valid_chars(fname);
- if (NT_STATUS_IS_ERR(ret)) return ret;
+ ret = has_valid_chars(fname, allow_wildcards);
+ if (NT_STATUS_IS_ERR(ret))
+ return ret;
str = strdup_w(fname);
p = strchr_w(str, UCS2_CHAR('.'));
+ if (p && p[1] == UCS2_CHAR(0)) {
+ /* Name cannot end in '.' */
+ SAFE_FREE(str);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
if (p) *p = 0;
strupper_w(str);
p = &(str[1]);
@@ -254,27 +270,34 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname)
return ret;
}
-static NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
+static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
{
smb_ucs2_t *pref = 0, *ext = 0;
size_t plen;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
+ if (!fname || !*fname)
+ return NT_STATUS_INVALID_PARAMETER;
- if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
+ if (strlen_w(fname) > 12)
+ return NT_STATUS_UNSUCCESSFUL;
if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
return NT_STATUS_OK;
- if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
+ if (NT_STATUS_IS_ERR(is_valid_name(fname, allow_wildcards)))
+ goto done;
- if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
+ if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext, allow_wildcards)))
+ goto done;
plen = strlen_w(pref);
- if (strchr_wa(pref, '.')) goto done;
- if (plen < 1 || plen > 8) goto done;
- if (ext) if (strlen_w(ext) > 3) goto done;
+ if (strchr_wa(pref, '.'))
+ goto done;
+ if (plen < 1 || plen > 8)
+ goto done;
+ if (ext && (strlen_w(ext) > 3))
+ goto done;
ret = NT_STATUS_OK;
@@ -284,26 +307,29 @@ done:
return ret;
}
-static BOOL is_8_3(const char *fname, BOOL check_case)
+static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards)
{
const char *f;
smb_ucs2_t *ucs2name;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- if (!fname || !*fname) return False;
- if ((f = strrchr(fname, '/')) == NULL) f = fname;
- else f++;
+ if (!fname || !*fname)
+ return False;
+ if ((f = strrchr(fname, '/')) == NULL)
+ f = fname;
+ else
+ f++;
- if (strlen(f) > 12) return False;
+ if (strlen(f) > 12)
+ return False;
ucs2name = acnv_uxu2(f);
- if (!ucs2name)
- {
+ if (!ucs2name) {
DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
goto done;
}
- ret = is_8_3_w(ucs2name);
+ ret = is_8_3_w(ucs2name, allow_wildcards);
done:
SAFE_FREE(ucs2name);
@@ -334,21 +360,20 @@ done:
* ************************************************************************** **
*/
static void init_chartest( void )
- {
- char *illegalchars = "*\\/?<>|\":";
- unsigned char *s;
+{
+ char *illegalchars = "*\\/?<>|\":";
+ unsigned char *s;
- memset( (char *)chartest, '\0', 256 );
-
- for( s = (unsigned char *)illegalchars; *s; s++ )
- chartest[*s] = ILLEGAL_MASK;
+ memset( (char *)chartest, '\0', 256 );
- for( s = (unsigned char *)basechars; *s; s++ )
- chartest[*s] |= BASECHAR_MASK;
+ for( s = (unsigned char *)illegalchars; *s; s++ )
+ chartest[*s] = ILLEGAL_MASK;
- ct_initialized = True;
- } /* init_chartest */
+ for( s = (unsigned char *)basechars; *s; s++ )
+ chartest[*s] |= BASECHAR_MASK;
+ ct_initialized = True;
+}
/* ************************************************************************** **
* Return True if the name *could be* a mangled name.
@@ -368,24 +393,22 @@ static void init_chartest( void )
* ************************************************************************** **
*/
static BOOL is_mangled(const char *s)
- {
- char *magic;
-
- if( !ct_initialized )
- init_chartest();
-
- magic = strchr_m( s, magic_char );
- while( magic && magic[1] && magic[2] ) /* 3 chars, 1st is magic. */
- {
- if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */
- && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */
- && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */
- return( True ); /* If all above, then true, */
- magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */
- }
- return( False );
- } /* is_mangled */
-
+{
+ char *magic;
+
+ if( !ct_initialized )
+ init_chartest();
+
+ magic = strchr_m( s, magic_char );
+ while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */
+ if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */
+ && isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */
+ && isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */
+ return( True ); /* If all above, then true, */
+ magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */
+ }
+ return( False );
+}
/* ************************************************************************** **
* Compare two cache keys and return a value indicating their ordinal
@@ -407,12 +430,12 @@ static BOOL is_mangled(const char *s)
* ************************************************************************** **
*/
static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
- {
- char *Key1 = (char *)ItemPtr;
- char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
+{
+ char *Key1 = (char *)ItemPtr;
+ char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
- return( StrCaseCmp( Key1, Key2 ) );
- } /* cache_compare */
+ return( StrCaseCmp( Key1, Key2 ) );
+}
/* ************************************************************************** **
* Free a cache entry.
@@ -428,10 +451,10 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
* ************************************************************************** **
*/
static void cache_free_entry( ubi_trNodePtr WarrenZevon )
- {
- ZERO_STRUCTP(WarrenZevon);
- SAFE_FREE( WarrenZevon );
- } /* cache_free_entry */
+{
+ ZERO_STRUCTP(WarrenZevon);
+ SAFE_FREE( WarrenZevon );
+}
/* ************************************************************************** **
* Initializes or clears the mangled cache.
@@ -449,28 +472,25 @@ static void cache_free_entry( ubi_trNodePtr WarrenZevon )
*
* ************************************************************************** **
*/
+
static void mangle_reset( void )
- {
- if( !mc_initialized )
- {
- (void)ubi_cacheInit( mangled_cache,
- cache_compare,
- cache_free_entry,
- MANGLED_CACHE_MAX_ENTRIES,
- MANGLED_CACHE_MAX_MEMORY );
- mc_initialized = True;
- }
- else
- {
- (void)ubi_cacheClear( mangled_cache );
- }
-
- /*
- (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
- (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
- */
- } /* reset_mangled_cache */
+{
+ if( !mc_initialized ) {
+ (void)ubi_cacheInit( mangled_cache,
+ cache_compare,
+ cache_free_entry,
+ MANGLED_CACHE_MAX_ENTRIES,
+ MANGLED_CACHE_MAX_MEMORY );
+ mc_initialized = True;
+ } else {
+ (void)ubi_cacheClear( mangled_cache );
+ }
+ /*
+ (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
+ (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
+ */
+}
/* ************************************************************************** **
* Add a mangled name into the cache.
@@ -497,51 +517,49 @@ static void mangle_reset( void )
* ************************************************************************** **
*/
static void cache_mangled_name( char *mangled_name, char *raw_name )
- {
- ubi_cacheEntryPtr new_entry;
- char *s1;
- char *s2;
- size_t mangled_len;
- size_t raw_len;
- size_t i;
-
- /* If the cache isn't initialized, give up. */
- if( !mc_initialized )
- return;
-
- /* Init the string lengths. */
- mangled_len = strlen( mangled_name );
- raw_len = strlen( raw_name );
-
- /* See if the extensions are unmangled. If so, store the entry
- * without the extension, thus creating a "group" reverse map.
- */
- s1 = strrchr( mangled_name, '.' );
- if( s1 && (s2 = strrchr( raw_name, '.' )) )
- {
- i = 1;
- while( s1[i] && (tolower( s1[i] ) == s2[i]) )
- i++;
- if( !s1[i] && !s2[i] )
- {
- mangled_len -= i;
- raw_len -= i;
- }
- }
-
- /* Allocate a new cache entry. If the allocation fails, just return. */
- i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
- new_entry = malloc( i );
- if( !new_entry )
- return;
-
- /* Fill the new cache entry, and add it to the cache. */
- s1 = (char *)(new_entry + 1);
- s2 = (char *)&(s1[mangled_len + 1]);
- (void)StrnCpy( s1, mangled_name, mangled_len );
- (void)StrnCpy( s2, raw_name, raw_len );
- ubi_cachePut( mangled_cache, i, new_entry, s1 );
- } /* cache_mangled_name */
+{
+ ubi_cacheEntryPtr new_entry;
+ char *s1;
+ char *s2;
+ size_t mangled_len;
+ size_t raw_len;
+ size_t i;
+
+ /* If the cache isn't initialized, give up. */
+ if( !mc_initialized )
+ return;
+
+ /* Init the string lengths. */
+ mangled_len = strlen( mangled_name );
+ raw_len = strlen( raw_name );
+
+ /* See if the extensions are unmangled. If so, store the entry
+ * without the extension, thus creating a "group" reverse map.
+ */
+ s1 = strrchr( mangled_name, '.' );
+ if( s1 && (s2 = strrchr( raw_name, '.' )) ) {
+ i = 1;
+ while( s1[i] && (tolower( s1[i] ) == s2[i]) )
+ i++;
+ if( !s1[i] && !s2[i] ) {
+ mangled_len -= i;
+ raw_len -= i;
+ }
+ }
+
+ /* Allocate a new cache entry. If the allocation fails, just return. */
+ i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
+ new_entry = malloc( i );
+ if( !new_entry )
+ return;
+
+ /* Fill the new cache entry, and add it to the cache. */
+ s1 = (char *)(new_entry + 1);
+ s2 = (char *)&(s1[mangled_len + 1]);
+ (void)StrnCpy( s1, mangled_name, mangled_len );
+ (void)StrnCpy( s2, raw_name, raw_len );
+ ubi_cachePut( mangled_cache, i, new_entry, s1 );
+}
/* ************************************************************************** **
* Check for a name on the mangled name stack
@@ -560,63 +578,57 @@ static void cache_mangled_name( char *mangled_name, char *raw_name )
static BOOL check_cache( char *s )
{
- ubi_cacheEntryPtr FoundPtr;
- char *ext_start = NULL;
- char *found_name;
- char *saved_ext = NULL;
-
- /* If the cache isn't initialized, give up. */
- if( !mc_initialized )
- return( False );
-
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
-
- /* If we didn't find the name *with* the extension, try without. */
- if( !FoundPtr )
- {
- ext_start = strrchr( s, '.' );
- if( ext_start )
- {
- if((saved_ext = strdup(ext_start)) == NULL)
- return False;
-
- *ext_start = '\0';
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
- /*
- * At this point s is the name without the
- * extension. We re-add the extension if saved_ext
- * is not null, before freeing saved_ext.
- */
- }
- }
-
- /* Okay, if we haven't found it we're done. */
- if( !FoundPtr )
- {
- if(saved_ext)
- {
- /* Replace the saved_ext as it was truncated. */
- (void)pstrcat( s, saved_ext );
- SAFE_FREE(saved_ext);
- }
- return( False );
- }
-
- /* If we *did* find it, we need to copy it into the string buffer. */
- found_name = (char *)(FoundPtr + 1);
- found_name += (strlen( found_name ) + 1);
-
- (void)pstrcpy( s, found_name );
- if( saved_ext )
- {
- /* Replace the saved_ext as it was truncated. */
- (void)pstrcat( s, saved_ext );
- SAFE_FREE(saved_ext);
- }
-
- return( True );
-} /* check_mangled_cache */
+ ubi_cacheEntryPtr FoundPtr;
+ char *ext_start = NULL;
+ char *found_name;
+ char *saved_ext = NULL;
+
+ /* If the cache isn't initialized, give up. */
+ if( !mc_initialized )
+ return( False );
+
+ FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+
+ /* If we didn't find the name *with* the extension, try without. */
+ if( !FoundPtr ) {
+ ext_start = strrchr( s, '.' );
+ if( ext_start ) {
+ if((saved_ext = strdup(ext_start)) == NULL)
+ return False;
+
+ *ext_start = '\0';
+ FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ /*
+ * At this point s is the name without the
+ * extension. We re-add the extension if saved_ext
+ * is not null, before freeing saved_ext.
+ */
+ }
+ }
+
+ /* Okay, if we haven't found it we're done. */
+ if( !FoundPtr ) {
+ if(saved_ext) {
+ /* Replace the saved_ext as it was truncated. */
+ (void)pstrcat( s, saved_ext );
+ SAFE_FREE(saved_ext);
+ }
+ return( False );
+ }
+
+ /* If we *did* find it, we need to copy it into the string buffer. */
+ found_name = (char *)(FoundPtr + 1);
+ found_name += (strlen( found_name ) + 1);
+
+ (void)pstrcpy( s, found_name );
+ if( saved_ext ) {
+ /* Replace the saved_ext as it was truncated. */
+ (void)pstrcat( s, saved_ext );
+ SAFE_FREE(saved_ext);
+ }
+ return( True );
+}
/*****************************************************************************
* do the actual mangling to 8.3 format
@@ -624,77 +636,67 @@ static BOOL check_cache( char *s )
*****************************************************************************
*/
static void to_8_3(char *s)
- {
- int csum;
- char *p;
- char extension[4];
- char base[9];
- int baselen = 0;
- int extlen = 0;
-
- extension[0] = 0;
- base[0] = 0;
-
- p = strrchr(s,'.');
- if( p && (strlen(p+1) < (size_t)4) )
- {
- BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
-
- if( all_normal && p[1] != 0 )
- {
- *p = 0;
- csum = str_checksum( s );
- *p = '.';
- }
- else
- csum = str_checksum(s);
- }
- else
- csum = str_checksum(s);
-
- strupper( s );
-
- if( p )
- {
- if( p == s )
- safe_strcpy( extension, "___", 3 );
- else
- {
- *p++ = 0;
- while( *p && extlen < 3 )
- {
- if ( *p != '.') {
- extension[extlen++] = p[0];
- }
- p++;
- }
- extension[extlen] = 0;
- }
- }
-
- p = s;
-
- while( *p && baselen < 5 )
- {
- if (*p != '.') {
- base[baselen++] = p[0];
- }
- p++;
- }
- base[baselen] = 0;
+{
+ int csum;
+ char *p;
+ char extension[4];
+ char base[9];
+ int baselen = 0;
+ int extlen = 0;
+
+ extension[0] = 0;
+ base[0] = 0;
+
+ p = strrchr(s,'.');
+ if( p && (strlen(p+1) < (size_t)4) ) {
+ BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
+
+ if( all_normal && p[1] != 0 ) {
+ *p = 0;
+ csum = str_checksum( s );
+ *p = '.';
+ } else
+ csum = str_checksum(s);
+ } else
+ csum = str_checksum(s);
+
+ strupper( s );
+
+ if( p ) {
+ if( p == s )
+ safe_strcpy( extension, "___", 3 );
+ else {
+ *p++ = 0;
+ while( *p && extlen < 3 ) {
+ if ( *p != '.') {
+ extension[extlen++] = p[0];
+ }
+ p++;
+ }
+ extension[extlen] = 0;
+ }
+ }
- csum = csum % (MANGLE_BASE*MANGLE_BASE);
+ p = s;
+
+ while( *p && baselen < 5 ) {
+ if (*p != '.') {
+ base[baselen++] = p[0];
+ }
+ p++;
+ }
+ base[baselen] = 0;
- (void)slprintf(s, 12, "%s%c%c%c",
- base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
+ csum = csum % (MANGLE_BASE*MANGLE_BASE);
- if( *extension )
- {
- (void)pstrcat( s, "." );
- (void)pstrcat( s, extension );
- }
+ (void)slprintf(s, 12, "%s%c%c%c",
+ base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
- } /* mangle_name_83 */
+ if( *extension ) {
+ (void)pstrcat( s, "." );
+ (void)pstrcat( s, extension );
+ }
+}
/*****************************************************************************
* Convert a filename to DOS format. Return True if successful.
@@ -721,7 +723,8 @@ static void to_8_3(char *s)
*
* ****************************************************************************
*/
-static BOOL name_map(char *OutName, BOOL need83, BOOL cache83)
+
+static void name_map(char *OutName, BOOL need83, BOOL cache83)
{
smb_ucs2_t *OutName_ucs2;
DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
@@ -729,11 +732,14 @@ static BOOL name_map(char *OutName, BOOL need83, BOOL cache83)
if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
- return False;
+ return;
}
+ if( !need83 && NT_STATUS_IS_ERR(is_valid_name(OutName_ucs2, False)))
+ need83 = True;
+
/* check if it's already in 8.3 format */
- if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2))) {
+ if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) {
char *tmp = NULL;
/* mangle it into 8.3 */
@@ -750,9 +756,7 @@ static BOOL name_map(char *OutName, BOOL need83, BOOL cache83)
DEBUG(5,("name_map() ==> [%s]\n", OutName));
SAFE_FREE(OutName_ucs2);
- return(True);
-} /* name_map */
-
+}
/*
the following provides the abstraction layer to make it easier
diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c
index 959a93e07b..e2c4b43bc3 100644
--- a/source3/smbd/mangle_hash2.c
+++ b/source3/smbd/mangle_hash2.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
new hash based name mangling implementation
Copyright (C) Andrew Tridgell 2002
+ Copyright (C) Simo Sorce 2002
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
@@ -30,6 +31,10 @@
for simplicity, we only allow ascii characters in 8.3 names
*/
+ /* hash alghorithm changed to FNV1 by idra@samba.org (Simo Sorce).
+ * see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a
+ * discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors
+ */
/*
===============================================================================
@@ -73,6 +78,10 @@
#define MANGLE_CACHE_SIZE 4096
#endif
+#define FNV1_PRIME 0x01000193
+/*the following number is a fnv1 of the string: idra@samba.org 2002 */
+#define FNV1_INIT 0xa6b93095
+
/* these tables are used to provide fast tests for characters */
static unsigned char char_flags[256];
@@ -88,13 +97,14 @@ static char **prefix_cache;
static u32 *prefix_cache_hashes;
/* these are the characters we use in the 8.3 hash. Must be 36 chars long */
-const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static unsigned char base_reverse[256];
#define base_forward(v) basechars[v]
/* the list of reserved dos names - all of these are illegal */
-const char *reserved_names[] = { "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4",
- "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL };
+static const char *reserved_names[] =
+{ "AUX", "LOCK$", "CON", "COM1", "COM2", "COM3", "COM4",
+ "LPT1", "LPT2", "LPT3", "NUL", "PRN", NULL };
/*
hash a string of the specified length. The string does not need to be
@@ -120,13 +130,14 @@ static u32 mangle_hash(const char *key, unsigned length)
length = strlen(str);
/* Set the initial value from the key size. */
- for (value = 0x238F13AF * length, i=0; i < length; i++) {
- value = (value + (((unsigned char)str[i]) << (i*5 % 24)));
- }
+ for (value = FNV1_INIT, i=0; i < length; i++) {
+ value *= (u32)FNV1_PRIME;
+ value ^= (u32)(str[i]);
+ }
/* note that we force it to a 31 bit hash, to keep within the limits
of the 36^6 mangle space */
- return (1103515243 * value + 12345) & ~0x80000000;
+ return value & ~0x80000000;
}
/*
@@ -184,12 +195,12 @@ 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(const char *name)
+ */
+static BOOL is_mangled_component(const char *name)
{
int len, i;
- M_DEBUG(0,("is_mangled %s ?\n", name));
+ M_DEBUG(0,("is_mangled_component %s ?\n", name));
/* the best distinguishing characteristic is the ~ */
if (name[6] != '~') return False;
@@ -229,6 +240,39 @@ static BOOL is_mangled(const char *name)
}
+
+/*
+ determine if a string is possibly in a mangled format, ignoring
+ case
+
+ In this algorithm, mangled names use only pure ascii characters (no
+ multi-byte) so we can avoid doing a UCS2 conversion
+
+ NOTE! This interface must be able to handle a path with unix
+ directory separators. It should return true if any component is
+ mangled
+ */
+static BOOL is_mangled(const char *name)
+{
+ const char *p;
+ const char *s;
+
+ M_DEBUG(0,("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);
+ return True;
+ }
+ free(component);
+ }
+
+ /* and the last part ... */
+ return is_mangled_component(s);
+}
+
+
/*
see if a filename is an allowable 8.3 name.
@@ -236,7 +280,7 @@ static BOOL is_mangled(const char *name)
simplifies things greatly (it means that we know the string won't
get larger when converted from UNIX to DOS formats)
*/
-static BOOL is_8_3(const char *name, BOOL check_case)
+static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
{
int len, i;
char *dot_p;
@@ -286,8 +330,8 @@ static BOOL is_8_3(const char *name, BOOL check_case)
/* the length are all OK. Now check to see if the characters themselves are OK */
for (i=0; name[i]; i++) {
- /* note that we allow wildcard petterns! */
- if (!FLAG_CHECK(name[i], FLAG_ASCII|FLAG_WILDCARD) && name[i] != '.') {
+ /* note that we may allow wildcard petterns! */
+ if (!FLAG_CHECK(name[i], FLAG_ASCII|(allow_wildcards ? FLAG_WILDCARD : 0)) && name[i] != '.') {
return False;
}
}
@@ -343,8 +387,12 @@ static BOOL check_cache(char *name)
}
/* we found it - construct the full name */
- strncpy(extension, name+9, 3);
- extension[3] = 0;
+ if (name[8] == '.') {
+ strncpy(extension, name+9, 3);
+ extension[3] = 0;
+ } else {
+ extension[0] = 0;
+ }
if (extension[0]) {
M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension));
@@ -383,17 +431,38 @@ static BOOL is_reserved_name(const char *name)
}
/*
- see if a filename is a legal long filename
+ See if a filename is a legal long filename.
+ A filename ending in a '.' is not legal unless it's "." or "..". JRA.
*/
+
static BOOL is_legal_name(const char *name)
{
+ const char *dot_pos = NULL;
+ BOOL alldots = True;
+ size_t numdots = 0;
+
while (*name) {
if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) {
return False;
}
+ if (name[0] == '.') {
+ dot_pos = name;
+ numdots++;
+ } else {
+ alldots = False;
+ }
name++;
}
+ if (dot_pos) {
+ if (alldots && (numdots == 1 || numdots == 2))
+ return True; /* . or .. is a valid name */
+
+ /* A valid long name cannot end in '.' */
+ if (dot_pos[1] == '\0')
+ return False;
+ }
+
return True;
}
@@ -408,7 +477,7 @@ static BOOL is_legal_name(const char *name)
the name parameter must be able to hold 13 bytes
*/
-static BOOL name_map(char *name, BOOL need83, BOOL cache83)
+static void name_map(char *name, BOOL need83, BOOL cache83)
{
char *dot_p;
char lead_char;
@@ -422,14 +491,14 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83)
if (!is_reserved_name(name)) {
/* if the name is already a valid 8.3 name then we don't need to
do anything */
- if (is_8_3(name, False)) {
- return True;
+ if (is_8_3(name, False, False)) {
+ return;
}
/* if the caller doesn't strictly need 8.3 then just check for illegal
filenames */
if (!need83 && is_legal_name(name)) {
- return True;
+ return;
}
}
@@ -511,7 +580,6 @@ static BOOL name_map(char *name, BOOL need83, BOOL cache83)
fstrcpy(name, new_name);
/* all done, we've managed to mangle it */
- return True;
}
diff --git a/source3/smbd/mangle_map.c b/source3/smbd/mangle_map.c
index 71d9340718..553e3d949d 100644
--- a/source3/smbd/mangle_map.c
+++ b/source3/smbd/mangle_map.c
@@ -127,8 +127,8 @@ static char *map_filename( char *s, /* This is null terminated */
*/
static void mangled_map(char *s, const char *MangledMap)
{
- char *start=MangledMap; /* Use this to search for mappings. */
- char *end; /* Used to find the end of strings. */
+ const char *start=MangledMap; /* Use this to search for mappings. */
+ const char *end; /* Used to find the end of strings. */
char *match_string;
pstring new_string; /* Make up the result here. */
char *np; /* Points into new_string. */
diff --git a/source3/smbd/message.c b/source3/smbd/message.c
index 971834c012..ba646f12aa 100644
--- a/source3/smbd/message.c
+++ b/source3/smbd/message.c
@@ -85,7 +85,7 @@ static void msg_deliver(void)
pstrcpy(s,lp_msg_command());
pstring_sub(s,"%f",alpha_strcpy(alpha_msgfrom,msgfrom,NULL,sizeof(alpha_msgfrom)));
pstring_sub(s,"%t",alpha_strcpy(alpha_msgto,msgto,NULL,sizeof(alpha_msgto)));
- standard_sub_basic(current_user_info.smb_name, s);
+ standard_sub_basic(current_user_info.smb_name, s, sizeof(s));
pstring_sub(s,"%s",name);
smbrun(s,NULL);
}
@@ -118,8 +118,8 @@ int reply_sends(connection_struct *conn,
outsize = set_message(outbuf,0,0,True);
p = smb_buf(inbuf)+1;
- p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1;
- p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1;
msg = p;
@@ -160,8 +160,8 @@ int reply_sendstrt(connection_struct *conn,
msgpos = 0;
p = smb_buf(inbuf)+1;
- p += srvstr_pull(inbuf, msgfrom, p, sizeof(msgfrom), -1, STR_TERMINATE) + 1;
- p += srvstr_pull(inbuf, msgto, p, sizeof(msgto), -1, STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_TERMINATE) + 1;
DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) );
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 18682e6c9f..81c2427a00 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -50,8 +50,9 @@ static void get_challenge(char buff[8])
}
/****************************************************************************
-reply for the core protocol
+ Reply for the core protocol.
****************************************************************************/
+
static int reply_corep(char *inbuf, char *outbuf)
{
int outsize = set_message(outbuf,1,0,True);
@@ -61,107 +62,110 @@ static int reply_corep(char *inbuf, char *outbuf)
return outsize;
}
-
/****************************************************************************
-reply for the coreplus protocol
+ Reply for the coreplus protocol.
****************************************************************************/
+
static int reply_coreplus(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(outbuf,13,0,True);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw and writebraw (possibly) */
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int outsize = set_message(outbuf,13,0,True);
+ SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
+ readbraw and writebraw (possibly) */
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
- Protocol = PROTOCOL_COREPLUS;
+ Protocol = PROTOCOL_COREPLUS;
- return outsize;
+ return outsize;
}
-
/****************************************************************************
-reply for the lanman 1.0 protocol
+ Reply for the lanman 1.0 protocol.
****************************************************************************/
+
static int reply_lanman1(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = time(NULL);
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int secword=0;
+ time_t t = time(NULL);
- global_encrypted_passwords_negotiated = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
- if (lp_security()>=SEC_USER) secword |= 1;
- if (global_encrypted_passwords_negotiated) secword |= 2;
+ if (lp_security()>=SEC_USER)
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
+ if (global_encrypted_passwords_negotiated)
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- /* Create a token value and add it to the outgoing packet. */
- if (global_encrypted_passwords_negotiated) {
- get_challenge(smb_buf(outbuf));
- }
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ SSVAL(outbuf,smb_vwv1,secword);
+ /* Create a token value and add it to the outgoing packet. */
+ if (global_encrypted_passwords_negotiated) {
+ get_challenge(smb_buf(outbuf));
+ }
- Protocol = PROTOCOL_LANMAN1;
+ Protocol = PROTOCOL_LANMAN1;
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv2,max_recv);
- SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw writebraw (possibly) */
- SIVAL(outbuf,smb_vwv6,sys_getpid());
- SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv2,max_recv);
+ SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
+ SSVAL(outbuf,smb_vwv4,1);
+ SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
+ readbraw writebraw (possibly) */
+ SIVAL(outbuf,smb_vwv6,sys_getpid());
+ SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
- put_dos_date(outbuf,smb_vwv8,t);
+ put_dos_date(outbuf,smb_vwv8,t);
- return (smb_len(outbuf)+4);
+ return (smb_len(outbuf)+4);
}
-
/****************************************************************************
-reply for the lanman 2.0 protocol
+ Reply for the lanman 2.0 protocol.
****************************************************************************/
+
static int reply_lanman2(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = time(NULL);
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int secword=0;
+ time_t t = time(NULL);
- global_encrypted_passwords_negotiated = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
- if (lp_security()>=SEC_USER) secword |= 1;
- if (global_encrypted_passwords_negotiated) secword |= 2;
-
- set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- SIVAL(outbuf,smb_vwv6,sys_getpid());
-
- /* Create a token value and add it to the outgoing packet. */
- if (global_encrypted_passwords_negotiated) {
- get_challenge(smb_buf(outbuf));
- }
-
- Protocol = PROTOCOL_LANMAN2;
-
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv2,max_recv);
- SSVAL(outbuf,smb_vwv3,lp_maxmux());
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
- SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
- put_dos_date(outbuf,smb_vwv8,t);
-
- return (smb_len(outbuf)+4);
-}
+ if (lp_security()>=SEC_USER)
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
+ if (global_encrypted_passwords_negotiated)
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ SSVAL(outbuf,smb_vwv1,secword);
+ SIVAL(outbuf,smb_vwv6,sys_getpid());
+ /* Create a token value and add it to the outgoing packet. */
+ if (global_encrypted_passwords_negotiated) {
+ get_challenge(smb_buf(outbuf));
+ }
+
+ Protocol = PROTOCOL_LANMAN2;
+
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv2,max_recv);
+ SSVAL(outbuf,smb_vwv3,lp_maxmux());
+ SSVAL(outbuf,smb_vwv4,1);
+ SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
+ SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
+ put_dos_date(outbuf,smb_vwv8,t);
+
+ return (smb_len(outbuf)+4);
+}
+
+/****************************************************************************
+ Generate the spnego negprot reply blob. Return the number of bytes used.
+****************************************************************************/
-/*
- generate the spnego negprot reply blob. Return the number of bytes used
-*/
static int negprot_spnego(char *p)
{
DATA_BLOB blob;
@@ -197,7 +201,7 @@ static int negprot_spnego(char *p)
blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
} else {
ADS_STRUCT *ads;
- ads = ads_init(NULL, NULL, NULL, NULL);
+ ads = ads_init_simple();
/* win2000 uses host$@REALM, which we will probably use eventually,
but for now this works */
asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
@@ -211,11 +215,10 @@ static int negprot_spnego(char *p)
return len;
}
-
-
/****************************************************************************
-reply for the nt protocol
+ Reply for the nt protocol.
****************************************************************************/
+
static int reply_nt1(char *inbuf, char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
@@ -262,9 +265,9 @@ static int reply_nt1(char *inbuf, char *outbuf)
capabilities |= CAP_DFS;
if (lp_security() >= SEC_USER)
- secword |= 1;
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
if (global_encrypted_passwords_negotiated)
- secword |= 2;
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
set_message(outbuf,17,0,True);
@@ -377,133 +380,128 @@ protocol [LANMAN2.1]
/* List of supported protocols, most desired first */
static struct {
- char *proto_name;
- char *short_name;
- int (*proto_reply_fn)(char *, char *);
- int protocol_level;
+ char *proto_name;
+ char *short_name;
+ int (*proto_reply_fn)(char *, char *);
+ int protocol_level;
} supported_protocols[] = {
- {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
- {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
- {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
- {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
- {NULL,NULL,NULL,0},
+ {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
+ {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
+ {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
+ {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
+ {NULL,NULL,NULL,0},
};
-
/****************************************************************************
- reply to a negprot
+ Reply to a negprot.
****************************************************************************/
+
int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize)
{
- int outsize = set_message(outbuf,1,0,True);
- int Index=0;
- int choice= -1;
- int protocol;
- char *p;
- int bcc = SVAL(smb_buf(inbuf),-2);
- int arch = ARCH_ALL;
- START_PROFILE(SMBnegprot);
-
- p = smb_buf(inbuf)+1;
- while (p < (smb_buf(inbuf) + bcc))
- {
- Index++;
- DEBUG(3,("Requested protocol [%s]\n",p));
- if (strcsequal(p,"Windows for Workgroups 3.1a"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcsequal(p,"DOS LM1.2X002"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"DOS LANMAN2.1"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"NT LM 0.12"))
- arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcsequal(p,"LANMAN2.1"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"LM1.2X002"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
- arch &= ARCH_WINNT;
- else if (strcsequal(p,"XENIX CORE"))
- arch &= ( ARCH_WINNT | ARCH_OS2 );
- else if (strcsequal(p,"Samba")) {
- arch = ARCH_SAMBA;
- break;
- }
+ int outsize = set_message(outbuf,1,0,True);
+ int Index=0;
+ int choice= -1;
+ int protocol;
+ char *p;
+ int bcc = SVAL(smb_buf(inbuf),-2);
+ int arch = ARCH_ALL;
+ START_PROFILE(SMBnegprot);
+
+ p = smb_buf(inbuf)+1;
+ while (p < (smb_buf(inbuf) + bcc)) {
+ Index++;
+ DEBUG(3,("Requested protocol [%s]\n",p));
+ if (strcsequal(p,"Windows for Workgroups 3.1a"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
+ else if (strcsequal(p,"DOS LM1.2X002"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 );
+ else if (strcsequal(p,"DOS LANMAN2.1"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 );
+ else if (strcsequal(p,"NT LM 0.12"))
+ arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
+ else if (strcsequal(p,"LANMAN2.1"))
+ arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
+ else if (strcsequal(p,"LM1.2X002"))
+ arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
+ else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
+ arch &= ARCH_WINNT;
+ else if (strcsequal(p,"XENIX CORE"))
+ arch &= ( ARCH_WINNT | ARCH_OS2 );
+ else if (strcsequal(p,"Samba")) {
+ arch = ARCH_SAMBA;
+ break;
+ }
- p += strlen(p) + 2;
- }
+ p += strlen(p) + 2;
+ }
- switch ( arch ) {
- case ARCH_SAMBA:
- set_remote_arch(RA_SAMBA);
- break;
- case ARCH_WFWG:
- set_remote_arch(RA_WFWG);
- break;
- case ARCH_WIN95:
- set_remote_arch(RA_WIN95);
- break;
- case ARCH_WINNT:
- if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
- set_remote_arch(RA_WIN2K);
- else
- set_remote_arch(RA_WINNT);
- break;
- case ARCH_WIN2K:
- set_remote_arch(RA_WIN2K);
- break;
- case ARCH_OS2:
- set_remote_arch(RA_OS2);
- break;
- default:
- set_remote_arch(RA_UNKNOWN);
- break;
- }
+ switch ( arch ) {
+ case ARCH_SAMBA:
+ set_remote_arch(RA_SAMBA);
+ break;
+ case ARCH_WFWG:
+ set_remote_arch(RA_WFWG);
+ break;
+ case ARCH_WIN95:
+ set_remote_arch(RA_WIN95);
+ break;
+ case ARCH_WINNT:
+ if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
+ set_remote_arch(RA_WIN2K);
+ else
+ set_remote_arch(RA_WINNT);
+ break;
+ case ARCH_WIN2K:
+ set_remote_arch(RA_WIN2K);
+ break;
+ case ARCH_OS2:
+ set_remote_arch(RA_OS2);
+ break;
+ default:
+ set_remote_arch(RA_UNKNOWN);
+ break;
+ }
- /* possibly reload - change of architecture */
- reload_services(True);
+ /* possibly reload - change of architecture */
+ reload_services(True);
- /* Check for protocols, most desirable first */
- for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
- {
- p = smb_buf(inbuf)+1;
- Index = 0;
- if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
- (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
- while (p < (smb_buf(inbuf) + bcc))
- {
- if (strequal(p,supported_protocols[protocol].proto_name))
- choice = Index;
- Index++;
- p += strlen(p) + 2;
- }
- if(choice != -1)
- break;
- }
+ /* Check for protocols, most desirable first */
+ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
+ p = smb_buf(inbuf)+1;
+ Index = 0;
+ if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
+ (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
+ while (p < (smb_buf(inbuf) + bcc)) {
+ if (strequal(p,supported_protocols[protocol].proto_name))
+ choice = Index;
+ Index++;
+ p += strlen(p) + 2;
+ }
+ if(choice != -1)
+ break;
+ }
- SSVAL(outbuf,smb_vwv0,choice);
- if(choice != -1) {
- extern fstring remote_proto;
- fstrcpy(remote_proto,supported_protocols[protocol].short_name);
- reload_services(True);
- outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
- DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
- }
- else {
- DEBUG(0,("No protocol supported !\n"));
- }
- SSVAL(outbuf,smb_vwv0,choice);
+ SSVAL(outbuf,smb_vwv0,choice);
+ if(choice != -1) {
+ extern fstring remote_proto;
+ fstrcpy(remote_proto,supported_protocols[protocol].short_name);
+ reload_services(True);
+ outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
+ DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
+ } else {
+ DEBUG(0,("No protocol supported !\n"));
+ }
+ SSVAL(outbuf,smb_vwv0,choice);
- DEBUG( 5, ( "negprot index=%d\n", choice ) );
+ DEBUG( 5, ( "negprot index=%d\n", choice ) );
- END_PROFILE(SMBnegprot);
- return(outsize);
+ END_PROFILE(SMBnegprot);
+ return(outsize);
}
-
diff --git a/source3/smbd/notify_kernel.c b/source3/smbd/notify_kernel.c
index 19ea41e195..8454917163 100644
--- a/source3/smbd/notify_kernel.c
+++ b/source3/smbd/notify_kernel.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 3.0
change notify handling - linux kernel based implementation
Copyright (C) Andrew Tridgell 2000
@@ -22,9 +23,9 @@
#if HAVE_KERNEL_CHANGE_NOTIFY
-static VOLATILE sig_atomic_t fd_pending;
-static VOLATILE sig_atomic_t signals_received;
-static VOLATILE sig_atomic_t signals_processed;
+#define FD_PENDING_SIZE 20
+static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE];
+static SIG_ATOMIC_T signals_received;
#ifndef DN_ACCESS
#define DN_ACCESS 0x00000001 /* File accessed in directory */
@@ -53,84 +54,114 @@ static VOLATILE sig_atomic_t signals_processed;
This is the structure to keep the information needed to
determine if a directory has changed.
*****************************************************************************/
+
struct change_data {
int directory_handle;
};
/****************************************************************************
-the signal handler for change notify
+ The signal handler for change notify.
+ The Linux kernel has a bug in that we should be able to block any
+ further delivery of RT signals until the kernel_check_notify() function
+ unblocks them, but it seems that any signal mask we're setting here is
+ being overwritten on exit from this handler. I should create a standalone
+ test case for the kernel hackers. JRA.
*****************************************************************************/
+
static void signal_handler(int sig, siginfo_t *info, void *unused)
{
- BlockSignals(True, sig);
- fd_pending = (sig_atomic_t)info->si_fd;
- signals_received++;
+ if (signals_received < FD_PENDING_SIZE - 1) {
+ fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd;
+ signals_received++;
+ } /* Else signal is lost. */
sys_select_signal();
}
-
-
/****************************************************************************
Check if a change notify should be issued.
time non-zero means timeout check (used for hash). Ignore this (async method
where time is zero will be used instead).
*****************************************************************************/
+
static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t)
{
struct change_data *data = (struct change_data *)datap;
+ int i;
+ BOOL ret = False;
if (t)
return False;
- if (data->directory_handle != (int)fd_pending) return False;
-
- DEBUG(3,("kernel change notify on %s fd=%d\n", path, (int)fd_pending));
-
- close((int)fd_pending);
- fd_pending = (sig_atomic_t)-1;
- data->directory_handle = -1;
- signals_processed++;
+ BlockSignals(True, RT_SIGNAL_NOTIFY);
+ for (i = 0; i < signals_received; i++) {
+ if (data->directory_handle == (int)fd_pending_array[i]) {
+ DEBUG(3,("kernel_check_notify: kernel change notify on %s fd[%d]=%d (signals_received=%d)\n",
+ path, i, (int)fd_pending_array[i], (int)signals_received ));
+
+ close((int)fd_pending_array[i]);
+ fd_pending_array[i] = (SIG_ATOMIC_T)-1;
+ if (signals_received - i - 1) {
+ memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1],
+ sizeof(SIG_ATOMIC_T)*(signals_received-i-1));
+ }
+ data->directory_handle = -1;
+ signals_received--;
+ ret = True;
+ break;
+ }
+ }
BlockSignals(False, RT_SIGNAL_NOTIFY);
- return True;
+ return ret;
}
/****************************************************************************
-remove a change notify data structure
+ Remove a change notify data structure.
*****************************************************************************/
+
static void kernel_remove_notify(void *datap)
{
struct change_data *data = (struct change_data *)datap;
int fd = data->directory_handle;
if (fd != -1) {
- if (fd == (int)fd_pending) {
- fd_pending = (sig_atomic_t)-1;
- signals_processed++;
- BlockSignals(False, RT_SIGNAL_NOTIFY);
+ int i;
+ BlockSignals(True, RT_SIGNAL_NOTIFY);
+ for (i = 0; i < signals_received; i++) {
+ if (fd == (int)fd_pending_array[i]) {
+ close(fd);
+ fd_pending_array[i] = (SIG_ATOMIC_T)-1;
+ if (signals_received - i - 1) {
+ memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1],
+ sizeof(SIG_ATOMIC_T)*(signals_received-i-1));
+ }
+ data->directory_handle = -1;
+ signals_received--;
+ break;
+ }
}
- close(fd);
+ BlockSignals(False, RT_SIGNAL_NOTIFY);
}
SAFE_FREE(data);
- DEBUG(3,("removed kernel change notify fd=%d\n", fd));
+ DEBUG(3,("kernel_remove_notify: fd=%d\n", fd));
}
-
/****************************************************************************
-register a change notify request
+ Register a change notify request.
*****************************************************************************/
+
static void *kernel_register_notify(connection_struct *conn, char *path, uint32 flags)
{
struct change_data data;
int fd;
unsigned long kernel_flags;
- fd = conn->vfs_ops.open(conn, path, O_RDONLY, 0);
+ fd = sys_open(path,O_RDONLY, 0);
if (fd == -1) {
DEBUG(3,("Failed to open directory %s for change notify\n", path));
return NULL;
}
- if (fcntl(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) {
+ if (sys_fcntl_long(fd, F_SETSIG, RT_SIGNAL_NOTIFY) == -1) {
DEBUG(3,("Failed to set signal handler for change notify\n"));
return NULL;
}
@@ -147,7 +178,7 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32
if (flags & FILE_NOTIFY_CHANGE_EA) kernel_flags |= DN_ATTRIB;
if (flags & FILE_NOTIFY_CHANGE_FILE_NAME) kernel_flags |= DN_RENAME|DN_DELETE;
- if (fcntl(fd, F_NOTIFY, kernel_flags) == -1) {
+ if (sys_fcntl_long(fd, F_NOTIFY, kernel_flags) == -1) {
DEBUG(3,("Failed to set async flag for change notify\n"));
return NULL;
}
@@ -161,22 +192,24 @@ static void *kernel_register_notify(connection_struct *conn, char *path, uint32
}
/****************************************************************************
-see if the kernel supports change notify
+ See if the kernel supports change notify.
****************************************************************************/
+
static BOOL kernel_notify_available(void)
{
int fd, ret;
fd = open("/tmp", O_RDONLY);
- if (fd == -1) return False; /* uggh! */
- ret = fcntl(fd, F_NOTIFY, 0);
+ if (fd == -1)
+ return False; /* uggh! */
+ ret = sys_fcntl_long(fd, F_NOTIFY, 0);
close(fd);
return ret == 0;
}
-
/****************************************************************************
-setup kernel based change notify
+ Setup kernel based change notify.
****************************************************************************/
+
struct cnotify_fns *kernel_notify_init(void)
{
static struct cnotify_fns cnotify;
@@ -190,7 +223,8 @@ struct cnotify_fns *kernel_notify_init(void)
return NULL;
}
- if (!kernel_notify_available()) return NULL;
+ if (!kernel_notify_available())
+ return NULL;
cnotify.register_notify = kernel_register_notify;
cnotify.check_notify = kernel_check_notify;
@@ -200,7 +234,6 @@ struct cnotify_fns *kernel_notify_init(void)
return &cnotify;
}
-
#else
void notify_kernel_dummy(void) {}
#endif /* HAVE_KERNEL_CHANGE_NOTIFY */
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index edee14513c..e0a0da7a75 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -454,6 +454,7 @@ to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_acces
/****************************************************************************
Reply to an NT create and X call on a pipe.
****************************************************************************/
+
static int nt_open_pipe(char *fname, connection_struct *conn,
char *inbuf, char *outbuf, int *ppnum)
{
@@ -502,7 +503,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
int pnum = -1;
char *p = NULL;
- srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
return ret;
@@ -605,12 +606,13 @@ int reply_ntcreate_and_X(connection_struct *conn,
}
if(!dir_fsp->is_directory) {
+
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+
/*
* Check to see if this is a mac fork of some kind.
*/
- srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
-
if( strchr_m(fname, ':')) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
@@ -635,10 +637,18 @@ int reply_ntcreate_and_X(connection_struct *conn,
dir_name_len++;
}
- srvstr_pull(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len,
- -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE);
} else {
- srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+
+ /*
+ * Check to see if this is a mac fork of some kind.
+ */
+
+ if( strchr_m(fname, ':')) {
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
}
/*
@@ -880,29 +890,29 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
return ERROR_DOS(ERRDOS,ERRbadaccess);
}
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE);
-
- if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
- return ret;
+ srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
+ if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
+ return ret;
+
/* Realloc the size of parameters and data we will return */
params = Realloc(*ppparams, 69);
if(params == NULL)
return ERROR_DOS(ERRDOS,ERRnomem);
-
+
*ppparams = params;
-
+
memset((char *)params,'\0',69);
-
+
p = params;
SCVAL(p,0,NO_OPLOCK_RETURN);
-
+
p += 2;
SSVAL(p,0,pnum);
p += 2;
SIVAL(p,0,FILE_WAS_OPENED);
p += 8;
-
+
p += 32;
SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
p += 20;
@@ -910,12 +920,12 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
/* Device state. */
SSVAL(p,2, 0x5FF); /* ? */
-
+
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
-
+
/* Send the required number of replies */
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
-
+
return -1;
}
@@ -923,17 +933,15 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
Internal fn to set security descriptors.
****************************************************************************/
-static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent, int *pdef_class,uint32 *pdef_code)
+static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent)
{
prs_struct pd;
SEC_DESC *psd = NULL;
TALLOC_CTX *mem_ctx;
BOOL ret;
-
+
if (sd_len == 0) {
- *pdef_class = ERRDOS;
- *pdef_code = ERRbadaccess;
- return False;
+ return NT_STATUS_OK;
}
/*
@@ -942,9 +950,7 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security
if ((mem_ctx = talloc_init()) == NULL) {
DEBUG(0,("set_sd: talloc_init failed.\n"));
- *pdef_class = ERRDOS;
- *pdef_code = ERRnomem;
- return False;
+ return NT_STATUS_NO_MEMORY;
}
prs_init(&pd, 0, mem_ctx, UNMARSHALL);
@@ -966,11 +972,9 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security
* Return access denied for want of a better error message..
*/
talloc_destroy(mem_ctx);
- *pdef_class = ERRDOS;
- *pdef_code = ERRnomem;
- return False;
+ return NT_STATUS_NO_MEMORY;
}
-
+
if (psd->off_owner_sid==0)
security_info_sent &= ~OWNER_SECURITY_INFORMATION;
if (psd->off_grp_sid==0)
@@ -981,19 +985,15 @@ static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security
security_info_sent &= ~DACL_SECURITY_INFORMATION;
ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd);
-
+
if (!ret) {
talloc_destroy(mem_ctx);
- *pdef_class = ERRDOS;
- *pdef_code = ERRnoaccess;
- return False;
+ return NT_STATUS_ACCESS_DENIED;
}
-
+
talloc_destroy(mem_ctx);
-
- *pdef_class = 0;
- *pdef_code = 0;
- return True;
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -1005,304 +1005,307 @@ static int call_nt_transact_create(connection_struct *conn,
int bufsize, char **ppsetup, char **ppparams,
char **ppdata)
{
- pstring fname;
- char *params = *ppparams;
- char *data = *ppdata;
- int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount);
- /* Breakout the oplock request bits so we can set the
- reply bits separately. */
- int oplock_request = 0;
- mode_t unixmode;
- int fmode=0,rmode=0;
- SMB_OFF_T file_len = 0;
- SMB_STRUCT_STAT sbuf;
- int smb_action = 0;
- BOOL bad_path = False;
- files_struct *fsp = NULL;
- char *p = NULL;
- uint32 flags;
- uint32 desired_access;
- uint32 file_attributes;
- uint32 share_access;
- uint32 create_disposition;
- uint32 create_options;
- uint32 sd_len;
- uint16 root_dir_fid;
- int smb_ofun;
- int smb_open_mode;
- int smb_attr;
- int error_class;
- uint32 error_code;
- time_t c_time;
-
- DEBUG(5,("call_nt_transact_create\n"));
+ pstring fname;
+ char *params = *ppparams;
+ char *data = *ppdata;
+ int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount);
+ /* Breakout the oplock request bits so we can set the reply bits separately. */
+ int oplock_request = 0;
+ mode_t unixmode;
+ int fmode=0,rmode=0;
+ SMB_OFF_T file_len = 0;
+ SMB_STRUCT_STAT sbuf;
+ int smb_action = 0;
+ BOOL bad_path = False;
+ files_struct *fsp = NULL;
+ char *p = NULL;
+ uint32 flags;
+ uint32 desired_access;
+ uint32 file_attributes;
+ uint32 share_access;
+ uint32 create_disposition;
+ uint32 create_options;
+ uint32 sd_len;
+ uint16 root_dir_fid;
+ int smb_ofun;
+ int smb_open_mode;
+ int smb_attr;
+ time_t c_time;
+ NTSTATUS nt_status;
- /*
- * If it's an IPC, use the pipe handler.
- */
+ DEBUG(5,("call_nt_transact_create\n"));
+
+ /*
+ * If it's an IPC, use the pipe handler.
+ */
- if (IS_IPC(conn)) {
+ if (IS_IPC(conn)) {
if (lp_nt_pipe_support())
return do_nt_transact_create_pipe(conn, inbuf, outbuf, length,
bufsize, ppsetup, ppparams, ppdata);
else
return ERROR_DOS(ERRDOS,ERRbadaccess);
- }
+ }
- /*
- * Ensure minimum number of parameters sent.
- */
+ /*
+ * Ensure minimum number of parameters sent.
+ */
- if(total_parameter_count < 54) {
- DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count));
- return ERROR_DOS(ERRDOS,ERRbadaccess);
- }
+ if(total_parameter_count < 54) {
+ DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count));
+ return ERROR_DOS(ERRDOS,ERRbadaccess);
+ }
- flags = IVAL(params,0);
- desired_access = IVAL(params,8);
- file_attributes = IVAL(params,20);
- share_access = IVAL(params,24);
- create_disposition = IVAL(params,28);
- create_options = IVAL(params,32);
- sd_len = IVAL(params,36);
- root_dir_fid = (uint16)IVAL(params,4);
- smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+ flags = IVAL(params,0);
+ desired_access = IVAL(params,8);
+ file_attributes = IVAL(params,20);
+ share_access = IVAL(params,24);
+ create_disposition = IVAL(params,28);
+ create_options = IVAL(params,32);
+ sd_len = IVAL(params,36);
+ root_dir_fid = (uint16)IVAL(params,4);
+ smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
- /*
- * We need to construct the open_and_X ofun value from the
- * NT values, as that's what our code is structured to accept.
- */
+ /*
+ * We need to construct the open_and_X ofun value from the
+ * NT values, as that's what our code is structured to accept.
+ */
- if((smb_ofun = map_create_disposition( create_disposition )) == -1)
- return ERROR_DOS(ERRDOS,ERRbadmem);
+ if((smb_ofun = map_create_disposition( create_disposition )) == -1)
+ return ERROR_DOS(ERRDOS,ERRbadmem);
- /*
- * Get the file name.
- */
+ /*
+ * Get the file name.
+ */
- if(root_dir_fid != 0) {
- /*
- * This filename is relative to a directory fid.
- */
+ if(root_dir_fid != 0) {
+ /*
+ * This filename is relative to a directory fid.
+ */
- files_struct *dir_fsp = file_fsp(params,4);
- size_t dir_name_len;
+ files_struct *dir_fsp = file_fsp(params,4);
+ size_t dir_name_len;
- if(!dir_fsp)
- return ERROR_DOS(ERRDOS,ERRbadfid);
+ if(!dir_fsp)
+ return ERROR_DOS(ERRDOS,ERRbadfid);
- if(!dir_fsp->is_directory) {
- /*
- * Check to see if this is a mac fork of some kind.
- */
+ if(!dir_fsp->is_directory) {
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
- if( strchr_m(fname, ':')) {
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
+ /*
+ * Check to see if this is a mac fork of some kind.
+ */
- return ERROR_DOS(ERRDOS,ERRbadfid);
- }
+ if( strchr_m(fname, ':'))
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- /*
- * Copy in the base directory name.
- */
+ return ERROR_DOS(ERRDOS,ERRbadfid);
+ }
- pstrcpy( fname, dir_fsp->fsp_name );
- dir_name_len = strlen(fname);
+ /*
+ * Copy in the base directory name.
+ */
- /*
- * Ensure it ends in a '\'.
- */
+ pstrcpy( fname, dir_fsp->fsp_name );
+ dir_name_len = strlen(fname);
- if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "\\");
- dir_name_len++;
- }
+ /*
+ * Ensure it ends in a '\'.
+ */
- srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len,
- -1, STR_TERMINATE);
- } else {
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), -1, STR_TERMINATE);
- }
+ if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+ pstrcat(fname, "\\");
+ dir_name_len++;
+ }
- /*
- * Now contruct the smb_open_mode value from the desired access
- * and the share access.
- */
+ srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len,
+ total_parameter_count-53, STR_TERMINATE);
+ } else {
+ srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
+
+ /*
+ * Check to see if this is a mac fork of some kind.
+ */
- if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
- share_access, file_attributes)) == -1)
- return ERROR_DOS(ERRDOS,ERRbadaccess);
+ if( strchr_m(fname, ':'))
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
- oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
- oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+ /*
+ * Now contruct the smb_open_mode value from the desired access
+ * and the share access.
+ */
- /*
- * Check if POSIX semantics are wanted.
- */
+ if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
+ share_access, file_attributes)) == -1)
+ return ERROR_DOS(ERRDOS,ERRbadaccess);
- set_posix_case_semantics(file_attributes);
+ oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
+ oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+
+ /*
+ * Check if POSIX semantics are wanted.
+ */
+
+ set_posix_case_semantics(file_attributes);
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
+ unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
+ unixmode = unix_mode(conn,smb_attr | aARCH, fname);
- /*
- * If it's a request for a directory open, deal with it separately.
- */
+ /*
+ * If it's a request for a directory open, deal with it separately.
+ */
- if(create_options & FILE_DIRECTORY_FILE) {
+ if(create_options & FILE_DIRECTORY_FILE) {
- oplock_request = 0;
+ oplock_request = 0;
- /*
- * We will get a create directory here if the Win32
- * app specified a security descriptor in the
- * CreateDirectory() call.
- */
+ /*
+ * We will get a create directory here if the Win32
+ * app specified a security descriptor in the
+ * CreateDirectory() call.
+ */
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
- if(!fsp) {
- restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if(!fsp) {
+ restore_case_semantics(file_attributes);
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- } else {
+ } else {
- /*
- * Ordinary file case.
- */
+ /*
+ * Ordinary file case.
+ */
- fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
- smb_open_mode,smb_ofun,unixmode,
- oplock_request,&rmode,&smb_action);
+ fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
+ smb_open_mode,smb_ofun,unixmode,
+ oplock_request,&rmode,&smb_action);
- if (!fsp) {
+ if (!fsp) {
- if(errno == EISDIR) {
+ if(errno == EISDIR) {
- /*
- * Fail the open if it was explicitly a non-directory file.
- */
+ /*
+ * Fail the open if it was explicitly a non-directory file.
+ */
- if (create_options & FILE_NON_DIRECTORY_FILE) {
- restore_case_semantics(file_attributes);
- SSVAL(outbuf, smb_flg2,
- SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
- return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
- }
+ if (create_options & FILE_NON_DIRECTORY_FILE) {
+ restore_case_semantics(file_attributes);
+ SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
+ return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
+ }
- oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ oplock_request = 0;
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
- if(!fsp) {
+ if(!fsp) {
+ restore_case_semantics(file_attributes);
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+ } else {
restore_case_semantics(file_attributes);
set_bad_path_error(errno, bad_path);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- } else {
-
- restore_case_semantics(file_attributes);
- set_bad_path_error(errno, bad_path);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- }
+ }
- file_len = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
- if(fmode == 0)
- fmode = FILE_ATTRIBUTE_NORMAL;
+ file_len = sbuf.st_size;
+ fmode = dos_mode(conn,fname,&sbuf);
+ if(fmode == 0)
+ fmode = FILE_ATTRIBUTE_NORMAL;
- if (fmode & aDIR) {
- close_file(fsp,False);
- restore_case_semantics(file_attributes);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
- }
+ if (fmode & aDIR) {
+ close_file(fsp,False);
+ restore_case_semantics(file_attributes);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
- /*
- * If the caller set the extended oplock request bit
- * and we granted one (by whatever means) - set the
- * correct bit for extended oplock reply.
- */
+ /*
+ * If the caller set the extended oplock request bit
+ * and we granted one (by whatever means) - set the
+ * correct bit for extended oplock reply.
+ */
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
- smb_action |= EXTENDED_OPLOCK_GRANTED;
+ if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ smb_action |= EXTENDED_OPLOCK_GRANTED;
- if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- smb_action |= EXTENDED_OPLOCK_GRANTED;
- }
-
- /*
- * Now try and apply the desired SD.
- */
+ if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
- if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) {
- close_file(fsp,False);
- restore_case_semantics(file_attributes);
- return ERROR_DOS(error_class, error_code);
- }
+ /*
+ * Now try and apply the desired SD.
+ */
- restore_case_semantics(file_attributes);
+ if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
+ close_file(fsp,False);
+ restore_case_semantics(file_attributes);
+ return ERROR_NT(nt_status);
+ }
+
+ restore_case_semantics(file_attributes);
- /* Realloc the size of parameters and data we will return */
- params = Realloc(*ppparams, 69);
- if(params == NULL)
- return ERROR_DOS(ERRDOS,ERRnomem);
+ /* Realloc the size of parameters and data we will return */
+ params = Realloc(*ppparams, 69);
+ if(params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
- *ppparams = params;
+ *ppparams = params;
- memset((char *)params,'\0',69);
+ memset((char *)params,'\0',69);
- p = params;
- if (smb_action & EXTENDED_OPLOCK_GRANTED)
- SCVAL(p,0, BATCH_OPLOCK_RETURN);
- else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
- SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
- else
- SCVAL(p,0,NO_OPLOCK_RETURN);
+ p = params;
+ if (smb_action & EXTENDED_OPLOCK_GRANTED)
+ SCVAL(p,0, BATCH_OPLOCK_RETURN);
+ else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
+ SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
+ else
+ SCVAL(p,0,NO_OPLOCK_RETURN);
- p += 2;
- SSVAL(p,0,fsp->fnum);
- p += 2;
- SIVAL(p,0,smb_action);
- p += 8;
-
- /* Create time. */
- c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
-
- if (lp_dos_filetime_resolution(SNUM(conn))) {
- c_time &= ~1;
- sbuf.st_atime &= ~1;
- sbuf.st_mtime &= ~1;
- sbuf.st_mtime &= ~1;
- }
+ p += 2;
+ SSVAL(p,0,fsp->fnum);
+ p += 2;
+ SIVAL(p,0,smb_action);
+ p += 8;
- put_long_date(p,c_time);
- p += 8;
- put_long_date(p,sbuf.st_atime); /* access time */
- p += 8;
- put_long_date(p,sbuf.st_mtime); /* write time */
- p += 8;
- put_long_date(p,sbuf.st_mtime); /* change time */
- p += 8;
- SIVAL(p,0,fmode); /* File Attributes. */
- p += 4;
- SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len));
- p += 8;
- SOFF_T(p,0,file_len);
-
- DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
-
- /* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ /* Create time. */
+ c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
- return -1;
+ if (lp_dos_filetime_resolution(SNUM(conn))) {
+ c_time &= ~1;
+ sbuf.st_atime &= ~1;
+ sbuf.st_mtime &= ~1;
+ sbuf.st_mtime &= ~1;
+ }
+
+ put_long_date(p,c_time);
+ p += 8;
+ put_long_date(p,sbuf.st_atime); /* access time */
+ p += 8;
+ put_long_date(p,sbuf.st_mtime); /* write time */
+ p += 8;
+ put_long_date(p,sbuf.st_mtime); /* change time */
+ p += 8;
+ SIVAL(p,0,fmode); /* File Attributes. */
+ p += 4;
+ SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len));
+ p += 8;
+ SOFF_T(p,0,file_len);
+
+ DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
+
+ /* Send the required number of replies */
+ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+
+ return -1;
}
/****************************************************************************
@@ -1560,8 +1563,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount);
files_struct *fsp = NULL;
uint32 security_info_sent = 0;
- int error_class;
- uint32 error_code;
+ NTSTATUS nt_status;
if(total_parameter_count < 8)
return ERROR_DOS(ERRDOS,ERRbadfunc);
@@ -1577,8 +1579,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name,
(unsigned int)security_info_sent ));
- if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code))
- return ERROR_DOS(error_class, error_code);
+ if (total_data_count == 0)
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
+
+ if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent)))
+ return ERROR_NT(nt_status);
done:
@@ -1589,18 +1594,19 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
/****************************************************************************
Reply to IOCTL - not implemented - no plans.
****************************************************************************/
+
static int call_nt_transact_ioctl(connection_struct *conn,
char *inbuf, char *outbuf, int length,
int bufsize,
char **ppsetup, char **ppparams, char **ppdata)
{
- static BOOL logged_message = False;
+ static BOOL logged_message = False;
- if(!logged_message) {
- DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
- logged_message = True; /* Only print this once... */
- }
- return ERROR_DOS(ERRSRV,ERRnosupport);
+ if(!logged_message) {
+ DEBUG(3,("call_nt_transact_ioctl: Currently not implemented.\n"));
+ logged_message = True; /* Only print this once... */
+ }
+ return ERROR_DOS(ERRSRV,ERRnosupport);
}
/****************************************************************************
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 29a854a397..8c6e8ed805 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -87,7 +87,7 @@ static void check_for_pipe(char *fname)
****************************************************************************/
static BOOL open_file(files_struct *fsp,connection_struct *conn,
- char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
+ const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
{
extern struct current_user current_user;
pstring fname;
@@ -169,11 +169,15 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
if (fsp->fd == -1)
ret = vfs_stat(conn, fname, psbuf);
- else
+ else {
ret = vfs_fstat(fsp,fsp->fd,psbuf);
+ /* If we have an fd, this stat should succeed. */
+ if (ret == -1)
+ DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
+ }
+ /* For a non-io open, this stat failing means file not found. JRA */
if (ret == -1) {
- DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
fd_close(conn, fsp);
return False;
}
@@ -1046,7 +1050,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
Open a file for for write to ensure that we can fchmod it.
****************************************************************************/
-files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf)
+files_struct *open_file_fchmod(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
{
files_struct *fsp = NULL;
BOOL fsp_open;
@@ -1058,7 +1062,9 @@ files_struct *open_file_fchmod(connection_struct *conn, char *fname, SMB_STRUCT_
if(!fsp)
return NULL;
- fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,0);
+ /* note! we must use a non-zero desired access or we don't get
+ a real file descriptor. Oh what a twisted web we weave. */
+ fsp_open = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA);
/*
* This is not a user visible file open.
@@ -1158,7 +1164,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
*/
if(!got_stat) {
- DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
+ DEBUG(3,("open_directory: unable to stat name = %s. Error was %s\n",
fname, strerror(errno) ));
file_free(fsp);
return NULL;
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 23606f1d14..14b243b36e 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -72,34 +72,69 @@ BOOL oplock_message_waiting(fd_set *fds)
****************************************************************************/
-BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeout)
+BOOL receive_local_message( char *buffer, int buffer_len, int timeout)
{
struct sockaddr_in from;
- int fromlen = sizeof(from);
+ socklen_t fromlen = sizeof(from);
int32 msg_len = 0;
+ fd_set fds;
+ int selrtn = -1;
+ FD_ZERO(&fds);
smb_read_error = 0;
- if(timeout != 0) {
+ /*
+ * We need to check for kernel oplocks before going into the select
+ * here, as the EINTR generated by the linux kernel oplock may have
+ * already been eaten. JRA.
+ */
+
+ if (koplocks && koplocks->msg_waiting(&fds)) {
+ return koplocks->receive_message(&fds, buffer, buffer_len);
+ }
+
+ while (timeout > 0 && selrtn == -1) {
struct timeval to;
- int selrtn;
int maxfd = oplock_sock;
+ time_t starttime = time(NULL);
- if (koplocks && koplocks->notification_fd != -1) {
- FD_SET(koplocks->notification_fd, fds);
- maxfd = MAX(maxfd, koplocks->notification_fd);
- }
+ FD_ZERO(&fds);
+ maxfd = setup_oplock_select_set(&fds);
to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000;
- selrtn = sys_select(maxfd+1,fds,NULL,NULL,&to);
+ DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout));
+
+ selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
if (selrtn == -1 && errno == EINTR) {
+
/* could be a kernel oplock interrupt */
- if (koplocks && koplocks->msg_waiting(fds)) {
- return koplocks->receive_message(fds, buffer, buffer_len);
+ if (koplocks && koplocks->msg_waiting(&fds)) {
+ return koplocks->receive_message(&fds, buffer, buffer_len);
+ }
+
+ /*
+ * Linux 2.0.x seems to have a bug in that
+ * it can return -1, EINTR with a timeout of zero.
+ * Make sure we bail out here with a read timeout
+ * if we got EINTR on a timeout of 1 or less.
+ */
+
+ if (timeout <= 1) {
+ smb_read_error = READ_TIMEOUT;
+ return False;
}
+
+ /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */
+ /* We need to decrement the timeout here. */
+ timeout -= ((time(NULL) - starttime)*1000);
+ if (timeout < 0)
+ timeout = 1;
+
+ DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout));
+ continue;
}
/* Check if error */
@@ -116,11 +151,11 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou
}
}
- if (koplocks && koplocks->msg_waiting(fds)) {
- return koplocks->receive_message(fds, buffer, buffer_len);
+ if (koplocks && koplocks->msg_waiting(&fds)) {
+ return koplocks->receive_message(&fds, buffer, buffer_len);
}
- if (!FD_ISSET(oplock_sock, fds))
+ if (!FD_ISSET(oplock_sock, &fds))
return False;
/*
@@ -131,7 +166,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou
/*
* Read a loopback udp message.
*/
- msg_len = recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN],
+ msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN],
buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen);
if(msg_len < 0) {
@@ -417,7 +452,7 @@ oplocks. Returning success.\n"));
toaddr.sin_port = htons(from_port);
toaddr.sin_family = AF_INET;
- if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
+ if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
(struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) {
DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
(int)remotepid, strerror(errno)));
@@ -930,7 +965,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n",
(unsigned int)dev, (double)inode, file_id );
}
- if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
+ if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
(struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) {
if( DEBUGLVL( 0 ) ) {
dbgtext( "request_oplock_break: failed when sending a oplock " );
@@ -967,16 +1002,8 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n",
char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
uint16 reply_from_port;
char *reply_msg_start;
- fd_set fds;
-
- FD_ZERO(&fds);
- FD_SET(oplock_sock,&fds);
-
- if (koplocks && koplocks->notification_fd != -1) {
- FD_SET(koplocks->notification_fd, &fds);
- }
- if(receive_local_message(&fds, op_break_reply, sizeof(op_break_reply),
+ if(receive_local_message(op_break_reply, sizeof(op_break_reply),
time_left ? time_left * 1000 : 1) == False) {
if(smb_read_error == READ_TIMEOUT) {
if( DEBUGLVL( 0 ) ) {
diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c
index 14f6de27c4..ffcf3d0af4 100644
--- a/source3/smbd/oplock_irix.c
+++ b/source3/smbd/oplock_irix.c
@@ -56,7 +56,7 @@ static BOOL irix_oplocks_available(void)
unlink(tmpname);
- if(fcntl(fd, F_OPLKREG, pfd[1]) == -1) {
+ if(sys_fcntl_long(fd, F_OPLKREG, pfd[1]) == -1) {
DEBUG(0,("check_kernel_oplocks: Kernel oplocks are not available on this machine. \
Disabling kernel oplock support.\n" ));
close(pfd[0]);
@@ -65,7 +65,7 @@ Disabling kernel oplock support.\n" ));
return False;
}
- if(fcntl(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
+ if(sys_fcntl_long(fd, F_OPLKACK, OP_REVOKE) < 0 ) {
DEBUG(0,("check_kernel_oplocks: Error when removing kernel oplock. Error was %s. \
Disabling kernel oplock support.\n", strerror(errno) ));
close(pfd[0]);
@@ -99,7 +99,7 @@ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_le
*/
if(read(oplock_pipe_read, &dummy, 1) != 1) {
- DEBUG(0,("receive_local_message: read of kernel notification failed. \
+ DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \
Error was %s.\n", strerror(errno) ));
smb_read_error = READ_ERROR;
return False;
@@ -111,8 +111,8 @@ Error was %s.\n", strerror(errno) ));
* request outstanding.
*/
- if(fcntl(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
- DEBUG(0,("receive_local_message: fcntl of kernel notification failed. \
+ if(sys_fcntl_ptr(oplock_pipe_read, F_OPLKSTAT, &os) < 0) {
+ DEBUG(0,("irix_oplock_receive_message: fcntl of kernel notification failed. \
Error was %s.\n", strerror(errno) ));
if(errno == EAGAIN) {
/*
@@ -131,12 +131,12 @@ Error was %s.\n", strerror(errno) ));
*/
if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev, (SMB_INO_T)os.os_ino)) == NULL) {
- DEBUG(0,("receive_local_message: unable to find open file with dev = %x, inode = %.0f\n",
+ DEBUG(0,("irix_oplock_receive_message: unable to find open file with dev = %x, inode = %.0f\n",
(unsigned int)os.os_dev, (double)os.os_ino ));
return False;
}
- DEBUG(5,("receive_local_message: kernel oplock break request received for \
+ DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \
dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
/*
@@ -164,21 +164,21 @@ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->i
static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
- if (fcntl(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) {
+ if (sys_fcntl_long(fsp->fd, F_OPLKREG, oplock_pipe_write) == -1) {
if(errno != EAGAIN) {
- DEBUG(0,("set_file_oplock: Unable to get kernel oplock on file %s, dev = %x, \
+ DEBUG(0,("irix_set_kernel_oplock: Unable to get kernel oplock on file %s, dev = %x, \
inode = %.0f, file_id = %ul. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id,
strerror(errno) ));
} else {
- DEBUG(5,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
+ DEBUG(5,("irix_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
inode = %.0f, file_id = %ul. Another process had the file open.\n",
fsp->fsp_name, fsp->fd, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
}
return False;
}
- DEBUG(10,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n",
+ DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %ul\n",
fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id));
return True;
@@ -195,8 +195,8 @@ static void irix_release_kernel_oplock(files_struct *fsp)
* Check and print out the current kernel
* oplock state of this file.
*/
- int state = fcntl(fsp->fd, F_OPLKACK, -1);
- dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \
+ int state = sys_fcntl_long(fsp->fd, F_OPLKACK, -1);
+ dbgtext("irix_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %ul, has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->file_id, state );
}
@@ -204,9 +204,9 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
/*
* Remove the kernel oplock on this file.
*/
- if(fcntl(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) {
+ if(sys_fcntl_long(fsp->fd, F_OPLKACK, OP_REVOKE) < 0) {
if( DEBUGLVL( 0 )) {
- dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " );
+ dbgtext("irix_release_kernel_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->file_id, strerror(errno) );
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index d946578380..85f89c12a0 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -22,9 +22,9 @@
#if HAVE_KERNEL_OPLOCKS_LINUX
-static VOLATILE sig_atomic_t signals_received;
-static VOLATILE sig_atomic_t signals_processed;
-static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal */
+static SIG_ATOMIC_T signals_received;
+#define FD_PENDING_SIZE 100
+static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE];
#ifndef F_SETLEASE
#define F_SETLEASE 1024
@@ -52,9 +52,10 @@ static VOLATILE sig_atomic_t fd_pending; /* the fd of the current pending signal
static void signal_handler(int sig, siginfo_t *info, void *unused)
{
- BlockSignals(True, sig);
- fd_pending = (sig_atomic_t)info->si_fd;
- signals_received++;
+ if (signals_received < FD_PENDING_SIZE - 1) {
+ fd_pending_array[signals_received] = (SIG_ATOMIC_T)info->si_fd;
+ signals_received++;
+ } /* Else signal is lost. */
sys_select_signal();
}
@@ -124,20 +125,28 @@ static int linux_setlease(int fd, int leasetype)
static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len)
{
- BOOL ret = True;
+ int fd;
struct files_struct *fsp;
- if (signals_received == signals_processed)
- return False;
+ BlockSignals(True, RT_SIGNAL_LEASE);
+ fd = fd_pending_array[0];
+ fsp = file_find_fd(fd);
+ fd_pending_array[0] = (SIG_ATOMIC_T)-1;
+ if (signals_received > 1)
+ memmove((void *)&fd_pending_array[0], (void *)&fd_pending_array[1],
+ sizeof(SIG_ATOMIC_T)*(signals_received-1));
+ signals_received--;
+ /* now we can receive more signals */
+ BlockSignals(False, RT_SIGNAL_LEASE);
- if ((fsp = file_find_fd(fd_pending)) == NULL) {
- DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd_pending));
- ret = False;
- goto out;
+ if (fsp == NULL) {
+ DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd));
+ return False;
}
- DEBUG(3,("receive_local_message: kernel oplock break request received for \
-dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode ));
+ DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \
+dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode,
+ fd, fsp->file_id));
/*
* Create a kernel oplock break message.
@@ -155,13 +164,7 @@ dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode ));
memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode));
memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id));
- out:
- /* now we can receive more signals */
- fd_pending = (sig_atomic_t)-1;
- signals_processed++;
- BlockSignals(False, RT_SIGNAL_LEASE);
-
- return ret;
+ return True;
}
/****************************************************************************
@@ -171,14 +174,14 @@ dev = %x, inode = %.0f\n", (unsigned int)fsp->dev, (double)fsp->inode ));
static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
if (linux_setlease(fsp->fd, F_WRLCK) == -1) {
- DEBUG(3,("set_file_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
+ DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, fd = %d, dev = %x, \
inode = %.0f. (%s)\n",
fsp->fsp_name, fsp->fd,
(unsigned int)fsp->dev, (double)fsp->inode, strerror(errno)));
return False;
}
- DEBUG(3,("set_file_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n",
+ DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, dev = %x, inode = %.0f, file_id = %lu\n",
fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id));
return True;
@@ -196,7 +199,7 @@ static void linux_release_kernel_oplock(files_struct *fsp)
* oplock state of this file.
*/
int state = fcntl(fsp->fd, F_GETLEASE, 0);
- dbgtext("release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \
+ dbgtext("linux_release_kernel_oplock: file %s, dev = %x, inode = %.0f file_id = %lu has kernel \
oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->file_id, state );
}
@@ -206,7 +209,7 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
*/
if (linux_setlease(fsp->fd, F_UNLCK) == -1) {
if (DEBUGLVL(0)) {
- dbgtext("release_kernel_oplock: Error when removing kernel oplock on file " );
+ dbgtext("linux_release_kernel_oplock: Error when removing kernel oplock on file " );
dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. Error was %s\n",
fsp->fsp_name, (unsigned int)fsp->dev,
(double)fsp->inode, fsp->file_id, strerror(errno) );
@@ -244,7 +247,7 @@ static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *i
static BOOL linux_oplock_msg_waiting(fd_set *fds)
{
- return signals_processed != signals_received;
+ return signals_received != 0;
}
/****************************************************************************
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 629157f22d..82c0cef77d 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -259,9 +259,19 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
{
/* Keep the homedir handy */
const char *homedir = pdb_get_homedir(server_info->sam_account);
+ const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
+ const char *logon_script = pdb_get_logon_script(server_info->sam_account);
if (homedir) {
vuser->homedir = smb_xstrdup(homedir);
}
+
+ if (unix_homedir) {
+ vuser->unix_homedir = smb_xstrdup(unix_homedir);
+ }
+
+ if (logon_script) {
+ vuser->logon_script = smb_xstrdup(logon_script);
+ }
}
memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key));
@@ -279,7 +289,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
/* Find all the groups this uid is in and store them.
Used by change_to_user() */
initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid);
- get_current_groups( &vuser->n_groups, &vuser->groups);
+ get_current_groups(vuser->gid, &vuser->n_groups, &vuser->groups);
if (server_info->ptok)
add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok);
@@ -301,9 +311,11 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
}
/* Register a home dir service for this user */
- if ((!vuser->guest) && vuser->homedir && *(vuser->homedir)
+ if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)
&& (lp_servicenumber(vuser->user.unix_name) < 0)) {
- add_home_service(vuser->user.unix_name, vuser->homedir);
+ vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir);
+ } else {
+ vuser->homes_snum = -1;
}
return vuser->vuid;
@@ -336,7 +348,7 @@ void add_session_user(char *user)
/****************************************************************************
check if a username is valid
****************************************************************************/
-BOOL user_ok(char *user,int snum)
+BOOL user_ok(const char *user,int snum)
{
char **valid, **invalid;
BOOL ret;
@@ -345,27 +357,27 @@ BOOL user_ok(char *user,int snum)
ret = True;
if (lp_invalid_users(snum)) {
- lp_list_copy(&invalid, lp_invalid_users(snum));
- if (invalid && lp_list_substitute(invalid, "%S", lp_servicename(snum))) {
+ str_list_copy(&invalid, lp_invalid_users(snum));
+ if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) {
ret = !user_in_list(user, invalid);
}
}
- if (invalid) lp_list_free (&invalid);
+ if (invalid) str_list_free (&invalid);
if (ret && lp_valid_users(snum)) {
- lp_list_copy(&valid, lp_valid_users(snum));
- if (valid && lp_list_substitute(valid, "%S", lp_servicename(snum))) {
+ str_list_copy(&valid, lp_valid_users(snum));
+ if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) {
ret = user_in_list(user,valid);
}
}
- if (valid) lp_list_free (&valid);
+ if (valid) str_list_free (&valid);
if (ret && lp_onlyuser(snum)) {
- char **user_list = lp_list_make (lp_username(snum));
- if (user_list && lp_list_substitute(user_list, "%S", lp_servicename(snum))) {
+ char **user_list = str_list_make (lp_username(snum));
+ if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) {
ret = user_in_list(user, user_list);
}
- if (user_list) lp_list_free (&user_list);
+ if (user_list) str_list_free (&user_list);
}
return(ret);
@@ -462,42 +474,17 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
****************************************************************************/
BOOL authorise_login(int snum,char *user, DATA_BLOB password,
- BOOL *guest,BOOL *force,uint16 vuid)
+ BOOL *guest)
{
BOOL ok = False;
- user_struct *vuser = get_valid_user_struct(vuid);
-
+
#if DEBUG_PASSWORD
- DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s vuid=%d\n",
- user,password.data, vuid));
+ DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n",
+ user,password.data));
#endif
*guest = False;
- if (GUEST_ONLY(snum))
- *force = True;
-
- if (!GUEST_ONLY(snum) && (lp_security() > SEC_SHARE)) {
-
- /*
- * We should just use the given vuid from a sessionsetup_and_X.
- */
-
- if (!vuser) {
- DEBUG(1,("authorise_login: refusing user '%s' with no session setup\n", user));
- return False;
- }
-
- if ((!vuser->guest && user_ok(vuser->user.unix_name,snum)) ||
- (vuser->guest && GUEST_OK(snum))) {
- fstrcpy(user,vuser->user.unix_name);
- *guest = vuser->guest;
- DEBUG(3,("authorise_login: ACCEPTED: validated based on vuid as %sguest \
-(user=%s)\n", vuser->guest ? "" : "non-", user));
- return True;
- }
- }
-
/* there are several possibilities:
1) login as the given user with given password
2) login as a previously registered username with the given password
@@ -510,84 +497,61 @@ BOOL authorise_login(int snum,char *user, DATA_BLOB password,
if the service is guest_only then steps 1 to 5 are skipped
*/
- if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) {
- /* check for a previously registered guest username */
- if (!ok && (vuser != 0) && vuser->guest) {
- if (user_ok(vuser->user.unix_name,snum) &&
- password_ok(vuser->user.unix_name, password)) {
- fstrcpy(user, vuser->user.unix_name);
- *guest = False;
- DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user));
+ /* now check the list of session users */
+ if (!ok) {
+ char *auser;
+ char *user_list = strdup(session_users);
+ if (!user_list)
+ return(False);
+
+ for (auser=strtok(user_list,LIST_SEP); !ok && auser;
+ auser = strtok(NULL,LIST_SEP)) {
+ fstring user2;
+ fstrcpy(user2,auser);
+ if (!user_ok(user2,snum))
+ continue;
+
+ if (password_ok(user2,password)) {
ok = True;
+ fstrcpy(user,user2);
+ DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \
+and given password ok\n", user));
}
}
-
- /* now check the list of session users */
- if (!ok) {
- char *auser;
- char *user_list = strdup(session_users);
- if (!user_list)
- return(False);
-
- for (auser=strtok(user_list,LIST_SEP); !ok && auser;
- auser = strtok(NULL,LIST_SEP)) {
+
+ SAFE_FREE(user_list);
+ }
+
+ /* check the user= fields and the given password */
+ if (!ok && lp_username(snum)) {
+ char *auser;
+ pstring user_list;
+ StrnCpy(user_list,lp_username(snum),sizeof(pstring));
+
+ pstring_sub(user_list,"%S",lp_servicename(snum));
+
+ for (auser=strtok(user_list,LIST_SEP); auser && !ok;
+ auser = strtok(NULL,LIST_SEP)) {
+ if (*auser == '@') {
+ auser = validate_group(auser+1,password,snum);
+ if (auser) {
+ ok = True;
+ fstrcpy(user,auser);
+ DEBUG(3,("authorise_login: ACCEPTED: group username \
+and given password ok (%s)\n", user));
+ }
+ } else {
fstring user2;
fstrcpy(user2,auser);
- if (!user_ok(user2,snum))
- continue;
-
- if (password_ok(user2,password)) {
+ if (user_ok(user2,snum) && password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
- DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \
-and given password ok\n", user));
- }
- }
-
- SAFE_FREE(user_list);
- }
-
- /* check for a previously validated username/password pair */
- if (!ok && (lp_security() > SEC_SHARE) && (vuser != 0) && !vuser->guest &&
- user_ok(vuser->user.unix_name,snum)) {
- fstrcpy(user,vuser->user.unix_name);
- *guest = False;
- DEBUG(3,("authorise_login: ACCEPTED: validated uid (%s) as non-guest\n",
- user));
- ok = True;
- }
-
- /* check the user= fields and the given password */
- if (!ok && lp_username(snum)) {
- char *auser;
- pstring user_list;
- StrnCpy(user_list,lp_username(snum),sizeof(pstring));
-
- pstring_sub(user_list,"%S",lp_servicename(snum));
-
- for (auser=strtok(user_list,LIST_SEP); auser && !ok;
- auser = strtok(NULL,LIST_SEP)) {
- if (*auser == '@') {
- auser = validate_group(auser+1,password,snum);
- if (auser) {
- ok = True;
- fstrcpy(user,auser);
- DEBUG(3,("authorise_login: ACCEPTED: group username \
+ DEBUG(3,("authorise_login: ACCEPTED: user list username \
and given password ok (%s)\n", user));
- }
- } else {
- fstring user2;
- fstrcpy(user2,auser);
- if (user_ok(user2,snum) && password_ok(user2,password)) {
- ok = True;
- fstrcpy(user,user2);
- DEBUG(3,("authorise_login: ACCEPTED: user list username \
-and given password ok (%s)\n", user));
- }
}
}
}
- } /* not guest only */
+ }
/* check for a normal guest connection */
if (!ok && GUEST_OK(snum)) {
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 6c1e6efa73..f7e9c595c1 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -50,7 +50,7 @@ int reply_open_pipe_and_X(connection_struct *conn,
int i;
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_pull(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE);
/* If the name doesn't start \PIPE\ then this is directed */
/* at a mailslot or something we really, really don't understand, */
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 9c8835214f..85818d524a 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -104,7 +104,7 @@ static void print_canon_ace(canon_ace *pace, int num)
dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));
if (pace->owner_type == UID_ACE) {
- char *u_name = uidtoname(pace->unix_ug.uid);
+ const char *u_name = uidtoname(pace->unix_ug.uid);
dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name);
} else if (pace->owner_type == GID_ACE) {
char *g_name = gidtoname(pace->unix_ug.gid);
@@ -439,9 +439,15 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
if (security_info_sent & OWNER_SECURITY_INFORMATION) {
sid_copy(&owner_sid, psd->owner_sid);
if (!sid_to_uid( &owner_sid, puser, &sid_type)) {
+#if ACL_FORCE_UNMAPPABLE
+ /* this allows take ownership to work reasonably */
+ extern struct current_user current_user;
+ *puser = current_user.uid;
+#else
DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n",
sid_string_static(&owner_sid)));
return False;
+#endif
}
}
@@ -453,8 +459,14 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
if (security_info_sent & GROUP_SECURITY_INFORMATION) {
sid_copy(&grp_sid, psd->grp_sid);
if (!sid_to_gid( &grp_sid, pgrp, &sid_type)) {
+#if ACL_FORCE_UNMAPPABLE
+ /* this allows take group ownership to work reasonably */
+ extern struct current_user current_user;
+ *pgrp = current_user.gid;
+#else
DEBUG(3,("unpack_nt_owners: unable to validate group sid.\n"));
return False;
+#endif
}
}
@@ -467,7 +479,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
Ensure the enforced permissions for this share apply.
****************************************************************************/
-static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type)
+static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
{
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
@@ -486,6 +498,10 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type)
/* Now bounce them into the S_USR space. */
switch(type) {
case S_IRUSR:
+ /* Ensure owner has read access. */
+ pace->perms |= S_IRUSR;
+ if (fsp->is_directory)
+ pace->perms |= (S_IWUSR|S_IXUSR);
and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
break;
@@ -499,7 +515,34 @@ static mode_t apply_default_perms(files_struct *fsp, mode_t perms, mode_t type)
break;
}
- return ((perms & and_bits)|or_bits);
+ pace->perms = ((pace->perms & and_bits)|or_bits);
+}
+
+/****************************************************************************
+ Check if a given uid/SID is in a group gid/SID. This is probably very
+ expensive and will need optimisation. A *lot* of optimisation :-). JRA.
+****************************************************************************/
+
+static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
+{
+ extern DOM_SID global_sid_World;
+ fstring u_name;
+ fstring g_name;
+
+ /* "Everyone" always matches every uid. */
+
+ if (sid_equal(&group_ace->trustee, &global_sid_World))
+ return True;
+
+ fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
+ fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
+
+ /*
+ * Due to the winbind interfaces we need to do this via names,
+ * not uids/gids.
+ */
+
+ return user_in_group_list(u_name, g_name );
}
/****************************************************************************
@@ -524,24 +567,16 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
BOOL got_user = False;
BOOL got_grp = False;
BOOL got_other = False;
+ canon_ace *pace_other = NULL;
+ canon_ace *pace_group = NULL;
for (pace = *pp_ace; pace; pace = pace->next) {
if (pace->type == SMB_ACL_USER_OBJ) {
- if (setting_acl) {
- /* Ensure owner has read access. */
- pace->perms |= S_IRUSR;
- if (fsp->is_directory)
- pace->perms |= (S_IWUSR|S_IXUSR);
-
- /*
- * Ensure create mask/force create mode is respected on set.
- */
-
- pace->perms = apply_default_perms(fsp, pace->perms, S_IRUSR);
- }
-
+ if (setting_acl)
+ apply_default_perms(fsp, pace, S_IRUSR);
got_user = True;
+
} else if (pace->type == SMB_ACL_GROUP_OBJ) {
/*
@@ -549,8 +584,10 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
*/
if (setting_acl)
- pace->perms = apply_default_perms(fsp, pace->perms, S_IRGRP);
+ apply_default_perms(fsp, pace, S_IRGRP);
got_grp = True;
+ pace_group = pace;
+
} else if (pace->type == SMB_ACL_OTHER) {
/*
@@ -558,8 +595,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
*/
if (setting_acl)
- pace->perms = apply_default_perms(fsp, pace->perms, S_IROTH);
+ apply_default_perms(fsp, pace, S_IROTH);
got_other = True;
+ pace_other = pace;
}
}
@@ -574,9 +612,21 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = UID_ACE;
pace->unix_ug.uid = pst->st_uid;
pace->trustee = *pfile_owner_sid;
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
pace->attr = ALLOW_ACE;
+ if (setting_acl) {
+ /* If we only got an "everyone" perm, just use that. */
+ if (!got_grp && got_other)
+ pace->perms = pace_other->perms;
+ else if (got_grp && uid_entry_in_group(pace, pace_group))
+ pace->perms = pace_group->perms;
+ else
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
+ apply_default_perms(fsp, pace, S_IRUSR);
+ } else {
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
+ }
+
DLIST_ADD(*pp_ace, pace);
}
@@ -591,8 +641,17 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = GID_ACE;
pace->unix_ug.uid = pst->st_gid;
pace->trustee = *pfile_grp_sid;
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
pace->attr = ALLOW_ACE;
+ if (setting_acl) {
+ /* If we only got an "everyone" perm, just use that. */
+ if (got_other)
+ pace->perms = pace_other->perms;
+ else
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
+ apply_default_perms(fsp, pace, S_IRGRP);
+ } else {
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
+ }
DLIST_ADD(*pp_ace, pace);
}
@@ -608,8 +667,9 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
pace->owner_type = WORLD_ACE;
pace->unix_ug.world = -1;
pace->trustee = global_sid_World;
- pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
pace->attr = ALLOW_ACE;
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
+ apply_default_perms(fsp, pace, S_IROTH);
DLIST_ADD(*pp_ace, pace);
}
@@ -919,33 +979,6 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
}
/****************************************************************************
- Check if a given uid/SID is in a group gid/SID. This is probably very
- expensive and will need optimisation. A *lot* of optimisation :-). JRA.
-****************************************************************************/
-
-static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
-{
- extern DOM_SID global_sid_World;
- fstring u_name;
- fstring g_name;
-
- /* "Everyone" always matches every uid. */
-
- if (sid_equal(&group_ace->trustee, &global_sid_World))
- return True;
-
- fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
- fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
-
- /*
- * Due to the winbind interfaces we need to do this via names,
- * not uids/gids.
- */
-
- return user_in_group_list(u_name, g_name );
-}
-
-/****************************************************************************
ASCII art time again... JRA :-).
We have 3 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
@@ -1996,6 +2029,52 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
return sd_size;
}
+/*
+ try to chown a file. We will be able to chown it under the following conditions
+
+ 1) if we have root privileges, then it will just work
+ 2) if we have write permission to the file and dos_filemodes is set
+ then allow chown to the currently authenticated user.
+
+ */
+static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
+{
+ int ret;
+ extern struct current_user current_user;
+ files_struct *fsp;
+ SMB_STRUCT_STAT st;
+
+ /* try the direct way first */
+ ret = vfs_chown(conn, fname, uid, gid);
+ if (ret == 0)
+ return 0;
+
+ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
+ return -1;
+
+ if (vfs_stat(conn,fname,&st))
+ return -1;
+
+ fsp = open_file_fchmod(conn,fname,&st);
+ if (!fsp)
+ return -1;
+
+ /* only allow chown to the current user. This is more secure,
+ and also copes with the case where the SID in a take ownership ACL is
+ a local SID on the users workstation
+ */
+ uid = current_user.uid;
+
+ become_root();
+ /* Keep the current file gid the same. */
+ ret = vfswrap_fchown(fsp, fsp->fd, uid, (gid_t)-1);
+ unbecome_root();
+
+ close_file_fchmod(fsp);
+
+ return ret;
+}
+
/****************************************************************************
Reply to set a security descriptor on an fsp. security_info_sent is the
description of the following NT ACL.
@@ -2052,7 +2131,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
- if(vfs_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
return False;
@@ -2308,6 +2387,7 @@ BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1))
has_acl = True;
- conn->vfs_ops.sys_acl_free_acl(conn, dir_acl);
+ if (dir_acl)
+ conn->vfs_ops.sys_acl_free_acl(conn, dir_acl);
return has_acl;
}
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 007621f6bb..43d3c6c531 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -42,8 +42,8 @@ extern int last_message;
extern int global_oplock_break;
extern userdom_struct current_user_info;
extern int smb_read_error;
-extern VOLATILE sig_atomic_t reload_after_sighup;
-extern VOLATILE sig_atomic_t got_sig_term;
+SIG_ATOMIC_T reload_after_sighup;
+SIG_ATOMIC_T got_sig_term;
extern BOOL global_machine_password_needs_changing;
extern fstring global_myworkgroup;
extern pstring global_myname;
@@ -109,10 +109,12 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
oplock messages, change notify events etc.
****************************************************************************/
-static void async_processing(fd_set *fds, char *buffer, int buffer_len)
+static void async_processing(char *buffer, int buffer_len)
{
+ DEBUG(10,("async_processing: Doing async processing.\n"));
+
/* check for oplock messages (both UDP and kernel) */
- if (receive_local_message(fds, buffer, buffer_len, 0)) {
+ if (receive_local_message(buffer, buffer_len, 1)) {
process_local_message(buffer, buffer_len);
}
@@ -193,6 +195,27 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
*/
FD_ZERO(&fds);
+
+ /*
+ * Ensure we process oplock break messages by preference.
+ * We have to do this before the select, after the select
+ * and if the select returns EINTR. This is due to the fact
+ * that the selects called from async_processing can eat an EINTR
+ * caused by a signal (we can't take the break message there).
+ * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
+ */
+
+ if (oplock_message_waiting(&fds)) {
+ DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
+ async_processing(buffer, buffer_len);
+ /*
+ * After async processing we must go and do the select again, as
+ * the state of the flag in fds for the server file descriptor is
+ * indeterminate - we may have done I/O on it in the oplock processing. JRA.
+ */
+ goto again;
+ }
+
FD_SET(smbd_server_fd(),&fds);
maxfd = setup_oplock_select_set(&fds);
@@ -206,7 +229,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
is the best we can do until the oplock code knows more about
signals */
if (selrtn == -1 && errno == EINTR) {
- async_processing(&fds, buffer, buffer_len);
+ async_processing(buffer, buffer_len);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
@@ -235,7 +258,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
*/
if (oplock_message_waiting(&fds)) {
- async_processing(&fds, buffer, buffer_len);
+ async_processing(buffer, buffer_len);
/*
* After async processing we must go and do the select again, as
* the state of the flag in fds for the server file descriptor is
@@ -275,7 +298,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
void respond_to_all_remaining_local_messages(void)
{
char buffer[1024];
- fd_set fds;
/*
* Assert we have no exclusive open oplocks.
@@ -288,23 +310,12 @@ void respond_to_all_remaining_local_messages(void)
}
/*
- * Setup the select read fd set.
- */
-
- FD_ZERO(&fds);
- if(!setup_oplock_select_set(&fds))
- return;
-
- /*
* Keep doing receive_local_message with a 1 ms timeout until
* we have no more messages.
*/
- while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
+ while(receive_local_message(buffer, sizeof(buffer), 1)) {
/* Deal with oplock break requests from other smbd's. */
process_local_message(buffer, sizeof(buffer));
-
- FD_ZERO(&fds);
- (void)setup_oplock_select_set(&fds);
}
return;
@@ -829,10 +840,6 @@ set. Ignoring max smbd restriction.\n"));
****************************************************************************/
void process_smb(char *inbuf, char *outbuf)
{
-#ifdef WITH_SSL
- extern BOOL sslEnabled; /* don't use function for performance reasons */
- static int sslConnected = 0;
-#endif /* WITH_SSL */
static int trans_num;
int msg_type = CVAL(inbuf,0);
int32 len = smb_len(inbuf);
@@ -860,18 +867,6 @@ void process_smb(char *inbuf, char *outbuf)
DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
-#ifdef WITH_SSL
- if(sslEnabled && !sslConnected){
- sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
- if(sslConnected < 0){ /* an error occured */
- exit_server("SSL negotiation failed");
- }else if(sslConnected){
- trans_num++;
- return;
- }
- }
-#endif /* WITH_SSL */
-
if (msg_type == 0)
show_msg(inbuf);
else if(msg_type == SMBkeepalive)
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index fbb981781f..0ccdf7c241 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -163,10 +163,10 @@ int reply_tcon(connection_struct *conn,
*service = *password = *dev = 0;
p = smb_buf(inbuf)+1;
- p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
- pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1;
+ pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
p += pwlen;
- p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
p = strrchr_m(service,'\\');
if (p) {
@@ -233,7 +233,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
p = smb_buf(inbuf) + passlen;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
/*
* the service name can be either: \\server\share
@@ -377,7 +377,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBchkpth);
- srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
@@ -429,7 +429,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBgetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -505,7 +505,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBsetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
unix_convert(fname,conn,0,&bad_path,&sbuf);
mode = SVAL(inbuf,smb_vwv0);
@@ -542,23 +542,46 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
****************************************************************************/
int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = 0;
- SMB_BIG_UINT dfree,dsize,bsize;
- START_PROFILE(SMBdskattr);
-
- conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
-
- outsize = set_message(outbuf,5,0,True);
+ int outsize = 0;
+ SMB_BIG_UINT dfree,dsize,bsize;
+ START_PROFILE(SMBdskattr);
+
+ conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
- SSVAL(outbuf,smb_vwv0,dsize);
- SSVAL(outbuf,smb_vwv1,bsize/512);
- SSVAL(outbuf,smb_vwv2,512);
- SSVAL(outbuf,smb_vwv3,dfree);
+ outsize = set_message(outbuf,5,0,True);
+
+ if (Protocol <= PROTOCOL_LANMAN2) {
+ double total_space, free_space;
+ /* we need to scale this to a number that DOS6 can handle. We
+ use floating point so we can handle large drives on systems
+ that don't have 64 bit integers
- DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
+ we end up displaying a maximum of 2G to DOS systems
+ */
+ total_space = dsize * (double)bsize;
+ free_space = dfree * (double)bsize;
- END_PROFILE(SMBdskattr);
- return(outsize);
+ dsize = (total_space+63*512) / (64*512);
+ dfree = (free_space+63*512) / (64*512);
+
+ if (dsize > 0xFFFF) dsize = 0xFFFF;
+ if (dfree > 0xFFFF) dfree = 0xFFFF;
+
+ SSVAL(outbuf,smb_vwv0,dsize);
+ SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
+ SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
+ SSVAL(outbuf,smb_vwv3,dfree);
+ } else {
+ SSVAL(outbuf,smb_vwv0,dsize);
+ SSVAL(outbuf,smb_vwv1,bsize/512);
+ SSVAL(outbuf,smb_vwv2,512);
+ SSVAL(outbuf,smb_vwv3,dfree);
+ }
+
+ DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
+
+ END_PROFILE(SMBdskattr);
+ return(outsize);
}
@@ -602,7 +625,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
p++;
status_len = SVAL(p, 0);
p += 2;
@@ -783,7 +806,7 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
p++;
status_len = SVAL(p,0);
p += 2;
@@ -831,7 +854,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
share_mode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -921,7 +944,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -1040,7 +1063,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
com = SVAL(inbuf,smb_com);
createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -1112,7 +1135,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBctemp);
createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
pstrcat(fname,"\\TMXXXXXX");
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -1370,7 +1393,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
dirtype = SVAL(inbuf,smb_vwv0);
- srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
@@ -2719,7 +2742,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
START_PROFILE(SMBmkdir);
- srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
status = mkdir_internal(conn, directory);
if (!NT_STATUS_IS_OK(status))
@@ -2880,7 +2903,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBrmdir);
- srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
@@ -3241,9 +3264,9 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
- p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
p++;
- p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
@@ -3373,8 +3396,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
@@ -3526,7 +3549,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
if (strlen(newdir) == 0) {
ok = True;
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index 87bf8b1744..bdcdce6e14 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -132,29 +132,39 @@ static void gain_root(void)
Get the list of current groups.
****************************************************************************/
-int get_current_groups(int *p_ngroups, gid_t **p_groups)
+int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
{
int i;
gid_t grp;
- int ngroups = sys_getgroups(0,&grp);
- gid_t *groups;
+ int ngroups;
+ gid_t *groups = NULL;
(*p_ngroups) = 0;
(*p_groups) = NULL;
- if (ngroups <= 0)
- return -1;
+ /* this looks a little strange, but is needed to cope with
+ systems that put the current egid in the group list
+ returned from getgroups() (tridge) */
+ save_re_gid();
+ set_effective_gid(gid);
+ setgid(gid);
- if((groups = (gid_t *)malloc(sizeof(gid_t)*ngroups)) == NULL) {
+ ngroups = sys_getgroups(0,&grp);
+ if (ngroups <= 0) {
+ goto fail;
+ }
+
+ if((groups = (gid_t *)malloc(sizeof(gid_t)*(ngroups+1))) == NULL) {
DEBUG(0,("setup_groups malloc fail !\n"));
- return -1;
+ goto fail;
}
if ((ngroups = sys_getgroups(ngroups,groups)) == -1) {
- SAFE_FREE(groups);
- return -1;
+ goto fail;
}
+ restore_re_gid();
+
(*p_ngroups) = ngroups;
(*p_groups) = groups;
@@ -164,7 +174,12 @@ int get_current_groups(int *p_ngroups, gid_t **p_groups)
}
DEBUG( 3, ( "\n" ) );
- return ngroups;
+ return ngroups;
+
+fail:
+ SAFE_FREE(groups);
+ restore_re_gid();
+ return -1;
}
/****************************************************************************
@@ -204,7 +219,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid)
SAFE_FREE(prev_ctx_p->groups);
prev_ctx_p->ngroups = 0;
- get_current_groups(&prev_ctx_p->ngroups, &prev_ctx_p->groups);
+ get_current_groups(gid, &prev_ctx_p->ngroups, &prev_ctx_p->groups);
done:
unbecome_root();
@@ -404,7 +419,7 @@ void init_sec_ctx(void)
ctx_p->uid = geteuid();
ctx_p->gid = getegid();
- get_current_groups(&ctx_p->ngroups, &ctx_p->groups);
+ get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups);
ctx_p->token = NULL; /* Maps to guest user. */
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index c759f56e0c..6f0d0238b0 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -53,7 +53,7 @@ int smbd_server_fd(void)
return server_fd;
}
-void smbd_set_server_fd(int fd)
+static void smbd_set_server_fd(int fd)
{
server_fd = fd;
client_setfd(fd);
@@ -63,7 +63,7 @@ void smbd_set_server_fd(int fd)
Terminate signal.
****************************************************************************/
-VOLATILE sig_atomic_t got_sig_term = 0;
+SIG_ATOMIC_T got_sig_term = 0;
static void sig_term(void)
{
@@ -75,7 +75,7 @@ static void sig_term(void)
Catch a sighup.
****************************************************************************/
-VOLATILE sig_atomic_t reload_after_sighup = 0;
+SIG_ATOMIC_T reload_after_sighup = 0;
static void sig_hup(int sig)
{
@@ -382,6 +382,8 @@ BOOL reload_services(BOOL test)
{
BOOL ret;
+ set_register_printer_fn();
+
if (lp_loaded()) {
pstring fname;
pstrcpy(fname,lp_configfile());
@@ -531,6 +533,7 @@ void exit_server(char *reason)
}
locking_end();
+ printing_end();
DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
exit(0);
@@ -782,15 +785,6 @@ static void usage(char *pname)
}
#endif
-#ifdef WITH_SSL
- {
- extern BOOL sslEnabled;
- sslEnabled = lp_ssl_enabled();
- if(sslEnabled)
- sslutil_init(True);
- }
-#endif /* WITH_SSL */
-
fstrcpy(global_myworkgroup, lp_workgroup());
DEBUG(3,( "loaded services\n"));
@@ -861,6 +855,9 @@ static void usage(char *pname)
if (!share_info_db_init())
exit(1);
+ if (!init_registry())
+ exit(1);
+
if(!initialize_password_db(False))
exit(1);
@@ -869,7 +866,7 @@ static void usage(char *pname)
/* possibly reload the services file. */
reload_services(True);
- if(!pdb_generate_sam_sid()) {
+ if(!get_global_sam_sid()) {
DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
exit(1);
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 0ae49b7adf..9ac610ab5a 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -78,12 +78,9 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
Add a home service. Returns the new service number or -1 if fail.
****************************************************************************/
-int add_home_service(const char *service, const char *homedir)
+int add_home_service(const char *service, const char *username, const char *homedir)
{
int iHomeService;
- int iService;
- fstring new_service;
- fstring domain;
if (!service || !homedir)
return -1;
@@ -98,11 +95,19 @@ int add_home_service(const char *service, const char *homedir)
* include any macros.
*/
- split_domain_and_name(service, domain, new_service);
- lp_add_home(new_service, iHomeService, homedir);
- iService = lp_servicenumber(new_service);
+ {
+ const char *p = strchr(service,*lp_winbind_separator());
+
+ /* We only want the 'user' part of the string */
+ if (p) {
+ service = p + 1;
+ }
+ }
+
+ lp_add_home(service, iHomeService, username, homedir);
+
+ return lp_servicenumber(service);
- return iService;
}
@@ -122,7 +127,7 @@ int find_service(fstring service)
/* now handle the special case of a home directory */
if (iService < 0)
{
- char *phome_dir = get_user_service_home_dir(service);
+ char *phome_dir = get_user_home_dir(service);
if(!phome_dir)
{
@@ -131,13 +136,13 @@ int find_service(fstring service)
* be a Windows to unix mapped user name.
*/
if(map_username(service))
- phome_dir = get_user_service_home_dir(service);
+ phome_dir = get_user_home_dir(service);
}
DEBUG(3,("checking for home directory %s gave %s\n",service,
phome_dir?phome_dir:"(NULL)"));
- iService = add_home_service(service,phome_dir);
+ iService = add_home_service(service,service /* 'username' */, phome_dir);
}
/* If we still don't have a service, attempt to add it as a printer. */
@@ -213,7 +218,7 @@ int find_service(fstring service)
do some basic sainity checks on the share.
This function modifies dev, ecode.
****************************************************************************/
-static NTSTATUS share_sanity_checks(int snum, const char* service, pstring dev)
+static NTSTATUS share_sanity_checks(int snum, pstring dev)
{
if (!lp_snum_ok(snum) ||
@@ -223,7 +228,7 @@ static NTSTATUS share_sanity_checks(int snum, const char* service, pstring dev)
}
/* you can only connect to the IPC$ service as an ipc device */
- if (strequal(service,"IPC$") || strequal(service,"ADMIN$"))
+ if (strequal(lp_fstype(snum), "IPC"))
pstrcpy(dev,"IPC");
if (dev[0] == '?' || !dev[0]) {
@@ -261,24 +266,24 @@ static void set_read_only(connection_struct *conn)
if (!service) return;
- lp_list_copy(&list, lp_readlist(conn->service));
+ str_list_copy(&list, lp_readlist(conn->service));
if (list) {
- if (!lp_list_substitute(list, "%S", service)) {
+ if (!str_list_substitute(list, "%S", service)) {
DEBUG(0, ("ERROR: read list substitution failed\n"));
}
if (user_in_list(conn->user, list))
conn->read_only = True;
- lp_list_free(&list);
+ str_list_free(&list);
}
- lp_list_copy(&list, lp_writelist(conn->service));
+ str_list_copy(&list, lp_writelist(conn->service));
if (list) {
- if (!lp_list_substitute(list, "%S", service)) {
+ if (!str_list_substitute(list, "%S", service)) {
DEBUG(0, ("ERROR: write list substitution failed\n"));
}
if (user_in_list(conn->user, list))
conn->read_only = False;
- lp_list_free(&list);
+ str_list_free(&list);
}
}
@@ -314,89 +319,26 @@ static void set_admin_user(connection_struct *conn)
}
/****************************************************************************
- Make a connection to a service.
- *
- * @param service (May be modified to canonical form???)
+ Make a connection, given the snum to connect to, and the vuser of the
+ connecting user if appropriate.
****************************************************************************/
-connection_struct *make_connection(char *service, DATA_BLOB password,
- char *dev, uint16 vuid, NTSTATUS *status)
+static connection_struct *make_connection_snum(int snum, user_struct *vuser,
+ DATA_BLOB password,
+ char *dev, NTSTATUS *status)
{
- int snum;
struct passwd *pass = NULL;
BOOL guest = False;
BOOL force = False;
connection_struct *conn;
- uid_t euid;
-
+ struct stat st;
fstring user;
- ZERO_STRUCT(user);
-
- /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
- if (!non_root_mode() && (euid = geteuid()) != 0) {
- DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
- smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
- }
-
- strlower(service);
-
- snum = find_service(service);
-
- if (snum < 0) {
- if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
- DEBUG(3,("refusing IPC connection\n"));
- *status = NT_STATUS_ACCESS_DENIED;
- return NULL;
- }
-
- DEBUG(0,("%s (%s) couldn't find service %s\n",
- remote_machine, client_addr(), service));
- *status = NT_STATUS_BAD_NETWORK_NAME;
- return NULL;
- }
-
- if (strequal(service,HOMES_NAME)) {
- if(lp_security() != SEC_SHARE) {
- if (validated_username(vuid)) {
- fstring unix_username;
- fstrcpy(unix_username,validated_username(vuid));
- return make_connection(unix_username,
- password,dev,vuid,status);
- }
- } else {
- /* Security = share. Try with current_user_info.smb_name
- * as the username. */
- if (* current_user_info.smb_name) {
- fstring unix_username;
- fstrcpy(unix_username,
- current_user_info.smb_name);
- map_username(unix_username);
- return make_connection(unix_username,
- password,dev,vuid,status);
- }
- }
- }
+ *user = 0;
- if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, service, dev))) {
+ if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
return NULL;
}
- /* add it as a possible user name if we
- are in share mode security */
- if (lp_security() == SEC_SHARE) {
- add_session_user(service);
- }
-
-
- /* shall we let them in? */
- if (!authorise_login(snum,user,password,&guest,&force,vuid)) {
- DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) );
- *status = NT_STATUS_WRONG_PASSWORD;
- return NULL;
- }
-
- add_session_user(user);
-
conn = conn_new();
if (!conn) {
DEBUG(0,("Couldn't find free connection.\n"));
@@ -404,20 +346,72 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
return NULL;
}
- /* find out some info about the user */
- pass = smb_getpwnam(user,True);
+ if (lp_guest_only(snum)) {
+ char *guestname = lp_guestaccount();
+ guest = True;
+ force = True;
+ pass = getpwnam_alloc(guestname);
+ if (!pass) {
+ DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname));
+ conn_free(conn);
+ *status = NT_STATUS_NO_SUCH_USER;
+ return NULL;
+ }
+ fstrcpy(user,pass->pw_name);
+ conn->force_user = True;
+ string_set(&conn->user,pass->pw_name);
+ passwd_free(&pass);
+ DEBUG(3,("Guest only user %s\n",user));
+ } else if (vuser) {
+ if (vuser->guest) {
+ if (!lp_guest_ok(snum)) {
+ DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
+ } else {
+ if (!user_ok(vuser->user.unix_name, snum)) {
+ DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum)));
+ conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
+ }
+ conn->vuid = vuser->vuid;
+ conn->uid = vuser->uid;
+ conn->gid = vuser->gid;
+ string_set(&conn->user,vuser->user.unix_name);
+ fstrcpy(user,vuser->user.unix_name);
+ guest = vuser->guest;
+ } else if (lp_security() == SEC_SHARE) {
+ /* add it as a possible user name if we
+ are in share mode security */
+ add_session_user(lp_servicename(snum));
+ /* shall we let them in? */
+ if (!authorise_login(snum,user,password,&guest)) {
+ DEBUG( 2, ( "Invalid username/password for [%s]\n",
+ lp_servicename(snum)) );
+ conn_free(conn);
+ *status = NT_STATUS_WRONG_PASSWORD;
+ return NULL;
+ }
+ pass = Get_Pwnam(user);
+ conn->force_user = force;
+ conn->uid = pass->pw_uid;
+ conn->gid = pass->pw_gid;
+ string_set(&conn->user, pass->pw_name);
+ fstrcpy(user, pass->pw_name);
- if (pass == NULL) {
- DEBUG(0,( "Couldn't find account %s\n",user));
- *status = NT_STATUS_NO_SUCH_USER;
+ } else {
+ DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
return NULL;
}
- conn->force_user = force;
- conn->vuid = vuid;
- conn->uid = pass->pw_uid;
- conn->gid = pass->pw_gid;
+ add_session_user(user);
+
safe_strcpy(conn->client_address, client_addr(),
sizeof(conn->client_address)-1);
conn->num_files_open = 0;
@@ -450,18 +444,21 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
pstrcpy(fuser,lp_force_user(snum));
/* Allow %S to be used by force user. */
- pstring_sub(fuser,"%S",service);
+ pstring_sub(fuser,"%S",lp_servicename(snum));
- pass2 = (struct passwd *)Get_Pwnam_Modify(fuser);
+ pass2 = (struct passwd *)Get_Pwnam(fuser);
if (pass2) {
conn->uid = pass2->pw_uid;
conn->gid = pass2->pw_gid;
- string_set(&conn->user,fuser);
- fstrcpy(user,fuser);
+ string_set(&conn->user,pass2->pw_name);
+ fstrcpy(user,pass2->pw_name);
conn->force_user = True;
- DEBUG(3,("Forced user %s\n",fuser));
+ DEBUG(3,("Forced user %s\n",user));
} else {
DEBUG(1,("Couldn't find user %s\n",fuser));
+ conn_free(conn);
+ *status = NT_STATUS_NO_SUCH_USER;
+ return NULL;
}
}
@@ -483,7 +480,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
BOOL user_must_be_member = False;
StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1);
-
+
if (tmp_gname[0] == '+') {
user_must_be_member = True;
StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2);
@@ -491,7 +488,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
StrnCpy(gname,tmp_gname,sizeof(pstring)-1);
}
/* default service may be a group name */
- pstring_sub(gname,"%S",service);
+ pstring_sub(gname,"%S",lp_servicename(snum));
gid = nametogid(gname);
if (gid != (gid_t)-1) {
@@ -512,6 +509,9 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
}
} else {
DEBUG(1,("Couldn't find group %s\n",gname));
+ conn_free(conn);
+ *status = NT_STATUS_NO_SUCH_GROUP;
+ return NULL;
}
}
#endif /* HAVE_GETGRNAM */
@@ -519,7 +519,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
{
pstring s;
pstrcpy(s,lp_pathname(snum));
- standard_sub_conn(conn,s);
+ standard_sub_conn(conn,s,sizeof(s));
string_set(&conn->connectpath,s);
DEBUG(3,("Connect path is %s\n",s));
}
@@ -531,7 +531,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
/* Find all the groups this uid is in and
store them. Used by change_to_user() */
initialise_groups(conn->user, conn->uid, conn->gid);
- get_current_groups(&conn->ngroups,&conn->groups);
+ get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
conn->ngroups, conn->groups,
@@ -544,15 +544,15 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
*/
{
- BOOL can_write = share_access_check(conn, snum, vuid, FILE_WRITE_DATA);
+ BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
if (!can_write) {
- if (!share_access_check(conn, snum, vuid, FILE_READ_DATA)) {
+ if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
/* No access, read or write. */
- *status = NT_STATUS_ACCESS_DENIED;
DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
- service ));
+ lp_servicename(snum)));
conn_free(conn);
+ *status = NT_STATUS_ACCESS_DENIED;
return NULL;
} else {
conn->read_only = True;
@@ -564,6 +564,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
if (!smbd_vfs_init(conn)) {
DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
conn_free(conn);
+ *status = NT_STATUS_UNSUCCESSFUL;
return NULL;
}
@@ -574,8 +575,8 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
lp_max_connections(SNUM(conn)),
False)) {
DEBUG(1,("too many connections - rejected\n"));
- *status = NT_STATUS_INSUFFICIENT_RESOURCES;
conn_free(conn);
+ *status = NT_STATUS_INSUFFICIENT_RESOURCES;
return NULL;
}
@@ -585,7 +586,7 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
int ret;
pstring cmd;
pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
- standard_sub_conn(conn,cmd);
+ standard_sub_conn(conn,cmd,sizeof(cmd));
DEBUG(5,("cmd=%s\n",cmd));
ret = smbrun(cmd,NULL);
if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
@@ -605,16 +606,16 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
*status = NT_STATUS_LOGON_FAILURE;
return NULL;
}
-
+
/* Remember that a different vuid can connect later without these checks... */
-
+
/* Preexecs are done here as they might make the dir we are to ChDir to below */
/* execute any "preexec = " line */
if (*lp_preexec(SNUM(conn))) {
int ret;
pstring cmd;
pstrcpy(cmd,lp_preexec(SNUM(conn)));
- standard_sub_conn(conn,cmd);
+ standard_sub_conn(conn,cmd,sizeof(cmd));
ret = smbrun(cmd,NULL);
if (ret != 0 && lp_preexec_close(SNUM(conn))) {
DEBUG(1,("preexec gave %d - failing connection\n", ret));
@@ -625,7 +626,12 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
return NULL;
}
}
-
+
+#if CHECK_PATH_ON_TCONX
+ /* win2000 does not check the permissions on the directory
+ during the tree connect, instead relying on permission
+ check during individual operations. To match this behaviour
+ I have disabled this chdir check (tridge) */
if (vfs_ChDir(conn,conn->connectpath) != 0) {
DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
remote_machine, conn->client_address,
@@ -636,12 +642,23 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
*status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
+#else
+ /* the alternative is just to check the directory exists */
+ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
+ DEBUG(0,("%s is not a directory\n", conn->connectpath));
+ change_to_root_user();
+ yield_connection(conn, lp_servicename(SNUM(conn)));
+ conn_free(conn);
+ *status = NT_STATUS_BAD_NETWORK_NAME;
+ return NULL;
+ }
+#endif
string_set(&conn->origpath,conn->connectpath);
#if SOFTLINK_OPTIMISATION
- /* resolve any soft links early */
- {
+ /* resolve any soft links early if possible */
+ if (vfs_ChDir(conn,conn->connectpath) == 0) {
pstring s;
pstrcpy(s,conn->connectpath);
vfs_GetWd(conn,s);
@@ -674,11 +691,11 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
/* Invoke VFS make connection hook */
if (conn->vfs_ops.connect) {
- if (conn->vfs_ops.connect(conn, service, user) < 0) {
+ if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) {
DEBUG(0,("make_connection: VFS make connection failed!\n"));
- *status = NT_STATUS_UNSUCCESSFUL;
change_to_root_user();
conn_free(conn);
+ *status = NT_STATUS_UNSUCCESSFUL;
return NULL;
}
}
@@ -689,6 +706,130 @@ connection_struct *make_connection(char *service, DATA_BLOB password,
return(conn);
}
+/***************************************************************************************
+ Simple wrapper function for make_connection() to include a call to
+ vfs_chdir()
+ **************************************************************************************/
+
+connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
+ char *dev, uint16 vuid, NTSTATUS *status)
+{
+ connection_struct *conn = NULL;
+
+ conn = make_connection(service_in, password, dev, vuid, status);
+
+ /*
+ * make_connection() does not change the directory for us any more
+ * so we have to do it as a separate step --jerry
+ */
+
+ if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
+ DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
+ conn->connectpath,strerror(errno)));
+ yield_connection(conn, lp_servicename(SNUM(conn)));
+ conn_free(conn);
+ *status = NT_STATUS_UNSUCCESSFUL;
+ return NULL;
+ }
+
+ return conn;
+}
+
+/****************************************************************************
+ Make a connection to a service.
+ *
+ * @param service
+****************************************************************************/
+
+connection_struct *make_connection(const char *service_in, DATA_BLOB password,
+ char *dev, uint16 vuid, NTSTATUS *status)
+{
+ uid_t euid;
+ user_struct *vuser = NULL;
+ pstring service;
+ int snum = -1;
+
+ /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
+ if (!non_root_mode() && (euid = geteuid()) != 0) {
+ DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
+ smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
+ }
+
+ if(lp_security() != SEC_SHARE) {
+ vuser = get_valid_user_struct(vuid);
+ if (!vuser) {
+ DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
+ return NULL;
+ }
+ }
+
+ /* Logic to try and connect to the correct [homes] share, preferably without too many
+ getpwnam() lookups. This is particulary nasty for winbind usernames, where the
+ share name isn't the same as unix username.
+
+ The snum of the homes share is stored on the vuser at session setup time.
+ */
+
+ if (strequal(service_in,HOMES_NAME)) {
+ if(lp_security() != SEC_SHARE) {
+ DATA_BLOB no_pw = data_blob(NULL, 0);
+ if (vuser->homes_snum != -1) {
+ DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
+ return make_connection_snum(vuser->homes_snum,
+ vuser, no_pw,
+ dev, status);
+ }
+ } else {
+ /* Security = share. Try with current_user_info.smb_name
+ * as the username. */
+ if (*current_user_info.smb_name) {
+ fstring unix_username;
+ fstrcpy(unix_username,
+ current_user_info.smb_name);
+ map_username(unix_username);
+ snum = find_service(unix_username);
+ }
+ if (snum != -1) {
+ DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
+ return make_connection_snum(snum, NULL,
+ password,
+ dev, status);
+ }
+ }
+ } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
+ && strequal(service, lp_servicename(vuser->homes_snum))) {
+ DATA_BLOB no_pw = data_blob(NULL, 0);
+ DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service));
+ return make_connection_snum(vuser->homes_snum,
+ vuser, no_pw,
+ dev, status);
+ }
+
+ pstrcpy(service, service_in);
+
+ strlower(service);
+
+ snum = find_service(service);
+
+ if (snum < 0) {
+ if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
+ DEBUG(3,("refusing IPC connection to %s\n", service));
+ *status = NT_STATUS_ACCESS_DENIED;
+ return NULL;
+ }
+
+ DEBUG(0,("%s (%s) couldn't find service %s\n",
+ remote_machine, client_addr(), service));
+ *status = NT_STATUS_BAD_NETWORK_NAME;
+ return NULL;
+ }
+
+ DEBUG(5, ("making a connection to 'normal' service %s\n", service));
+
+ return make_connection_snum(snum, vuser,
+ password,
+ dev, status);
+}
/****************************************************************************
close a cnum
@@ -721,7 +862,7 @@ void close_cnum(connection_struct *conn, uint16 vuid)
change_to_user(conn, vuid)) {
pstring cmd;
pstrcpy(cmd,lp_postexec(SNUM(conn)));
- standard_sub_conn(conn,cmd);
+ standard_sub_conn(conn,cmd,sizeof(cmd));
smbrun(cmd,NULL);
change_to_root_user();
}
@@ -731,8 +872,12 @@ void close_cnum(connection_struct *conn, uint16 vuid)
if (*lp_rootpostexec(SNUM(conn))) {
pstring cmd;
pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
- standard_sub_conn(conn,cmd);
+ standard_sub_conn(conn,cmd,sizeof(cmd));
smbrun(cmd,NULL);
}
+
+ /* make sure we leave the directory available for unmount */
+ vfs_ChDir(conn, "/");
+
conn_free(conn);
}
diff --git a/source3/smbd/session.c b/source3/smbd/session.c
index 05a7b24da2..dade953ec1 100644
--- a/source3/smbd/session.c
+++ b/source3/smbd/session.c
@@ -163,16 +163,54 @@ void session_yield(user_struct *vuser)
tdb_delete(tdb, key);
}
-BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state)
+static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state)
{
- if (!tdb) {
- DEBUG(3, ("No tdb opened\n"));
- return False;
- }
+ if (!tdb) {
+ DEBUG(3, ("No tdb opened\n"));
+ return False;
+ }
- tdb_traverse(tdb, fn, state);
- return True;
+ tdb_traverse(tdb, fn, state);
+ return True;
}
+struct session_list {
+ int count;
+ struct sessionid *sessions;
+};
+
+static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *state)
+{
+ struct session_list *sesslist = (struct session_list *) state;
+ const struct sessionid *current = (const struct sessionid *) dbuf.dptr;
+
+ sesslist->count += 1;
+ sesslist->sessions = REALLOC(sesslist->sessions, sesslist->count *
+ sizeof(struct sessionid));
+
+ memcpy(&sesslist->sessions[sesslist->count - 1], current,
+ sizeof(struct sessionid));
+ DEBUG(7,("gather_sessioninfo session from %s@%s\n",
+ current->username, current->remote_machine));
+ return 0;
+}
+int list_sessions(struct sessionid **session_list)
+{
+ struct session_list sesslist;
+
+ sesslist.count = 0;
+ sesslist.sessions = NULL;
+
+ if (!session_traverse(gather_sessioninfo, (void *) &sesslist)) {
+ DEBUG(3, ("Session traverse failed\n"));
+ SAFE_FREE(sesslist.sessions);
+ *session_list = NULL;
+ return 0;
+ }
+ *session_list = sesslist.sessions;
+ return sesslist.count;
+}
+
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 899c9174b2..867b00ff5c 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -120,7 +120,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- ads = ads_init(NULL, NULL, NULL, NULL);
+ ads = ads_init_simple();
ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
if (!NT_STATUS_IS_OK(ret)) {
@@ -235,11 +235,12 @@ static int reply_spnego_negotiate(connection_struct *conn,
char *OIDs[ASN1_MAX_OIDS];
DATA_BLOB secblob;
int i;
- uint32 ntlmssp_command, neg_flags;
- DATA_BLOB sess_key, chal, spnego_chal;
+ uint32 ntlmssp_command, neg_flags, chal_flags;
+ DATA_BLOB chal, spnego_chal, extra_data;
const uint8 *cryptkey;
BOOL got_kerberos = False;
NTSTATUS nt_status;
+ extern pstring global_myname;
/* parse out the OIDs and the first sec blob */
if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
@@ -274,18 +275,23 @@ static int reply_spnego_negotiate(connection_struct *conn,
"NTLMSSP",
&ntlmssp_command,
&neg_flags,
- &sess_key)) {
+ &extra_data)) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
+
+ DEBUG(5, ("Extra data: \n"));
+ dump_data(5, extra_data.data, extra_data.length);
data_blob_free(&secblob);
- data_blob_free(&sess_key);
+ data_blob_free(&extra_data);
if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- DEBUG(3,("Got neg_flags=%08x\n", neg_flags));
+ DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags));
+
+ debug_ntlmssp_flags(neg_flags);
if (ntlmssp_auth_context) {
(ntlmssp_auth_context->free)(&ntlmssp_auth_context);
@@ -300,22 +306,47 @@ static int reply_spnego_negotiate(connection_struct *conn,
/* Give them the challenge. For now, ignore neg_flags and just
return the flags we want. Obviously this is not correct */
- neg_flags = NTLMSSP_NEGOTIATE_UNICODE |
+ chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
NTLMSSP_NEGOTIATE_LM_KEY |
- NTLMSSP_NEGOTIATE_NTLM;
-
- msrpc_gen(&chal, "Cddddbdddd",
- "NTLMSSP",
- NTLMSSP_CHALLENGE,
- 0,
- 0x30, /* ?? */
- neg_flags,
- cryptkey, 8,
- 0, 0, 0,
- 0x3000); /* ?? */
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_CHAL_TARGET_INFO;
+
+ {
+ DATA_BLOB domain_blob, netbios_blob, realm_blob;
+
+ msrpc_gen(&domain_blob,
+ "U",
+ lp_workgroup());
+
+ msrpc_gen(&netbios_blob,
+ "U",
+ global_myname);
+
+ msrpc_gen(&realm_blob,
+ "U",
+ lp_realm());
+
+
+ msrpc_gen(&chal, "CddddbBBBB",
+ "NTLMSSP",
+ NTLMSSP_CHALLENGE,
+ 0,
+ 0x30, /* ?? */
+ chal_flags,
+ cryptkey, 8,
+ domain_blob.data, domain_blob.length,
+ domain_blob.data, domain_blob.length,
+ netbios_blob.data, netbios_blob.length,
+ realm_blob.data, realm_blob.length);
+
+ data_blob_free(&domain_blob);
+ data_blob_free(&netbios_blob);
+ data_blob_free(&realm_blob);
+ }
if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
DEBUG(3,("Failed to generate challenge\n"));
+ data_blob_free(&chal);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -346,10 +377,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
int sess_vuid;
BOOL as_guest;
uint32 auth_flags = AUTH_FLAG_NONE;
-
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
+ /* we must have setup the auth context by now */
+ if (!ntlmssp_auth_context) {
+ DEBUG(2,("ntlmssp_auth_context is NULL in reply_spnego_auth\n"));
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
file_save("auth.dat", blob1.data, blob1.length);
@@ -606,7 +642,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
plaintext_password.data[passlen1] = 0;
}
- srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE);
+ srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
*domain = 0;
} else {
@@ -669,14 +705,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
}
p += passlen1 + passlen2;
- p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
- STR_TERMINATE);
- p += srvstr_pull(inbuf, domain, p, sizeof(domain),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
- -1, STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
domain,native_os,native_lanman));
}
diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c
index 90da422f13..36fecf5bd2 100644
--- a/source3/smbd/srvstr.c
+++ b/source3/smbd/srvstr.c
@@ -30,3 +30,12 @@ int srvstr_pull(void *base_ptr, char *dest, const void *src, int dest_len, int s
{
return pull_string(base_ptr, dest, src, dest_len, src_len, flags);
}
+
+/* pull a string from the smb_buf part of a packet. In this case the
+ string can either be null terminated or it can be terminated by the
+ end of the smbbuf area
+*/
+int srvstr_pull_buf(void *inbuf, char *dest, const void *src, int dest_len, int flags)
+{
+ return pull_string(inbuf, dest, src, dest_len, smb_bufrem(inbuf, src), flags);
+}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 1972e9c8c8..f1dfb39aac 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -37,255 +37,261 @@ extern pstring global_myname;
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-static int send_trans2_replies(char *outbuf, int bufsize, char *params,
- int paramsize, char *pdata, int datasize)
+static int send_trans2_replies(char *outbuf,
+ int bufsize,
+ char *params,
+ int paramsize,
+ char *pdata,
+ int datasize)
{
- /* As we are using a protocol > LANMAN1 then the max_send
- variable must have been set in the sessetupX call.
- This takes precedence over the max_xmit field in the
- global struct. These different max_xmit variables should
- be merged as this is now too confusing */
-
- extern int max_send;
- int data_to_send = datasize;
- int params_to_send = paramsize;
- int useable_space;
- char *pp = params;
- char *pd = pdata;
- int params_sent_thistime, data_sent_thistime, total_sent_thistime;
- int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
- int data_alignment_offset = 0;
-
- /* Initially set the wcnt area to be 10 - this is true for all
- trans2 replies */
- set_message(outbuf,10,0,True);
-
- /* If there genuinely are no parameters or data to send just send
- the empty packet */
- if(params_to_send == 0 && data_to_send == 0)
- {
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans2_replies: send_smb failed.");
- return 0;
- }
-
- /* When sending params and data ensure that both are nicely aligned */
- /* Only do this alignment when there is also data to send - else
- can cause NT redirector problems. */
- if (((params_to_send % 4) != 0) && (data_to_send != 0))
- data_alignment_offset = 4 - (params_to_send % 4);
-
- /* Space is bufsize minus Netbios over TCP header minus SMB header */
- /* The alignment_offset is to align the param bytes on an even byte
- boundary. NT 4.0 Beta needs this to work correctly. */
- useable_space = bufsize - ((smb_buf(outbuf)+
- alignment_offset+data_alignment_offset) -
- outbuf);
-
- /* useable_space can never be more than max_send minus the
- alignment offset. */
- useable_space = MIN(useable_space,
- max_send - (alignment_offset+data_alignment_offset));
-
-
- while (params_to_send || data_to_send)
- {
- /* Calculate whether we will totally or partially fill this packet */
- total_sent_thistime = params_to_send + data_to_send +
- alignment_offset + data_alignment_offset;
- /* We can never send more than useable_space */
- /*
- * Note that 'useable_space' does not include the alignment offsets,
- * but we must include the alignment offsets in the calculation of
- * the length of the data we send over the wire, as the alignment offsets
- * are sent here. Fix from Marc_Jacobsen@hp.com.
- */
- total_sent_thistime = MIN(total_sent_thistime, useable_space+
- alignment_offset + data_alignment_offset);
-
- set_message(outbuf, 10, total_sent_thistime, True);
-
- /* Set total params and data to be sent */
- SSVAL(outbuf,smb_tprcnt,paramsize);
- SSVAL(outbuf,smb_tdrcnt,datasize);
-
- /* Calculate how many parameters and data we can fit into
- this packet. Parameters get precedence */
-
- params_sent_thistime = MIN(params_to_send,useable_space);
- data_sent_thistime = useable_space - params_sent_thistime;
- data_sent_thistime = MIN(data_sent_thistime,data_to_send);
-
- SSVAL(outbuf,smb_prcnt, params_sent_thistime);
-
- /* smb_proff is the offset from the start of the SMB header to the
- parameter bytes, however the first 4 bytes of outbuf are
- the Netbios over TCP header. Thus use smb_base() to subtract
- them from the calculation */
-
- SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
-
- if(params_sent_thistime == 0)
- SSVAL(outbuf,smb_prdisp,0);
- else
- /* Absolute displacement of param bytes sent in this packet */
- SSVAL(outbuf,smb_prdisp,pp - params);
-
- SSVAL(outbuf,smb_drcnt, data_sent_thistime);
- if(data_sent_thistime == 0)
- {
- SSVAL(outbuf,smb_droff,0);
- SSVAL(outbuf,smb_drdisp, 0);
- }
- else
- {
- /* The offset of the data bytes is the offset of the
- parameter bytes plus the number of parameters being sent this time */
- SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
- smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
- SSVAL(outbuf,smb_drdisp, pd - pdata);
- }
-
- /* Copy the param bytes into the packet */
- if(params_sent_thistime)
- memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
- /* Copy in the data bytes */
- if(data_sent_thistime)
- memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
- data_alignment_offset,pd,data_sent_thistime);
-
- DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
- params_sent_thistime, data_sent_thistime, useable_space));
- DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
- params_to_send, data_to_send, paramsize, datasize));
-
- /* Send the packet */
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_trans2_replies: send_smb failed.");
-
- pp += params_sent_thistime;
- pd += data_sent_thistime;
-
- params_to_send -= params_sent_thistime;
- data_to_send -= data_sent_thistime;
-
- /* Sanity check */
- if(params_to_send < 0 || data_to_send < 0)
- {
- DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
- params_to_send, data_to_send));
- return -1;
- }
- }
-
- return 0;
+ /* As we are using a protocol > LANMAN1 then the max_send
+ variable must have been set in the sessetupX call.
+ This takes precedence over the max_xmit field in the
+ global struct. These different max_xmit variables should
+ be merged as this is now too confusing */
+
+ extern int max_send;
+ int data_to_send = datasize;
+ int params_to_send = paramsize;
+ int useable_space;
+ char *pp = params;
+ char *pd = pdata;
+ int params_sent_thistime, data_sent_thistime, total_sent_thistime;
+ int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
+ int data_alignment_offset = 0;
+
+ /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
+
+ set_message(outbuf,10,0,True);
+
+ /* If there genuinely are no parameters or data to send just send the empty packet */
+
+ if(params_to_send == 0 && data_to_send == 0) {
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("send_trans2_replies: send_smb failed.");
+ return 0;
+ }
+
+ /* When sending params and data ensure that both are nicely aligned */
+ /* Only do this alignment when there is also data to send - else
+ can cause NT redirector problems. */
+
+ if (((params_to_send % 4) != 0) && (data_to_send != 0))
+ data_alignment_offset = 4 - (params_to_send % 4);
+
+ /* Space is bufsize minus Netbios over TCP header minus SMB header */
+ /* The alignment_offset is to align the param bytes on an even byte
+ boundary. NT 4.0 Beta needs this to work correctly. */
+
+ useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
+
+ /* useable_space can never be more than max_send minus the alignment offset. */
+
+ useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
+
+ while (params_to_send || data_to_send) {
+ /* Calculate whether we will totally or partially fill this packet */
+
+ total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
+
+ /* We can never send more than useable_space */
+ /*
+ * Note that 'useable_space' does not include the alignment offsets,
+ * but we must include the alignment offsets in the calculation of
+ * the length of the data we send over the wire, as the alignment offsets
+ * are sent here. Fix from Marc_Jacobsen@hp.com.
+ */
+
+ total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
+
+ set_message(outbuf, 10, total_sent_thistime, True);
+
+ /* Set total params and data to be sent */
+ SSVAL(outbuf,smb_tprcnt,paramsize);
+ SSVAL(outbuf,smb_tdrcnt,datasize);
+
+ /* Calculate how many parameters and data we can fit into
+ * this packet. Parameters get precedence
+ */
+
+ params_sent_thistime = MIN(params_to_send,useable_space);
+ data_sent_thistime = useable_space - params_sent_thistime;
+ data_sent_thistime = MIN(data_sent_thistime,data_to_send);
+
+ SSVAL(outbuf,smb_prcnt, params_sent_thistime);
+
+ /* smb_proff is the offset from the start of the SMB header to the
+ parameter bytes, however the first 4 bytes of outbuf are
+ the Netbios over TCP header. Thus use smb_base() to subtract
+ them from the calculation */
+
+ SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+
+ if(params_sent_thistime == 0)
+ SSVAL(outbuf,smb_prdisp,0);
+ else
+ /* Absolute displacement of param bytes sent in this packet */
+ SSVAL(outbuf,smb_prdisp,pp - params);
+
+ SSVAL(outbuf,smb_drcnt, data_sent_thistime);
+ if(data_sent_thistime == 0) {
+ SSVAL(outbuf,smb_droff,0);
+ SSVAL(outbuf,smb_drdisp, 0);
+ } else {
+ /* The offset of the data bytes is the offset of the
+ parameter bytes plus the number of parameters being sent this time */
+ SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
+ smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
+ SSVAL(outbuf,smb_drdisp, pd - pdata);
+ }
+
+ /* Copy the param bytes into the packet */
+
+ if(params_sent_thistime)
+ memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+
+ /* Copy in the data bytes */
+ if(data_sent_thistime)
+ memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
+ data_alignment_offset,pd,data_sent_thistime);
+
+ DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
+ params_sent_thistime, data_sent_thistime, useable_space));
+ DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
+ params_to_send, data_to_send, paramsize, datasize));
+
+ /* Send the packet */
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("send_trans2_replies: send_smb failed.");
+
+ pp += params_sent_thistime;
+ pd += data_sent_thistime;
+
+ params_to_send -= params_sent_thistime;
+ data_to_send -= data_sent_thistime;
+
+ /* Sanity check */
+ if(params_to_send < 0 || data_to_send < 0) {
+ DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
+ params_to_send, data_to_send));
+ return -1;
+ }
+ }
+
+ return 0;
}
/****************************************************************************
Reply to a TRANSACT2_OPEN.
****************************************************************************/
-static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf,
- int bufsize,
- char **pparams, char **ppdata)
+static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- char *params = *pparams;
- int16 open_mode = SVAL(params, 2);
- int16 open_attr = SVAL(params,6);
- BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
+ char *params = *pparams;
+ int16 open_mode;
+ int16 open_attr;
+ BOOL oplock_request;
+#if 0
+ BOOL return_additional_info;
+ int16 open_sattr;
+ time_t open_time;
+#endif
+ int16 open_ofun;
+ int32 open_size;
+ char *pname;
+ pstring fname;
+ mode_t unixmode;
+ SMB_OFF_T size=0;
+ int fmode=0,mtime=0,rmode;
+ SMB_INO_T inode = 0;
+ SMB_STRUCT_STAT sbuf;
+ int smb_action = 0;
+ BOOL bad_path = False;
+ files_struct *fsp;
+
+ /*
+ * Ensure we have enough parameters to perform the operation.
+ */
+
+ if (total_params < 29)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ open_mode = SVAL(params, 2);
+ open_attr = SVAL(params,6);
+ oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
#if 0
- BOOL return_additional_info = BITSETW(params,0);
- int16 open_sattr = SVAL(params, 4);
- time_t open_time = make_unix_date3(params+8);
+ return_additional_info = BITSETW(params,0);
+ open_sattr = SVAL(params, 4);
+ open_time = make_unix_date3(params+8);
#endif
- int16 open_ofun = SVAL(params,12);
- int32 open_size = IVAL(params,14);
- char *pname = &params[28];
- pstring fname;
- mode_t unixmode;
- SMB_OFF_T size=0;
- int fmode=0,mtime=0,rmode;
- SMB_INO_T inode = 0;
- SMB_STRUCT_STAT sbuf;
- int smb_action = 0;
- BOOL bad_path = False;
- files_struct *fsp;
-
- srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
-
- DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
- fname,open_mode, open_attr, open_ofun, open_size));
-
- if (IS_IPC(conn)) {
+ open_ofun = SVAL(params,12);
+ open_size = IVAL(params,14);
+ pname = &params[28];
+
+ srvstr_pull(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE);
+
+ DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
+ fname,open_mode, open_attr, open_ofun, open_size));
+
+ if (IS_IPC(conn))
return(ERROR_DOS(ERRSRV,ERRaccess));
- }
- /* XXXX we need to handle passed times, sattr and flags */
+ /* XXXX we need to handle passed times, sattr and flags */
- unix_convert(fname,conn,0,&bad_path,&sbuf);
+ unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn))
- {
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- unixmode = unix_mode(conn,open_attr | aARCH, fname);
+ if (!check_name(fname,conn)) {
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ unixmode = unix_mode(conn,open_attr | aARCH, fname);
- fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
- oplock_request, &rmode,&smb_action);
+ fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
+ oplock_request, &rmode,&smb_action);
- if (!fsp)
- {
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- size = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
- mtime = sbuf.st_mtime;
- inode = sbuf.st_ino;
- if (fmode & aDIR) {
- close_file(fsp,False);
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
- }
-
- /* Realloc the size of parameters and data we will return */
- params = Realloc(*pparams, 28);
- if( params == NULL ) {
- return(ERROR_DOS(ERRDOS,ERRnomem));
- }
- *pparams = params;
-
- memset((char *)params,'\0',28);
- SSVAL(params,0,fsp->fnum);
- SSVAL(params,2,fmode);
- put_dos_date2(params,4, mtime);
- SIVAL(params,8, (uint32)size);
- SSVAL(params,12,rmode);
-
- if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- smb_action |= EXTENDED_OPLOCK_GRANTED;
- }
-
- SSVAL(params,18,smb_action);
- /*
- * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
- */
- SIVAL(params,20,inode);
+ if (!fsp) {
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ size = sbuf.st_size;
+ fmode = dos_mode(conn,fname,&sbuf);
+ mtime = sbuf.st_mtime;
+ inode = sbuf.st_ino;
+ if (fmode & aDIR) {
+ close_file(fsp,False);
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ }
+
+ /* Realloc the size of parameters and data we will return */
+ params = Realloc(*pparams, 28);
+ if( params == NULL )
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ *pparams = params;
+
+ memset((char *)params,'\0',28);
+ SSVAL(params,0,fsp->fnum);
+ SSVAL(params,2,fmode);
+ put_dos_date2(params,4, mtime);
+ SIVAL(params,8, (uint32)size);
+ SSVAL(params,12,rmode);
+
+ if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ smb_action |= EXTENDED_OPLOCK_GRANTED;
+
+ SSVAL(params,18,smb_action);
+
+ /*
+ * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
+ */
+ SIVAL(params,20,inode);
- /* Send the required number of replies */
- send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
+ /* Send the required number of replies */
+ send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
- return -1;
+ return -1;
}
/*********************************************************
@@ -304,10 +310,6 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig)
return strcasecmp(str,mask) == 0;
}
-#if 0
-
-Not finished yet - jra.
-
/****************************************************************************
Return the filetype for UNIX extensions.
****************************************************************************/
@@ -370,35 +372,63 @@ static uint32 unix_dev_minor(SMB_DEV_T dev)
}
/****************************************************************************
- Map standard UNIX permissions onto wire representations.
+ Map wire perms onto standard UNIX permissions. Obey share restrictions.
****************************************************************************/
-static uint32 unix_perms_to_wire(mode_t perms)
+static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
{
- uint ret = 0;
-
- ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
- ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
- ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
- ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
- ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
- ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
- ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
- ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
- ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
+ mode_t ret = 0;
+
+ if (perms == SMB_MODE_NO_CHANGE)
+ return pst->st_mode;
+
+ ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
+ ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
+ ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
+ ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
+ ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
+ ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
+ ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
+ ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
+ ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
#ifdef S_ISVTX
- ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
+ ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
#endif
#ifdef S_ISGID
- ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
+ ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
#endif
#ifdef S_ISUID
- ret |= ((perms & S_ISVTX) ? UNIX_SET_UID : 0);
+ ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
#endif
+
+ if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
+ ret &= lp_dir_mask(SNUM(conn));
+ /* Add in force bits */
+ ret |= lp_force_dir_mode(SNUM(conn));
+ } else {
+ /* Apply mode mask */
+ ret &= lp_create_mask(SNUM(conn));
+ /* Add in force bits */
+ ret |= lp_force_create_mode(SNUM(conn));
+ }
+
return ret;
}
-#endif
+/****************************************************************************
+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"));
+ if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
+ IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
+ return -1;
+ } else {
+ return interpret_long_date(p);
+ }
+}
/****************************************************************************
Get a level dependent lanman2 dir entry.
@@ -508,16 +538,23 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
continue;
}
} else if (vfs_stat(conn,pathreal,&sbuf) != 0) {
- /* Needed to show the msdfs symlinks as directories */
- if(!lp_host_msdfs() || !lp_msdfs_root(SNUM(conn))
- || !is_msdfs_link(conn, pathreal)) {
+
+ /* Needed to show the msdfs symlinks as
+ * directories */
+
+ if(lp_host_msdfs() &&
+ lp_msdfs_root(SNUM(conn)) &&
+ is_msdfs_link(conn, pathreal, NULL, NULL,
+ &sbuf)) {
+
+ DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
+ sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
+
+ } else {
+
DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
- pathreal,strerror(errno)));
+ pathreal,strerror(errno)));
continue;
- } else {
- DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n",
- pathreal));
- sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
}
}
@@ -557,7 +594,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
switch (info_level) {
- case 1:
+ case SMB_INFO_STANDARD:
if(requires_resume_key) {
SIVAL(p,0,reskey);
p += 4;
@@ -576,7 +613,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
p += len;
break;
- case 2:
+ case SMB_INFO_QUERY_EA_SIZE:
if(requires_resume_key) {
SIVAL(p,0,reskey);
p += 4;
@@ -693,14 +730,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
/* CIFS UNIX Extension. */
-#if 0 /* JRA - FIXME - NEEDS UNICODE CONVERSION !!! */
case SMB_FIND_FILE_UNIX:
-
- len = 108+strlen(fname)+1; /* (length of SMB_QUERY_FILE_UNIX_BASIC = 100)+4+4+strlen(fname)*/
- /* +1 to be sure to transmit the termination of fname */
- len = (len + 3) & ~3;
-
- SIVAL(p,0,len); p+= 4; /* Offset from this structure to the beginning of the next one */
+ p+= 4;
SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
@@ -750,12 +781,16 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SIVAL(p,4,0);
p+= 8;
+ len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
+ p += len;
+
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
+ p = pdata + len;
/* End of SMB_QUERY_FILE_UNIX_BASIC */
- pstrcpy(p,fname);
- p=pdata+len;
break;
-#endif
default:
return(False);
@@ -782,612 +817,664 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
Reply to a TRANS2_FINDFIRST.
****************************************************************************/
-static int call_trans2findfirst(connection_struct *conn,
- char *inbuf, char *outbuf, int bufsize,
- char **pparams, char **ppdata)
+static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- /* We must be careful here that we don't return more than the
- allowed number of data bytes. If this means returning fewer than
- maxentries then so be it. We assume that the redirector has
- enough room for the fixed number of parameter bytes it has
- requested. */
- uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
- char *params = *pparams;
- char *pdata = *ppdata;
- int dirtype = SVAL(params,0);
- int maxentries = SVAL(params,2);
- BOOL close_after_first = BITSETW(params+4,0);
- BOOL close_if_end = BITSETW(params+4,1);
- BOOL requires_resume_key = BITSETW(params+4,2);
- int info_level = SVAL(params,6);
- pstring directory;
- pstring mask;
- char *p, *wcard;
- int last_name_off=0;
- int dptr_num = -1;
- int numentries = 0;
- int i;
- BOOL finished = False;
- BOOL dont_descend = False;
- BOOL out_of_space = False;
- int space_remaining;
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
-
- *directory = *mask = 0;
-
- DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
- dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
- info_level, max_data_bytes));
+ /* We must be careful here that we don't return more than the
+ allowed number of data bytes. If this means returning fewer than
+ maxentries then so be it. We assume that the redirector has
+ enough room for the fixed number of parameter bytes it has
+ requested. */
+ uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
+ char *params = *pparams;
+ char *pdata = *ppdata;
+ int dirtype = SVAL(params,0);
+ int maxentries = SVAL(params,2);
+ BOOL close_after_first = BITSETW(params+4,0);
+ BOOL close_if_end = BITSETW(params+4,1);
+ BOOL requires_resume_key = BITSETW(params+4,2);
+ int info_level = SVAL(params,6);
+ pstring directory;
+ pstring mask;
+ char *p, *wcard;
+ int last_name_off=0;
+ int dptr_num = -1;
+ int numentries = 0;
+ int i;
+ BOOL finished = False;
+ BOOL dont_descend = False;
+ BOOL out_of_space = False;
+ int space_remaining;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+
+ if (total_params < 12)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ *directory = *mask = 0;
+
+ DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
+close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
+ dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
+ info_level, max_data_bytes));
- switch (info_level)
- {
- case 1:
- case 2:
- case 3:
- case 4:
- case SMB_FIND_FILE_DIRECTORY_INFO:
- case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- case SMB_FIND_FILE_NAMES_INFO:
- case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- break;
- default:
- return(ERROR_DOS(ERRDOS,ERRunknownlevel));
- }
-
- srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
-
- RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
-
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if(!check_name(directory,conn)) {
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ switch (info_level) {
+ case SMB_INFO_STANDARD:
+ case SMB_INFO_QUERY_EA_SIZE:
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+ case SMB_FIND_FILE_NAMES_INFO:
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ break;
+ case SMB_FIND_FILE_UNIX:
+ if (!lp_unix_extensions())
+ return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ break;
+ default:
+ return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ }
-#if 0
- /* Ugly - NT specific hack - maybe not needed ? (JRA) */
- if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
- (get_remote_arch() == RA_WINNT))
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbaddirectory;
- }
-#endif
-
- return(UNIXERROR(ERRDOS,ERRbadpath));
- }
-
- p = strrchr_m(directory,'/');
- if(p == NULL) {
- pstrcpy(mask,directory);
- pstrcpy(directory,"./");
- } else {
- pstrcpy(mask,p+1);
- *p = 0;
- }
-
- DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
-
- pdata = Realloc(*ppdata, max_data_bytes + 1024);
- if( pdata == NULL ) {
- return(ERROR_DOS(ERRDOS,ERRnomem));
- }
- *ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
-
- /* Realloc the params space */
- params = Realloc(*pparams, 10);
- if (params == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *pparams = params;
-
- dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
- if (dptr_num < 0)
- return(UNIXERROR(ERRDOS,ERRbadfile));
-
- /* Save the wildcard match and attribs we are using on this directory -
- needed as lanman2 assumes these are being saved between calls */
-
- if(!(wcard = strdup(mask))) {
- dptr_close(&dptr_num);
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
-
- dptr_set_wcard(dptr_num, wcard);
- dptr_set_attr(dptr_num, dirtype);
-
- DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
-
- /* We don't need to check for VOL here as this is returned by
- a different TRANS2 call. */
+ srvstr_pull(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE);
+
+ RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
+
+ unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if(!check_name(directory,conn)) {
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+
+ p = strrchr_m(directory,'/');
+ if(p == NULL) {
+ pstrcpy(mask,directory);
+ pstrcpy(directory,"./");
+ } else {
+ pstrcpy(mask,p+1);
+ *p = 0;
+ }
+
+ DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
+
+ pdata = Realloc(*ppdata, max_data_bytes + 1024);
+ if( pdata == NULL )
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+
+ *ppdata = pdata;
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
+
+ /* Realloc the params space */
+ params = Realloc(*pparams, 10);
+ if (params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ *pparams = params;
+
+ dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
+ if (dptr_num < 0)
+ return(UNIXERROR(ERRDOS,ERRbadfile));
+
+ /* Save the wildcard match and attribs we are using on this directory -
+ needed as lanman2 assumes these are being saved between calls */
+
+ if(!(wcard = strdup(mask))) {
+ dptr_close(&dptr_num);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
+
+ dptr_set_wcard(dptr_num, wcard);
+ dptr_set_attr(dptr_num, dirtype);
+
+ DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
+
+ /* We don't need to check for VOL here as this is returned by
+ a different TRANS2 call. */
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- conn->dirpath,lp_dontdescend(SNUM(conn))));
- if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
- dont_descend = True;
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
+ dont_descend = True;
- p = pdata;
- space_remaining = max_data_bytes;
- out_of_space = False;
-
- for (i=0;(i<maxentries) && !finished && !out_of_space;i++)
- {
- BOOL got_exact_match = False;
-
- /* this is a heuristic to avoid seeking the dirptr except when
- absolutely necessary. It allows for a filename of about 40 chars */
- if (space_remaining < DIRLEN_GUESS && numentries > 0)
- {
- out_of_space = True;
- finished = False;
- }
- else
- {
- finished = !get_lanman2_dir_entry(conn,
+ p = pdata;
+ space_remaining = max_data_bytes;
+ out_of_space = False;
+
+ for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
+ BOOL got_exact_match = False;
+
+ /* this is a heuristic to avoid seeking the dirptr except when
+ absolutely necessary. It allows for a filename of about 40 chars */
+ if (space_remaining < DIRLEN_GUESS && numentries > 0) {
+ out_of_space = True;
+ finished = False;
+ } else {
+ finished = !get_lanman2_dir_entry(conn,
inbuf, outbuf,
mask,dirtype,info_level,
requires_resume_key,dont_descend,
&p,pdata,space_remaining, &out_of_space, &got_exact_match,
&last_name_off);
- }
+ }
- if (finished && out_of_space)
- finished = False;
+ if (finished && out_of_space)
+ finished = False;
- if (!finished && !out_of_space)
- numentries++;
+ if (!finished && !out_of_space)
+ numentries++;
- /*
- * As an optimisation if we know we aren't looking
- * for a wildcard name (ie. the name matches the wildcard exactly)
- * then we can finish on any (first) match.
- * This speeds up large directory searches. JRA.
- */
+ /*
+ * As an optimisation if we know we aren't looking
+ * for a wildcard name (ie. the name matches the wildcard exactly)
+ * then we can finish on any (first) match.
+ * This speeds up large directory searches. JRA.
+ */
- if(got_exact_match)
- finished = True;
+ if(got_exact_match)
+ finished = True;
- space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
- }
+ space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+ }
- /* Check if we can close the dirptr */
- if(close_after_first || (finished && close_if_end))
- {
- DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
- dptr_close(&dptr_num);
- }
-
- /*
- * If there are no matching entries we must return ERRDOS/ERRbadfile -
- * from observation of NT.
- */
-
- if(numentries == 0) {
- dptr_close(&dptr_num);
- return ERROR_DOS(ERRDOS,ERRbadfile);
- }
-
- /* At this point pdata points to numentries directory entries. */
-
- /* Set up the return parameter block */
- SSVAL(params,0,dptr_num);
- SSVAL(params,2,numentries);
- SSVAL(params,4,finished);
- SSVAL(params,6,0); /* Never an EA error */
- SSVAL(params,8,last_name_off);
-
- send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
-
- if ((! *directory) && dptr_path(dptr_num))
- slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
-
- DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
- smb_fn_name(CVAL(inbuf,smb_com)),
- mask, directory, dirtype, numentries ) );
-
- /*
- * Force a name mangle here to ensure that the
- * mask as an 8.3 name is top of the mangled cache.
- * The reasons for this are subtle. Don't remove
- * this code unless you know what you are doing
- * (see PR#13758). JRA.
- */
-
- if(!mangle_is_8_3( mask, False))
- mangle_map(mask, True, True, SNUM(conn));
-
- return(-1);
+ /* Check if we can close the dirptr */
+ if(close_after_first || (finished && close_if_end)) {
+ DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
+ dptr_close(&dptr_num);
+ }
+
+ /*
+ * If there are no matching entries we must return ERRDOS/ERRbadfile -
+ * from observation of NT.
+ */
+
+ if(numentries == 0) {
+ dptr_close(&dptr_num);
+ return ERROR_DOS(ERRDOS,ERRbadfile);
+ }
+
+ /* At this point pdata points to numentries directory entries. */
+
+ /* Set up the return parameter block */
+ SSVAL(params,0,dptr_num);
+ SSVAL(params,2,numentries);
+ SSVAL(params,4,finished);
+ SSVAL(params,6,0); /* Never an EA error */
+ SSVAL(params,8,last_name_off);
+
+ send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
+
+ if ((! *directory) && dptr_path(dptr_num))
+ slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+
+ DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+ smb_fn_name(CVAL(inbuf,smb_com)),
+ mask, directory, dirtype, numentries ) );
+
+ /*
+ * Force a name mangle here to ensure that the
+ * mask as an 8.3 name is top of the mangled cache.
+ * The reasons for this are subtle. Don't remove
+ * this code unless you know what you are doing
+ * (see PR#13758). JRA.
+ */
+
+ if(!mangle_is_8_3_wildcards( mask, False))
+ mangle_map(mask, True, True, SNUM(conn));
+
+ return(-1);
}
/****************************************************************************
Reply to a TRANS2_FINDNEXT.
****************************************************************************/
-static int call_trans2findnext(connection_struct *conn,
- char *inbuf, char *outbuf,
- int length, int bufsize,
- char **pparams, char **ppdata)
+static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- /* We must be careful here that we don't return more than the
- allowed number of data bytes. If this means returning fewer than
- maxentries then so be it. We assume that the redirector has
- enough room for the fixed number of parameter bytes it has
- requested. */
- int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
- char *params = *pparams;
- char *pdata = *ppdata;
- int dptr_num = SVAL(params,0);
- int maxentries = SVAL(params,2);
- uint16 info_level = SVAL(params,4);
- uint32 resume_key = IVAL(params,6);
- BOOL close_after_request = BITSETW(params+10,0);
- BOOL close_if_end = BITSETW(params+10,1);
- BOOL requires_resume_key = BITSETW(params+10,2);
- BOOL continue_bit = BITSETW(params+10,3);
- pstring resume_name;
- pstring mask;
- pstring directory;
- char *p;
- uint16 dirtype;
- int numentries = 0;
- int i, last_name_off=0;
- BOOL finished = False;
- BOOL dont_descend = False;
- BOOL out_of_space = False;
- int space_remaining;
-
- *mask = *directory = *resume_name = 0;
-
- srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
-
- DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
+ /* We must be careful here that we don't return more than the
+ allowed number of data bytes. If this means returning fewer than
+ maxentries then so be it. We assume that the redirector has
+ enough room for the fixed number of parameter bytes it has
+ requested. */
+ int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
+ char *params = *pparams;
+ char *pdata = *ppdata;
+ int dptr_num = SVAL(params,0);
+ int maxentries = SVAL(params,2);
+ uint16 info_level = SVAL(params,4);
+ uint32 resume_key = IVAL(params,6);
+ BOOL close_after_request = BITSETW(params+10,0);
+ BOOL close_if_end = BITSETW(params+10,1);
+ BOOL requires_resume_key = BITSETW(params+10,2);
+ BOOL continue_bit = BITSETW(params+10,3);
+ pstring resume_name;
+ pstring mask;
+ pstring directory;
+ char *p;
+ uint16 dirtype;
+ int numentries = 0;
+ int i, last_name_off=0;
+ BOOL finished = False;
+ BOOL dont_descend = False;
+ BOOL out_of_space = False;
+ int space_remaining;
+
+ if (total_params < 12)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ *mask = *directory = *resume_name = 0;
+
+ srvstr_pull(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE);
+
+ DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
close_after_request=%d, close_if_end = %d requires_resume_key = %d \
resume_key = %d resume name = %s continue=%d level = %d\n",
- dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
- requires_resume_key, resume_key, resume_name, continue_bit, info_level));
-
- switch (info_level)
- {
- case 1:
- case 2:
- case 3:
- case 4:
- case SMB_FIND_FILE_DIRECTORY_INFO:
- case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- case SMB_FIND_FILE_NAMES_INFO:
- case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- break;
- default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
- }
-
- pdata = Realloc( *ppdata, max_data_bytes + 1024);
- if(pdata == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
-
- /* Realloc the params space */
- params = Realloc(*pparams, 6*SIZEOFWORD);
- if( params == NULL ) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *pparams = params;
-
- /* Check that the dptr is valid */
- if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
- return ERROR_DOS(ERRDOS,ERRnofiles);
-
- string_set(&conn->dirpath,dptr_path(dptr_num));
-
- /* Get the wildcard mask from the dptr */
- if((p = dptr_wcard(dptr_num))== NULL) {
- DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
- return ERROR_DOS(ERRDOS,ERRnofiles);
- }
- pstrcpy(mask, p);
- pstrcpy(directory,conn->dirpath);
-
- /* Get the attr mask from the dptr */
- dirtype = dptr_attr(dptr_num);
-
- DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
- dptr_num, mask, dirtype,
- (long)conn->dirptr,
- TellDir(conn->dirptr)));
-
- /* We don't need to check for VOL here as this is returned by
- a different TRANS2 call. */
-
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
- if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
- dont_descend = True;
+ dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
+ requires_resume_key, resume_key, resume_name, continue_bit, info_level));
+
+ switch (info_level) {
+ case SMB_INFO_STANDARD:
+ case SMB_INFO_QUERY_EA_SIZE:
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+ case SMB_FIND_FILE_NAMES_INFO:
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ break;
+ case SMB_FIND_FILE_UNIX:
+ if (!lp_unix_extensions())
+ return(ERROR_DOS(ERRDOS,ERRunknownlevel));
+ break;
+ default:
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ }
+
+ pdata = Realloc( *ppdata, max_data_bytes + 1024);
+ if(pdata == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+
+ *ppdata = pdata;
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
+
+ /* Realloc the params space */
+ params = Realloc(*pparams, 6*SIZEOFWORD);
+ if( params == NULL )
+ return ERROR_DOS(ERRDOS,ERRnomem);
+
+ *pparams = params;
+
+ /* Check that the dptr is valid */
+ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
+ return ERROR_DOS(ERRDOS,ERRnofiles);
+
+ string_set(&conn->dirpath,dptr_path(dptr_num));
+
+ /* Get the wildcard mask from the dptr */
+ if((p = dptr_wcard(dptr_num))== NULL) {
+ DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
+ return ERROR_DOS(ERRDOS,ERRnofiles);
+ }
+
+ pstrcpy(mask, p);
+ pstrcpy(directory,conn->dirpath);
+
+ /* Get the attr mask from the dptr */
+ dirtype = dptr_attr(dptr_num);
+
+ DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
+ dptr_num, mask, dirtype,
+ (long)conn->dirptr,
+ TellDir(conn->dirptr)));
+
+ /* We don't need to check for VOL here as this is returned by
+ a different TRANS2 call. */
+
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),case_sensitive))
+ dont_descend = True;
- p = pdata;
- space_remaining = max_data_bytes;
- out_of_space = False;
-
- /*
- * Seek to the correct position. We no longer use the resume key but
- * depend on the last file name instead.
- */
- if(requires_resume_key && *resume_name && !continue_bit)
- {
- /*
- * Fix for NT redirector problem triggered by resume key indexes
- * changing between directory scans. We now return a resume key of 0
- * and instead look for the filename to continue from (also given
- * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
- * findfirst/findnext (as is usual) then the directory pointer
- * should already be at the correct place. Check this by scanning
- * backwards looking for an exact (ie. case sensitive) filename match.
- * If we get to the beginning of the directory and haven't found it then scan
- * forwards again looking for a match. JRA.
- */
-
- int current_pos, start_pos;
- char *dname = NULL;
- void *dirptr = conn->dirptr;
- start_pos = TellDir(dirptr);
- for(current_pos = start_pos; current_pos >= 0; current_pos--)
- {
- DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
-
- SeekDir(dirptr, current_pos);
- dname = ReadDirName(dirptr);
-
- /*
- * Remember, mangle_map is called by
- * get_lanman2_dir_entry(), so the resume name
- * could be mangled. Ensure we do the same
- * here.
- */
-
- if(dname != NULL)
- mangle_map( dname, False, True, SNUM(conn));
-
- if(dname && strcsequal( resume_name, dname))
- {
- SeekDir(dirptr, current_pos+1);
- DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
- break;
- }
- }
-
- /*
- * Scan forward from start if not found going backwards.
- */
-
- if(current_pos < 0)
- {
- DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
- SeekDir(dirptr, start_pos);
- for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos))
- {
- /*
- * Remember, mangle_map is called by
- * get_lanman2_dir_entry(), so the resume name
- * could be mangled. Ensure we do the same
- * here.
- */
-
- if(dname != NULL)
- mangle_map( dname, False, True, SNUM(conn));
-
- if(dname && strcsequal( resume_name, dname))
- {
- SeekDir(dirptr, current_pos+1);
- DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
- break;
- }
- } /* end for */
- } /* end if current_pos */
- } /* end if requires_resume_key && !continue_bit */
-
- for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++)
- {
- BOOL got_exact_match = False;
-
- /* this is a heuristic to avoid seeking the dirptr except when
- absolutely necessary. It allows for a filename of about 40 chars */
- if (space_remaining < DIRLEN_GUESS && numentries > 0)
- {
- out_of_space = True;
- finished = False;
- }
- else
- {
- finished = !get_lanman2_dir_entry(conn,
- inbuf, outbuf,
- mask,dirtype,info_level,
- requires_resume_key,dont_descend,
- &p,pdata,space_remaining, &out_of_space, &got_exact_match,
- &last_name_off);
- }
+ p = pdata;
+ space_remaining = max_data_bytes;
+ out_of_space = False;
+
+ /*
+ * Seek to the correct position. We no longer use the resume key but
+ * depend on the last file name instead.
+ */
+
+ if(requires_resume_key && *resume_name && !continue_bit) {
+
+ /*
+ * Fix for NT redirector problem triggered by resume key indexes
+ * changing between directory scans. We now return a resume key of 0
+ * and instead look for the filename to continue from (also given
+ * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
+ * findfirst/findnext (as is usual) then the directory pointer
+ * should already be at the correct place. Check this by scanning
+ * backwards looking for an exact (ie. case sensitive) filename match.
+ * If we get to the beginning of the directory and haven't found it then scan
+ * forwards again looking for a match. JRA.
+ */
+
+ int current_pos, start_pos;
+ char *dname = NULL;
+ void *dirptr = conn->dirptr;
+ start_pos = TellDir(dirptr);
+ for(current_pos = start_pos; current_pos >= 0; current_pos--) {
+ DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
+
+ SeekDir(dirptr, current_pos);
+ dname = ReadDirName(dirptr);
+
+ /*
+ * Remember, mangle_map is called by
+ * get_lanman2_dir_entry(), so the resume name
+ * could be mangled. Ensure we do the same
+ * here.
+ */
+
+ if(dname != NULL)
+ mangle_map( dname, False, True, SNUM(conn));
+
+ if(dname && strcsequal( resume_name, dname)) {
+ SeekDir(dirptr, current_pos+1);
+ DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
+ break;
+ }
+ }
+
+ /*
+ * Scan forward from start if not found going backwards.
+ */
+
+ if(current_pos < 0) {
+ DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
+ SeekDir(dirptr, start_pos);
+ for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
+
+ /*
+ * Remember, mangle_map is called by
+ * get_lanman2_dir_entry(), so the resume name
+ * could be mangled. Ensure we do the same
+ * here.
+ */
+
+ if(dname != NULL)
+ mangle_map( dname, False, True, SNUM(conn));
+
+ if(dname && strcsequal( resume_name, dname)) {
+ SeekDir(dirptr, current_pos+1);
+ DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
+ break;
+ }
+ } /* end for */
+ } /* end if current_pos */
+ } /* end if requires_resume_key && !continue_bit */
+
+ for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
+ BOOL got_exact_match = False;
+
+ /* this is a heuristic to avoid seeking the dirptr except when
+ absolutely necessary. It allows for a filename of about 40 chars */
+ if (space_remaining < DIRLEN_GUESS && numentries > 0) {
+ out_of_space = True;
+ finished = False;
+ } else {
+ finished = !get_lanman2_dir_entry(conn,
+ inbuf, outbuf,
+ mask,dirtype,info_level,
+ requires_resume_key,dont_descend,
+ &p,pdata,space_remaining, &out_of_space, &got_exact_match,
+ &last_name_off);
+ }
- if (finished && out_of_space)
- finished = False;
+ if (finished && out_of_space)
+ finished = False;
- if (!finished && !out_of_space)
- numentries++;
+ if (!finished && !out_of_space)
+ numentries++;
- /*
- * As an optimisation if we know we aren't looking
- * for a wildcard name (ie. the name matches the wildcard exactly)
- * then we can finish on any (first) match.
- * This speeds up large directory searches. JRA.
- */
+ /*
+ * As an optimisation if we know we aren't looking
+ * for a wildcard name (ie. the name matches the wildcard exactly)
+ * then we can finish on any (first) match.
+ * This speeds up large directory searches. JRA.
+ */
- if(got_exact_match)
- finished = True;
+ if(got_exact_match)
+ finished = True;
- space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
- }
+ space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
+ }
- /* Check if we can close the dirptr */
- if(close_after_request || (finished && close_if_end))
- {
- DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
- dptr_close(&dptr_num); /* This frees up the saved mask */
- }
+ /* Check if we can close the dirptr */
+ if(close_after_request || (finished && close_if_end)) {
+ DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
+ dptr_close(&dptr_num); /* This frees up the saved mask */
+ }
- /* Set up the return parameter block */
- SSVAL(params,0,numentries);
- SSVAL(params,2,finished);
- SSVAL(params,4,0); /* Never an EA error */
- SSVAL(params,6,last_name_off);
+ /* Set up the return parameter block */
+ SSVAL(params,0,numentries);
+ SSVAL(params,2,finished);
+ SSVAL(params,4,0); /* Never an EA error */
+ SSVAL(params,6,last_name_off);
- send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
+ send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
- if ((! *directory) && dptr_path(dptr_num))
- slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+ if ((! *directory) && dptr_path(dptr_num))
+ slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
- DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
- smb_fn_name(CVAL(inbuf,smb_com)),
- mask, directory, dirtype, numentries ) );
+ DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
+ smb_fn_name(CVAL(inbuf,smb_com)),
+ mask, directory, dirtype, numentries ) );
- return(-1);
+ return(-1);
}
/****************************************************************************
Reply to a TRANS2_QFSINFO (query filesystem info).
****************************************************************************/
-static int call_trans2qfsinfo(connection_struct *conn,
- char *inbuf, char *outbuf,
- int length, int bufsize,
- char **pparams, char **ppdata)
+static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
+ int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
- char *pdata = *ppdata;
- char *params = *pparams;
- uint16 info_level = SVAL(params,0);
- int data_len, len;
- SMB_STRUCT_STAT st;
- char *vname = volume_label(SNUM(conn));
- int snum = SNUM(conn);
- char *fstype = lp_fstype(SNUM(conn));
-
- DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
-
- if(vfs_stat(conn,".",&st)!=0) {
- DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
- return ERROR_DOS(ERRSRV,ERRinvdevice);
- }
-
- pdata = Realloc(*ppdata, max_data_bytes + 1024);
- if ( pdata == NULL ) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
-
- switch (info_level)
- {
- case 1:
- {
- SMB_BIG_UINT dfree,dsize,bsize;
- data_len = 18;
- conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
- SIVAL(pdata,l1_idFileSystem,st.st_dev);
- SIVAL(pdata,l1_cSectorUnit,bsize/512);
- SIVAL(pdata,l1_cUnit,dsize);
- SIVAL(pdata,l1_cUnitAvail,dfree);
- SSVAL(pdata,l1_cbSector,512);
- DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
- (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
- (unsigned int)dfree, 512));
- break;
- }
- case 2:
- /* Return volume name */
- /*
- * Add volume serial number - hash of a combination of
- * 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,
- STR_TERMINATE);
- SCVAL(pdata,l2_vol_cch,len);
- data_len = l2_vol_szVolLabel + len;
- DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
- (unsigned)st.st_ctime, len, vname));
- break;
+ int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
+ char *pdata = *ppdata;
+ char *params = *pparams;
+ uint16 info_level = SVAL(params,0);
+ int data_len, len;
+ SMB_STRUCT_STAT st;
+ char *vname = volume_label(SNUM(conn));
+ int snum = SNUM(conn);
+ char *fstype = lp_fstype(SNUM(conn));
+
+ DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
+
+ if(vfs_stat(conn,".",&st)!=0) {
+ DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
+ return ERROR_DOS(ERRSRV,ERRinvdevice);
+ }
- case SMB_QUERY_FS_ATTRIBUTE_INFO:
- SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
- (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
- SIVAL(pdata,4,255); /* Max filename component length */
- /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
- and will think we can't do long filenames */
- len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
- SIVAL(pdata,8,len);
- data_len = 12 + len;
- break;
+ pdata = Realloc(*ppdata, max_data_bytes + 1024);
+ if ( pdata == NULL )
+ return ERROR_DOS(ERRDOS,ERRnomem);
- case SMB_QUERY_FS_LABEL_INFO:
- len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
- data_len = 4 + len;
- SIVAL(pdata,0,len);
- break;
- case SMB_QUERY_FS_VOLUME_INFO:
- /*
- * Add volume serial number - hash of a combination of
- * the called hostname and the service name.
- */
- SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
- (str_checksum(local_machine)<<16));
-
- len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
- SIVAL(pdata,12,len);
- data_len = 18+len;
- DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
- (int)strlen(vname),vname, lp_servicename(snum)));
- break;
- case SMB_QUERY_FS_SIZE_INFO:
- {
- SMB_BIG_UINT dfree,dsize,bsize;
- data_len = 24;
- conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
- SBIG_UINT(pdata,0,dsize);
- SBIG_UINT(pdata,8,dfree);
- SIVAL(pdata,16,bsize/512);
- SIVAL(pdata,20,512);
- break;
- }
- case SMB_QUERY_FS_DEVICE_INFO:
- data_len = 8;
- SIVAL(pdata,0,0); /* dev type */
- SIVAL(pdata,4,0); /* characteristics */
- break;
- case SMB_MAC_QUERY_FS_INFO:
- /*
- * Thursby MAC extension... ONLY on NTFS filesystems
- * once we do streams then we don't need this
- */
- if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
- data_len = 88;
- SIVAL(pdata,84,0x100); /* Don't support mac... */
- break;
- }
- /* drop through */
- default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
- }
-
-
- send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
-
- DEBUG( 4, ( "%s info_level = %d\n",
- smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
-
- return -1;
+ *ppdata = pdata;
+ memset((char *)pdata,'\0',max_data_bytes + 1024);
+
+ switch (info_level) {
+ case SMB_INFO_ALLOCATION:
+ {
+ SMB_BIG_UINT dfree,dsize,bsize;
+ data_len = 18;
+ conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
+ SIVAL(pdata,l1_idFileSystem,st.st_dev);
+ SIVAL(pdata,l1_cSectorUnit,bsize/512);
+ SIVAL(pdata,l1_cUnit,dsize);
+ SIVAL(pdata,l1_cUnitAvail,dfree);
+ SSVAL(pdata,l1_cbSector,512);
+ DEBUG(5,("call_trans2qfsinfo : bsize=%u, id=%x, cSectorUnit=%u, cUnit=%u, cUnitAvail=%u, cbSector=%d\n",
+ (unsigned int)bsize, (unsigned int)st.st_dev, ((unsigned int)bsize)/512, (unsigned int)dsize,
+ (unsigned int)dfree, 512));
+ break;
+ }
+
+ case SMB_INFO_VOLUME:
+ /* Return volume name */
+ /*
+ * Add volume serial number - hash of a combination of
+ * 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, STR_TERMINATE);
+ SCVAL(pdata,l2_vol_cch,len);
+ data_len = l2_vol_szVolLabel + len;
+ DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
+ (unsigned)st.st_ctime, len, vname));
+ break;
+
+ case SMB_QUERY_FS_ATTRIBUTE_INFO:
+ case SMB_FS_ATTRIBUTE_INFORMATION:
+
+ SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
+ (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */
+ SIVAL(pdata,4,255); /* Max filename component length */
+ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
+ and will think we can't do long filenames */
+ len = srvstr_push(outbuf, pdata+12, fstype, -1, 0);
+ SIVAL(pdata,8,len);
+ data_len = 12 + len;
+ break;
+
+ case SMB_QUERY_FS_LABEL_INFO:
+ case SMB_FS_LABEL_INFORMATION:
+ len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE);
+ data_len = 4 + len;
+ SIVAL(pdata,0,len);
+ break;
+
+ case SMB_QUERY_FS_VOLUME_INFO:
+ case SMB_FS_VOLUME_INFORMATION:
+
+ /*
+ * Add volume serial number - hash of a combination of
+ * the called hostname and the service name.
+ */
+ SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
+ (str_checksum(local_machine)<<16));
+
+ len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE);
+ SIVAL(pdata,12,len);
+ data_len = 18+len;
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
+ (int)strlen(vname),vname, lp_servicename(snum)));
+ break;
+
+ case SMB_QUERY_FS_SIZE_INFO:
+ case SMB_FS_SIZE_INFORMATION:
+ {
+ SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+ data_len = 24;
+ conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
+ block_size = lp_block_size(snum);
+ if (bsize < block_size) {
+ SMB_BIG_UINT factor = block_size/bsize;
+ bsize = block_size;
+ dsize /= factor;
+ dfree /= factor;
+ }
+ if (bsize > block_size) {
+ SMB_BIG_UINT factor = bsize/block_size;
+ bsize = block_size;
+ dsize *= factor;
+ dfree *= factor;
+ }
+ bytes_per_sector = 512;
+ sectors_per_unit = bsize/bytes_per_sector;
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
+ (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
+ SBIG_UINT(pdata,0,dsize);
+ SBIG_UINT(pdata,8,dfree);
+ SIVAL(pdata,16,sectors_per_unit);
+ SIVAL(pdata,20,bytes_per_sector);
+ break;
+ }
+
+ case SMB_FS_FULL_SIZE_INFORMATION:
+ {
+ SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+ data_len = 32;
+ conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize);
+ block_size = lp_block_size(snum);
+ if (bsize < block_size) {
+ SMB_BIG_UINT factor = block_size/bsize;
+ bsize = block_size;
+ dsize /= factor;
+ dfree /= factor;
+ }
+ if (bsize > block_size) {
+ SMB_BIG_UINT factor = bsize/block_size;
+ bsize = block_size;
+ dsize *= factor;
+ dfree *= factor;
+ }
+ bytes_per_sector = 512;
+ sectors_per_unit = bsize/bytes_per_sector;
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
+ (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
+ SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
+ SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
+ SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
+ SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
+ SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
+ break;
+ }
+
+ case SMB_QUERY_FS_DEVICE_INFO:
+ case SMB_FS_DEVICE_INFORMATION:
+ data_len = 8;
+ SIVAL(pdata,0,0); /* dev type */
+ SIVAL(pdata,4,0); /* characteristics */
+ break;
+
+ case SMB_FS_OBJECTID_INFORMATION:
+ data_len = 64;
+ break;
+
+ /*
+ * Query the version and capabilities of the CIFS UNIX extensions
+ * in use.
+ */
+
+ case SMB_QUERY_CIFS_UNIX_INFO:
+ if (!lp_unix_extensions())
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ data_len = 12;
+ SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
+ SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
+ SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
+ break;
+
+ case SMB_MAC_QUERY_FS_INFO:
+ /*
+ * Thursby MAC extension... ONLY on NTFS filesystems
+ * once we do streams then we don't need this
+ */
+ if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
+ data_len = 88;
+ SIVAL(pdata,84,0x100); /* Don't support mac... */
+ break;
+ }
+ /* drop through */
+ default:
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ }
+
+
+ send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
+
+ DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
+
+ return -1;
}
/****************************************************************************
@@ -1395,21 +1482,20 @@ static int call_trans2qfsinfo(connection_struct *conn,
****************************************************************************/
static int call_trans2setfsinfo(connection_struct *conn,
- char *inbuf, char *outbuf, int length,
- int bufsize,
- char **pparams, char **ppdata)
+ char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- /* Just say yes we did it - there is nothing that
- can be set here so it doesn't matter. */
- int outsize;
- DEBUG(3,("call_trans2setfsinfo\n"));
+ /* Just say yes we did it - there is nothing that
+ can be set here so it doesn't matter. */
+ int outsize;
+ DEBUG(3,("call_trans2setfsinfo\n"));
- if (!CAN_WRITE(conn))
- return ERROR_DOS(ERRSRV,ERRaccess);
+ if (!CAN_WRITE(conn))
+ return ERROR_DOS(ERRSRV,ERRaccess);
- outsize = set_message(outbuf,10,0,True);
+ outsize = set_message(outbuf,10,0,True);
- return outsize;
+ return outsize;
}
/****************************************************************************
@@ -1434,8 +1520,7 @@ NTSTATUS set_bad_path_error(int err, BOOL bad_path)
static int call_trans2qfilepathinfo(connection_struct *conn,
char *inbuf, char *outbuf, int length,
int bufsize,
- char **pparams,char **ppdata,
- int total_data)
+ char **pparams, int total_params, char **ppdata, int total_data)
{
int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
@@ -1448,6 +1533,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
unsigned int data_size;
SMB_STRUCT_STAT sbuf;
pstring fname, dos_fname;
+ char *fullpathname;
char *base_name;
char *p;
SMB_OFF_T pos = 0;
@@ -1456,9 +1542,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
int len;
time_t c_time;
- if (!params) {
+ if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
if (tran_call == TRANSACT2_QFILEINFO) {
files_struct *fsp = file_fsp(params,0);
@@ -1474,16 +1559,25 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
*/
pstrcpy(fname, fsp->fsp_name);
unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn) ||
- (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
- DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ 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));
}
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (vfs_lstat(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+ } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+
delete_pending = fsp->directory_delete_on_close;
} else {
/*
@@ -1503,6 +1597,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
}
} else {
/* qpathinfo */
+ if (total_params < 6)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
info_level = SVAL(params,0);
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
@@ -1512,17 +1609,28 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn) ||
- (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf))) {
- DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
+ 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));
+ }
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (vfs_lstat(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno)));
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRbadpath));
}
+ } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno)));
+ set_bad_path_error(errno, bad_path);
return(UNIXERROR(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));
@@ -1534,9 +1642,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
base_name = p+1;
mode = dos_mode(conn,fname,&sbuf);
+ fullpathname = fname;
size = sbuf.st_size;
allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
-
if (mode & aDIR)
size = 0;
@@ -1568,12 +1676,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
sbuf.st_mtime &= ~1;
}
- /* NT expects the name to be in an exact form */
- if (strequal(fname,".")) {
+ /* NT expects the name to be in an exact form of the *full*
+ filename. See the trans2 torture test */
+ if (strequal(base_name,".")) {
pstrcpy(dos_fname, "\\");
} else {
snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname);
- string_replace( dos_fname, '/', '\\');
+ string_replace(dos_fname, '/', '\\');
}
switch (info_level) {
@@ -1636,6 +1745,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
case SMB_FILE_STANDARD_INFORMATION:
case SMB_QUERY_FILE_STANDARD_INFO:
+
data_size = 24;
/* Fake up allocation size. */
SOFF_T(pdata,0,allocation_size);
@@ -1658,8 +1768,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
pstrcpy(short_name,base_name);
/* Mangle if not already 8.3 */
if(!mangle_is_8_3(short_name, True)) {
- if(!mangle_map(short_name,True,True,SNUM(conn)))
- *short_name = '\0';
+ mangle_map(short_name,True,True,SNUM(conn));
}
len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_TERMINATE|STR_UPPER);
data_size = 4 + len;
@@ -1676,18 +1785,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
SIVAL(pdata,0,len);
break;
- case SMB_FILE_END_OF_FILE_INFORMATION:
- case SMB_QUERY_FILE_END_OF_FILEINFO:
- data_size = 8;
- SOFF_T(pdata,0,size);
- break;
-
case SMB_FILE_ALLOCATION_INFORMATION:
case SMB_QUERY_FILE_ALLOCATION_INFO:
data_size = 8;
SOFF_T(pdata,0,allocation_size);
break;
+ case SMB_FILE_END_OF_FILE_INFORMATION:
+ case SMB_QUERY_FILE_END_OF_FILEINFO:
+ data_size = 8;
+ SOFF_T(pdata,0,size);
+ break;
+
case SMB_QUERY_FILE_ALL_INFO:
put_long_date(pdata,c_time);
put_long_date(pdata+8,sbuf.st_atime);
@@ -1793,6 +1902,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
break;
}
+#if 0
+ /*
+ * NT4 server just returns "invalid query" to this - if we try to answer
+ * it then NTws gets a BSOD! (tridge).
+ * W2K seems to want this. JRA.
+ */
+ case SMB_QUERY_FILE_STREAM_INFO:
+#endif
case SMB_FILE_STREAM_INFORMATION:
if (mode & aDIR) {
data_size = 0;
@@ -1832,18 +1949,92 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
data_size = 8;
break;
-#if 0
- /* NT4 server just returns "invalid query" to this - if we try to answer
- it then NTws gets a BSOD! (tridge) */
- case SMB_QUERY_FILE_STREAM_INFO:
- SIVAL(pdata,0,pos);
- SIVAL(pdata,4,(uint32)size);
- SIVAL(pdata,12,(uint32)allocation_size);
- len = srvstr_push(outbuf, pdata+24, fname, -1, STR_TERMINATE);
- SIVAL(pdata,20,len);
- data_size = 24 + len;
+ /*
+ * CIFS UNIX Extensions.
+ */
+
+ case SMB_QUERY_FILE_UNIX_BASIC:
+
+ DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
+
+ SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */
+ pdata += 8;
+
+#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+ SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
+#else
+ /* Can't get the value - fake it using size. */
+ SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
+#endif
+ pdata += 8;
+
+ put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
+ put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 Bit */
+ put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 Bit */
+ pdata += 24;
+
+ SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,sbuf.st_gid); /* group id of owner */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
+ pdata += 4;
+
+ SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
+ pdata += 8;
+
+ SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
+ SIVAL(pdata,4,0);
+ pdata += 8;
+
+ SIVAL(pdata,0,sbuf.st_nlink); /* number of hard links */
+ SIVAL(pdata,4,0);
+ pdata += 8+1;
+ data_size = PTR_DIFF(pdata,(*ppdata));
+
+ {
+ int i;
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
+
+ for (i=0; i<100; i++)
+ DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
+ DEBUG(4,("\n"));
+ }
+
break;
+
+ case SMB_QUERY_FILE_UNIX_LINK:
+ {
+ pstring buffer;
+
+#ifdef S_ISLNK
+ if(!S_ISLNK(sbuf.st_mode))
+ return(UNIXERROR(ERRSRV,ERRbadlink));
+#else
+ return(UNIXERROR(ERRDOS,ERRbadlink));
#endif
+ len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */
+ if (len == -1)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ buffer[len] = 0;
+ len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
+ pdata += len;
+ data_size = PTR_DIFF(pdata,(*ppdata));
+
+ break;
+ }
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
@@ -1943,19 +2134,78 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
}
/****************************************************************************
+ Returns true if this pathname is within the share, and thus safe.
+****************************************************************************/
+
+static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
+{
+#ifdef PATH_MAX
+ char resolved_name[PATH_MAX+1];
+#else
+ pstring resolved_name;
+#endif
+ fstring last_component;
+ pstring link_dest;
+ pstring link_test;
+ char *p;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+
+ pstrcpy(link_dest, link_dest_in);
+ unix_convert(link_dest,conn,0,&bad_path,&sbuf);
+
+ /* Store the UNIX converted path. */
+ pstrcpy(link_dest_out, link_dest);
+
+ p = strrchr(link_dest, '/');
+ if (p) {
+ fstrcpy(last_component, p+1);
+ *p = '\0';
+ } else {
+ fstrcpy(last_component, link_dest);
+ pstrcpy(link_dest, "./");
+ }
+
+ if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL)
+ return -1;
+
+ pstrcpy(link_dest, resolved_name);
+ pstrcat(link_dest, "/");
+ pstrcat(link_dest, last_component);
+
+ if (*link_dest != '/') {
+ /* Relative path. */
+ pstrcpy(link_test, conn->connectpath);
+ pstrcat(link_test, "/");
+ pstrcat(link_test, link_dest);
+ } else {
+ pstrcpy(link_test, link_dest);
+ }
+
+ /*
+ * Check if the link is within the share.
+ */
+
+ if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
+ errno = EACCES;
+ return -1;
+ }
+ return 0;
+}
+
+/****************************************************************************
Reply to a TRANS2_SETFILEINFO (set file info by fileid).
****************************************************************************/
static int call_trans2setfilepathinfo(connection_struct *conn,
- char *inbuf, char *outbuf, int length,
- int bufsize, char **pparams,
- char **ppdata, int total_data)
+ char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
char *params = *pparams;
char *pdata = *ppdata;
uint16 tran_call = SVAL(inbuf, smb_setup0);
uint16 info_level;
- int mode=0;
+ int dosmode=0;
SMB_OFF_T size=0;
struct utimbuf tvs;
SMB_STRUCT_STAT sbuf;
@@ -1963,6 +2213,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
int fd = -1;
BOOL bad_path = False;
files_struct *fsp = NULL;
+ uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
+ gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
+ mode_t unixmode = 0;
if (tran_call == TRANSACT2_SETFILEINFO) {
fsp = file_fsp(params,0);
@@ -1977,11 +2230,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
pstrcpy(fname, fsp->fsp_name);
unix_convert(fname,conn,0,&bad_path,&sbuf);
if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
- DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ set_bad_path_error(errno, bad_path);
return(UNIXERROR(ERRDOS,ERRbadpath));
}
} else if (fsp && fsp->print_file) {
@@ -2007,29 +2257,30 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
fd = fsp->fd;
if (vfs_fstat(fsp,fd,&sbuf) != 0) {
- DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRbadfid));
}
}
} else {
/* set path info */
+ if (total_params < 6)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
info_level = SVAL(params,0);
srvstr_pull(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE);
unix_convert(fname,conn,0,&bad_path,&sbuf);
if(!check_name(fname, conn)) {
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+ set_bad_path_error(errno, bad_path);
return(UNIXERROR(ERRDOS,ERRbadpath));
}
-
- if(!VALID_STAT(sbuf)) {
- DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
+
+ /*
+ * For CIFS UNIX extensions the target name may not exist.
+ */
+
+ 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));
}
}
@@ -2037,6 +2288,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if (!CAN_WRITE(conn))
return ERROR_DOS(ERRSRV,ERRaccess);
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+
+ 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));
@@ -2048,29 +2305,36 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
SSVAL(params,0,0);
+ if (fsp) {
+ /* the pending modtime overrides the current modtime */
+ sbuf.st_mtime = fsp->pending_modtime;
+ }
+
size = sbuf.st_size;
tvs.modtime = sbuf.st_mtime;
tvs.actime = sbuf.st_atime;
- mode = dos_mode(conn,fname,&sbuf);
+ dosmode = dos_mode(conn,fname,&sbuf);
+ unixmode = sbuf.st_mode;
- if (total_data > 4 && IVAL(pdata,0) == total_data) {
- /* uggh, EAs for OS2 */
- DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
- return ERROR_DOS(ERRDOS,ERReasnotsupported);
- }
+ set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
+ set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
switch (info_level) {
case SMB_INFO_STANDARD:
case SMB_INFO_QUERY_EA_SIZE:
{
+ if (total_data < l1_cbFile+4)
+ 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);
- mode = SVAL(pdata,l1_attrFile);
+ dosmode = SVAL(pdata,l1_attrFile);
size = IVAL(pdata,l1_cbFile);
+
break;
}
@@ -2078,18 +2342,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
it's also not in the cifs6.txt spec.
*/
case SMB_INFO_QUERY_EAS_FROM_LIST:
+ if (total_data < 28)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
tvs.actime = make_unix_date2(pdata+8);
tvs.modtime = make_unix_date2(pdata+12);
size = IVAL(pdata,16);
- mode = IVAL(pdata,24);
+ dosmode = IVAL(pdata,24);
break;
/* XXXX nor this. not in cifs6.txt, either. */
case SMB_INFO_QUERY_ALL_EAS:
+ if (total_data < 28)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
tvs.actime = make_unix_date2(pdata+8);
tvs.modtime = make_unix_date2(pdata+12);
size = IVAL(pdata,16);
- mode = IVAL(pdata,24);
+ dosmode = IVAL(pdata,24);
break;
case SMB_SET_FILE_BASIC_INFO:
@@ -2099,6 +2369,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
time_t write_time;
time_t changed_time;
+ if (total_data < 36)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
/* Ignore create time at offset pdata. */
/* access time */
@@ -2109,21 +2382,28 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
tvs.modtime = MIN(write_time, changed_time);
+ if (write_time > tvs.modtime && write_time != 0xffffffff) {
+ tvs.modtime = write_time;
+ }
/* Prefer a defined time to an undefined one. */
if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
? changed_time : write_time);
/* attributes */
- mode = IVAL(pdata,32);
+ dosmode = IVAL(pdata,32);
break;
}
- case SMB_FILE_ALLOCATION_INFORMATION:
+ case SMB_FILE_ALLOCATION_INFORMATION:
case SMB_SET_FILE_ALLOCATION_INFO:
{
int ret = -1;
SMB_OFF_T allocation_size = IVAL(pdata,0);
+
+ if (total_data < 8)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
#ifdef LARGE_SMB_OFF_T
allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
#else /* LARGE_SMB_OFF_T */
@@ -2163,14 +2443,16 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
return(UNIXERROR(ERRDOS,ERRbadpath));
ret = vfs_allocate_file_space(new_fsp, allocation_size);
if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
- DEBUG(3,("fstat of fnum %d failed (%s)\n",new_fsp->fnum, strerror(errno)));
+ DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
+ new_fsp->fnum, strerror(errno)));
ret = -1;
}
close_file(new_fsp,True);
} else {
ret = vfs_allocate_file_space(fsp, allocation_size);
if (vfs_fstat(fsp,fd,&new_sbuf) != 0) {
- DEBUG(3,("fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
+ fsp->fnum, strerror(errno)));
ret = -1;
}
}
@@ -2184,9 +2466,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
break;
}
- case SMB_FILE_END_OF_FILE_INFORMATION:
+ case SMB_FILE_END_OF_FILE_INFORMATION:
case SMB_SET_FILE_END_OF_FILE_INFO:
{
+ if (total_data < 8)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
size = IVAL(pdata,0);
#ifdef LARGE_SMB_OFF_T
size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
@@ -2204,6 +2489,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
BOOL delete_on_close = (CVAL(pdata,0) ? True : False);
NTSTATUS status;
+ if (total_data < 1)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
if (tran_call != TRANSACT2_SETFILEINFO)
return ERROR_DOS(ERRDOS,ERRunknownlevel);
@@ -2218,6 +2506,183 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
break;
}
+ /*
+ * CIFS UNIX extensions.
+ */
+
+ case SMB_SET_FILE_UNIX_BASIC:
+ {
+ uint32 raw_unixmode;
+
+ if (total_data < 100)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
+ IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
+ size=IVAL(pdata,0); /* first 8 Bytes are size */
+#ifdef LARGE_SMB_OFF_T
+ size |= (((SMB_OFF_T)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 */
+ }
+ pdata+=24; /* ctime & st_blocks are not changed */
+ tvs.actime = interpret_long_unix_date(pdata); /* access_time */
+ tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
+ pdata+=16;
+ set_owner = (uid_t)IVAL(pdata,0);
+ pdata += 8;
+ set_grp = (gid_t)IVAL(pdata,0);
+ pdata += 8;
+ raw_unixmode = IVAL(pdata,28);
+ unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
+ dosmode = 0; /* Ensure dos mode change doesn't override this. */
+
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
+size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
+ fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
+
+ if (!VALID_STAT(sbuf)) {
+
+ /*
+ * The only valid use of this is to create character and block
+ * devices, and named pipes. This is deprecated (IMHO) and
+ * a new info level should be used for mknod. JRA.
+ */
+
+#if !defined(HAVE_MAKEDEV_FN)
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+#else /* HAVE_MAKEDEV_FN */
+ uint32 file_type = IVAL(pdata,0);
+ uint32 dev_major = IVAL(pdata,4);
+ uint32 dev_minor = IVAL(pdata,12);
+
+ uid_t myuid = geteuid();
+ gid_t mygid = getegid();
+ SMB_DEV_T dev;
+
+ if (tran_call == TRANSACT2_SETFILEINFO)
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+
+ if (raw_unixmode == SMB_MODE_NO_CHANGE)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ dev = makedev(dev_major, dev_minor);
+
+ /* We can only create as the owner/group we are. */
+
+ if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+
+ if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
+ file_type != UNIX_TYPE_FIFO)
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
+0%o for file %s\n", (double)dev, unixmode, fname ));
+
+ /* Ok - do the mknod. */
+ if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ return(-1);
+#endif /* HAVE_MAKEDEV_FN */
+
+ }
+
+ /*
+ * Deal with the UNIX specific mode set.
+ */
+
+ if (raw_unixmode != SMB_MODE_NO_CHANGE) {
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
+ (unsigned int)unixmode, fname ));
+ if (vfs_chmod(conn,fname,unixmode) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ /*
+ * Deal with the UNIX specific uid set.
+ */
+
+ if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
+ (unsigned int)set_owner, fname ));
+ if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ /*
+ * Deal with the UNIX specific gid set.
+ */
+
+ if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
+ (unsigned int)set_owner, fname ));
+ if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+ break;
+ }
+
+ case SMB_SET_FILE_UNIX_LINK:
+ {
+ pstring link_dest;
+ /* Set a symbolic link. */
+ /* Don't allow this if follow links is false. */
+
+ if (!lp_symlinks(SNUM(conn)))
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+
+ /* Disallow if already exists. */
+ if (VALID_STAT(sbuf))
+ return(ERROR_DOS(ERRDOS,ERRbadpath));
+
+ srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
+
+ if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
+ fname, link_dest ));
+
+ if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ return(-1);
+ }
+
+ case SMB_SET_FILE_UNIX_HLINK:
+ {
+ pstring link_dest;
+
+ /* Set a hard link. */
+
+ /* Disallow if already exists. */
+ if (VALID_STAT(sbuf))
+ return(ERROR_DOS(ERRDOS,ERRbadpath));
+
+ srvstr_pull(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE);
+
+ if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
+ fname, link_dest ));
+
+ if (conn->vfs_ops.link(conn,link_dest,fname) != 0)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ return(-1);
+ }
+
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
}
@@ -2232,17 +2697,18 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
DEBUG(6,("size: %.0f ", (double)size));
- DEBUG(6,("mode: %x\n" , mode));
if (S_ISDIR(sbuf.st_mode))
- mode |= aDIR;
+ dosmode |= aDIR;
else
- mode &= ~aDIR;
+ dosmode &= ~aDIR;
+
+ DEBUG(6,("dosmode: %x\n" , dosmode));
if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
(info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
(info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
- (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
+ (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
/*
* Only do this test if we are not explicitly
@@ -2263,7 +2729,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
* NT does this a lot. It's actually pointless
* setting the time here, as it will be overwritten
* on the next write, so we save the request
- * away and will set it on file code. JRA.
+ * away and will set it on file close. JRA.
*/
if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
@@ -2281,11 +2747,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
}
/* check the mode isn't different, before changing it */
- if ((mode != 0) && (mode != dos_mode(conn, fname, &sbuf))) {
+ if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
- DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, mode ));
+ DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
- if(file_chmod(conn, fname, mode, NULL)) {
+ if(file_chmod(conn, fname, dosmode, NULL)) {
DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
@@ -2331,7 +2797,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
}
SSVAL(params,0,0);
-
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
return(-1);
@@ -2343,48 +2808,45 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
static int call_trans2mkdir(connection_struct *conn,
char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, char **ppdata)
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- char *params = *pparams;
- pstring directory;
- int ret = -1;
- SMB_STRUCT_STAT sbuf;
- BOOL bad_path = False;
+ char *params = *pparams;
+ pstring directory;
+ int ret = -1;
+ SMB_STRUCT_STAT sbuf;
+ BOOL bad_path = False;
- if (!CAN_WRITE(conn))
- return ERROR_DOS(ERRSRV,ERRaccess);
+ if (!CAN_WRITE(conn))
+ return ERROR_DOS(ERRSRV,ERRaccess);
- srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
+ if (total_params < 4)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
- DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+ srvstr_pull(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE);
- unix_convert(directory,conn,0,&bad_path,&sbuf);
- if (check_name(directory,conn))
- ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
+ DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+
+ unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if (check_name(directory,conn))
+ ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
- if(ret < 0)
- {
- DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- /* Realloc the parameter and data sizes */
- params = Realloc(*pparams,2);
- if(params == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *pparams = params;
-
- SSVAL(params,0,0);
-
- send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ if(ret < 0) {
+ DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
+ set_bad_path_error(errno, bad_path);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ /* Realloc the parameter and data sizes */
+ params = Realloc(*pparams,2);
+ if(params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ *pparams = params;
+
+ SSVAL(params,0,0);
+
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
- return(-1);
+ return(-1);
}
/****************************************************************************
@@ -2393,44 +2855,45 @@ static int call_trans2mkdir(connection_struct *conn,
****************************************************************************/
static int call_trans2findnotifyfirst(connection_struct *conn,
- char *inbuf, char *outbuf,
- int length, int bufsize,
- char **pparams, char **ppdata)
+ char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- static uint16 fnf_handle = 257;
- char *params = *pparams;
- uint16 info_level = SVAL(params,4);
-
- DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
-
- switch (info_level)
- {
- case 1:
- case 2:
- break;
- default:
- return ERROR_DOS(ERRDOS,ERRunknownlevel);
- }
-
- /* Realloc the parameter and data sizes */
- params = Realloc(*pparams,6);
- if(params == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *pparams = params;
-
- SSVAL(params,0,fnf_handle);
- SSVAL(params,2,0); /* No changes */
- SSVAL(params,4,0); /* No EA errors */
-
- fnf_handle++;
-
- if(fnf_handle == 0)
- fnf_handle = 257;
-
- send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
+ static uint16 fnf_handle = 257;
+ char *params = *pparams;
+ uint16 info_level;
+
+ if (total_params < 6)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ info_level = SVAL(params,4);
+ DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
+
+ switch (info_level) {
+ case 1:
+ case 2:
+ break;
+ default:
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+ }
+
+ /* Realloc the parameter and data sizes */
+ params = Realloc(*pparams,6);
+ if(params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ *pparams = params;
+
+ SSVAL(params,0,fnf_handle);
+ SSVAL(params,2,0); /* No changes */
+ SSVAL(params,4,0); /* No EA errors */
+
+ fnf_handle++;
+
+ if(fnf_handle == 0)
+ fnf_handle = 257;
+
+ send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
- return(-1);
+ return(-1);
}
/****************************************************************************
@@ -2439,27 +2902,25 @@ static int call_trans2findnotifyfirst(connection_struct *conn,
****************************************************************************/
static int call_trans2findnotifynext(connection_struct *conn,
- char *inbuf, char *outbuf,
- int length, int bufsize,
- char **pparams, char **ppdata)
+ char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- char *params = *pparams;
+ char *params = *pparams;
- DEBUG(3,("call_trans2findnotifynext\n"));
+ DEBUG(3,("call_trans2findnotifynext\n"));
- /* Realloc the parameter and data sizes */
- params = Realloc(*pparams,4);
- if(params == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *pparams = params;
+ /* Realloc the parameter and data sizes */
+ params = Realloc(*pparams,4);
+ if(params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ *pparams = params;
- SSVAL(params,0,0); /* No changes */
- SSVAL(params,2,0); /* No EA errors */
+ SSVAL(params,0,0); /* No changes */
+ SSVAL(params,2,0); /* No EA errors */
- send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
+ send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
- return(-1);
+ return(-1);
}
/****************************************************************************
@@ -2467,29 +2928,33 @@ static int call_trans2findnotifynext(connection_struct *conn,
****************************************************************************/
static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
- char* outbuf, int length, int bufsize,
- char** pparams, char** ppdata)
+ char* outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- char *params = *pparams;
- pstring pathname;
- int reply_size = 0;
- int max_referral_level = SVAL(params,0);
+ char *params = *pparams;
+ pstring pathname;
+ int reply_size = 0;
+ int max_referral_level;
+ DEBUG(10,("call_trans2getdfsreferral\n"));
- DEBUG(10,("call_trans2getdfsreferral\n"));
+ if (total_params < 2)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
- if(!lp_host_msdfs())
- return ERROR_DOS(ERRDOS,ERRbadfunc);
+ max_referral_level = SVAL(params,0);
- srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
+ if(!lp_host_msdfs())
+ return ERROR_DOS(ERRDOS,ERRbadfunc);
- if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
- return ERROR_DOS(ERRDOS,ERRbadfile);
+ srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
+
+ if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
+ return ERROR_DOS(ERRDOS,ERRbadfile);
- SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
- send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
+ send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
- return(-1);
+ return(-1);
}
#define LMCAT_SPL 0x53
@@ -2500,32 +2965,31 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
****************************************************************************/
static int call_trans2ioctl(connection_struct *conn, char* inbuf,
- char* outbuf, int length, int bufsize,
- char** pparams, char** ppdata)
+ char* outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data)
{
- char *pdata = *ppdata;
- files_struct *fsp = file_fsp(inbuf,smb_vwv15);
-
- if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
- (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
- pdata = Realloc(*ppdata, 32);
- if(pdata == NULL) {
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
- *ppdata = pdata;
-
- /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
- CAN ACCEPT THIS IN UNICODE. JRA. */
-
- SSVAL(pdata,0,fsp->print_jobid); /* Job number */
- srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
- srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
- send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
- return(-1);
- } else {
- DEBUG(2,("Unknown TRANS2_IOCTL\n"));
- return ERROR_DOS(ERRSRV,ERRerror);
- }
+ char *pdata = *ppdata;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv15);
+
+ if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
+ (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+ pdata = Realloc(*ppdata, 32);
+ if(pdata == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ *ppdata = pdata;
+
+ /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
+ CAN ACCEPT THIS IN UNICODE. JRA. */
+
+ SSVAL(pdata,0,fsp->print_jobid); /* Job number */
+ srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
+ srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
+ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
+ return(-1);
+ } else {
+ DEBUG(2,("Unknown TRANS2_IOCTL\n"));
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
}
/****************************************************************************
@@ -2736,93 +3200,84 @@ int reply_trans2(connection_struct *conn,
switch(tran_call) {
case TRANSACT2_OPEN:
START_PROFILE_NESTED(Trans2_open);
- outsize = call_trans2open(conn,
- inbuf, outbuf, bufsize,
- &params, &data);
+ outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_open);
break;
case TRANSACT2_FINDFIRST:
START_PROFILE_NESTED(Trans2_findfirst);
- outsize = call_trans2findfirst(conn, inbuf, outbuf,
- bufsize, &params, &data);
+ outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_findfirst);
break;
case TRANSACT2_FINDNEXT:
START_PROFILE_NESTED(Trans2_findnext);
- outsize = call_trans2findnext(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data);
+ outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_findnext);
break;
case TRANSACT2_QFSINFO:
START_PROFILE_NESTED(Trans2_qfsinfo);
- outsize = call_trans2qfsinfo(conn, inbuf, outbuf,
- length, bufsize, &params,
- &data);
+ outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_qfsinfo);
break;
case TRANSACT2_SETFSINFO:
START_PROFILE_NESTED(Trans2_setfsinfo);
- outsize = call_trans2setfsinfo(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data);
+ outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_setfsinfo);
break;
case TRANSACT2_QPATHINFO:
case TRANSACT2_QFILEINFO:
START_PROFILE_NESTED(Trans2_qpathinfo);
- outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data, total_data);
+ outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_qpathinfo);
break;
case TRANSACT2_SETPATHINFO:
case TRANSACT2_SETFILEINFO:
START_PROFILE_NESTED(Trans2_setpathinfo);
- outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data,
- total_data);
+ outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_setpathinfo);
break;
case TRANSACT2_FINDNOTIFYFIRST:
START_PROFILE_NESTED(Trans2_findnotifyfirst);
- outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data);
+ outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_findnotifyfirst);
break;
case TRANSACT2_FINDNOTIFYNEXT:
START_PROFILE_NESTED(Trans2_findnotifynext);
- outsize = call_trans2findnotifynext(conn, inbuf, outbuf,
- length, bufsize,
- &params, &data);
+ outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_findnotifynext);
break;
case TRANSACT2_MKDIR:
START_PROFILE_NESTED(Trans2_mkdir);
- outsize = call_trans2mkdir(conn, inbuf, outbuf, length,
- bufsize, &params, &data);
+ outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_mkdir);
break;
case TRANSACT2_GET_DFS_REFERRAL:
START_PROFILE_NESTED(Trans2_get_dfs_referral);
- outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length,
- bufsize, &params, &data);
+ outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_get_dfs_referral);
break;
case TRANSACT2_IOCTL:
START_PROFILE_NESTED(Trans2_ioctl);
- outsize = call_trans2ioctl(conn,inbuf,outbuf,length,
- bufsize,&params,&data);
+ outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
+ &params, total_params, &data, total_data);
END_PROFILE_NESTED(Trans2_ioctl);
break;
default:
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index ac0b535c13..a18f62c9cc 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -465,11 +465,11 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N
if (ret) {
DEBUG(10,
- ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %u)\n",
+ ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
domain, name, sid_to_string(sid,psid),
- (unsigned int)*name_type ));
+ sid_type_lookup(*name_type), (unsigned int)*name_type));
return True;
- } else if (winbind_lookup_name(domain, name, psid, name_type) || (*name_type != SID_NAME_USER) ) {
+ } else 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),
@@ -504,7 +504,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE
sid_copy(&tmp_sid, sid);
sid_split_rid(&tmp_sid, &rid);
- if (sid_equal(&global_sam_sid, &tmp_sid)) {
+ 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);
@@ -521,7 +521,7 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE
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);
+ lookup_known_rid(&tmp_sid, rid, name, name_type);
}
return True;
}
@@ -578,7 +578,8 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid)
}
}
- local_gid_to_sid(psid, gid);
+ /* Make sure we report failure, (when psid == NULL) */
+ psid = local_gid_to_sid(psid, gid);
DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid)));
@@ -597,7 +598,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
fstring sid_str;
/* if we know its local then don't try winbindd */
- if (sid_compare_domain(&global_sam_sid, psid) == 0) {
+ if (sid_compare_domain(get_global_sam_sid(), psid) == 0) {
return local_sid_to_uid(puid, psid, sidtype);
}
diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c
index fadc435a2f..394086dc07 100644
--- a/source3/smbd/vfs-wrap.c
+++ b/source3/smbd/vfs-wrap.c
@@ -147,7 +147,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
ssize_t result;
START_PROFILE_BYTES(syscall_read, n);
- result = read(fd, data, n);
+ result = sys_read(fd, data, n);
END_PROFILE(syscall_read);
return result;
}
@@ -157,7 +157,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
ssize_t result;
START_PROFILE_BYTES(syscall_write, n);
- result = write(fd, data, n);
+ result = sys_write(fd, data, n);
END_PROFILE(syscall_write);
return result;
}
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 4e2e353ed8..5e1dc68bdb 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -32,7 +32,7 @@ struct vfs_syminfo {
very important. They must be in the same order as defined in
vfs.h. Change at your own peril. */
-struct vfs_ops default_vfs_ops = {
+static struct vfs_ops default_vfs_ops = {
/* Disk operations */
@@ -139,7 +139,7 @@ static BOOL vfs_init_custom(connection_struct *conn)
/* Open object file */
if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) {
- DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), dlerror()));
+ DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror()));
return False;
}
@@ -222,7 +222,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_
/*******************************************************************
vfs getwd wrapper
********************************************************************/
-char *vfs_getwd(connection_struct *conn, char *path)
+static char *vfs_getwd(connection_struct *conn, char *path)
{
return conn->vfs_ops.getwd(conn,path);
}
@@ -562,7 +562,7 @@ int vfs_ChDir(connection_struct *conn, char *path)
/* number of list structures for a caching GetWd function. */
#define MAX_GETWDCACHE (50)
-struct {
+static struct {
SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
char *dos_path; /* The pathname in DOS format. */