]> err.no Git - linux-2.6/blobdiff - fs/cifs/connect.c
Merge git://git.infradead.org/hdrcleanup-2.6
[linux-2.6] / fs / cifs / connect.c
index cf4bcf3a45e68e3d781576efe7fcfdf6822a5ccf..bae1479318d10fc6fd34a141a564aeb49252ba80 100644 (file)
@@ -630,7 +630,7 @@ multi_t2_fnd:
                                        smallbuf = NULL;
                        }
                        wake_up_process(task_to_wake);
-               } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
+               } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
                    && (isMultiRsp == FALSE)) {                          
                        cERROR(1, ("No task to wake, unknown frame rcvd!"));
                        cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                        rc = smb_send(*csocket, smb_buf, 0x44,
                                (struct sockaddr *)psin_server);
                        kfree(ses_init_buf);
+                       msleep(1); /* RFC1001 layer in at least one server 
+                                     requires very short break before negprot
+                                     presumably because not expecting negprot
+                                     to follow so fast.  This is a simple
+                                     solution that works without 
+                                     complicating the code and causes no
+                                     significant slowing down on mount
+                                     for everyone else */
                }
                /* else the negprot may still work without this 
                even though malloc failed */
@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                cifs_sb->tcon = tcon;
                tcon->ses = pSesInfo;
 
-               /* do not care if following two calls succeed - informational only */
+               /* do not care if following two calls succeed - informational */
                CIFSSMBQFSDeviceInfo(xid, tcon);
                CIFSSMBQFSAttributeInfo(xid, tcon);
+
                if (tcon->ses->capabilities & CAP_UNIX) {
                        if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
-                               if(!volume_info.no_psx_acl) {
-                                       if(CIFS_UNIX_POSIX_ACL_CAP & 
-                                          le64_to_cpu(tcon->fsUnixInfo.Capability))
-                                               cFYI(1,("server negotiated posix acl support"));
-                                               sb->s_flags |= MS_POSIXACL;
+                               __u64 cap = 
+                                      le64_to_cpu(tcon->fsUnixInfo.Capability);
+                               cap &= CIFS_UNIX_CAP_MASK;
+                               if(volume_info.no_psx_acl)
+                                       cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+                               else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
+                                       cFYI(1,("negotiated posix acl support"));
+                                       sb->s_flags |= MS_POSIXACL;
                                }
 
-                               /* Try and negotiate POSIX pathnames if we can. */
-                               if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
-                                   le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-                                       if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP))  {
-                                               cFYI(1,("negotiated posix pathnames support"));
-                                               cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
-                                       } else {
-                                               cFYI(1,("posix pathnames support requested but not supported"));
-                                       }
+                               if(volume_info.posix_paths == 0)
+                                       cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
+                               else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+                                       cFYI(1,("negotiate posix pathnames"));
+                                       cifs_sb->mnt_cifs_flags |= 
+                                               CIFS_MOUNT_POSIX_PATHS;
+                               }
+                                       
+                               cFYI(1,("Negotiate caps 0x%x",(int)cap));
+
+                               if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+                                       cFYI(1,("setting capabilities failed"));
                                }
                        }
                }
@@ -2133,6 +2148,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                               if(ses->serverOS)
+                                       kfree(ses->serverOS);
                                ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
                                if(ses->serverOS == NULL)
                                        goto sesssetup_nomem;
@@ -2145,6 +2162,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                if (remaining_words > 0) {
                                        len = UniStrnlen((wchar_t *)bcc_ptr,
                                                         remaining_words-1);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
@@ -2162,6 +2181,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (remaining_words > 0) {
                                                len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(2*(len+1),GFP_KERNEL);
                                                if(ses->serverDomain == NULL)
@@ -2172,15 +2193,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                ses->serverDomain[2*len] = 0;
                                                ses->serverDomain[1+(2*len)] = 0;
                                        } /* else no more room so create dummy domain string */
-                                       else
+                                       else {
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = 
                                                        kzalloc(2, GFP_KERNEL);
+                                       }
                                } else {        /* no room so create dummy domain and NOS string */
                                        /* if these kcallocs fail not much we
                                           can do, but better to not fail the
                                           sesssetup itself */
+                                       if(ses->serverDomain)
+                                               kfree(ses->serverDomain);
                                        ses->serverDomain =
                                            kzalloc(2, GFP_KERNEL);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS =
                                            kzalloc(2, GFP_KERNEL);
                                }
