s4:libcli/smb2: add smb2_session_channel()
authorStefan Metzmacher <metze@samba.org>
Mon, 23 Jun 2014 22:22:30 +0000 (00:22 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 24 Jul 2014 17:07:06 +0000 (19:07 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source4/libcli/smb2/session.c
source4/libcli/smb2/smb2.h

index 4d1402a09b34439c3fe52abd14a676095b033169..9ab96a3a13fd6f94e32ea098106f53b33c00f639 100644 (file)
@@ -66,11 +66,54 @@ struct smb2_session *smb2_session_init(struct smb2_transport *transport,
        return session;
 }
 
+/*
+ * Note: that the caller needs to keep 'transport' around as
+ *       long as the returned session is active!
+ */
+struct smb2_session *smb2_session_channel(struct smb2_transport *transport,
+                                         struct gensec_settings *settings,
+                                         TALLOC_CTX *parent_ctx,
+                                         struct smb2_session *base_session)
+{
+       struct smb2_session *session;
+       NTSTATUS status;
+
+       session = talloc_zero(parent_ctx, struct smb2_session);
+       if (!session) {
+               return NULL;
+       }
+       session->transport = transport;
+
+       status = smb2cli_session_create_channel(session,
+                                               base_session->smbXcli,
+                                               transport->conn,
+                                               &session->smbXcli);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(session);
+               return NULL;
+       }
+
+       session->needs_bind = true;
+
+       /* prepare a gensec context for later use */
+       status = gensec_client_start(session, &session->gensec,
+                                    settings);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(session);
+               return NULL;
+       }
+
+       gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
+
+       return session;
+}
+
 struct smb2_session_setup_spnego_state {
        struct tevent_context *ev;
        struct smb2_session *session;
        struct cli_credentials *credentials;
        uint64_t previous_session_id;
+       bool session_bind;
        bool reauth;
        NTSTATUS gensec_status;
        DATA_BLOB in_secblob;
@@ -98,6 +141,7 @@ struct tevent_req *smb2_session_setup_spnego_send(
        const DATA_BLOB *server_gss_blob;
        DATA_BLOB negprot_secblob = data_blob_null;
        uint32_t timeout_msec;
+       uint8_t in_flags = 0;
 
        timeout_msec = session->transport->options.request_timeout * 1000;
 
@@ -112,10 +156,11 @@ struct tevent_req *smb2_session_setup_spnego_send(
        state->previous_session_id = previous_session_id;
 
        current_session_id = smb2cli_session_current_id(state->session->smbXcli);
-       if (current_session_id != 0) {
+       if (state->session->needs_bind) {
+               state->session_bind = true;
+       } else if (current_session_id != 0) {
                state->reauth = true;
        }
-
        server_gss_blob = smbXcli_conn_server_gss_blob(session->transport->conn);
        if (server_gss_blob) {
                negprot_secblob = *server_gss_blob;
@@ -158,11 +203,15 @@ struct tevent_req *smb2_session_setup_spnego_send(
        }
        state->gensec_status = status;
 
+       if (state->session_bind) {
+               in_flags |= SMB2_SESSION_FLAG_BINDING;
+       }
+
        subreq = smb2cli_session_setup_send(state, state->ev,
                                            session->transport->conn,
                                            timeout_msec,
                                            session->smbXcli,
-                                           0, /* in_flags */
+                                           in_flags,
                                            0, /* in_capabilities */
                                            0, /* in_channel */
                                            state->previous_session_id,
@@ -191,6 +240,7 @@ static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
        NTSTATUS status;
        struct iovec *recv_iov;
        uint32_t timeout_msec;
+       uint8_t in_flags = 0;
 
        timeout_msec = session->transport->options.request_timeout * 1000;
 
@@ -246,22 +296,35 @@ static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
                        return;
                }
 
-               status = smb2cli_session_set_session_key(session->smbXcli,
-                                                        session_key,
-                                                        recv_iov);
-               if (tevent_req_nterror(req, status)) {
-                       return;
+               if (state->session_bind) {
+                       status = smb2cli_session_set_channel_key(session->smbXcli,
+                                                                session_key,
+                                                                recv_iov);
+                       if (tevent_req_nterror(req, status)) {
+                               return;
+                       }
+                       session->needs_bind = false;
+               } else {
+                       status = smb2cli_session_set_session_key(session->smbXcli,
+                                                                session_key,
+                                                                recv_iov);
+                       if (tevent_req_nterror(req, status)) {
+                               return;
+                       }
                }
-
                tevent_req_done(req);
                return;
        }
 
+       if (state->session_bind) {
+               in_flags |= SMB2_SESSION_FLAG_BINDING;
+       }
+
        subreq = smb2cli_session_setup_send(state, state->ev,
                                            session->transport->conn,
                                            timeout_msec,
                                            session->smbXcli,
-                                           0, /* in_flags */
+                                           in_flags,
                                            0, /* in_capabilities */
                                            0, /* in_channel */
                                            state->previous_session_id,
index 101ef7380760146e2662e75059bd628deac04441..73e117a961d550ff8efe37543c17ce88f8585169 100644 (file)
@@ -116,6 +116,7 @@ struct smb2_session {
        struct smb2_transport *transport;
        struct gensec_security *gensec;
        struct smbXcli_session *smbXcli;
+       bool needs_bind;
 };