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/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 ++++++++++++++++++++++++--- 7 files changed, 48 insertions(+), 16 deletions(-) (limited to 'source3/smbd') 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); -- cgit