@@ -2189,6 +2217,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                if (((long) bcc_ptr + len) - (long)
                                    pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverOS == NULL)
                                                goto sesssetup_nomem;
@@ -2199,6 +2229,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
@@ -2208,6 +2240,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
+                                       if(ses->serverDomain)
+                                               kfree(ses->serverDomain);
                                        ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverDomain == NULL)
                                                goto sesssetup_nomem;
@@ -2412,6 +2446,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -2426,6 +2462,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                len = UniStrnlen((wchar_t *)bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -2439,7 +2477,9 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                remaining_words -= len + 1;
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
-                            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                     /* last string not null terminated (e.g.Windows XP/2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
                                                        cifs_strfromUCS_le(ses->serverDomain,
                                                             (__le16 *)bcc_ptr, 
@@ -2448,11 +2488,18 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                        ses->serverDomain[2*len] = 0;
                                                        ses->serverDomain[1+(2*len)] = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2,GFP_KERNEL);
-                                       } else {        /* no room so create dummy domain and NOS string */
+                                               }
+                                       } else {/* no room use dummy domain&NOS */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
@@ -2461,6 +2508,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (((long) bcc_ptr + len) - (long)
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverOS, bcc_ptr, len);
 
@@ -2469,6 +2518,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -2476,6 +2527,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -2713,6 +2766,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -2728,6 +2783,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                                 bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -2745,6 +2802,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2 *
                                                                    (len +
@@ -2762,13 +2821,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                                [1 + (2 * len)]
                                                            = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2,
                                                                    GFP_KERNEL);
+                                               }
                                        } else {        /* no room so create dummy domain and NOS string */
+                                               if(ses->serverDomain);
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2, GFP_KERNEL);
                                        }
@@ -2777,6 +2843,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                        if (((long) bcc_ptr + len) - (long)
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -2788,6 +2856,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -2797,6 +2867,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -3101,6 +3173,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -3116,6 +3190,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                 bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -3132,6 +3208,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
      /* last string not always null terminated (e.g. for Windows XP & 2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2 *
                                                                    (len +
@@ -3157,10 +3235,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                          len)]
                                                            = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain = kzalloc(2,GFP_KERNEL);
+                                               }
                                        } else {  /* no room so create dummy domain and NOS string */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
@@ -3168,6 +3253,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (((long) bcc_ptr + len) - 
                         (long) pByteArea(smb_buffer_response) 
                             <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverOS,bcc_ptr, len);
 
@@ -3176,6 +3263,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);  
                                                bcc_ptr += len;
@@ -3183,6 +3272,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -3267,7 +3358,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                bcc_ptr++; /* align */
        }
 
-       if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+       if(ses->server->secMode & 
+                       (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
        if (ses->capabilities & CAP_STATUS32) {
@@ -3279,8 +3371,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
                length =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
-               bcc_ptr += 2 * length;  /* convert num of 16 bit words to bytes */
+                   cifs_strtoUCS((__le16 *) bcc_ptr, tree, 
+                       6 /* max utf8 char length in bytes */ * 
+                       (/* server len*/ + 256 /* share len */), nls_codepage);
+               bcc_ptr += 2 * length;  /* convert num 16 bit words to bytes */
                bcc_ptr += 2;   /* skip trailing null */
        } else {                /* ASCII */
                strcpy(bcc_ptr, tree);
@@ -3432,6 +3526,12 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
                        pSesInfo->server->secMode,
                        pSesInfo->server->capabilities,
                        pSesInfo->server->timeZone));
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+               if(experimEnabled > 1)
+                       rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
+                                           &ntlmv2_flag, nls_info);    
+               else
+#endif
                if (extended_security
                                && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
                                && (pSesInfo->server->secType == NTLMSSP)) {