Thread (4 messages) 4 messages, 2 authors, 2021-08-17

Re: [PATCH 3/3] cifs: move functions that depend on DES to smp1ops.c

From: Steve French <smfrench@gmail.com>
Date: 2021-08-17 05:51:20

Fixed minor typo in patch 1 (<ctype.h>) and tentatively pushed all 3
to cifs-2.6.git for-next pending more testing and review

On Tue, Aug 17, 2021 at 12:25 AM Ronnie Sahlberg [off-list ref] wrote:
quoted hunk ↗ jump to hunk
Move all dependencies of DES into smb1ops.c
Make SMB1 support depend on CONFIG_LIB_DES

Signed-off-by: Ronnie Sahlberg <redacted>
---
 fs/cifs/Kconfig       |   3 +-
 fs/cifs/cifsencrypt.c |  39 ------
 fs/cifs/cifsproto.h   |   9 --
 fs/cifs/connect.c     | 162 ---------------------
 fs/cifs/ntlmssp.h     |   1 +
 fs/cifs/sess.c        |   5 +
 fs/cifs/smb1ops.c     | 319 ++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/smbencrypt.c  | 114 ---------------
 8 files changed, 326 insertions(+), 326 deletions(-)
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 7364950a9ef4..c01464476ba9 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -16,7 +16,6 @@ config CIFS
        select CRYPTO_GCM
        select CRYPTO_ECB
        select CRYPTO_AES
-       select CRYPTO_LIB_DES
        select KEYS
        select DNS_RESOLVER
        select ASN1
@@ -72,7 +71,7 @@ config CIFS_STATS2

 config CIFS_ALLOW_INSECURE_LEGACY
        bool "Support legacy servers which use less secure dialects"
-       depends on CIFS
+       depends on CIFS && CRYPTO_LIB_DES
        default y
        help
          Modern dialects, SMB2.1 and later (including SMB3 and 3.1.1), have
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 79572d18ad7a..7680e0a9bea3 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -250,45 +250,6 @@ int cifs_verify_signature(struct smb_rqst *rqst,

 }

