]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
[CIFS] Fix allocation of buffers for new session setup routine to allow
authorSteve French <sfrench@us.ibm.com>
Tue, 27 Jun 2006 06:28:30 +0000 (06:28 +0000)
committerSteve French <sfrench@us.ibm.com>
Tue, 27 Jun 2006 06:28:30 +0000 (06:28 +0000)
longer user and domain names and allow passing sec options on mount

Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/sess.c

index 79a202b8f66ab64ede3a4bc4c1e55322c43a4a26..a61d17ed1827e3552a6808a8f705fdd2281d7fe4 100644 (file)
@@ -7,7 +7,8 @@ so we can do search (ls etc.) to OS/2.  Do not send NTCreateX
 or recent levels of FindFirst unless server says it supports NT SMBs
 (instead use legacy equivalents from LANMAN dialect). Fix to allow
 NTLMv2 authentication support (now can use stronger password hashing
-on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004)
+on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
+Allow override of global cifs security flags on mount via "sec=" option(s).
 
 Version 1.43
 ------------
index 46c2cfa5acf3aea97a9e7387c6c0a11c6ffe5686..7986d0d97ace4f97b3b3d10b0800d03fcaabb631 100644 (file)
@@ -443,7 +443,10 @@ A partial list of the supported mount options follows:
                SFU does).  In the future the bottom 9 bits of the mode
                mode also will be emulated using queries of the security
                descriptor (ACL).
-sec            Security mode.  Allowed values are:
+ sign           Must use packet signing (helps avoid unwanted data modification
+               by intermediate systems in the route).  Note that signing
+               does not work with lanman or plaintext authentication.
+ sec            Security mode.  Allowed values are:
                        none    attempt to connection as a null user (no name)
                        krb5    Use Kerberos version 5 authentication
                        krb5i   Use Kerberos authentication and packet signing
