]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/cifs/cifssmb.c
Merge branch 'master' into upstream
[linux-2.6-omap-h63xx.git] / fs / cifs / cifssmb.c
index 6b5be6d59f07d86bd7043fb60724fb09d9602ab4..075d8fb3d37608a96d0610c519794388351d1173 100644 (file)
@@ -209,7 +209,6 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL  
 int
 small_smb_init_no_tc(const int smb_command, const int wct, 
                     struct cifsSesInfo *ses, void **request_buf)
@@ -235,7 +234,6 @@ small_smb_init_no_tc(const int smb_command, const int wct,
 
        return rc;
 }
-#endif  /* CONFIG_CIFS_EXPERIMENTAL */
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
@@ -398,6 +396,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        int i;
        struct TCP_Server_Info * server;
        u16 count;
+       unsigned int secFlags;
 
        if(ses->server)
                server = ses->server;
@@ -409,10 +408,19 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                      (void **) &pSMB, (void **) &pSMBr);
        if (rc)
                return rc;
+
+       /* if any of auth flags (ie not sign or seal) are overriden use them */
+       if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
+               secFlags = ses->overrideSecFlg;
+       else /* if override flags set only sign/seal OR them with global auth */
+               secFlags = extended_security | ses->overrideSecFlg;
+
+       cFYI(1,("secFlags 0x%x",secFlags));
+
        pSMB->hdr.Mid = GetNextMid(server);
        pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
-/*     if (extended_security)
-               pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;*/
+       if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+               pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
        
        count = 0;
        for(i=0;i<CIFS_NUM_PROT;i++) {
@@ -425,154 +433,175 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
        rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-       if (rc == 0) {
-               cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
-               /* Check wct = 1 error case */
-               if((pSMBr->hdr.WordCount < 13)  
-                       || (pSMBr->DialectIndex == BAD_PROT)) {
-                       /* core returns wct = 1, but we do not ask for
-                       core - otherwise it just comes when dialect
-                       index is -1 indicating we could not negotiate
-                       a common dialect */
+       if (rc != 0) 
+               goto neg_err_exit;
+
+       cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
+       /* Check wct = 1 error case */
+       if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
+               /* core returns wct = 1, but we do not ask for core - otherwise
+               small wct just comes when dialect index is -1 indicating we 
+               could not negotiate a common dialect */
+               rc = -EOPNOTSUPP;
+               goto neg_err_exit;
+#ifdef CONFIG_CIFS_WEAK_PW_HASH 
+       } else if((pSMBr->hdr.WordCount == 13)
+                       && (pSMBr->DialectIndex == LANMAN_PROT)) {
+               struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
+
+               if((secFlags & CIFSSEC_MAY_LANMAN) || 
+                       (secFlags & CIFSSEC_MAY_PLNTXT))
+                       server->secType = LANMAN;
+               else {
+                       cERROR(1, ("mount failed weak security disabled"
+                                  " in /proc/fs/cifs/SecurityFlags"));
                        rc = -EOPNOTSUPP;
                        goto neg_err_exit;
-               } else if((pSMBr->hdr.WordCount == 13) && 
-                       (pSMBr->DialectIndex == LANMAN_PROT)) {
-#ifdef CONFIG_CIFS_WEAK_PW_HASH
-                       struct lanman_neg_rsp * rsp = 
-                               (struct lanman_neg_rsp *)pSMBr;
-
-                       if((extended_security & CIFSSEC_MAY_LANMAN) || 
-                               (extended_security & CIFSSEC_MAY_PLNTXT))
-                               server->secType = LANMAN;
-                       else {
-                               cERROR(1, ("mount failed weak security disabled"
-                                       " in /proc/fs/cifs/SecurityFlags"));
-                               rc = -EOPNOTSUPP;
-                               goto neg_err_exit;
-                       }       
-                       server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
-                       server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
-                       server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
+               }       
+               server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
+               server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
+               server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
                                (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+               GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
+               /* even though we do not use raw we might as well set this
+               accurately, in case we ever find a need for it */
+               if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
+                       server->maxRw = 0xFF00;
+                       server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
+               } else {
+                       server->maxRw = 0;/* we do not need to use raw anyway */
+                       server->capabilities = CAP_MPX_MODE;
+               }
+               server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
 
-                       /* BB what do we do with raw mode? BB */
-                       server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
-                       /* Do we have to set signing flags? no signing
-                       was available LANMAN - default should be ok */
-
-                       /* BB FIXME set default dummy capabilities since
-                       they are not returned by the server in this dialect */
-
-                       /* get server time for time conversions and add
-                       code to use it and timezone since this is not UTC */    
+               /* BB get server time for time conversions and add
+               code to use it and timezone since this is not UTC */    
 
-                       if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-                               memcpy(server->cryptKey, rsp->EncryptionKey,
-                                       CIFS_CRYPTO_KEY_SIZE);
-                       } else {
-                               rc = -EIO;
-                               goto neg_err_exit;
-                       }
+               if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
+                       memcpy(server->cryptKey, rsp->EncryptionKey,
+                               CIFS_CRYPTO_KEY_SIZE);
+               } else if (server->secMode & SECMODE_PW_ENCRYPT) {
+                       rc = -EIO; /* need cryptkey unless plain text */
+                       goto neg_err_exit;
+               }
 
-                       cFYI(1,("LANMAN negotiated")); /* BB removeme BB */
+               cFYI(1,("LANMAN negotiated"));
+               /* we will not end up setting signing flags - as no signing
+               was in LANMAN and server did not return the flags on */
+               goto signing_check;
 #else /* weak security disabled */
-                       cERROR(1,("mount failed, cifs module not built with "
-                               "CIFS_WEAK_PW_HASH support"));
+       } else if(pSMBr->hdr.WordCount == 13) {
+               cERROR(1,("mount failed, cifs module not built "
+                         "with CIFS_WEAK_PW_HASH support"));
                        rc = -EOPNOTSUPP;
 #endif /* WEAK_PW_HASH */
-                       goto neg_err_exit;
-               } else if(pSMBr->hdr.WordCount != 17) {
-                       /* unknown wct */
-                       rc = -EOPNOTSUPP;
-                       goto neg_err_exit;
-               }
+               goto neg_err_exit;
+       } else if(pSMBr->hdr.WordCount != 17) {
+               /* unknown wct */
+               rc = -EOPNOTSUPP;
+               goto neg_err_exit;
+       }
+       /* else wct == 17 NTLM */
+       server->secMode = pSMBr->SecurityMode;
+       if((server->secMode & SECMODE_USER) == 0)
+               cFYI(1,("share mode security"));
 
