From 2acd0848663f28afedff9b11b738e048f5ead2cc Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Jun 2004 18:36:45 +0000 Subject: 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) --- source3/client/client.c | 16 ++++++++++++++++ source3/include/client.h | 1 + source3/include/smb.h | 3 ++- source3/libsmb/clientgen.c | 19 ++++++++++++++++++- source3/param/loadparm.c | 26 ++++++++++++-------------- source3/smbd/blocking.c | 2 +- source3/smbd/conn.c | 2 +- source3/smbd/negprot.c | 19 ++++++++++++++++--- source3/smbd/notify_hash.c | 2 +- source3/smbd/process.c | 2 +- source3/smbd/server.c | 10 ++++------ source3/smbd/service.c | 27 ++++++++++++++++++++++++--- source3/torture/vfstest.c | 2 +- 13 files changed, 98 insertions(+), 33 deletions(-) (limited to 'source3') 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 @@ -1868,6 +1868,21 @@ static int cmd_lowercase(void) return 0; } +/**************************************************************************** + 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,"\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 (default 20)",{COMPL_NONE,COMPL_NONE}}, {"cancel",cmd_cancel," 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," chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}}, {"chown",cmd_chown," 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(); @@ -440,6 +446,17 @@ uint16 cli_setpid(struct cli_state *cli, uint16 pid) return ret; } +/**************************************************************************** + 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 ****************************************************************************/ 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); } -- cgit