Fix inspired by work done by David Disseldorp for bug #8040 - smbclient segfaults...
[ira/wip.git] / libcli / auth / ntlmssp_server.c
index 9c177eece0d8ead5df4be2401fadaf014a099313..802ac402b4969fb861117db53c0b182661b47ad0 100644 (file)
@@ -144,12 +144,15 @@ NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
        /* This creates the 'blob' of names that appears at the end of the packet */
        if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
        {
-               msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
+               status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
                          MsvAvNbDomainName, target_name,
                          MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
                          MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
                          MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
                          MsvAvEOL, "");
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
        } else {
                struct_blob = data_blob_null;
        }
@@ -161,7 +164,7 @@ NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
 
                if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
                        enum ndr_err_code err;
-                       struct VERSION vers;
+                       struct ntlmssp_VERSION vers;
 
                        /* "What Windows returns" as a version number. */
                        ZERO_STRUCT(vers);
@@ -173,7 +176,7 @@ NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
                        err = ndr_push_struct_blob(&version_blob,
                                                ntlmssp_state,
                                                &vers,
-                                               (ndr_push_flags_fn_t)ndr_push_VERSION);
+                                               (ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);
 
                        if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
                                data_blob_free(&struct_blob);
@@ -187,7 +190,7 @@ NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
                        gen_string = "CdAdbddBb";
                }
 
-               msrpc_gen(out_mem_ctx, reply, gen_string,
+               status = msrpc_gen(out_mem_ctx, reply, gen_string,
                        "NTLMSSP",
                        NTLMSSP_CHALLENGE,
                        target_name,
@@ -197,6 +200,12 @@ NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
                        struct_blob.data, struct_blob.length,
                        version_blob.data, version_blob.length);
 
+               if (!NT_STATUS_IS_OK(status)) {
+                       data_blob_free(&version_blob);
+                       data_blob_free(&struct_blob);
+                       return status;
+               }
+
                data_blob_free(&version_blob);
 
                if (DEBUGLEVEL >= 10) {
@@ -393,7 +402,7 @@ static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
 {
        DATA_BLOB user_session_key = state->user_session_key;
        DATA_BLOB lm_session_key = state->lm_session_key;
-       NTSTATUS nt_status;
+       NTSTATUS nt_status = NT_STATUS_OK;
        DATA_BLOB session_key = data_blob(NULL, 0);
 
        dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
@@ -478,7 +487,6 @@ static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
                if (!state->encrypted_session_key.data
                    || state->encrypted_session_key.length != 16) {
-                       data_blob_free(&state->encrypted_session_key);
                        DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
                                  (unsigned)state->encrypted_session_key.length));
                        return NT_STATUS_INVALID_PARAMETER;
@@ -486,6 +494,7 @@ static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
                        DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
                                  (unsigned int)session_key.length));
                        ntlmssp_state->session_key = session_key;
+                       talloc_steal(ntlmssp_state, session_key.data);
                } else {
                        dump_data_pw("KEY_EXCH session key (enc):\n",
                                     state->encrypted_session_key.data,
@@ -499,10 +508,10 @@ static NTSTATUS ntlmssp_server_postauth(struct ntlmssp_state *ntlmssp_state,
                        dump_data_pw("KEY_EXCH session key:\n",
                                     state->encrypted_session_key.data,
                                     state->encrypted_session_key.length);
-                       talloc_free(session_key.data);
                }
        } else {
                ntlmssp_state->session_key = session_key;
+               talloc_steal(ntlmssp_state, session_key.data);
        }
 
        if (ntlmssp_state->session_key.length) {
@@ -555,6 +564,7 @@ NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
 
        /* Finally, actually ask if the password is OK */
        nt_status = ntlmssp_state->check_password(ntlmssp_state,
+                                                 state,
                                                  &state->user_session_key,
                                                  &state->lm_session_key);
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -567,11 +577,6 @@ NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
           can be done in a callback */
 
        nt_status = ntlmssp_server_postauth(ntlmssp_state, state);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               TALLOC_FREE(state);
-               return nt_status;
-       }
-
        TALLOC_FREE(state);
-       return NT_STATUS_OK;
+       return nt_status;
 }