-/* first calculate 24 bytes ntlm response and then 16 byte session key */
-int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
-{
-       int rc = 0;
-       unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
-       char temp_key[CIFS_SESS_KEY_SIZE];
-
-       if (!ses)
-               return -EINVAL;
-
-       ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
-       if (!ses->auth_key.response)
-               return -ENOMEM;
-
-       ses->auth_key.len = temp_len;
-
-       rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
-                       ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
-       if (rc) {
-               cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
-                        __func__, rc);
-               return rc;
-       }
-
-       rc = E_md4hash(ses->password, temp_key, nls_cp);
-       if (rc) {
-               cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
-                        __func__, rc);
-               return rc;
-       }
-
-       rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
-       if (rc)
-               cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
-                        __func__, rc);
-
-       return rc;
-}
-
 /* Build a proper attribute value/target info pairs blob.
  * Fill in netbios and dns domain name and workstation name
  * and client time (total five av pairs and + one end of fields indicator.
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e0def0f0714b..4a686048f1fa 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -296,10 +296,6 @@ extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
 extern int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required);
 extern int CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses);

-extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
-                   const char *tree, struct cifs_tcon *tcon,
-                   const struct nls_table *);
-
 extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon,
                const char *searchName, struct cifs_sb_info *cifs_sb,
                __u16 *searchHandle, __u16 search_flags,
@@ -498,9 +494,6 @@ extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
 extern int cifs_verify_signature(struct smb_rqst *rqst,
                                 struct TCP_Server_Info *server,
                                __u32 expected_sequence_number);
-extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
-                       const struct nls_table *);
-extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
 extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
 extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
 extern int calc_seckey(struct cifs_ses *);
@@ -550,8 +543,6 @@ extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
 extern int mdfour(unsigned char *, unsigned char *, int);
 extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
                        const struct nls_table *codepage);
-extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
-                       unsigned char *p24);

 extern int
 cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3781eee9360a..7dba7b59dd51 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3642,168 +3642,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
 }
 #endif

-/*
- * Issue a TREE_CONNECT request.
- */
-int
-CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
-        const char *tree, struct cifs_tcon *tcon,
-        const struct nls_table *nls_codepage)
-{
-       struct smb_hdr *smb_buffer;
-       struct smb_hdr *smb_buffer_response;
-       TCONX_REQ *pSMB;
-       TCONX_RSP *pSMBr;
-       unsigned char *bcc_ptr;
-       int rc = 0;
-       int length;
-       __u16 bytes_left, count;
-
-       if (ses == NULL)
-               return -EIO;
-
-       smb_buffer = cifs_buf_get();
-       if (smb_buffer == NULL)
-               return -ENOMEM;
-
-       smb_buffer_response = smb_buffer;
-
-       header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
-                       NULL /*no tid */ , 4 /*wct */ );
-
-       smb_buffer->Mid = get_next_mid(ses->server);
-       smb_buffer->Uid = ses->Suid;
-       pSMB = (TCONX_REQ *) smb_buffer;
-       pSMBr = (TCONX_RSP *) smb_buffer_response;
-
-       pSMB->AndXCommand = 0xFF;
-       pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
-       bcc_ptr = &pSMB->Password[0];
-       if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
-               pSMB->PasswordLength = cpu_to_le16(1);  /* minimum */
-               *bcc_ptr = 0; /* password is null byte */
-               bcc_ptr++;              /* skip password */
-               /* already aligned so no need to do it below */
-       } else {
-               pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
-               /* BB FIXME add code to fail this if NTLMv2 or Kerberos
-                  specified as required (when that support is added to
-                  the vfs in the future) as only NTLM or the much
-                  weaker LANMAN (which we do not send by default) is accepted
-                  by Samba (not sure whether other servers allow
-                  NTLMv2 password here) */
-#ifdef CONFIG_CIFS_WEAK_PW_HASH
-               if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
-                   (ses->sectype == LANMAN))
-                       calc_lanman_hash(tcon->password, ses->server->cryptkey,
-                                        ses->server->sec_mode &
-                                           SECMODE_PW_ENCRYPT ? true : false,
-                                        bcc_ptr);
-               else
-#endif /* CIFS_WEAK_PW_HASH */
-               rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
-                                       bcc_ptr, nls_codepage);
-               if (rc) {
-                       cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
-                                __func__, rc);
-                       cifs_buf_release(smb_buffer);
-                       return rc;
-               }
-
-               bcc_ptr += CIFS_AUTH_RESP_SIZE;
-               if (ses->capabilities & CAP_UNICODE) {
-                       /* must align unicode strings */
-                       *bcc_ptr = 0; /* null byte password */
-                       bcc_ptr++;
-               }
-       }
-
-       if (ses->server->sign)
-               smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
-       if (ses->capabilities & CAP_STATUS32) {
-               smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-       }
-       if (ses->capabilities & CAP_DFS) {
-               smb_buffer->Flags2 |= SMBFLG2_DFS;
-       }
-       if (ses->capabilities & CAP_UNICODE) {
-               smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-               length =
-                   cifs_strtoUTF16((__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);
-               bcc_ptr += strlen(tree) + 1;
-       }
-       strcpy(bcc_ptr, "?????");
-       bcc_ptr += strlen("?????");
-       bcc_ptr += 1;
-       count = bcc_ptr - &pSMB->Password[0];
-       be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
-       pSMB->ByteCount = cpu_to_le16(count);
-
-       rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
-                        0);
-
-       /* above now done in SendReceive */
-       if (rc == 0) {
-               bool is_unicode;
-
-               tcon->tidStatus = CifsGood;
-               tcon->need_reconnect = false;
-               tcon->tid = smb_buffer_response->Tid;
-               bcc_ptr = pByteArea(smb_buffer_response);
-               bytes_left = get_bcc(smb_buffer_response);
-               length = strnlen(bcc_ptr, bytes_left - 2);
-               if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
-                       is_unicode = true;
-               else
-                       is_unicode = false;
-
-
-               /* skip service field (NB: this field is always ASCII) */
-               if (length == 3) {
-                       if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
-                           (bcc_ptr[2] == 'C')) {
-                               cifs_dbg(FYI, "IPC connection\n");
-                               tcon->ipc = true;
-                               tcon->pipe = true;
-                       }
-               } else if (length == 2) {
-                       if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
-                               /* the most common case */
-                               cifs_dbg(FYI, "disk share connection\n");
-                       }
-               }
-               bcc_ptr += length + 1;
-               bytes_left -= (length + 1);
-               strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
-
-               /* mostly informational -- no need to fail on error here */
-               kfree(tcon->nativeFileSystem);
-               tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
-                                                     bytes_left, is_unicode,
-                                                     nls_codepage);
-
-               cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
-
-               if ((smb_buffer_response->WordCount == 3) ||
-                        (smb_buffer_response->WordCount == 7))
-                       /* field is in same location */
-                       tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
-               else
-                       tcon->Flags = 0;
-               cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
-       }
-
-       cifs_buf_release(smb_buffer);
-       return rc;
-}
-
 static void delayed_free(struct rcu_head *p)
 {
        struct cifs_sb_info *cifs_sb = container_of(p, struct cifs_sb_info, rcu);
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 378133ce8869..54f740c75be6 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -124,3 +124,4 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
 int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
                        struct cifs_ses *ses,
                        const struct nls_table *nls_cp);