-               server->secMode = pSMBr->SecurityMode;
-               if((server->secMode & SECMODE_USER) == 0)
-                       cFYI(1,("share mode security"));
-               
-               if(extended_security & CIFSSEC_MUST_NTLMV2)
-                       server->secType = NTLMv2;
-               else
-                       server->secType = NTLM;
-               /* else krb5 ... */
-
-               /* one byte - no need to convert this or EncryptionKeyLen
-                  from little endian */
-               server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
-               /* probably no need to store and check maxvcs */
-               server->maxBuf =
-                       min(le32_to_cpu(pSMBr->MaxBufferSize),
+       if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+               if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
+#endif /* CIFS_WEAK_PW_HASH */
+                       cERROR(1,("Server requests plain text password"
+                                 " but client support disabled"));
+
+       if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
+               server->secType = NTLMv2;
+       else if(secFlags & CIFSSEC_MAY_NTLM)
+               server->secType = NTLM;
+       else if(secFlags & CIFSSEC_MAY_NTLMV2)
+               server->secType = NTLMv2;
+       /* else krb5 ... any others ... */
+
+       /* one byte, so no need to convert this or EncryptionKeyLen from
+          little endian */
+       server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+       /* probably no need to store and check maxvcs */
+       server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
                        (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
-               server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
-               cFYI(0, ("Max buf = %d", ses->server->maxBuf));
-               GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
-               server->capabilities = le32_to_cpu(pSMBr->Capabilities);
-               server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
-        /* BB with UTC do we ever need to be using srvr timezone? */
-               if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-                       memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
-                              CIFS_CRYPTO_KEY_SIZE);
-               } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
-                          && (pSMBr->EncryptionKeyLength == 0)) {
-                       /* decode security blob */
-               } else
-                       rc = -EIO;
+       server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+       cFYI(0, ("Max buf = %d", ses->server->maxBuf));
+       GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
+       server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+       server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
+       if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+               memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+                      CIFS_CRYPTO_KEY_SIZE);
+       } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
+                       && (pSMBr->EncryptionKeyLength == 0)) {
+               /* decode security blob */
+       } else if (server->secMode & SECMODE_PW_ENCRYPT) {
+               rc = -EIO; /* no crypt key only if plain text pwd */
+               goto neg_err_exit;
+       }
 
-               /* BB might be helpful to save off the domain of server here */
+       /* BB might be helpful to save off the domain of server here */
 
