summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2004-06-15 18:36:45 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:51:57 -0500
commit2acd0848663f28afedff9b11b738e048f5ead2cc (patch)
tree3f36e5c0fc1bba20f626ae58ee5cfa9371a4f8d0
parent2895acb6e7c476e88735096b7f5d01f616739fe3 (diff)
downloadsamba-2acd0848663f28afedff9b11b738e048f5ead2cc.tar.gz
samba-2acd0848663f28afedff9b11b738e048f5ead2cc.tar.bz2
samba-2acd0848663f28afedff9b11b738e048f5ead2cc.zip
r1154: Change default setting for case sensitivity to "auto". If set to auto
then is the client supports it (current clients supported are Samba and CIFSVFS - detected by the negprot strings "Samba", "POSIX 2" and a bare "NT LM 0.12" string) then the setting of the per packet flag smb_flag FLAG_CASELESS_PATHNAMES is taken into account per packet. This allows the linux CIFS client to use Samba in a case sensitive manner. Additional command in smbclient "case_sensitive", toggles the flag in subsequent packets. Docs to follow. Jeremy. (This used to be commit cf84c0fe1a061acc0313f7db124b8f947cdf623d)
-rw-r--r--source3/client/client.c16
-rw-r--r--source3/include/client.h1
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/libsmb/clientgen.c19
-rw-r--r--source3/param/loadparm.c26
-rw-r--r--source3/smbd/blocking.c2
-rw-r--r--source3/smbd/conn.c2
-rw-r--r--source3/smbd/negprot.c19
-rw-r--r--source3/smbd/notify_hash.c2
-rw-r--r--source3/smbd/process.c2
-rw-r--r--source3/smbd/server.c10
-rw-r--r--source3/smbd/service.c27
-rw-r--r--source3/torture/vfstest.c2
13 files changed, 98 insertions, 33 deletions
diff --git a/source3/client/client.c b/source3/client/client.c
index 63d73c2d4c..ea8ec93f97 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -1869,6 +1869,21 @@ static int cmd_lowercase(void)
}
/****************************************************************************
+ Toggle the case sensitive flag.
+****************************************************************************/
+
+static int cmd_setcase(void)
+{
+ BOOL orig_case_sensitive = cli_set_case_sensitive(cli, False);
+
+ cli_set_case_sensitive(cli, !orig_case_sensitive);
+ DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
+ "on":"off"));
+
+ return 0;
+}
+
+/****************************************************************************
Toggle the recurse flag.
****************************************************************************/
@@ -2179,6 +2194,7 @@ static struct
{"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
{"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
{"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
+ {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
{"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
{"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
{"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
diff --git a/source3/include/client.h b/source3/include/client.h
index 968b73f0b4..52a6c76299 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -153,6 +153,7 @@ struct cli_state {
BOOL (*oplock_handler)(struct cli_state *cli, int fnum, unsigned char level);
BOOL force_dos_errors;
+ BOOL case_sensitive; /* False by default. */
/* was this structure allocated by cli_initialise? If so, then
free in cli_shutdown() */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 9100701e21..a802e96226 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1349,7 +1349,8 @@ enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS};
enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, LDAP_PASSWD_SYNC_ONLY};
/* Remote architectures we know about. */
-enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_SAMBA};
+enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
+ RA_WIN2K, RA_WINXP, RA_WIN2K3, RA_SAMBA, RA_CIFSFS};
/* case handling */
enum case_handling {CASE_LOWER,CASE_UPPER};
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index b75d6be0a6..281ee3af84 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -176,7 +176,12 @@ void cli_setup_packet(struct cli_state *cli)
SSVAL(cli->outbuf,smb_mid,cli->mid);
if (cli->protocol > PROTOCOL_CORE) {
uint16 flags2;
- SCVAL(cli->outbuf,smb_flg,0x8);
+ if (cli->case_sensitive) {
+ SCVAL(cli->outbuf,smb_flg,0x0);
+ } else {
+ /* Default setting, case insensitive. */
+ SCVAL(cli->outbuf,smb_flg,0x8);
+ }
flags2 = FLAGS2_LONG_PATH_COMPONENTS;
if (cli->capabilities & CAP_UNICODE)
flags2 |= FLAGS2_UNICODE_STRINGS;
@@ -273,6 +278,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli->outbuf = (char *)malloc(cli->bufsize+SAFETY_MARGIN);
cli->inbuf = (char *)malloc(cli->bufsize+SAFETY_MARGIN);
cli->oplock_handler = cli_oplock_ack;
+ cli->case_sensitive = False;
cli->use_spnego = lp_client_use_spnego();
@@ -441,6 +447,17 @@ uint16 cli_setpid(struct cli_state *cli, uint16 pid)
}
/****************************************************************************
+ Set the case sensitivity flag on the packets. Returns old state.
+****************************************************************************/
+
+BOOL cli_set_case_sensitive(struct cli_state *cli, BOOL case_sensitive)
+{
+ BOOL ret = cli->case_sensitive;
+ cli->case_sensitive = case_sensitive;
+ return ret;
+}
+
+/****************************************************************************
Send a keepalive packet to the server
****************************************************************************/
BOOL cli_send_keepalive(struct cli_state *cli)
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 03b86a9c18..5e959dbba3 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -364,7 +364,7 @@ typedef struct
int iBlock_size;
BOOL bPreexecClose;
BOOL bRootpreexecClose;
- BOOL bCaseSensitive;
+ int iCaseSensitive;
BOOL bCasePreserve;
BOOL bShortCasePreserve;
BOOL bHideDotFiles;
@@ -487,7 +487,7 @@ static service sDefault = {
1024, /* iBlock_size */
False, /* bPreexecClose */
False, /* bRootpreexecClose */
- False, /* case sensitive */
+ Auto, /* case sensitive */
True, /* case preserve */
True, /* short case preserve */
True, /* bHideDotFiles */
@@ -980,8 +980,8 @@ static struct parm_struct parm_table[] = {
{"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED},
{"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE},
- {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
- {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE},
+ {"case sensitive", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"casesignames", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE},
{"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
@@ -1836,7 +1836,7 @@ FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
-FN_LOCAL_BOOL(lp_casesensitive, bCaseSensitive)
+FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
@@ -2997,10 +2997,8 @@ static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue
{
int i;
- for (i = 0; parm->enum_list[i].name; i++)
- {
- if ( strequal(pszParmValue, parm->enum_list[i].name))
- {
+ for (i = 0; parm->enum_list[i].name; i++) {
+ if ( strequal(pszParmValue, parm->enum_list[i].name)) {
*ptr = parm->enum_list[i].value;
break;
}
@@ -3870,11 +3868,12 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
/* get the username for substituion -- preference to the current_user_info */
- if ( strlen( current_user_info.smb_name ) != 0 )
+ if ( strlen( current_user_info.smb_name ) != 0 ) {
username = current_user_info.smb_name;
- else
+ } else {
username = sub_get_smb_name();
-
+ }
+
standard_sub_basic( username, n2,sizeof(n2) );
add_to_file_list(pszFname, n2);
@@ -3889,8 +3888,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
init_globals();
debug_init();
- if (save_defaults)
- {
+ if (save_defaults) {
init_locals();
lp_save_defaults();
}
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index c0512d5539..3983a4cbdf 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -680,7 +680,7 @@ void process_blocking_lock_queue(time_t t)
continue;
}
- if(!set_current_service(conn,True)) {
+ if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
/*
* Remove the entry and return an error to the client.
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index e083e14426..34e19a3ca6 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -161,7 +161,7 @@ void conn_close_all(void)
connection_struct *conn, *next;
for (conn=Connections;conn;conn=next) {
next=conn->next;
- set_current_service(conn, True);
+ set_current_service(conn, 0, True);
close_cnum(conn, conn->vuid);
}
}
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 1843c174bb..5ff53f6300 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -401,8 +401,9 @@ protocol [LANMAN2.1]
#define ARCH_WIN2K 0xC /* Win2K is like NT */
#define ARCH_OS2 0x14 /* Again OS/2 is like NT */
#define ARCH_SAMBA 0x20
+#define ARCH_CIFSFS 0x40
-#define ARCH_ALL 0x3F
+#define ARCH_ALL 0x7F
/* List of supported protocols, most desired first */
static const struct {
@@ -413,6 +414,7 @@ static const struct {
} supported_protocols[] = {
{"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
{"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"POSIX 2", "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},
@@ -460,7 +462,7 @@ int reply_negprot(connection_struct *conn,
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 );
+ arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
else if (strcsequal(p,"LANMAN2.1"))
arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
else if (strcsequal(p,"LM1.2X002"))
@@ -472,12 +474,23 @@ int reply_negprot(connection_struct *conn,
else if (strcsequal(p,"Samba")) {
arch = ARCH_SAMBA;
break;
+ } else if (strcsequal(p,"POSIX 2")) {
+ arch = ARCH_CIFSFS;
+ break;
}
p += strlen(p) + 2;
}
-
+
+ /* CIFSFS can send one arch only, NT LM 0.12. */
+ if (Index == 1 && (arch & ARCH_CIFSFS)) {
+ arch = ARCH_CIFSFS;
+ }
+
switch ( arch ) {
+ case ARCH_CIFSFS:
+ set_remote_arch(RA_CIFSFS);
+ break;
case ARCH_SAMBA:
set_remote_arch(RA_SAMBA);
break;
diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c
index ec414454f9..843580f6ed 100644
--- a/source3/smbd/notify_hash.c
+++ b/source3/smbd/notify_hash.c
@@ -164,7 +164,7 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,
if (!change_to_user(conn,vuid))
return True;
- if (!set_current_service(conn,True)) {
+ if (!set_current_service(conn,FLAG_CASELESS_PATHNAMES,True)) {
change_to_root_user();
return True;
}
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 05e4d0b1d9..72a604811b 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -934,7 +934,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
return(ERROR_DOS(ERRSRV,ERRaccess));
/* load service specific parameters */
- if (conn && !set_current_service(conn,(flags & (AS_USER|DO_CHDIR)?True:False)))
+ if (conn && !set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False)))
return(ERROR_DOS(ERRSRV,ERRaccess));
/* does this protocol need to be run as guest? */
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 343a835be8..c3e0da542e 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -494,18 +494,16 @@ BOOL reload_services(BOOL test)
load_interfaces();
- {
- if (smbd_server_fd() != -1) {
- set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
- set_socket_options(smbd_server_fd(), user_socket_options);
- }
+ if (smbd_server_fd() != -1) {
+ set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
+ set_socket_options(smbd_server_fd(), user_socket_options);
}
mangle_reset_cache();
reset_stat_cache();
/* this forces service parameters to be flushed */
- set_current_service(NULL,True);
+ set_current_service(NULL,0,True);
return(ret);
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 192a043bf5..3b499d5cc1 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -28,10 +28,11 @@ extern userdom_struct current_user_info;
Load parameters specific to a connection/service.
****************************************************************************/
-BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
+BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
{
extern char magic_char;
static connection_struct *last_conn;
+ static uint16 last_flags;
int snum;
if (!conn) {
@@ -51,10 +52,24 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
return(False);
}
- if (conn == last_conn)
+ if ((conn == last_conn) && (last_flags == flags)) {
return(True);
+ }
last_conn = conn;
+ last_flags = flags;
+
+ /* Obey the client case sensitivity requests - only for clients that support it. */
+ if (lp_casesensitive(snum) == Auto) {
+ /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
+ enum remote_arch_types ra_type = get_remote_arch();
+ if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
+ /* Client can't support per-packet case sensitive pathnames. */
+ conn->case_sensitive = False;
+ } else {
+ conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
+ }
+ }
magic_char = lp_magicchar(snum);
return(True);
@@ -347,7 +362,13 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->dirptr = NULL;
/* Case options for the share. */
- conn->case_sensitive = lp_casesensitive(snum);
+ if (lp_casesensitive(snum) == Auto) {
+ /* We will be setting this per packet. Set to be case insensitive for now. */
+ conn->case_sensitive = False;
+ } else {
+ conn->case_sensitive = (BOOL)lp_casesensitive(snum);
+ }
+
conn->case_preserve = lp_preservecase(snum);
conn->short_case_preserve = lp_shortpreservecase(snum);
diff --git a/source3/torture/vfstest.c b/source3/torture/vfstest.c
index 88fe348649..48556aa257 100644
--- a/source3/torture/vfstest.c
+++ b/source3/torture/vfstest.c
@@ -466,7 +466,7 @@ BOOL reload_services(BOOL test)
reset_stat_cache();
/* this forces service parameters to be flushed */
- set_current_service(NULL,True);
+ set_current_service(NULL,0,True);
return (ret);
}