+int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index c5785fd3f52e..34a990e1ae44 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -1061,6 +1061,8 @@ sess_auth_lanman(struct sess_data *sess_data)

 #endif

+
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
 static void
 sess_auth_ntlm(struct sess_data *sess_data)
 {
@@ -1170,6 +1172,7 @@ sess_auth_ntlm(struct sess_data *sess_data)
        kfree(ses->auth_key.response);
        ses->auth_key.response = NULL;
 }
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */

 static void
 sess_auth_ntlmv2(struct sess_data *sess_data)
@@ -1687,9 +1690,11 @@ static int select_sec(struct cifs_ses *ses, struct sess_data *sess_data)
 #else
                return -EOPNOTSUPP;
 #endif
+#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
        case NTLM:
                sess_data->func = sess_auth_ntlm;
                break;
+#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
        case NTLMv2:
                sess_data->func = sess_auth_ntlmv2;
                break;
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 5444cbc42043..c79d5bb2440d 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -6,6 +6,7 @@
  */

 #include <ctype.h>
+#include <linux/fips.h>
 #include <linux/pagemap.h>
 #include <linux/vfs.h>
 #include "cifsglob.h"
@@ -14,8 +15,103 @@
 #include "cifspdu.h"
 #include "cifs_unicode.h"
 #include "fs_context.h"
+#include "ntlmssp.h"
+
+#include <crypto/des.h>
+
+static void
+str_to_key(unsigned char *str, unsigned char *key)
+{
+       int i;
+
+       key[0] = str[0] >> 1;
+       key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
+       key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
+       key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
+       key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
+       key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
+       key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
+       key[7] = str[6] & 0x7F;
+       for (i = 0; i < 8; i++)
+               key[i] = (key[i] << 1);
+}
+
+static int
+smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
+{
+       unsigned char key2[8];
+       struct des_ctx ctx;
+
+       str_to_key(key, key2);
+
+       if (fips_enabled) {
+               cifs_dbg(VFS, "FIPS compliance enabled: DES not permitted\n");
+               return -ENOENT;
+       }
+
+       des_expand_key(&ctx, key2, DES_KEY_SIZE);
+       des_encrypt(&ctx, out, in);
+       memzero_explicit(&ctx, sizeof(ctx));
+
+       return 0;
+}
+
+static int
+E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
+{
+       int rc;
+
+       rc = smbhash(p24, c8, p21);
+       if (rc)
+               return rc;
+       rc = smbhash(p24 + 8, c8, p21 + 7);
+       if (rc)
+               return rc;
+       rc = smbhash(p24 + 16, c8, p21 + 14);
+       return rc;
+}

 #ifdef CONFIG_CIFS_WEAK_PW_HASH