-               if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
-                       (server->capabilities & CAP_EXTENDED_SECURITY)) {
-                       count = pSMBr->ByteCount;
-                       if (count < 16)
-                               rc = -EIO;
-                       else if (count == 16) {
-                               server->secType = RawNTLMSSP;
-                               if (server->socketUseCount.counter > 1) {
-                                       if (memcmp
-                                               (server->server_GUID,
-                                               pSMBr->u.extended_response.
-                                               GUID, 16) != 0) {
-                                               cFYI(1, ("server UID changed"));
-                                               memcpy(server->
-                                                       server_GUID,
-                                                       pSMBr->u.
-                                                       extended_response.
-                                                       GUID, 16);
-                                       }
-                               } else
+       if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+               (server->capabilities & CAP_EXTENDED_SECURITY)) {
+               count = pSMBr->ByteCount;
+               if (count < 16)
+                       rc = -EIO;
+               else if (count == 16) {
+                       server->secType = RawNTLMSSP;
+                       if (server->socketUseCount.counter > 1) {
+                               if (memcmp(server->server_GUID,
+                                          pSMBr->u.extended_response.
+                                          GUID, 16) != 0) {
+                                       cFYI(1, ("server UID changed"));
                                        memcpy(server->server_GUID,
-                                              pSMBr->u.extended_response.
-                                              GUID, 16);
-                       } else {
-                               rc = decode_negTokenInit(pSMBr->u.
-                                                        extended_response.
-                                                        SecurityBlob,
-                                                        count - 16,
-                                                        &server->secType);
-                               if(rc == 1) {
-                               /* BB Need to fill struct for sessetup here */
-                                       rc = -EOPNOTSUPP;
-                               } else {
-                                       rc = -EINVAL;
+                                               pSMBr->u.extended_response.GUID,
+                                               16);
                                }
+                       } else
+                               memcpy(server->server_GUID,
+                                      pSMBr->u.extended_response.GUID, 16);
+               } else {
+                       rc = decode_negTokenInit(pSMBr->u.extended_response.
+                                                SecurityBlob,
+                                                count - 16,
+                                                &server->secType);
+                       if(rc == 1) {
+                       /* BB Need to fill struct for sessetup here */
+                               rc = -EOPNOTSUPP;
+                       } else {
+                               rc = -EINVAL;
                        }
-               } else
-                       server->capabilities &= ~CAP_EXTENDED_SECURITY;
-               if(sign_CIFS_PDUs == FALSE) {        
-                       if(server->secMode & SECMODE_SIGN_REQUIRED)
-                               cERROR(1,
-                                ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
-                       server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
-               } else if(sign_CIFS_PDUs == 1) {
-                       if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
-                               server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
                }
-                               
+       } else
+               server->capabilities &= ~CAP_EXTENDED_SECURITY;
+
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+signing_check:
+#endif
+       if(sign_CIFS_PDUs == FALSE) {        
+               if(server->secMode & SECMODE_SIGN_REQUIRED)
+                       cERROR(1,("Server requires "
+                                "/proc/fs/cifs/PacketSigningEnabled to be on"));
+               server->secMode &= 
+                       ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+       } else if(sign_CIFS_PDUs == 1) {
+               if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
+                       server->secMode &= 
+                               ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+       } else if(sign_CIFS_PDUs == 2) {
+               if((server->secMode & 
+                       (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
+                       cERROR(1,("signing required but server lacks support"));
+               }
        }
 neg_err_exit:  
        cifs_buf_release(pSMB);
+
+       cFYI(1,("negprot rc %d",rc));
        return rc;
 }
 
@@ -1431,8 +1460,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        pSMB->hdr.smb_buf_length += count;
        pSMB->ByteCount = cpu_to_le16(count);
 
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+       if (waitFlag) {
+               rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+                       (struct smb_hdr *) pSMBr, &bytes_returned);
+       } else {
+               rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+       }
        cifs_stats_inc(&tcon->num_locks);
        if (rc) {
                cFYI(1, ("Send error in Lock = %d", rc));
@@ -1455,6 +1489,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        char *data_offset;
        struct cifs_posix_lock *parm_data;
        int rc = 0;
+       int timeout = 0;
        int bytes_returned = 0;
        __u16 params, param_offset, offset, byte_count, count;
 
@@ -1474,7 +1509,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
-       pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
        param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
        offset = param_offset + params;
@@ -1500,8 +1534,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                        (((char *) &pSMB->hdr.Protocol) + offset);
 
        parm_data->lock_type = cpu_to_le16(lock_type);
-       if(waitFlag)
+       if(waitFlag) {
+               timeout = 3;  /* blocking operation, no timeout */
                parm_data->lock_flags = cpu_to_le16(1);
+               pSMB->Timeout = cpu_to_le32(-1);
+       } else
+               pSMB->Timeout = 0;
+
        parm_data->pid = cpu_to_le32(current->tgid);
        parm_data->start = cpu_to_le64(pLockData->fl_start);
        parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
@@ -1512,8 +1551,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
        pSMB->ByteCount = cpu_to_le16(byte_count);
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                       (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (waitFlag) {
+               rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+                       (struct smb_hdr *) pSMBr, &bytes_returned);
+       } else {
+               rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                       (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+       }
+
        if (rc) {
                cFYI(1, ("Send error in Posix Lock = %d", rc));
        } else if (get_flag) {