On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <[email protected]> wrote:
> Modify cifs to assume that the supplied password is encoded according to
> iocharset. Before this patch passwords would be treated as raw 8-bit data,
> which made authentication with Unicode passwords impossible (at least
> passwords with characters > 0xFF).
>
> The previous code would as a side effect accept passwords encoded with ISO
> 8859-1, since Unicode < 0x100 basically is ISO 8859-1. Software which
> relies on that will no longer support password chars > 0x7F unless it also
> uses iocharset=iso8859-1. (mount.cifs does not care about the encoding so
> it will work as expected.)
>
> Signed-off-by: Oskar Liljeblad <[email protected]>
> ---
> fs/cifs/cifsencrypt.c | 8 +++---
> fs/cifs/cifsproto.h | 8 ++++--
> fs/cifs/connect.c | 2 +-
> fs/cifs/sess.c | 2 +-
> fs/cifs/smbencrypt.c | 60
> +++++++++----------------------------------------
> 5 files changed, 22 insertions(+), 58 deletions(-)
>
> 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;
> -}
> -
Good clean-up of these functions.
> /*
> * 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 */
Perhaps we can use some minor clean-up of this function!
I think we should return an error if passwd is NULL.
There is no point in doing further processing if password is NULL,
auth will fail.
> + }
>
> - 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 * );
> memset(wpwd, 0, 129 * 2);
Perhaps we should use sizeof(__u16) instead of 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;
>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html