Re: [PATCH] CIFS: Assume passwords are encoded according to iocharset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 11 Apr 2011 12:21:59 -0500
Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote:

> On Sun, Mar 27, 2011 at 7:56 AM, Oskar Liljeblad <oskar@xxxxxxxxxxx> 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@xxxxxxxxxxx>
> > ---
> > Â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@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux