smbd:smb2: fix crash when smb2 session reauth fails
authorMichael Adam <obnox@samba.org>
Thu, 19 Sep 2013 21:41:51 +0000 (23:41 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 15 Oct 2013 18:48:19 +0000 (11:48 -0700)
https://bugzilla.samba.org/show_bug.cgi?id=10208

Authentication error in smb2 session reauth invalidates
the session. In this case the session must in contrast
to successful session setup requests be torn down and live
no longer than the request.

The talloc move of the session from the global session
table to the request ensures that the session setup
reply can still be correctly signed, but subsequent
requests on the connection don't find a session any more.

Pair-Programmed-With: Jeremy Allison <jra@samba.org>
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Michael Adam <obnox@samba.org>
source3/smbd/smb2_sesssetup.c

index 265f8020215805a50f83525a570da6470ab2e40b..dd243c91d157ebeaf89eb1e8aab761847c837be2 100644 (file)
@@ -458,10 +458,19 @@ static int pp_self_ref_destructor(struct smbd_smb2_session_setup_state **pp_stat
 static int smbd_smb2_session_setup_state_destructor(struct smbd_smb2_session_setup_state *state)
 {
        /*
-        * if state->session is not NULL,
-        * we remove the session on failure
+        * If state->session is not NULL,
+        * we move the session from the session table to the request on failure
+        * so that the error response can be correctly signed, but the session
+        * is then really deleted when the request is done.
         */
-       TALLOC_FREE(state->session);
+
+       if (state->session == NULL) {
+               return 0;
+       }
+
+       state->session->status = NT_STATUS_USER_SESSION_DELETED;
+       state->smb2req->session = talloc_move(state->smb2req, &state->session);
+
        return 0;
 }
 
@@ -614,6 +623,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
        if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                state->out_session_id = state->session->global->session_wire_id;
                /* we want to keep the session */
+               state->session = NULL;
                TALLOC_FREE(state->pp_self_ref);
                tevent_req_nterror(req, status);
                return;
@@ -654,6 +664,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
                        return;
                }
                /* we want to keep the session */
+               state->session = NULL;
                TALLOC_FREE(state->pp_self_ref);
                tevent_req_done(req);
                return;
@@ -670,6 +681,7 @@ static void smbd_smb2_session_setup_gensec_done(struct tevent_req *subreq)
        }
 
        /* we want to keep the session */
+       state->session = NULL;
        TALLOC_FREE(state->pp_self_ref);
        tevent_req_done(req);
        return;
@@ -701,6 +713,7 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
                        return;
                }
                /* we want to keep the session */
+               state->session = NULL;
                TALLOC_FREE(state->pp_self_ref);
                tevent_req_done(req);
                return;
@@ -717,6 +730,7 @@ static void smbd_smb2_session_setup_previous_done(struct tevent_req *subreq)
        }
 
        /* we want to keep the session */
+       state->session = NULL;
        TALLOC_FREE(state->pp_self_ref);
        tevent_req_done(req);
        return;