index 87453a6bcaf838ca15c892fba91bd4a8c780514e..6d7cf5f3bc0bdb3549b7e038fdd099ada89bee3c 100644 (file)
@@ -186,6 +186,7 @@ struct cifsSesInfo {
        struct TCP_Server_Info *server; /* pointer to server info */
        atomic_t inUse; /* # of mounts (tree connections) on this ses */
        enum statusEnum status;
+       unsigned overrideSecFlg;  /* if non-zero override global sec flags */
        __u16 ipc_tid;          /* special tid for connection to IPC share */
        __u16 flags;
        char *serverOS;         /* name of operating system underlying server */
index 38f83db207643bcadb2efbb33f9191797e7939af..de405bfb67d2ec7d7f0c5d0f2a10f77d495797bb 100644 (file)
@@ -396,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;
@@ -407,9 +408,16 @@ 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;
+
        pSMB->hdr.Mid = GetNextMid(server);
        pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
-       if((extended_security & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+       if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
                pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
        
        count = 0;
@@ -439,8 +447,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                        && (pSMBr->DialectIndex == LANMAN_PROT)) {
                struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
 
-               if((extended_security & CIFSSEC_MAY_LANMAN) || 
-                       (extended_security & CIFSSEC_MAY_PLNTXT))
+               if((secFlags & CIFSSEC_MAY_LANMAN) || 
+                       (secFlags & CIFSSEC_MAY_PLNTXT))
                        server->secType = LANMAN;
                else {
                        cERROR(1, ("mount failed weak security disabled"
@@ -498,12 +506,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
        if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
-               if ((extended_security & CIFSSEC_MAY_PLNTXT) == 0)
+               if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
 #endif /* CIFS_WEAK_PW_HASH */
                        cERROR(1,("Server requests plain text password"
                                  " but client support disabled"));
 
-       if(extended_security & CIFSSEC_MUST_NTLMV2)
+       if(secFlags & CIFSSEC_MUST_NTLMV2)
                server->secType = NTLMv2;
        else
                server->secType = NTLM;
index c0f98ddea88cf6987f9000ed1173cc60aa9f1d08..876eb9ef85fecd83ae57042b2114cdd3b8355e00 100644 (file)
@@ -915,32 +915,32 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                                cERROR(1,("no security value specified"));
                                 continue;
                         } else if (strnicmp(value, "krb5i", 5) == 0) {
-                               vol->secFlg = CIFSSEC_MAY_KRB5 | 
+                               vol->secFlg |= CIFSSEC_MAY_KRB5 | 
                                        CIFSSEC_MUST_SIGN;
                        } else if (strnicmp(value, "krb5p", 5) == 0) {
-                               /* vol->secFlg = CIFSSEC_MUST_SEAL | 
+                               /* vol->secFlg |= CIFSSEC_MUST_SEAL | 
                                        CIFSSEC_MAY_KRB5; */ 
                                cERROR(1,("Krb5 cifs privacy not supported"));
                                return 1;
                        } else if (strnicmp(value, "krb5", 4) == 0) {
-                               vol->secFlg = CIFSSEC_MAY_KRB5;
+                               vol->secFlg |= CIFSSEC_MAY_KRB5;
                        } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
-                               vol->secFlg = CIFSSEC_MAY_NTLMV2 |
+                               vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
                                        CIFSSEC_MUST_SIGN;
                        } else if (strnicmp(value, "ntlmv2", 6) == 0) {
-                               vol->secFlg = CIFSSEC_MAY_NTLMV2;
+                               vol->secFlg |= CIFSSEC_MAY_NTLMV2;
                        } else if (strnicmp(value, "ntlmi", 5) == 0) {
-                               vol->secFlg = CIFSSEC_MAY_NTLM |
+                               vol->secFlg |= CIFSSEC_MAY_NTLM |
                                        CIFSSEC_MUST_SIGN;
                        } else if (strnicmp(value, "ntlm", 4) == 0) {
                                /* ntlm is default so can be turned off too */
-                               vol->secFlg = CIFSSEC_MAY_NTLM;
+                               vol->secFlg |= CIFSSEC_MAY_NTLM;
                        } else if (strnicmp(value, "nontlm", 6) == 0) {
                                /* BB is there a better way to do this? */
-                               vol->secFlg = CIFSSEC_MAY_NTLMV2;
+                               vol->secFlg |= CIFSSEC_MAY_NTLMV2;
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
                        } else if (strnicmp(value, "lanman", 6) == 0) {
-                                vol->secFlg = CIFSSEC_MAY_LANMAN;
+                                vol->secFlg |= CIFSSEC_MAY_LANMAN;
 #endif
                        } else if (strnicmp(value, "none", 4) == 0) {
                                vol->nullauth = 1;
@@ -1173,6 +1173,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                        vol->no_psx_acl = 0;
                } else if (strnicmp(data, "noacl",5) == 0) {
                        vol->no_psx_acl = 1;
+               } else if (strnicmp(data, "sign",4) == 0) {
+                       vol->secFlg |= CIFSSEC_MUST_SIGN;
+/*             } else if (strnicmp(data, "seal",4) == 0) {
+                       vol->secFlg |= CIFSSEC_MUST_SEAL; */
                } else if (strnicmp(data, "direct",6) == 0) {
                        vol->direct_io = 1;
                } else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1776,6 +1780,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                                                volume_info.domainname);
                        }
                        pSesInfo->linux_uid = volume_info.linux_uid;
+                       pSesInfo->overrideSecFlg = volume_info.secFlg;
                        down(&pSesInfo->sesSem);
                        /* BB FIXME need to pass vol->secFlgs BB */
                        rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
index 70e32a81c213e0267dd3fc76a3d83f479e493c5f..7737edd1baf1a2ace5eeb50c7ef0bf041504a461 100644 (file)
@@ -138,7 +138,7 @@ static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
                 strncpy(bcc_ptr, ses->userName, 300);
         }
        /* BB improve check for overflow */
-        bcc_ptr += strnlen(ses->userName, 200);
+        bcc_ptr += strnlen(ses->userName, 300);
        *bcc_ptr = 0;
         bcc_ptr++; /* account for null termination */
 
@@ -313,11 +313,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
        int wct;
        struct smb_hdr *smb_buf;
        char *bcc_ptr;
+       char *str_area;
        SESSION_SETUP_ANDX *pSMB;
        __u32 capabilities;
        int count;
        int resp_buf_type = 0;
-       struct kvec iov[2];  /* BB split variable length info into 2nd iovec */
+       struct kvec iov[2];
        enum securityEnum type;
        __u16 action;
        int bytes_remaining;
@@ -351,7 +352,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
        pSMB = (SESSION_SETUP_ANDX *)smb_buf;
 
        capabilities = cifs_ssetup_hdr(ses, pSMB);
-       bcc_ptr = pByteArea(smb_buf);
+
+       /* we will send the SMB in two pieces,
+       a fixed length beginning part, and a
+       second part which will include the strings
+       and rest of bcc area, in order to avoid having
+       to do a large buffer 17K allocation */
+        iov[0].iov_base = (char *)pSMB;
+        iov[0].iov_len = smb_buf->smb_buf_length + 4;
+
+       /* 2000 big enough to fit max user, domain, NOS name etc. */
+       str_area = kmalloc(2000, GFP_KERNEL);
+       bcc_ptr = str_area;
 
        if(type == LANMAN) {
 #ifdef CONFIG_CIFS_WEAK_PW_HASH
@@ -365,10 +377,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
 
                calc_lanman_hash(ses, lnm_session_key);
 
-#ifdef CONFIG_CIFS_DEBUG2
+/* #ifdef CONFIG_CIFS_DEBUG2
                cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
                        CIFS_SESS_KEY_SIZE);
-#endif
+#endif */
                memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
                bcc_ptr += CIFS_SESS_KEY_SIZE;
 
@@ -377,7 +389,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
                changed to do higher than lanman dialect and
                we reconnected would we ever calc signing_key? */
 
-               cERROR(1,("Negotiating LANMAN setting up strings"));
+               cFYI(1,("Negotiating LANMAN setting up strings"));
                /* Unicode not allowed for LANMAN dialects */
                ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
 #endif    
@@ -396,7 +408,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
 
                if(first_time) /* should this be moved into common code 
                                  with similar ntlmv2 path? */
-                       cifs_calculate_mac_key( ses->server->mac_signing_key,
+                       cifs_calculate_mac_key(ses->server->mac_signing_key,
                                ntlm_session_key, ses->password);
                /* copy session key */
 
@@ -454,23 +466,14 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
                /* BB set password lengths */
        }
 
-       count = (long) bcc_ptr - (long) pByteArea(smb_buf);
+       count = (long) bcc_ptr - (long) str_area;
        smb_buf->smb_buf_length += count;
 
-       /* if we switch to small buffers, count will need to be fewer
-          than 383 (strings less than 335 bytes) */
-
        BCC_LE(smb_buf) = cpu_to_le16(count);
 
-
-       /* BB FIXME check for other non ntlm code paths */
-
-       /* BB check is this too big for a small smb? */
-
-       iov[0].iov_base = (char *)pSMB;
-       iov[0].iov_len = smb_buf->smb_buf_length + 4;
-
-       rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
+       iov[1].iov_base = str_area;
+       iov[1].iov_len = count; 
+       rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
        /* SMB request buf freed in SendReceive2 */
 
        cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
@@ -515,6 +518,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
                rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
        
 ssetup_exit:
+       kfree(str_area);
        if(resp_buf_type == CIFS_SMALL_BUFFER) {
                cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
                cifs_small_buf_release(iov[0].iov_base);