From patchwork Wed Sep 8 04:48:00 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 162881 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o884ktFR003235 for ; Wed, 8 Sep 2010 04:52:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751278Ab0IHEwg (ORCPT ); Wed, 8 Sep 2010 00:52:36 -0400 Received: from mail-iw0-f174.google.com ([209.85.214.174]:61711 "EHLO mail-iw0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751267Ab0IHEwg (ORCPT ); Wed, 8 Sep 2010 00:52:36 -0400 Received: by iwn5 with SMTP id 5so5993253iwn.19 for ; Tue, 07 Sep 2010 21:52:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer; bh=vUUv9Xzu8EfXrmKlAqyc+QOYQuotwBRri2NEQilt9Jk=; b=JoAaNmgdwGB2gfhtOgeJJ7XLJ0N7NAmLpKHRKQe/TmGgHUjyInXHSlHEgMdj7T2cb7 1ox7fkj9CaPAEDQYN1M3T1eswOoNwFHE5bAHZGBRVFfYy++YmCnTEVnI3iNT8E5xvvCp DTR6hp1J19mg3g5EjGHINfP8HlxPZva7P1THo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=HeRb809FdiJytcnMkHT5JCsf8yzvgviJX1uBimntJ3hLn8PW4yB0L/lYJ8Jih4NumZ XHTZC/O+IbRtcPWOQUsK2mLcJ0WLgy7/qQIwPfoaX8hpRutDUvt4cax7LHrfZ1OYEn6E D0DICGiEfPY/DHQc0o8L1pmfbApiPevWCc88w= Received: by 10.231.171.7 with SMTP id f7mr9221363ibz.72.1283921555617; Tue, 07 Sep 2010 21:52:35 -0700 (PDT) Received: from localhost ([32.97.110.58]) by mx.google.com with ESMTPS id g31sm7870792ibh.4.2010.09.07.21.52.34 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 07 Sep 2010 21:52:34 -0700 (PDT) From: shirishpargaonkar@gmail.com To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, Shirish Pargaonkar Subject: [PATCH 7/8] ntlmv2/ntlmssp generate secondary session key and ciphertext and send it if signing enabled Date: Tue, 7 Sep 2010 23:48:00 -0500 Message-Id: <1283921280-13163-1-git-send-email-shirishpargaonkar@gmail.com> X-Mailer: git-send-email 1.6.0.2 Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 08 Sep 2010 04:52:37 +0000 (UTC) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index f9c140a..ff576a8 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -470,6 +470,47 @@ void CalcNTLMv2_response(const struct cifsSesInfo *ses, /* cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */ } +int +calc_seckey(struct TCP_Server_Info *server) +{ + int rc; + struct crypto_blkcipher *tfm_arc4; + struct scatterlist sgin, sgout; + struct blkcipher_desc desc; + + if (!server) { + cERROR(1, "%s: Can't determine ciphertext key\n", __func__); + return 1; + } + + if (server->cphready) + return 0; + + get_random_bytes(server->ntlmssp.sec_key, CIFS_NTLMV2_SESSKEY_SIZE); + + tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", + 0, CRYPTO_ALG_ASYNC); + if (!tfm_arc4 || IS_ERR(tfm_arc4)) { + cERROR(1, "could not allocate crypto API arc4\n"); + return 1; + } + + desc.tfm = tfm_arc4; + + crypto_blkcipher_setkey(tfm_arc4, + server->session_key.data.ntlmv2.key, CIFS_CPHTXT_SIZE); + sg_init_one(&sgin, server->ntlmssp.sec_key, CIFS_CPHTXT_SIZE); + sg_init_one(&sgout, server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); + rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); + + crypto_free_blkcipher(tfm_arc4); + + server->sequence_number = 0; + server->cphready = true; + + return 0; +} + void cifs_crypto_shash_release(struct TCP_Server_Info *server) { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fbfdd8e..b78bb77 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -370,6 +370,7 @@ extern int setup_ntlmv2_rsp(struct cifsSesInfo *, char *, const struct nls_table *); extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); extern void cifs_crypto_shash_release(struct TCP_Server_Info *); +extern int calc_seckey(struct TCP_Server_Info *); #ifdef CONFIG_CIFS_WEAK_PW_HASH extern void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, char *lnm_session_key); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0621a72..e3883f3 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1587,6 +1587,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) goto out_err2; } + tcp_ses->cphready = false; tcp_ses->noblocksnd = volume_info->noblocksnd; tcp_ses->noautotune = volume_info->noautotune; tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 68ea153..7c94d7b 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -444,10 +444,12 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_NTLM; if (ses->server->secMode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { flags |= NTLMSSP_NEGOTIATE_SIGN; - if (ses->server->secMode & SECMODE_SIGN_REQUIRED) - flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + if (!ses->server->cphready) + flags |= NTLMSSP_NEGOTIATE_KEY_XCH | + NTLMSSP_NEGOTIATE_EXTENDED_SEC; + } sec_blob->NegotiateFlags |= cpu_to_le32(flags); @@ -554,9 +556,19 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, sec_blob->WorkstationName.MaximumLength = 0; tmp += 2; - sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); - sec_blob->SessionKey.Length = 0; - sec_blob->SessionKey.MaximumLength = 0; + if ((ses->server->ntlmssp.server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && + !calc_seckey(ses->server)) { + memcpy(tmp, ses->server->ntlmssp.ciphertext, CIFS_CPHTXT_SIZE); + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); + sec_blob->SessionKey.MaximumLength = + cpu_to_le16(CIFS_CPHTXT_SIZE); + tmp += CIFS_CPHTXT_SIZE; + } else { + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->SessionKey.Length = 0; + sec_blob->SessionKey.MaximumLength = 0; + } setup_ntlmv2_ret: return tmp - pbuffer;