All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sachin Prabhu <sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
To: Steve French <smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: linux-cifs <linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH 1/2] SMB2: Separate Kerberos authentication from SMB2_sess_setup
Date: Fri, 07 Oct 2016 14:42:25 +0100	[thread overview]
Message-ID: <1475847745.2493.14.camel@redhat.com> (raw)
In-Reply-To: <CAH2r5mth8ov+5XuYVoNDy+s-umDDp4+20o4q6t=wHAvipMxT5g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Thu, 2016-10-06 at 16:02 -0500, Steve French wrote:
> Shouldn't the
> 
> #ifdef CONFIG_CIFS_UPCALL
> before SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) be moved
> up (before SMB2_sess_esablish_session)?
> 

No. This helper function is intended to also be used by the RawNTLMSSP
authentication method which the subsequent patch introduces.

The patch 
fab27e8c595a2028c71366fbb9fb2dada00ef7e7
Set previous session id correctly on SMB3 reconnect
changes a bit of the code which these patches change. I am rebasing the
two patches on top of the for-next branch and posting it to the list as
soon as I've completed my testing again.

Sachin Prabhu

> On Thu, Sep 22, 2016 at 9:04 AM, Sachin Prabhu <sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> wrote:
> > 
> > Add helper functions and split Kerberos authentication off
> > SMB2_sess_setup.
> > 
> > Signed-off-by: Sachin Prabhu <sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> > ---
> >  fs/cifs/smb2pdu.c | 270
> > ++++++++++++++++++++++++++++++++++++++++++++----------
> >  1 file changed, 224 insertions(+), 46 deletions(-)
> > 
> > diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> > index 29e06db..3cfdb6b 100644
> > --- a/fs/cifs/smb2pdu.c
> > +++ b/fs/cifs/smb2pdu.c
> > @@ -574,6 +574,211 @@ vneg_out:
> >         return -EIO;
> >  }
> > 
> > +struct SMB2_sess_data {
> > +       unsigned int xid;
> > +       struct cifs_ses *ses;
> > +       struct nls_table *nls_cp;
> > +       void (*func)(struct SMB2_sess_data *);
> > +       int result;
> > +
> > +       /* we will send the SMB in three pieces:
> > +        * a fixed length beginning part, an optional
> > +        * SPNEGO blob (which can be zero length), and a
> > +        * last part which will include the strings
> > +        * and rest of bcc area. This allows us to avoid
> > +        * a large buffer 17K allocation
> > +        */
> > +       int buf0_type;
> > +       struct kvec iov[2];
> > +};
> > +
> > +static int
> > +SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
> > +{
> > +       int rc;
> > +       struct cifs_ses *ses = sess_data->ses;
> > +       struct smb2_sess_setup_req *req;
> > +       struct TCP_Server_Info *server = ses->server;
> > +
> > +       rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **)
> > &req);
> > +       if (rc)
> > +               return rc;
> > +
> > +       req->hdr.SessionId = 0; /* First session, not a
> > reauthenticate */
> > +       req->Flags = 0; /* MBZ */
> > +       /* to enable echos and oplocks */
> > +       req->hdr.CreditRequest = cpu_to_le16(3);
> > +
> > +       /* only one of SMB2 signing flags may be set in SMB2
> > request */
> > +       if (server->sign)
> > +               req->SecurityMode =
> > SMB2_NEGOTIATE_SIGNING_REQUIRED;
> > +       else if (global_secflags & CIFSSEC_MAY_SIGN) /* one flag
> > unlike MUST_ */
> > +               req->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED;
> > +       else
> > +               req->SecurityMode = 0;
> > +
> > +       req->Capabilities = 0;
> > +       req->Channel = 0; /* MBZ */
> > +
> > +       sess_data->iov[0].iov_base = (char *)req;
> > +       /* 4 for rfc1002 length field and 1 for pad */
> > +       sess_data->iov[0].iov_len = get_rfc1002_length(req) + 4 -
> > 1;
> > +       /*
> > +        * This variable will be used to clear the buffer
> > +        * allocated above in case of any error in the calling
> > function.
> > +        */
> > +       sess_data->buf0_type = CIFS_SMALL_BUFFER;
> > +
> > +       return 0;
> > +}
> > +
> > +static void
> > +SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
> > +{
> > +       free_rsp_buf(sess_data->buf0_type, sess_data-
> > >iov[0].iov_base);
> > +       sess_data->buf0_type = CIFS_NO_BUFFER;
> > +}
> > +
> > +static int
> > +SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
> > +{
> > +       int rc;
> > +       struct smb2_sess_setup_req *req = sess_data-
> > >iov[0].iov_base;
> > +
> > +       /* Testing shows that buffer offset must be at location of
> > Buffer[0] */
> > +       req->SecurityBufferOffset =
> > +               cpu_to_le16(sizeof(struct smb2_sess_setup_req) -
> > +                       1 /* pad */ - 4 /* rfc1001 len */);
> > +       req->SecurityBufferLength = cpu_to_le16(sess_data-
> > >iov[1].iov_len);
> > +
> > +       inc_rfc1001_len(req, sess_data->iov[1].iov_len - 1 /* pad
> > */);
> > +
> > +       /* BB add code to build os and lm fields */
> > +
> > +       rc = SendReceive2(sess_data->xid, sess_data->ses,
> > +                               sess_data->iov, 2,
> > +                               &sess_data->buf0_type,
> > +                               CIFS_LOG_ERROR | CIFS_NEG_OP);
> > +
> > +       return rc;
> > +}
> > +
> > +static int
> > +SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
> > +{
> > +       int rc = 0;
> > +       struct cifs_ses *ses = sess_data->ses;
> > +
> > +       mutex_lock(&ses->server->srv_mutex);
> > +       if (ses->server->sign && ses->server->ops-
> > >generate_signingkey) {
> > +               rc = ses->server->ops->generate_signingkey(ses);
> > +               kfree(ses->auth_key.response);
> > +               ses->auth_key.response = NULL;
> > +               if (rc) {
> > +                       cifs_dbg(FYI,
> > +                               "SMB3 session key generation
> > failed\n");
> > +                       mutex_unlock(&ses->server->srv_mutex);
> > +                       goto keygen_exit;
> > +               }
> > +       }
> > +       if (!ses->server->session_estab) {
> > +               ses->server->sequence_number = 0x2;
> > +               ses->server->session_estab = true;
> > +       }
> > +       mutex_unlock(&ses->server->srv_mutex);
> > +
> > +       cifs_dbg(FYI, "SMB2/3 session established successfully\n");
> > +       spin_lock(&GlobalMid_Lock);
> > +       ses->status = CifsGood;
> > +       ses->need_reconnect = false;
> > +       spin_unlock(&GlobalMid_Lock);
> > +
> > +keygen_exit:
> > +       if (!ses->server->sign) {
> > +               kfree(ses->auth_key.response);
> > +               ses->auth_key.response = NULL;
> > +       }
> > +       return rc;
> > +}
> > +
> > +#ifdef CONFIG_CIFS_UPCALL
> > +static void
> > +SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
> > +{
> > +       int rc;
> > +       struct cifs_ses *ses = sess_data->ses;
> > +       struct cifs_spnego_msg *msg;
> > +       struct key *spnego_key = NULL;
> > +       struct smb2_sess_setup_rsp *rsp = NULL;
> > +
> > +       rc = SMB2_sess_alloc_buffer(sess_data);
> > +       if (rc)
> > +               goto out;
> > +
> > +       spnego_key = cifs_get_spnego_key(ses);
> > +       if (IS_ERR(spnego_key)) {
> > +               rc = PTR_ERR(spnego_key);
> > +               spnego_key = NULL;
> > +               goto out;
> > +       }
> > +
> > +       msg = spnego_key->payload.data[0];
> > +       /*
> > +        * check version field to make sure that cifs.upcall is
> > +        * sending us a response in an expected form
> > +        */
> > +       if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
> > +               cifs_dbg(VFS,
> > +                         "bad cifs.upcall version. Expected %d got
> > %d",
> > +                         CIFS_SPNEGO_UPCALL_VERSION, msg-
> > >version);
> > +               rc = -EKEYREJECTED;
> > +               goto out_put_spnego_key;
> > +       }
> > +
> > +       ses->auth_key.response = kmemdup(msg->data, msg-
> > >sesskey_len,
> > +                                        GFP_KERNEL);
> > +       if (!ses->auth_key.response) {
> > +               cifs_dbg(VFS,
> > +                       "Kerberos can't allocate (%u bytes)
> > memory",
> > +                       msg->sesskey_len);
> > +               rc = -ENOMEM;
> > +               goto out_put_spnego_key;
> > +       }
> > +       ses->auth_key.len = msg->sesskey_len;
> > +
> > +       sess_data->iov[1].iov_base = msg->data + msg->sesskey_len;
> > +       sess_data->iov[1].iov_len = msg->secblob_len;
> > +
> > +       rc = SMB2_sess_sendreceive(sess_data);
> > +       if (rc)
> > +               goto out_put_spnego_key;
> > +
> > +       rsp = (struct smb2_sess_setup_rsp *)sess_data-
> > >iov[0].iov_base;
> > +       ses->Suid = rsp->hdr.SessionId;
> > +
> > +       ses->session_flags = le16_to_cpu(rsp->SessionFlags);
> > +       if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
> > +               cifs_dbg(VFS, "SMB3 encryption not supported
> > yet\n");
> > +
> > +       rc = SMB2_sess_establish_session(sess_data);
> > +out_put_spnego_key:
> > +       key_invalidate(spnego_key);
> > +       key_put(spnego_key);
> > +out:
> > +       sess_data->result = rc;
> > +       sess_data->func = NULL;
> > +       SMB2_sess_free_buffer(sess_data);
> > +}
> > +#else
> > +static void
> > +SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
> > +{
> > +       cifs_dbg(VFS, "Kerberos negotiated but upcall support
> > disabled!\n");
> > +       sess_data->result = -EOPNOTSUPP;
> > +       sess_data->func = NULL;
> > +}
> > +#endif
> > +
> >  int
> >  SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
> >                 const struct nls_table *nls_cp)
> > @@ -586,10 +791,10 @@ SMB2_sess_setup(const unsigned int xid,
> > struct cifs_ses *ses,
> >         __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is
> > multistage */
> >         struct TCP_Server_Info *server = ses->server;
> >         u16 blob_length = 0;
> > -       struct key *spnego_key = NULL;
> >         char *security_blob = NULL;
> >         unsigned char *ntlmssp_blob = NULL;
> >         bool use_spnego = false; /* else use raw ntlmssp */
> > +       struct SMB2_sess_data *sess_data;
> > 
> >         cifs_dbg(FYI, "Session Setup\n");
> > 
> > @@ -598,6 +803,19 @@ SMB2_sess_setup(const unsigned int xid, struct
> > cifs_ses *ses,
> >                 return -EIO;
> >         }
> > 
> > +       sess_data = kzalloc(sizeof(struct SMB2_sess_data),
> > GFP_KERNEL);
> > +       if (!sess_data)
> > +               return -ENOMEM;
> > +       sess_data->xid = xid;
> > +       sess_data->ses = ses;
> > +       sess_data->buf0_type = CIFS_NO_BUFFER;
> > +       sess_data->nls_cp = (struct nls_table *) nls_cp;
> > +
> > +       if (ses->sectype == Kerberos) {
> > +               SMB2_auth_kerberos(sess_data);
> > +               goto out;
> > +       }
> > +
> >         /*
> >          * If we are here due to reconnect, free per-smb session
> > key
> >          * in case signing was required.
> > @@ -646,47 +864,7 @@ ssetup_ntlmssp_authenticate:
> >         /* 4 for rfc1002 length field and 1 for pad */
> >         iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
> > 
> > -       if (ses->sectype == Kerberos) {
> > -#ifdef CONFIG_CIFS_UPCALL
> > -               struct cifs_spnego_msg *msg;
> > -
> > -               spnego_key = cifs_get_spnego_key(ses);
> > -               if (IS_ERR(spnego_key)) {
> > -                       rc = PTR_ERR(spnego_key);
> > -                       spnego_key = NULL;
> > -                       goto ssetup_exit;
> > -               }
> > -
> > -               msg = spnego_key->payload.data[0];
> > -               /*
> > -                * check version field to make sure that
> > cifs.upcall is
> > -                * sending us a response in an expected form
> > -                */
> > -               if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
> > -                       cifs_dbg(VFS,
> > -                                 "bad cifs.upcall version.
> > Expected %d got %d",
> > -                                 CIFS_SPNEGO_UPCALL_VERSION, msg-
> > >version);
> > -                       rc = -EKEYREJECTED;
> > -                       goto ssetup_exit;
> > -               }
> > -               ses->auth_key.response = kmemdup(msg->data, msg-
> > >sesskey_len,
> > -                                                GFP_KERNEL);
> > -               if (!ses->auth_key.response) {
> > -                       cifs_dbg(VFS,
> > -                               "Kerberos can't allocate (%u bytes)
> > memory",
> > -                               msg->sesskey_len);
> > -                       rc = -ENOMEM;
> > -                       goto ssetup_exit;
> > -               }
> > -               ses->auth_key.len = msg->sesskey_len;
> > -               blob_length = msg->secblob_len;
> > -               iov[1].iov_base = msg->data + msg->sesskey_len;
> > -               iov[1].iov_len = blob_length;
> > -#else
> > -               rc = -EOPNOTSUPP;
> > -               goto ssetup_exit;
> > -#endif /* CONFIG_CIFS_UPCALL */
> > -       } else if (phase == NtLmNegotiate) { /* if not krb5 must be
> > ntlmssp */
> > +       if (phase == NtLmNegotiate) {
> >                 ntlmssp_blob = kmalloc(sizeof(struct
> > _NEGOTIATE_MESSAGE),
> >                                        GFP_KERNEL);
> >                 if (ntlmssp_blob == NULL) {
> > @@ -829,13 +1007,13 @@ keygen_exit:
> >                 kfree(ses->auth_key.response);
> >                 ses->auth_key.response = NULL;
> >         }
> > -       if (spnego_key) {
> > -               key_invalidate(spnego_key);
> > -               key_put(spnego_key);
> > -       }
> >         kfree(ses->ntlmssp);
> > 
> >         return rc;
> > +out:
> > +       rc = sess_data->result;
> > +       kfree(sess_data);
> > +       return rc;
> >  }
> > 
> >  int
> > --
> > 2.7.4
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> > cifs" in
> > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 

  parent reply	other threads:[~2016-10-07 13:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-22 14:04 [PATCH 0/2] Revamp SMB2 authentication code Sachin Prabhu
     [not found] ` <1474553094-8884-1-git-send-email-sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-09-22 14:04   ` [PATCH 1/2] SMB2: Separate Kerberos authentication from SMB2_sess_setup Sachin Prabhu
     [not found]     ` <1474553094-8884-2-git-send-email-sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-06 21:02       ` Steve French
     [not found]         ` <CAH2r5mth8ov+5XuYVoNDy+s-umDDp4+20o4q6t=wHAvipMxT5g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-10-07 13:42           ` Sachin Prabhu [this message]
2016-09-22 14:04   ` [PATCH 2/2] SMB2: Seperate RawNTLMSSP " Sachin Prabhu
2016-10-03 17:45   ` [PATCH 0/2] Revamp SMB2 authentication code Steve French
2016-10-07 18:11 [PATCH 0/2 v2 ] " Sachin Prabhu
     [not found] ` <1475863882-7223-1-git-send-email-sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-07 18:11   ` [PATCH 1/2] SMB2: Separate Kerberos authentication from SMB2_sess_setup Sachin Prabhu
     [not found]     ` <1475863882-7223-2-git-send-email-sprabhu-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-11 18:54       ` Pavel Shilovsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1475847745.2493.14.camel@redhat.com \
    --to=sprabhu-h+wxahxf7alqt0dzr+alfa@public.gmane.org \
    --cc=linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.