allow cifs passwords with utf8 characters
Subsystems (2)
PATCH 1/1 allow cifs passwords with utf8 characters
I noticed that I could not mount cifs shares when the password contained utf8-encoded latin1 characters. (But somehow it worked when those latin1 characters were encoded with ISO-8859-1.) So I made some modifications to assume utf8 passwords rather than raw 8-bit.
Regards,
Oskar Liljeblad ([email protected])
PS. This patch is against linux 2.6.35.7. I am not really sure which version/tree to work with, so please tell me so that I can update the patch if needed. DS.
cifs/smbencrypt.c renamed from cifs/smbencrypt.c.v0 +5 -44
@@ -29,6 +29,7 @@#include <linux/string.h> #include <linux/kernel.h> #include <linux/random.h> +#include <linux/nls.h> #include "cifs_unicode.h" #include "cifspdu.h" #include "cifsglob.h"
@@ -80,40 +81,6 @@ SMBencrypt(unsigned char *passwd, constmemset (p21,0 ,21 ); } -/* 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. */
@@ -126,20 +93,14 @@ E_md4hash(const unsigned char *passwd, u/* 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 =utf8s_to_ucs2 (passwd,128 , (wchar_t *) wpwd); + }else { len =0 ; - + } wpwd[len] =0 ;/* Ensure string is null terminated */ -/* Calculate length in bytes */ - len =_my_wcslen (wpwd) *sizeof (__u16); -mdfour (p16, (unsigned char *) wpwd, len); +mdfour (p16, (unsigned char *) wpwd, len *sizeof (__u16));memset (wpwd,0 ,129 *2 ); }
nls/nls_base.c renamed from nls/nls_base.c.v0 +26 -0
@@ -148,6 +148,32 @@ int utf8s_to_utf16s(const u8 *s, int len }EXPORT_SYMBOL (utf8s_to_utf16s); +int utf8s_to_ucs2 (const u8 *s,int len,wchar_t *pwcs) +{ +u16 *op; +int size; +unicode_t u; + + op = pwcs; +while (*s && len >0 ) { +if (*s &0x80 ) { + size =utf8_to_utf32 (s, len, &u); +if (size <0 ) +return -EINVAL ; + +if (u <PLANE_SIZE ) + *op++ = (wchar_t ) u; + s += size; + len -= size; + }else { + *op++ = *s++; + len--; + } + } +return op - pwcs; +} +EXPORT_SYMBOL (utf8s_to_ucs2); +static inline unsigned long get_utf16 (unsigned c,enum utf16_endian endian) {switch (endian) {
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 4 lines · Oskar Liljeblad
I noticed that I could not mount cifs shares when the password contained utf8-encoded latin1 characters. (But somehow it worked when those latin1 characters were encoded with ISO-8859-1.) So I made some modifications to assume utf8 passwords rather than raw 8-bit.
[..]
cifs/smbencrypt.c E_md4hash(const unsigned char *passwd, u · line 97
Quoted 1 line
cifs/smbencrypt.c renamed from cifs/smbencrypt.c.v0 +1
-0+ len =utf8s_to_ucs2 (passwd,128 , (wchar_t *) wpwd);
Looking at the code again, I wonder if not cifs_strtoUCS in cifs_unicode.c should've been used instead?
int
cifs_strtoUCS(__le16 *to, const char *from, int len,
const struct nls_table *codepage)
(I suspect people don't look so happily on exporting more symbols either (utf8s_to_ucs2).)
The problem with cifs_strtoUCS is the codepage parameter though. Can one assume that the "iocharset" codepage is used for the password as well?
Regards,
Oskar
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 7 lines · Oskar Liljeblad
Quoted 2 lines
I noticed that I could not mount cifs shares when the password contained utf8-encoded latin1 characters. [..]
[..]
Review
Quoted 1 line
(quoted diff) +1
-0+ len = utf8s_to_ucs2(passwd, 128, (wchar_t *) wpwd);Looking at the code again, I wonder if not
cifs_strtoUCSincifs_unicode.cshould've been used instead?
Here is a tested patch that uses cifs_strtoUCS rather than utf8s_to_ucs2.
Regards,
Oskar
cifs/cifsencrypt.c renamed from cifs/cifsencrypt.c.v0 +7 -5
@@ -37,7 +37,8 @@sequence number before this function is called */ extern void mdfour (unsigned char *out,unsigned char *in,int n); -extern void E_md4hash (const unsigned char *passwd,unsigned char *p16); +extern void E_md4hash (const unsigned char *passwd,unsigned char *p16, +const struct nls_table *codepage);extern void SMBencrypt (unsigned char *passwd,const unsigned char *c8,unsigned char *p24);
@@ -210,13 +211,14 @@ int cifs_verify_signature(struct smb_hdr/* We fill in key by putting in 40 byte array which was allocated by caller */ int cifs_calculate_mac_key (struct mac_key *key,const char *rn, -const char *password) +const char *password, +const struct nls_table *codepage) {char temp_key[16 ];if ((key ==NULL ) || (rn ==NULL ))return -EINVAL ; -E_md4hash (password, temp_key); +E_md4hash (password, temp_key, codepage);mdfour (key->data.ntlm, temp_key,16 );memcpy (key->data.ntlm+16 , rn,CIFS_SESS_KEY_SIZE ); key->len =40 ;
@@ -235,7 +237,7 @@ int CalcNTLMv2_partial_mac_key(struct ciif (ses ==NULL )return -EINVAL ; -E_md4hash (ses->password, temp_hash); +E_md4hash (ses->password, temp_hash, nls_info);hmac_md5_init_limK_to_64 (temp_hash,16 , &ctx); user_name_len =strlen (ses->userName);
@@ -335,7 +337,7 @@ static int calc_ntlmv2_hash(struct cifsSreturn -ENOMEM ;/* calculate md4 hash of password */ -E_md4hash (ses->password, nt_hash); +E_md4hash (ses->password, nt_hash, nls_cp);/* convert Domainname to unicode and uppercase */ hmac_md5_init_limK_to_64 (nt_hash,16 , pctxt);
cifs/cifsproto.h renamed from cifs/cifsproto.h.v0 +2 -1
@@ -362,7 +362,8 @@const struct mac_key *mac_key, __u32 expected_sequence_number);extern int cifs_calculate_mac_key (struct mac_key *key,const char *rn, -const char *pass); +const char *pass, +const struct nls_table *codepage);extern int CalcNTLMv2_partial_mac_key (struct cifsSesInfo *,const struct nls_table *);extern void CalcNTLMv2_response (const struct cifsSesInfo *,char *);
cifs/connect.c renamed from cifs/connect.c.v0 +2 -2
@@ -53,7 +53,7 @@#define RFC1001_PORT 139extern void SMBNTencrypt (unsigned char *passwd,unsigned char *c8, -unsigned char *p24); +unsigned char *p24,const struct nls_table *codepage);extern mempool_t *cifs_req_poolp;
@@ -2767,7 +2767,7 @@ CIFSTCon(unsigned int xid, struct cifsSe else#endif /* CIFS_WEAK_PW_HASH */ SMBNTencrypt (tcon->password, ses->server->cryptKey, - bcc_ptr); + bcc_ptr, nls_codepage); bcc_ptr +=CIFS_SESS_KEY_SIZE ;if (ses->capabilities &CAP_UNICODE ) {
cifs/sess.c renamed from cifs/sess.c.v0 +8 -5
@@ -33,7 +33,8 @@#include "cifs_spnego.h" extern void SMBNTencrypt (unsigned char *passwd,unsigned char *c8, -unsigned char *p24); +unsigned char *p24, +const struct nls_table *codepage);/* * Checks if this is the first smb session to be reconnected after
@@ -478,10 +479,12 @@ static int build_ntlmssp_auth_blob(unsig sec_blob->LmChallengeResponse.MaximumLength =0 ;/* calculate session key, BB what about adding similar ntlmv2 path? */ -SMBNTencrypt (ses->password, ses->server->cryptKey, ntlm_session_key); +SMBNTencrypt (ses->password, ses->server->cryptKey, ntlm_session_key, + nls_cp);if (first)cifs_calculate_mac_key (&ses->server->mac_signing_key, - ntlm_session_key, ses->password); + ntlm_session_key, ses->password, + nls_cp);memcpy (tmp, ntlm_session_key,CIFS_SESS_KEY_SIZE ); sec_blob->NtChallengeResponse.BufferOffset =cpu_to_le32 (tmp - pbuffer);
@@ -686,12 +689,12 @@ ssetup_ntlmssp_authenticate:/* calculate session key */ SMBNTencrypt (ses->password, ses->server->cryptKey, - ntlm_session_key); + ntlm_session_key, nls_cp);if (first_time)/* should this be moved into common code with similar ntlmv2 path? */ cifs_calculate_mac_key (&ses->server->mac_signing_key, - ntlm_session_key, ses->password); + ntlm_session_key, ses->password, nls_cp);/* copy session key */ memcpy (bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE );
cifs/smbencrypt.c renamed from cifs/smbencrypt.c.v0 +15 -51
111 lines not on this page · raw message
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 9 lines · On Sun, 27 Mar 2011 10:18:35 +0200 Oskar Liljeblad…
Quoted 7 lines · Oskar Liljeblad
Quoted 2 lines
I noticed that I could not mount cifs shares when the password contained utf8-encoded latin1 characters. [..]
[..]
Review
Quoted 1 line
(quoted diff) +1
-0+ len = utf8s_to_ucs2(passwd, 128, (wchar_t *) wpwd);Looking at the code again, I wonder if not
cifs_strtoUCSincifs_unicode.cshould've been used instead?
Quoted 5 lines
Here is a tested patch that uses
cifs_strtoUCSrather thanutf8s_to_ucs2.Regards,
Oskar
Looks good overall. I especially like the fact that we're removing those broken unicode conversion routines. You should however resend this patch with a proper description and "Signed-off-by:" line. Also, be sure to run it through scripts/checkpatch.pl and fix anything it complains about.
All that said, this is not an area of the code that I know very well. Shirish probably ought to review this... cc'ing him.
Signature · 1 line
Jeff Layton <[email protected]>