Message ID | 20110327125648.GA3621@osk.mine.nu (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > --- > 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; > -} > - > /* > * 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 */ > + } > > - 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 * sizeof(__u16)); > memset(wpwd, 0, 129 * 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; > But for really minor nits, looks correct. Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, 27 Mar 2011 14:56:48 +0200 Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > --- > 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; > -} > - > /* > * 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 */ > + } > > - 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 * sizeof(__u16)); > memset(wpwd, 0, 129 * 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 */); ^^^^^^^^^^^^^ Won't this fail to compile? > > /* 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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Apr 8, 2011 at 8:31 AM, Jeff Layton <jlayton@poochiereds.net> wrote: > On Sun, 27 Mar 2011 14:56:48 +0200 > Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> >> --- >> 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; >> -} >> - >> /* >> * 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 */ >> + } >> >> - 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 * sizeof(__u16)); >> memset(wpwd, 0, 129 * 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 */); > ^^^^^^^^^^^^^ > Won't this fail to compile? >> >> /* 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 majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > -- > Jeff Layton <jlayton@poochiereds.net> > Indeed, missed that. -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Friday, April 08, 2011 at 09:48, Jeff Layton wrote: > On Sun, 27 Mar 2011 14:56:48 +0200 > Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > > --- > > 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; > > -} > > - > > /* > > * 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 */ > > + } > > > > - 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 * sizeof(__u16)); > > memset(wpwd, 0, 129 * 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 */); > ^^^^^^^^^^^^^ > Won't this fail to compile? Yes, but it's inside a function which is commented out and not compiled. Instead of adding an extra parameter to the function (which would be required) I decided just to put a reminder there if that function is ever used in the future. #if 0 /* currently unused */ /* Does both the NT and LM owfs of a user's password */ static void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) { char passwd[514]; memset(passwd, '\0', 514); if (strlen(pwd) < 513) strcpy(passwd, pwd); else memcpy(passwd, pwd, 512); /* Calculate the MD4 hash (NT compatible) of the password */ memset(nt_p16, '\0', 16); E_md4hash(passwd, nt_p16, /* put nls codepage here */); /* Mangle the passwords into Lanman format */ passwd[14] = '\0'; /* strupper(passwd); */ /* Calculate the SMB (lanman) hash functions of the password */ memset(p16, '\0', 16); E_P16((unsigned char *) passwd, (unsigned char *) p16); /* clear out local copy of user's password (just being paranoid). */ memset(passwd, '\0', sizeof(passwd)); } #endif -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 8 Apr 2011 16:11:12 +0200 Oskar Liljeblad <oskar@osk.mine.nu> wrote: > On Friday, April 08, 2011 at 09:48, Jeff Layton wrote: > > On Sun, 27 Mar 2011 14:56:48 +0200 > > Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > > > --- > > > 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; > > > -} > > > - > > > /* > > > * 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 */ > > > + } > > > > > > - 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 * sizeof(__u16)); > > > memset(wpwd, 0, 129 * 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 */); > > ^^^^^^^^^^^^^ > > Won't this fail to compile? > > Yes, but it's inside a function which is commented out and not compiled. Instead > of adding an extra parameter to the function (which would be required) I > decided just to put a reminder there if that function is ever used in the > future. > > #if 0 /* currently unused */ > /* Does both the NT and LM owfs of a user's password */ > static void > nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) > { > char passwd[514]; > > memset(passwd, '\0', 514); > if (strlen(pwd) < 513) > strcpy(passwd, pwd); > else > memcpy(passwd, pwd, 512); > /* Calculate the MD4 hash (NT compatible) of the password */ > memset(nt_p16, '\0', 16); > E_md4hash(passwd, nt_p16, /* put nls codepage here */); > > /* Mangle the passwords into Lanman format */ > passwd[14] = '\0'; > /* strupper(passwd); */ > > /* Calculate the SMB (lanman) hash functions of the password */ > > memset(p16, '\0', 16); > E_P16((unsigned char *) passwd, (unsigned char *) p16); > > /* clear out local copy of user's password (just being paranoid). */ > memset(passwd, '\0', sizeof(passwd)); > } > #endif Ahh, ok. A perfect case to demonstrate why leaving unused crap lying around like this is a bad idea. Perhaps a better scheme would be a separate patch to just remove this function and then rebase your patch on top of that?
On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > --- > 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; > -} > - > /* > * 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 */ > + } > > - 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 * sizeof(__u16)); > memset(wpwd, 0, 129 * 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; > With this patch, I am unable to mount a share if user's password happens to contain characters like $ e.g. aa$a. A Windows client can. -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday, April 11, 2011 at 12:59, Shirish Pargaonkar 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 <oskar@osk.mine.nu> [..] > With this patch, I am unable to mount a share if user's password happens to > contain characters like $ e.g. aa$a. > A Windows client can. Hmm, strange, I was not able to reproduce this problem with domain accounts on Windows 2008 R2. For me $ worked. (That is with locale utf-8 at least.) REgards, OSkar -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 11 Apr 2011 12:21:59 -0500 Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote: > On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> > > --- > > 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; > > -} > > - > > /* > > * 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 */ > > + } > > > > - 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 * sizeof(__u16)); > > memset(wpwd, 0, 129 * 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; > > > > With this patch, I am unable to mount a share if user's password happens to > contain characters like $ e.g. aa$a. > A Windows client can. If you compare traces in wireshark, are there differences in how the username is encoded?
On Monday, April 11, 2011 at 21:31, Oskar Liljeblad wrote: > On Monday, April 11, 2011 at 12:59, Shirish Pargaonkar 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 <oskar@osk.mine.nu> > [..] > > With this patch, I am unable to mount a share if user's password happens to > > contain characters like $ e.g. aa$a. > > A Windows client can. > > Hmm, strange, I was not able to reproduce this problem with domain accounts > on Windows 2008 R2. For me $ worked. (That is with locale utf-8 at least.) I'm sorry, please disregard my comment. I tested with the wrong kernel. I will try again. Regards, Oskar -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Apr 11, 2011 at 2:16 PM, Jeff Layton <jlayton@redhat.com> wrote: > On Mon, 11 Apr 2011 12:21:59 -0500 > Shirish Pargaonkar <shirishpargaonkar@gmail.com> wrote: > >> On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <oskar@osk.mine.nu> 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 <oskar@osk.mine.nu> >> > --- >> > 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; >> > -} >> > - >> > /* >> > * 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 */ >> > + } >> > >> > - 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 * sizeof(__u16)); >> > memset(wpwd, 0, 129 * 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; >> > >> >> With this patch, I am unable to mount a share if user's password happens to >> contain characters like $ e.g. aa$a. >> A Windows client can. > > If you compare traces in wireshark, are there differences in how the > username is encoded? > -- > Jeff Layton <jlayton@redhat.com> > No differences. It is purely password that is making the difference. I compared traces when both cifs and Windows clients were using ntlmssp auth mech. -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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; -} - /* * 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 */ + } - 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 * sizeof(__u16)); memset(wpwd, 0, 129 * 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;