From patchwork Sun Mar 27 12:56:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oskar Liljeblad X-Patchwork-Id: 666551 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 p2RCuu6A020990 for ; Sun, 27 Mar 2011 12:56:56 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751822Ab1C0M4x (ORCPT ); Sun, 27 Mar 2011 08:56:53 -0400 Received: from smtp2.sensus.se ([193.13.139.17]:36244 "EHLO smtp2.sensus.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751076Ab1C0M4x (ORCPT ); Sun, 27 Mar 2011 08:56:53 -0400 Received: from h23n4-m-fb-gr100.ias.bredband.telia.com ([81.236.171.23] helo=osk.mine.nu) by smtp2.sensus.se with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1Q3pWT-00007X-97; Sun, 27 Mar 2011 14:56:49 +0200 Received: from usel by osk.mine.nu with local (Exim 4.72) (envelope-from ) id 1Q3pWS-00013K-9e; Sun, 27 Mar 2011 12:56:48 +0000 Date: Sun, 27 Mar 2011 14:56:48 +0200 From: Oskar Liljeblad To: linux-cifs@vger.kernel.org Cc: shirishpargaonkar@gmail.com Subject: [PATCH] CIFS: Assume passwords are encoded according to iocharset Message-ID: <20110327125648.GA3621@osk.mine.nu> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) 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.6 (demeter1.kernel.org [140.211.167.41]); Sun, 27 Mar 2011 12:56:56 +0000 (UTC) Reviewed-by: Shirish Pargaonkar diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 5bb4b09..3c1306d 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -226,7 +226,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, } /* first calculate 24 bytes ntlm response and then 16 byte session key */ -int setup_ntlm_response(struct cifs_ses *ses) +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; @@ -243,14 +243,14 @@ int setup_ntlm_response(struct cifs_ses *ses) ses->auth_key.len = temp_len; rc = SMBNTencrypt(ses->password, ses->server->cryptkey, - ses->auth_key.response + CIFS_SESS_KEY_SIZE); + ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp); if (rc) { cFYI(1, "%s Can't generate NTLM response, error: %d", __func__, rc); return rc; } - rc = E_md4hash(ses->password, temp_key); + rc = E_md4hash(ses->password, temp_key, nls_cp); if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc; @@ -458,7 +458,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, } /* calculate md4 hash of password */ - E_md4hash(ses->password, nt_hash); + E_md4hash(ses->password, nt_hash, nls_cp); crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, CIFS_NTHASH_SIZE); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e42dc82..fd6d873 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -376,8 +376,9 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, extern int cifs_verify_signature(struct smb_hdr *, struct TCP_Server_Info *server, __u32 expected_sequence_number); -extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); -extern int setup_ntlm_response(struct cifs_ses *); +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 int cifs_crypto_shash_allocate(struct TCP_Server_Info *); extern void cifs_crypto_shash_release(struct TCP_Server_Info *); @@ -429,7 +430,8 @@ extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, const unsigned char *path, struct cifs_sb_info *cifs_sb, int xid); extern int mdfour(unsigned char *, unsigned char *, int); -extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); +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); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 96544a4..3c0190f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3060,7 +3060,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, else #endif /* CIFS_WEAK_PW_HASH */ rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, - bcc_ptr); + bcc_ptr, nls_codepage); bcc_ptr += CIFS_AUTH_RESP_SIZE; if (ses->capabilities & CAP_UNICODE) { diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 6b140e1..17ae0db 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -694,7 +694,7 @@ ssetup_ntlmssp_authenticate: cpu_to_le16(CIFS_AUTH_RESP_SIZE); /* calculate ntlm response and session key */ - rc = setup_ntlm_response(ses); + rc = setup_ntlm_response(ses, nls_cp); if (rc) { cERROR(1, "Error %d during NTLM authentication", rc); goto ssetup_exit; diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 1525d5e..92291c1 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -195,46 +195,13 @@ SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) return rc; } -/* Routines for Windows NT MD4 Hash functions. */ -static int -_my_wcslen(__u16 *str) -{ - int len = 0; - while (*str++ != 0) - len++; - return len; -} - -/* - * Convert a string into an NT UNICODE string. - * Note that regardless of processor type - * this must be in intel (little-endian) - * format. - */ - -static int -_my_mbstowcs(__u16 *dst, const unsigned char *src, int len) -{ /* BB not a very good conversion routine - change/fix */ - int i; - __u16 val; - - for (i = 0; i < len; i++) { - val = *src; - SSVAL(dst, 0, val); - dst++; - src++; - if (val == 0) - break; - } - return i; -} - /* * Creates the MD4 Hash of the users password in NT UNICODE. */ int -E_md4hash(const unsigned char *passwd, unsigned char *p16) +E_md4hash(const unsigned char *passwd, unsigned char *p16, + const struct nls_table *codepage) { int rc; int len; @@ -242,20 +209,14 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) /* Password cannot be longer than 128 characters */ if (passwd) { - len = strlen((char *) passwd); - if (len > 128) - len = 128; - /* Password must be converted to NT unicode */ - _my_mbstowcs(wpwd, passwd, len); - } else + len = cifs_strtoUCS(wpwd, passwd, 128, codepage); + } else { len = 0; + *wpwd = 0; /* Ensure string is null terminated */ + } - wpwd[len] = 0; /* Ensure string is null terminated */ - /* Calculate length in bytes */ - len = _my_wcslen(wpwd) * sizeof(__u16); - - rc = mdfour(p16, (unsigned char *) wpwd, len); + rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__u16)); memset(wpwd, 0, 129 * 2); return rc; @@ -275,7 +236,7 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) memcpy(passwd, pwd, 512); /* Calculate the MD4 hash (NT compatible) of the password */ memset(nt_p16, '\0', 16); - E_md4hash(passwd, nt_p16); + E_md4hash(passwd, nt_p16, /* put nls codepage here */); /* Mangle the passwords into Lanman format */ passwd[14] = '\0'; @@ -348,7 +309,8 @@ NTLMSSPOWFencrypt(unsigned char passwd[8], /* Does the NT MD4 hash then des encryption. */ int -SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24, + const struct nls_table *codepage) { int rc; unsigned char p16[16], p21[21]; @@ -356,7 +318,7 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) memset(p16, '\0', 16); memset(p21, '\0', 21); - rc = E_md4hash(passwd, p16); + rc = E_md4hash(passwd, p16, codepage); if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc;