Add two flags to allow for handling of Extended Signatures (Session Key Protection...
[samba.git] / source3 / smbd / smb2_sesssetup.c
index ee588b06fe840d0be68f468e5086fbd3d3729923..53552929677ec9c6aaeca4e2532d5dfac54532f0 100644 (file)
@@ -411,6 +411,7 @@ static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_set
 }
 
 static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq);
+static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq);
 
 static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *ev,
@@ -440,6 +441,19 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx,
        state->in_previous_session_id = in_previous_session_id;
        state->in_security_buffer = in_security_buffer;
 
+       if (in_flags & SMB2_SESSION_FLAG_BINDING) {
+               if (smb2req->sconn->conn->protocol < PROTOCOL_SMB2_22) {
+                       tevent_req_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+                       return tevent_req_post(req, ev);
+               }
+
+               /*
+                * We do not support multi channel.
+                */
+               tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
+               return tevent_req_post(req, ev);
+       }
+
        talloc_set_destructor(state, smbd_smb2_session_setup_state_destructor);
 
        if (state->in_session_id == 0) {
@@ -534,6 +548,71 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
                return;
        }
 
+       if ((state->in_previous_session_id != 0) &&
+            (state->session->global->session_wire_id !=
+             state->in_previous_session_id))
+       {
+               subreq = smb2srv_session_close_previous_send(state, state->ev,
+                                               state->session->connection,
+                                               state->session_info,
+                                               state->in_previous_session_id,
+                                               state->session->global->session_wire_id);
+               if (tevent_req_nomem(subreq, req)) {
+                       return;
+               }
+               tevent_req_set_callback(subreq,
+                                       smbd_smb2_session_setup_previous_done,
+                                       req);
+               return;
+       }
+
+       if (state->session->global->auth_session_info != NULL) {
+               status = smbd_smb2_reauth_generic_return(state->session,
+                                                        state->smb2req,
+                                                        state->session_info,
+                                                        &state->out_session_flags,
+                                                        &state->out_session_id);
+               if (tevent_req_nterror(req, status)) {
+                       return;
+               }
+               /* we want to keep the session */
+               state->session = NULL;
+               tevent_req_done(req);
+               return;
+       }
+
+       status = smbd_smb2_auth_generic_return(state->session,
+                                              state->smb2req,
+                                              state->in_security_mode,
+                                              state->session_info,
+                                              &state->out_session_flags,
+                                              &state->out_session_id);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       /* we want to keep the session */
+       state->session = NULL;
+       tevent_req_done(req);
+       return;
+}
+
+static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq,
+               struct tevent_req);
+       struct smbd_smb2_session_setup_state *state =
+               tevent_req_data(req,
+               struct smbd_smb2_session_setup_state);
+       NTSTATUS status;
+
+       status = smb2srv_session_close_previous_recv(subreq);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
        if (state->session->global->auth_session_info != NULL) {
                status = smbd_smb2_reauth_generic_return(state->session,
                                                         state->smb2req,