+static int
+E_P16(unsigned char *p14, unsigned char *p16)
+{
+       int rc;
+       unsigned char sp8[8] =
+           { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
+
+       rc = smbhash(p16, sp8, p14);
+       if (rc)
+               return rc;
+       rc = smbhash(p16 + 8, sp8, p14 + 7);
+       return rc;
+}
+
+/*
+   This implements the X/Open SMB password encryption
+   It takes a password, a 8 byte "crypt key" and puts 24 bytes of
+   encrypted password into p24 */
+/* Note that password must be uppercased and null terminated */
+static int
+SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
+{
+       int rc;
+       unsigned char p14[14], p16[16], p21[21];
+
+       memset(p14, '\0', 14);
+       memset(p16, '\0', 16);
+       memset(p21, '\0', 21);
+
+       memcpy(p14, passwd, 14);
+       rc = E_P16(p14, p16);
+       if (rc)
+               return rc;
+
+       memcpy(p21, p16, 16);
+       rc = E_P24(p21, c8, p24);
+
+       return rc;
+}
+
 int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
                        char *lnm_session_key)
 {
@@ -57,6 +153,229 @@ int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
 }
 #endif /* CIFS_WEAK_PW_HASH */

+/* Does the NT MD4 hash then des encryption. */
+static int
+SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
+               const struct nls_table *codepage)
+{
+       int rc;
+       unsigned char p16[16], p21[21];
+
+       memset(p16, '\0', 16);
+       memset(p21, '\0', 21);
+
+       rc = E_md4hash(passwd, p16, codepage);
+       if (rc) {
+               cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
+                        __func__, rc);
+               return rc;
+       }
+       memcpy(p21, p16, 16);
+       rc = E_P24(p21, c8, p24);
+       return rc;
+}
+
+/*
+ * Issue a TREE_CONNECT request.
+ */
+static int
+CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
+        const char *tree, struct cifs_tcon *tcon,
+        const struct nls_table *nls_codepage)
+{
+       struct smb_hdr *smb_buffer;
+       struct smb_hdr *smb_buffer_response;
+       TCONX_REQ *pSMB;
+       TCONX_RSP *pSMBr;
+       unsigned char *bcc_ptr;
+       int rc = 0;
+       int length;
+       __u16 bytes_left, count;
+
+       if (ses == NULL)
+               return -EIO;
+
+       smb_buffer = cifs_buf_get();
+       if (smb_buffer == NULL)
+               return -ENOMEM;
+
+       smb_buffer_response = smb_buffer;
+
+       header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
+                       NULL /*no tid */ , 4 /*wct */ );
+
+       smb_buffer->Mid = get_next_mid(ses->server);
+       smb_buffer->Uid = ses->Suid;
+       pSMB = (TCONX_REQ *) smb_buffer;
+       pSMBr = (TCONX_RSP *) smb_buffer_response;
+
+       pSMB->AndXCommand = 0xFF;
+       pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
+       bcc_ptr = &pSMB->Password[0];
+       if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
+               pSMB->PasswordLength = cpu_to_le16(1);  /* minimum */
+               *bcc_ptr = 0; /* password is null byte */
+               bcc_ptr++;              /* skip password */
+               /* already aligned so no need to do it below */
+       } else {
+               pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+               /* BB FIXME add code to fail this if NTLMv2 or Kerberos
+                  specified as required (when that support is added to
+                  the vfs in the future) as only NTLM or the much
+                  weaker LANMAN (which we do not send by default) is accepted
+                  by Samba (not sure whether other servers allow
+                  NTLMv2 password here) */
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+               if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
+                   (ses->sectype == LANMAN))
+                       calc_lanman_hash(tcon->password, ses->server->cryptkey,
+                                        ses->server->sec_mode &
+                                           SECMODE_PW_ENCRYPT ? true : false,
+                                        bcc_ptr);
+               else
+#endif /* CIFS_WEAK_PW_HASH */
+               rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
+                                       bcc_ptr, nls_codepage);
+               if (rc) {
+                       cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
+                                __func__, rc);
+                       cifs_buf_release(smb_buffer);
+                       return rc;
+               }
+
+               bcc_ptr += CIFS_AUTH_RESP_SIZE;
+               if (ses->capabilities & CAP_UNICODE) {
+                       /* must align unicode strings */
+                       *bcc_ptr = 0; /* null byte password */
+                       bcc_ptr++;
+               }
+       }
+
+       if (ses->server->sign)
+               smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+       if (ses->capabilities & CAP_STATUS32) {
+               smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+       }
+       if (ses->capabilities & CAP_DFS) {
+               smb_buffer->Flags2 |= SMBFLG2_DFS;
+       }
+       if (ses->capabilities & CAP_UNICODE) {
+               smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+               length =
+                   cifs_strtoUTF16((__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);
+               bcc_ptr += strlen(tree) + 1;
+       }
+       strcpy(bcc_ptr, "?????");
+       bcc_ptr += strlen("?????");
+       bcc_ptr += 1;
+       count = bcc_ptr - &pSMB->Password[0];
+       be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
+       pSMB->ByteCount = cpu_to_le16(count);
+
+       rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
+                        0);
+
+       /* above now done in SendReceive */
+       if (rc == 0) {
+               bool is_unicode;
+
+               tcon->tidStatus = CifsGood;
+               tcon->need_reconnect = false;
+               tcon->tid = smb_buffer_response->Tid;
+               bcc_ptr = pByteArea(smb_buffer_response);
+               bytes_left = get_bcc(smb_buffer_response);
+               length = strnlen(bcc_ptr, bytes_left - 2);
+               if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
+                       is_unicode = true;
+               else
+                       is_unicode = false;
+
+
+               /* skip service field (NB: this field is always ASCII) */
+               if (length == 3) {
+                       if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
+                           (bcc_ptr[2] == 'C')) {
+                               cifs_dbg(FYI, "IPC connection\n");
+                               tcon->ipc = true;
+                               tcon->pipe = true;
+                       }
+               } else if (length == 2) {
+                       if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
+                               /* the most common case */
+                               cifs_dbg(FYI, "disk share connection\n");
+                       }
+               }
+               bcc_ptr += length + 1;
+               bytes_left -= (length + 1);
+               strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
+
+               /* mostly informational -- no need to fail on error here */
+               kfree(tcon->nativeFileSystem);
+               tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
+                                                     bytes_left, is_unicode,
+                                                     nls_codepage);
+
+               cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
+
+               if ((smb_buffer_response->WordCount == 3) ||
+                        (smb_buffer_response->WordCount == 7))
+                       /* field is in same location */
+                       tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+               else
+                       tcon->Flags = 0;
+               cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
+       }
+
+       cifs_buf_release(smb_buffer);
+       return rc;
+}
+
+/* first calculate 24 bytes ntlm response and then 16 byte session key */
+int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
+{
+       int rc = 0;
+       unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
+       char temp_key[CIFS_SESS_KEY_SIZE];
+
+       if (!ses)
+               return -EINVAL;
+
+       ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
+       if (!ses->auth_key.response)
+               return -ENOMEM;
+
+       ses->auth_key.len = temp_len;
+
+       rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
+                       ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
+       if (rc) {
+               cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
+                        __func__, rc);
+               return rc;
+       }
+
+       rc = E_md4hash(ses->password, temp_key, nls_cp);
+       if (rc) {
+               cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
+                        __func__, rc);
+               return rc;
+       }
+
+       rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
+       if (rc)
+               cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
+                        __func__, rc);
+
+       return rc;
+}
+
 /*
  * An NT cancel request header looks just like the original request except:
  *
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 39a938443e3e..0c5617427be9 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/random.h>
-#include <crypto/des.h>
 #include "cifs_fs_sb.h"
 #include "cifs_unicode.h"
 #include "cifspdu.h"
@@ -38,72 +37,6 @@
 #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
 #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))

-static void
-str_to_key(unsigned char *str, unsigned char *key)
-{
-       int i;
-
-       key[0] = str[0] >> 1;
-       key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
-       key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
-       key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
-       key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
-       key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
-       key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
-       key[7] = str[6] & 0x7F;
-       for (i = 0; i < 8; i++)
-               key[i] = (key[i] << 1);
-}
-
-static int
-smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
-{
-       unsigned char key2[8];
-       struct des_ctx ctx;
-
-       str_to_key(key, key2);
-
-       if (fips_enabled) {
-               cifs_dbg(VFS, "FIPS compliance enabled: DES not permitted\n");
-               return -ENOENT;
-       }
-
-       des_expand_key(&ctx, key2, DES_KEY_SIZE);
-       des_encrypt(&ctx, out, in);
-       memzero_explicit(&ctx, sizeof(ctx));
-
-       return 0;
-}
-
-static int
-E_P16(unsigned char *p14, unsigned char *p16)
-{
-       int rc;
-       unsigned char sp8[8] =
-           { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
-
-       rc = smbhash(p16, sp8, p14);
-       if (rc)
-               return rc;
-       rc = smbhash(p16 + 8, sp8, p14 + 7);
-       return rc;
-}
-
-static int
-E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
-{
-       int rc;
-
-       rc = smbhash(p24, c8, p21);
-       if (rc)
-               return rc;
-       rc = smbhash(p24 + 8, c8, p21 + 7);
-       if (rc)
-               return rc;
-       rc = smbhash(p24 + 16, c8, p21 + 14);
-       return rc;
-}
-
 /* produce a md4 message digest from data of length n bytes */
 int
 mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
