From patchwork Sun Mar 27 07:01:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oskar Liljeblad X-Patchwork-Id: 666411 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 p2R7jcHa027789 for ; Sun, 27 Mar 2011 07:45:39 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751962Ab1C0Hpi (ORCPT ); Sun, 27 Mar 2011 03:45:38 -0400 Received: from smtp2.sensus.se ([193.13.139.17]:37555 "EHLO smtp2.sensus.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751835Ab1C0Hph (ORCPT ); Sun, 27 Mar 2011 03:45:37 -0400 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 07:45:39 +0000 (UTC) X-Greylist: delayed 2629 seconds by postgrey-1.27 at vger.kernel.org; Sun, 27 Mar 2011 03:45:37 EDT 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 1Q3jyt-0007qS-58 for linux-cifs@vger.kernel.org; Sun, 27 Mar 2011 09:01:47 +0200 Received: from usel by osk.mine.nu with local (Exim 4.72) (envelope-from ) id 1Q3jyq-00016f-T0 for linux-cifs@vger.kernel.org; Sun, 27 Mar 2011 07:01:44 +0000 Date: Sun, 27 Mar 2011 09:01:44 +0200 From: Oskar Liljeblad To: linux-cifs@vger.kernel.org Subject: [PATCH] allow cifs passwords with utf8 characters Message-ID: <20110327070144.GA3772@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 diff -u -p fs/cifs/smbencrypt.c.v0 fs/cifs/smbencrypt.c --- fs/cifs/smbencrypt.c.v0 2010-09-29 03:09:08.000000000 +0200 +++ fs/cifs/smbencrypt.c 2011-03-27 08:39:20.000000000 +0200 @@ -29,6 +29,7 @@ #include #include #include +#include #include "cifs_unicode.h" #include "cifspdu.h" #include "cifsglob.h" @@ -80,40 +81,6 @@ SMBencrypt(unsigned char *passwd, const memset(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); } diff -u -p fs/nls/nls_base.c.v0 fs/nls/nls_base.c --- fs/nls/nls_base.c.v0 2010-09-29 03:09:08.000000000 +0200 +++ fs/nls/nls_base.c 2011-03-27 08:26:35.000000000 +0200 @@ -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) {