Re: [PATCH 5/8] ntlmv2/ntlmssp functions to either extract or create av pair/ti info blob

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

 



On Wed, 8 Sep 2010 15:48:54 -0500
Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote:

> On Wed, Sep 8, 2010 at 3:09 PM, Jeff Layton <jlayton@xxxxxxxxx> wrote:
> > On Tue,  7 Sep 2010 23:46:25 -0500
> > shirishpargaonkar@xxxxxxxxx wrote:
> >
> >> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> >>
> >>
> >> Attribue Value (AV) pairs or Target Info (TI) pairs are part of
> >> ntlmv2 authentication.
> >> Structure ntlmv2_resp had only definition for two av pairs.
> >> So removed it, and now allocation of av pairs is dynamic.
> >> For servers like Windows 7/2008, av pairs sent by server in
> >> challege packet (type 2 in the ntlmssp exchange/negotiation) can
> >> vary.
> >>
> >> Server sends them during ntlmssp negotiation. So when ntlmssp is used
> >> as an authentication mechanism, type 2 challenge packet from server
> >> has this information.  Pluck it and use the entire blob for
> >> authenticaiton purpose.  If user has not specified, extract
> >> (netbios) domain name from the av pairs which is used to calculate
> >> ntlmv2 hash.  Servers like Windows 7 are particular about the AV pair
> >> blob.
> >>
> >> Servers like Windows 2003, are not very strict about the contents
> >> of av pair blob used during ntlmv2 authentication.
> >> So when security mechanism such as ntlmv2 is used (not ntlmv2 in ntlmssp),
> >> there is no negotiation and so genereate a minimal blob that gets
> >> used in ntlmv2 authentication as well as gets sent.
> >>
> >>
> >> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> >> ---
> >>  fs/cifs/cifsencrypt.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++--
> >>  fs/cifs/cifspdu.h     |    1 -
> >>  fs/cifs/connect.c     |    2 +
> >>  fs/cifs/sess.c        |   18 +++++++++++
> >>  4 files changed, 93 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
> >> index 4772c4d..e53fbeb 100644
> >> --- a/fs/cifs/cifsencrypt.c
> >> +++ b/fs/cifs/cifsencrypt.c
> >> @@ -27,6 +27,7 @@
> >>  #include "md5.h"
> >>  #include "cifs_unicode.h"
> >>  #include "cifsproto.h"
> >> +#include "ntlmssp.h"
> >>  #include <linux/ctype.h>
> >>  #include <linux/random.h>
> >>
> >> @@ -263,6 +264,78 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt,
> >>  }
> >>  #endif /* CIFS_WEAK_PW_HASH */
> >>
> >> +/* This is just a filler for ntlmv2 type of security mechanisms.
> >> + * Older servers are not very particular about the contents of av pairs
> >> + * in the blob and for sec mechs like ntlmv2, there is no negotiation
> >> + * as in ntlmssp, so unless domain and server  netbios and dns names
> >> + * are specified, there is no way to obtain name.  In case of ntlmssp,
> >> + * server provides that info in type 2 challenge packet
> >> + */
> >> +
> > ^^^ nit: this blank line shouldn't be there
> >
> >> +static int
> >> +build_avpair_blob(struct cifsSesInfo *ses)
> >> +{
> >> +     struct ntlmssp2_name *attrptr;
> >> +
> >> +     ses->tilen = 2 * sizeof(struct ntlmssp2_name);
> >                    ^^^
> >                Why 2 here? This deserves a comment.
> >
> >> +     ses->tiblob = kzalloc(ses->tilen, GFP_KERNEL);
> >> +     if (!ses->tiblob) {
> >> +             ses->tilen = 0;
> >> +             cERROR(1, "Challenge target info allocation failure");
> >> +             return -ENOMEM;
> >> +     }
> >> +     attrptr = (struct ntlmssp2_name *) ses->tiblob;
> >> +     attrptr->type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
> >> +
> >> +     return 0;
> >> +}
> >> +
> >> +/* Server has provided av pairs/target info in the type 2 challenge
> >> + * packet and we have plucked it and stored within smb connection.
> >> + * We parse that blob here to find netbios domain name to be used
> >> + * as part of ntlmv2 authentication, if not already specified on
> >> + * the command line
> >> + */
> >> +
> > ^^^^
> > nit: again, blank line not needed there
> >
> >> +static int
> >> +find_domain_name(struct cifsSesInfo *ses)
> >> +{
> >> +     int rc = 0;
> >> +     unsigned int attrsize;
> >> +     unsigned int type;
> >> +     unsigned char *blobptr;
> >> +     struct ntlmssp2_name *attrptr;
> >> +
> >> +     if (ses->tiblob) {
> >> +             blobptr = ses->tiblob;
> >> +             attrptr = (struct ntlmssp2_name *) blobptr;
> >> +
> >> +             while ((type = attrptr->type) != 0) {
> >> +                     blobptr += 2; /* advance attr type */
> >> +                     attrsize = attrptr->length;
> >> +                     blobptr += 2; /* advance attr size */
> >> +                     if (type == NTLMSSP_AV_NB_DOMAIN_NAME) {
> >> +                             if (!ses->domainName) {
> >> +                                     ses->domainName =
> >> +                                             kmalloc(attrptr->length + 1,
> >> +                                                             GFP_KERNEL);
> >> +                                     if (!ses->domainName)
> >> +                                                     return -ENOMEM;
> >> +                                     cifs_from_ucs2(ses->domainName,
> >> +                                             (__le16 *)blobptr,
> >> +                                             attrptr->length,
> >> +                                             attrptr->length,
> >> +                                             load_nls_default(), false);
> >> +                             }
> >> +                     }
> >> +                     blobptr += attrsize; /* advance attr  value */
> >> +                     attrptr = (struct ntlmssp2_name *) blobptr;
> >> +             }
> >> +     }
> >> +
> >> +     return rc;
> >> +}
> >> +
> >
> > I think the above function needs some bounds checking. What prevents
> > the client from trying to access data past the end of the tiblob? I see
> > no reference to the tilen in that function.
> 
> Jeff, when a server provides AV pair blob in type 2 packet during
> ntlmssp negotiation, the last field is always supposed to be 0
> (I defined it as NTLMSSP_AV_EOL).
> 
> Would a change like
>    while ((type = attrptr->type) != NTLMSSP_AV_EOL) {
> be a good enough check?
> 

No. There's no guarantee that the server is well-behaved here. What if
the last field isn't 0? That's at least a possible DoS attack vector if
someone can replace the server.

> 
> >
> >
> >>  static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
> >>                           const struct nls_table *nls_cp)
> >>  {
> >> @@ -334,10 +407,6 @@ void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
> >>       buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
> >>       get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
> >>       buf->reserved2 = 0;
> >> -     buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
> >> -     buf->names[0].length = 0;
> >> -     buf->names[1].type = 0;
> >> -     buf->names[1].length = 0;
> >>
> >>       /* calculate buf->ntlmv2_hash */
> >>       rc = calc_ntlmv2_hash(ses, nls_cp);
> >> diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
> >> index f5c78fb..dc90a36 100644
> >> --- a/fs/cifs/cifspdu.h
> >> +++ b/fs/cifs/cifspdu.h
> >> @@ -670,7 +670,6 @@ struct ntlmv2_resp {
> >>       __le64  time;
> >>       __u64  client_chal; /* random */
> >>       __u32  reserved2;
> >> -     struct ntlmssp2_name names[2];
> >>       /* array of name entries could follow ending in minimum 4 byte struct */
> >>  } __attribute__((packed));
> >>
> >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> >> index f5369e7..0621a72 100644
> >> --- a/fs/cifs/connect.c
> >> +++ b/fs/cifs/connect.c
> >> @@ -1768,6 +1768,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
> >>       if (ses == NULL)
> >>               goto get_ses_fail;
> >>
> >> +     ses->tilen = 0;
> >> +     ses->tiblob = NULL;
> >>       /* new SMB session uses our server ref */
> >>       ses->server = server;
> >>       if (server->addr.sockAddr6.sin6_family == AF_INET6)
> >> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
> >> index 0a57cb7..756f410 100644
> >> --- a/fs/cifs/sess.c
> >> +++ b/fs/cifs/sess.c
> >> @@ -383,6 +383,9 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
> >>  static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
> >>                                   struct cifsSesInfo *ses)
> >>  {
> >> +     unsigned int tioffset; /* challenge message target info area */
> >> +     unsigned int tilen; /* challenge message target info area length  */
> >> +
> >>       CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
> >>
> >>       if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
> >> @@ -405,6 +408,20 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
> >>       /* BB spec says that if AvId field of MsvAvTimestamp is populated then
> >>               we must set the MIC field of the AUTHENTICATE_MESSAGE */
> >>
> >> +     ses->server->ntlmssp.server_flags = le32_to_cpu(pblob->NegotiateFlags);
> >> +
> >> +     tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
> >> +     tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
> >> +     ses->tilen = tilen;
> >> +     if (ses->tilen) {
> >> +             ses->tiblob = kmalloc(tilen, GFP_KERNEL);
> >> +             if (!ses->tiblob) {
> >> +                     cERROR(1, "Challenge target info allocation failure");
> >> +                     return -ENOMEM;
> >> +             }
> >> +             memcpy(ses->tiblob,  bcc_ptr + tioffset, ses->tilen);
> >> +     }
> >> +
> >>       return 0;
> >>  }
> >>
> >> @@ -533,6 +550,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
> >>       sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
> >>       sec_blob->SessionKey.Length = 0;
> >>       sec_blob->SessionKey.MaximumLength = 0;
> >> +
> >>       return tmp - pbuffer;
> >>  }
> >>
> >
> >
> > --
> > Jeff Layton <jlayton@xxxxxxxxx>
> > --
> > 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
> >
> --
> 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
> 


-- 
Jeff Layton <jlayton@xxxxxxxxx>
--
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