Commit 9ef5992e442b2b0bf6364bfcc5574e983a983159

Authored by Shirish Pargaonkar
Committed by Steve French
1 parent 5079276066

cifs: Assume passwords are encoded according to iocharset (try #2)

Re-posting a patch originally posted by Oskar Liljeblad after
rebasing on 3.2.

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 <oskar@osk.mine.nu>
Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Tested-by: A <nimbus1_03087@yahoo.com>
Signed-off-by: Steve French <smfrench@gmail.com>

Showing 5 changed files with 23 additions and 60 deletions Side-by-side Diff

fs/cifs/cifsencrypt.c
... ... @@ -204,7 +204,7 @@
204 204 }
205 205  
206 206 /* first calculate 24 bytes ntlm response and then 16 byte session key */
207   -int setup_ntlm_response(struct cifs_ses *ses)
  207 +int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
208 208 {
209 209 int rc = 0;
210 210 unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
211 211  
... ... @@ -221,14 +221,14 @@
221 221 ses->auth_key.len = temp_len;
222 222  
223 223 rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
224   - ses->auth_key.response + CIFS_SESS_KEY_SIZE);
  224 + ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
225 225 if (rc) {
226 226 cFYI(1, "%s Can't generate NTLM response, error: %d",
227 227 __func__, rc);
228 228 return rc;
229 229 }
230 230  
231   - rc = E_md4hash(ses->password, temp_key);
  231 + rc = E_md4hash(ses->password, temp_key, nls_cp);
232 232 if (rc) {
233 233 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
234 234 return rc;
... ... @@ -404,7 +404,7 @@
404 404 }
405 405  
406 406 /* calculate md4 hash of password */
407   - E_md4hash(ses->password, nt_hash);
  407 + E_md4hash(ses->password, nt_hash, nls_cp);
408 408  
409 409 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
410 410 CIFS_NTHASH_SIZE);
... ... @@ -395,8 +395,9 @@
395 395 extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
396 396 struct TCP_Server_Info *server,
397 397 __u32 expected_sequence_number);
398   -extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *);
399   -extern int setup_ntlm_response(struct cifs_ses *);
  398 +extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
  399 + const struct nls_table *);
  400 +extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
400 401 extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
401 402 extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
402 403 extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
... ... @@ -448,7 +449,8 @@
448 449 const unsigned char *path,
449 450 struct cifs_sb_info *cifs_sb, int xid);
450 451 extern int mdfour(unsigned char *, unsigned char *, int);
451   -extern int E_md4hash(const unsigned char *passwd, unsigned char *p16);
  452 +extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
  453 + const struct nls_table *codepage);
452 454 extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
453 455 unsigned char *p24);
454 456  
... ... @@ -3452,7 +3452,7 @@
3452 3452 else
3453 3453 #endif /* CIFS_WEAK_PW_HASH */
3454 3454 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
3455   - bcc_ptr);
  3455 + bcc_ptr, nls_codepage);
3456 3456  
3457 3457 bcc_ptr += CIFS_AUTH_RESP_SIZE;
3458 3458 if (ses->capabilities & CAP_UNICODE) {
... ... @@ -683,7 +683,7 @@
683 683 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
684 684  
685 685 /* calculate ntlm response and session key */
686   - rc = setup_ntlm_response(ses);
  686 + rc = setup_ntlm_response(ses, nls_cp);
687 687 if (rc) {
688 688 cERROR(1, "Error %d during NTLM authentication", rc);
689 689 goto ssetup_exit;
fs/cifs/smbencrypt.c
... ... @@ -199,75 +199,36 @@
199 199 return rc;
200 200 }
201 201  
202   -/* Routines for Windows NT MD4 Hash functions. */
203   -static int
204   -_my_wcslen(__u16 *str)
205   -{
206   - int len = 0;
207   - while (*str++ != 0)
208   - len++;
209   - return len;
210   -}
211   -
212 202 /*
213   - * Convert a string into an NT UNICODE string.
214   - * Note that regardless of processor type
215   - * this must be in intel (little-endian)
216   - * format.
217   - */
218   -
219   -static int
220   -_my_mbstowcs(__u16 *dst, const unsigned char *src, int len)
221   -{ /* BB not a very good conversion routine - change/fix */
222   - int i;
223   - __u16 val;
224   -
225   - for (i = 0; i < len; i++) {
226   - val = *src;
227   - SSVAL(dst, 0, val);
228   - dst++;
229   - src++;
230   - if (val == 0)
231   - break;
232   - }
233   - return i;
234   -}
235   -
236   -/*
237 203 * Creates the MD4 Hash of the users password in NT UNICODE.
238 204 */
239 205  
240 206 int
241   -E_md4hash(const unsigned char *passwd, unsigned char *p16)
  207 +E_md4hash(const unsigned char *passwd, unsigned char *p16,
  208 + const struct nls_table *codepage)
242 209 {
243 210 int rc;
244 211 int len;
245 212 __u16 wpwd[129];
246 213  
247 214 /* Password cannot be longer than 128 characters */
248   - if (passwd) {
249   - len = strlen((char *) passwd);
250   - if (len > 128)
251   - len = 128;
252   -
253   - /* Password must be converted to NT unicode */
254   - _my_mbstowcs(wpwd, passwd, len);
255   - } else
  215 + if (passwd) /* Password must be converted to NT unicode */
  216 + len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
  217 + else {
256 218 len = 0;
  219 + *wpwd = 0; /* Ensure string is null terminated */
  220 + }
257 221  
258   - wpwd[len] = 0; /* Ensure string is null terminated */
259   - /* Calculate length in bytes */
260   - len = _my_wcslen(wpwd) * sizeof(__u16);
  222 + rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__u16));
  223 + memset(wpwd, 0, 129 * sizeof(__u16));
261 224  
262   - rc = mdfour(p16, (unsigned char *) wpwd, len);
263   - memset(wpwd, 0, 129 * 2);
264   -
265 225 return rc;
266 226 }
267 227  
268 228 /* Does the NT MD4 hash then des encryption. */
269 229 int
270   -SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
  230 +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
  231 + const struct nls_table *codepage)
271 232 {
272 233 int rc;
273 234 unsigned char p16[16], p21[21];
... ... @@ -275,7 +236,7 @@
275 236 memset(p16, '\0', 16);
276 237 memset(p21, '\0', 21);
277 238  
278   - rc = E_md4hash(passwd, p16);
  239 + rc = E_md4hash(passwd, p16, codepage);
279 240 if (rc) {
280 241 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
281 242 return rc;