aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorShirish Pargaonkar <shirishpargaonkar@gmail.com>2011-10-20 14:21:59 -0400
committerSteve French <smfrench@gmail.com>2011-10-29 23:06:54 -0400
commit9ef5992e442b2b0bf6364bfcc5574e983a983159 (patch)
treeffd83c890d6d82c525b6030e49b483fee194a8a9 /fs/cifs
parent5079276066cc421b48a6a63a54a34775979e8506 (diff)
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>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsencrypt.c8
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/connect.c2
-rw-r--r--fs/cifs/sess.c2
-rw-r--r--fs/cifs/smbencrypt.c63
5 files changed, 23 insertions, 60 deletions
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 2cfb695d1f89..5d9b9acc5fce 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -204,7 +204,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
204} 204}
205 205
206/* first calculate 24 bytes ntlm response and then 16 byte session key */ 206/* first calculate 24 bytes ntlm response and then 16 byte session key */
207int setup_ntlm_response(struct cifs_ses *ses) 207int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
208{ 208{
209 int rc = 0; 209 int rc = 0;
210 unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; 210 unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
@@ -221,14 +221,14 @@ int setup_ntlm_response(struct cifs_ses *ses)
221 ses->auth_key.len = temp_len; 221 ses->auth_key.len = temp_len;
222 222
223 rc = SMBNTencrypt(ses->password, ses->server->cryptkey, 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 if (rc) { 225 if (rc) {
226 cFYI(1, "%s Can't generate NTLM response, error: %d", 226 cFYI(1, "%s Can't generate NTLM response, error: %d",
227 __func__, rc); 227 __func__, rc);
228 return rc; 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 if (rc) { 232 if (rc) {
233 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); 233 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
234 return rc; 234 return rc;
@@ -404,7 +404,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
404 } 404 }
405 405
406 /* calculate md4 hash of password */ 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 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, 409 rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
410 CIFS_NTHASH_SIZE); 410 CIFS_NTHASH_SIZE);
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index ef4f631e4c01..6f4e243e0f62 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -395,8 +395,9 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
395extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, 395extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov,
396 struct TCP_Server_Info *server, 396 struct TCP_Server_Info *server,
397 __u32 expected_sequence_number); 397 __u32 expected_sequence_number);
398extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); 398extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *,
399extern int setup_ntlm_response(struct cifs_ses *); 399 const struct nls_table *);
400extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *);
400extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); 401extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
401extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); 402extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *);
402extern void cifs_crypto_shash_release(struct TCP_Server_Info *); 403extern void cifs_crypto_shash_release(struct TCP_Server_Info *);
@@ -448,7 +449,8 @@ extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr,
448 const unsigned char *path, 449 const unsigned char *path,
449 struct cifs_sb_info *cifs_sb, int xid); 450 struct cifs_sb_info *cifs_sb, int xid);
450extern int mdfour(unsigned char *, unsigned char *, int); 451extern int mdfour(unsigned char *, unsigned char *, int);
451extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); 452extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
453 const struct nls_table *codepage);
452extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, 454extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8,
453 unsigned char *p24); 455 unsigned char *p24);
454 456
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d545a95c30ed..c0458c543f17 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3452,7 +3452,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
3452 else 3452 else
3453#endif /* CIFS_WEAK_PW_HASH */ 3453#endif /* CIFS_WEAK_PW_HASH */
3454 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, 3454 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
3455 bcc_ptr); 3455 bcc_ptr, nls_codepage);
3456 3456
3457 bcc_ptr += CIFS_AUTH_RESP_SIZE; 3457 bcc_ptr += CIFS_AUTH_RESP_SIZE;
3458 if (ses->capabilities & CAP_UNICODE) { 3458 if (ses->capabilities & CAP_UNICODE) {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index c7d80e24f24e..4ec3ee9d72cc 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -683,7 +683,7 @@ ssetup_ntlmssp_authenticate:
683 cpu_to_le16(CIFS_AUTH_RESP_SIZE); 683 cpu_to_le16(CIFS_AUTH_RESP_SIZE);
684 684
685 /* calculate ntlm response and session key */ 685 /* calculate ntlm response and session key */
686 rc = setup_ntlm_response(ses); 686 rc = setup_ntlm_response(ses, nls_cp);
687 if (rc) { 687 if (rc) {
688 cERROR(1, "Error %d during NTLM authentication", rc); 688 cERROR(1, "Error %d during NTLM authentication", rc);
689 goto ssetup_exit; 689 goto ssetup_exit;
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index ac1221d969d6..7cacba12b8f1 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -199,75 +199,36 @@ SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24)
199 return rc; 199 return rc;
200} 200}
201 201
202/* Routines for Windows NT MD4 Hash functions. */
203static int
204_my_wcslen(__u16 *str)
205{
206 int len = 0;
207 while (*str++ != 0)
208 len++;
209 return len;
210}
211
212/*
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
219static 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/* 202/*
237 * Creates the MD4 Hash of the users password in NT UNICODE. 203 * Creates the MD4 Hash of the users password in NT UNICODE.
238 */ 204 */
239 205
240int 206int
241E_md4hash(const unsigned char *passwd, unsigned char *p16) 207E_md4hash(const unsigned char *passwd, unsigned char *p16,
208 const struct nls_table *codepage)
242{ 209{
243 int rc; 210 int rc;
244 int len; 211 int len;
245 __u16 wpwd[129]; 212 __u16 wpwd[129];
246 213
247 /* Password cannot be longer than 128 characters */ 214 /* Password cannot be longer than 128 characters */
248 if (passwd) { 215 if (passwd) /* Password must be converted to NT unicode */
249 len = strlen((char *) passwd); 216 len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
250 if (len > 128) 217 else {
251 len = 128;
252
253 /* Password must be converted to NT unicode */
254 _my_mbstowcs(wpwd, passwd, len);
255 } else
256 len = 0; 218 len = 0;
219 *wpwd = 0; /* Ensure string is null terminated */
220 }
257 221
258 wpwd[len] = 0; /* Ensure string is null terminated */ 222 rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__u16));
259 /* Calculate length in bytes */ 223 memset(wpwd, 0, 129 * sizeof(__u16));
260 len = _my_wcslen(wpwd) * sizeof(__u16);
261
262 rc = mdfour(p16, (unsigned char *) wpwd, len);
263 memset(wpwd, 0, 129 * 2);
264 224
265 return rc; 225 return rc;
266} 226}
267 227
268/* Does the NT MD4 hash then des encryption. */ 228/* Does the NT MD4 hash then des encryption. */
269int 229int
270SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) 230SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24,
231 const struct nls_table *codepage)
271{ 232{
272 int rc; 233 int rc;
273 unsigned char p16[16], p21[21]; 234 unsigned char p16[16], p21[21];
@@ -275,7 +236,7 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
275 memset(p16, '\0', 16); 236 memset(p16, '\0', 16);
276 memset(p21, '\0', 21); 237 memset(p21, '\0', 21);
277 238
278 rc = E_md4hash(passwd, p16); 239 rc = E_md4hash(passwd, p16, codepage);
279 if (rc) { 240 if (rc) {
280 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); 241 cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
281 return rc; 242 return rc;