@@ -135,32 +68,6 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
        return rc;
 }

-/*
-   This implements the X/Open SMB password encryption
-   It takes a password, a 8 byte "crypt key" and puts 24 bytes of
-   encrypted password into p24 */
-/* Note that password must be uppercased and null terminated */
-int
-SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
-{
-       int rc;
-       unsigned char p14[14], p16[16], p21[21];
-
-       memset(p14, '\0', 14);
-       memset(p16, '\0', 16);
-       memset(p21, '\0', 21);
-
-       memcpy(p14, passwd, 14);
-       rc = E_P16(p14, p16);
-       if (rc)
-               return rc;
-
-       memcpy(p21, p16, 16);
-       rc = E_P24(p21, c8, p24);
-
-       return rc;
-}
-
 /*
  * Creates the MD4 Hash of the users password in NT UNICODE.
  */
@@ -187,24 +94,3 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
        return rc;
 }

-/* Does the NT MD4 hash then des encryption. */
-int
-SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
-               const struct nls_table *codepage)
-{
-       int rc;
-       unsigned char p16[16], p21[21];
-
-       memset(p16, '\0', 16);
-       memset(p21, '\0', 21);
-
-       rc = E_md4hash(passwd, p16, codepage);
-       if (rc) {
-               cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
-                        __func__, rc);
-               return rc;
-       }
-       memcpy(p21, p16, 16);
-       rc = E_P24(p21, c8, p24);
-       return rc;
-}
--
2.30.2

-- 
Thanks,

Steve
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help