s3-ntlmssp Remove a level of nesting in if/else statement
[amitay/samba.git] / source3 / auth / auth_ntlmssp.c
index af3a6f382787390c726e37e77a0a86455545f551..392955685c93f1571a4a4bd9edab2c54f3eeddb9 100644 (file)
 */
 
 #include "includes.h"
+#include "auth.h"
 #include "../libcli/auth/ntlmssp.h"
 #include "ntlmssp_wrap.h"
 #include "../librpc/gen_ndr/netlogon.h"
+#include "../lib/tsocket/tsocket.h"
+#include "auth/gensec/gensec.h"
+#include "librpc/rpc/dcerpc.h"
 
-NTSTATUS auth_ntlmssp_steal_server_info(TALLOC_CTX *mem_ctx,
-                                       struct auth_ntlmssp_state *auth_ntlmssp_state,
-                                       struct auth_serversupplied_info **server_info)
+NTSTATUS auth_ntlmssp_session_info(TALLOC_CTX *mem_ctx,
+                                  struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                  struct auth_session_info **session_info)
 {
-       /* Free the current server_info user_session_key and reset it from the
-        * current ntlmssp_state session_key */
-       data_blob_free(&auth_ntlmssp_state->server_info->user_session_key);
-       /* Set up the final session key for the connection */
-       auth_ntlmssp_state->server_info->user_session_key =
-               data_blob_talloc(
-                       auth_ntlmssp_state->server_info,
-                       auth_ntlmssp_state->ntlmssp_state->session_key.data,
-                       auth_ntlmssp_state->ntlmssp_state->session_key.length);
-       if (auth_ntlmssp_state->ntlmssp_state->session_key.length &&
-           !auth_ntlmssp_state->server_info->user_session_key.data) {
-               *server_info = NULL;
-               return NT_STATUS_NO_MEMORY;
+       NTSTATUS nt_status;
+       if (auth_ntlmssp_state->gensec_security) {
+
+               nt_status = gensec_session_info(auth_ntlmssp_state->gensec_security,
+                                               mem_ctx,
+                                               session_info);
+               return nt_status;
        }
-       /* Steal server_info away from auth_ntlmssp_state */
-       *server_info = talloc_move(mem_ctx, &auth_ntlmssp_state->server_info);
-       return NT_STATUS_OK;
+
+       nt_status = create_local_token(mem_ctx,
+                                      auth_ntlmssp_state->server_info,
+                                      &auth_ntlmssp_state->ntlmssp_state->session_key,
+                                      auth_ntlmssp_state->ntlmssp_state->user,
+                                      session_info);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(10, ("create_local_token failed: %s\n",
+                          nt_errstr(nt_status)));
+       }
+       return nt_status;
 }
 
 /**
@@ -107,7 +114,7 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state,
  */
 
 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *mem_ctx,
-                                           DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)
+                                           DATA_BLOB *session_key, DATA_BLOB *lm_session_key)
 {
        struct auth_ntlmssp_state *auth_ntlmssp_state =
                (struct auth_ntlmssp_state *)ntlmssp_state->callback_private;
@@ -124,23 +131,24 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
        /* sub_set_smb_name checks for weird internally */
        sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user);
 
-       reload_services(smbd_messaging_context(), -1, True);
+       lp_load(get_dyn_CONFIGFILE(), false, false, true, true);
 
-       nt_status = make_user_info_map(&user_info, 
+       nt_status = make_user_info_map(&user_info,
                                       auth_ntlmssp_state->ntlmssp_state->user, 
                                       auth_ntlmssp_state->ntlmssp_state->domain, 
                                       auth_ntlmssp_state->ntlmssp_state->client.netbios_name,
+                                      auth_ntlmssp_state->remote_address,
                                       auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
                                       auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
                                       NULL, NULL, NULL,
                                       AUTH_PASSWORD_RESPONSE);
 
-       user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
-
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
+       user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
+
        nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, 
                                                                          user_info, &auth_ntlmssp_state->server_info); 
 
@@ -149,30 +157,30 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
        free_user_info(&user_info);
 
        if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
+               nt_status = do_map_to_guest_server_info(nt_status,
+                                                       &auth_ntlmssp_state->server_info,
+                                                       auth_ntlmssp_state->ntlmssp_state->user,
+                                                       auth_ntlmssp_state->ntlmssp_state->domain);
        }
 
-       auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
-
-       nt_status = create_local_token(auth_ntlmssp_state->server_info);
-
        if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(10, ("create_local_token failed: %s\n",
-                       nt_errstr(nt_status)));
                return nt_status;
        }
 
+       talloc_steal(auth_ntlmssp_state, auth_ntlmssp_state->server_info);
+
+       auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
+
        /* Clear out the session keys, and pass them to the caller.
         * They will not be used in this form again - instead the
         * NTLMSSP code will decide on the final correct session key,
-        * and put it back here at the end of
-        * auth_ntlmssp_steal_server_info */
-       if (auth_ntlmssp_state->server_info->user_session_key.length) {
+        * and supply it to create_local_token() */
+       if (auth_ntlmssp_state->server_info->session_key.length) {
                DEBUG(10, ("Got NT session key of length %u\n",
-                       (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
-               *user_session_key = auth_ntlmssp_state->server_info->user_session_key;
-               talloc_steal(mem_ctx, auth_ntlmssp_state->server_info->user_session_key.data);
-               auth_ntlmssp_state->server_info->user_session_key = data_blob_null;
+                       (unsigned int)auth_ntlmssp_state->server_info->session_key.length));
+               *session_key = auth_ntlmssp_state->server_info->session_key;
+               talloc_steal(mem_ctx, auth_ntlmssp_state->server_info->session_key.data);
+               auth_ntlmssp_state->server_info->session_key = data_blob_null;
        }
        if (auth_ntlmssp_state->server_info->lm_session_key.length) {
                DEBUG(10, ("Got LM session key of length %u\n",
@@ -184,9 +192,8 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
        return nt_status;
 }
 
-static int auth_ntlmssp_state_destructor(void *ptr);
-
-NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
+NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address,
+                             struct auth_ntlmssp_state **auth_ntlmssp_state)
 {
        NTSTATUS nt_status;
        bool is_standalone;
@@ -197,13 +204,37 @@ NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
        struct auth_ntlmssp_state *ans;
        struct auth_context *auth_context;
 
-       if ((enum server_types)lp_server_role() == ROLE_STANDALONE) {
+       ans = talloc_zero(NULL, struct auth_ntlmssp_state);
+       if (!ans) {
+               DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       nt_status = make_auth_context_subsystem(talloc_tos(), &auth_context);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               TALLOC_FREE(ans);
+               return nt_status;
+       }
+
+       ans->auth_context = talloc_steal(ans, auth_context);
+
+       if (auth_context->prepare_gensec) {
+               nt_status = auth_context->prepare_gensec(ans, &ans->gensec_security);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       TALLOC_FREE(ans);
+                       return nt_status;
+               }
+               *auth_ntlmssp_state = ans;
+               return NT_STATUS_OK;
+       }
+
+       if ((enum server_role)lp_server_role() == ROLE_STANDALONE) {
                is_standalone = true;
        } else {
                is_standalone = false;
        }
 
-       netbios_name = global_myname();
+       netbios_name = lp_netbios_name();
        netbios_domain = lp_workgroup();
        /* This should be a 'netbios domain -> DNS domain' mapping */
        dns_domain = get_mydnsdomname(talloc_tos());
@@ -212,8 +243,8 @@ NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
        }
        dns_name = get_mydnsfullname();
 
-       ans = talloc_zero(NULL, struct auth_ntlmssp_state);
-       if (!ans) {
+       ans->remote_address = tsocket_address_copy(remote_address, ans);
+       if (ans->remote_address == NULL) {
                DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
                return NT_STATUS_NO_MEMORY;
        }
@@ -229,31 +260,72 @@ NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
                return nt_status;
        }
 
-       nt_status = make_auth_context_subsystem(&auth_context);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               return nt_status;
-       }
-       ans->auth_context = talloc_steal(ans, auth_context);
-
        ans->ntlmssp_state->callback_private = ans;
        ans->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
        ans->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
        ans->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
        ans->ntlmssp_state->check_password = auth_ntlmssp_check_password;
 
-       talloc_set_destructor((TALLOC_CTX *)ans, auth_ntlmssp_state_destructor);
-
        *auth_ntlmssp_state = ans;
        return NT_STATUS_OK;
 }
 
-static int auth_ntlmssp_state_destructor(void *ptr)
+NTSTATUS auth_generic_start(struct auth_ntlmssp_state *auth_ntlmssp_state, const char *oid)
 {
-       struct auth_ntlmssp_state *ans;
+       if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid) {
+               return auth_ntlmssp_state->auth_context->gensec_start_mech_by_oid(auth_ntlmssp_state->gensec_security, oid);
+       }
 
-       ans = talloc_get_type(ptr, struct auth_ntlmssp_state);
+       if (strcmp(oid, GENSEC_OID_NTLMSSP) != 0) {
+               /* The caller will then free the auth_ntlmssp_state,
+                * undoing what was done in auth_ntlmssp_prepare().
+                *
+                * We can't do that logic here, as
+                * auth_ntlmssp_want_feature() may have been called in
+                * between.
+                */
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS auth_generic_authtype_start(struct auth_ntlmssp_state *auth_ntlmssp_state, 
+                                    uint8_t auth_type, uint8_t auth_level)
+{
+       if (auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype) {
+               return auth_ntlmssp_state->auth_context->gensec_start_mech_by_authtype(auth_ntlmssp_state->gensec_security,
+                                                                                      auth_type, auth_level);
+       }
+
+       if (auth_type != DCERPC_AUTH_TYPE_NTLMSSP) {
+               /* The caller will then free the auth_ntlmssp_state,
+                * undoing what was done in auth_ntlmssp_prepare().
+                *
+                * We can't do that logic here, as
+                * auth_ntlmssp_want_feature() may have been called in
+                * between.
+                */
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
+               auth_ntlmssp_want_feature(auth_ntlmssp_state, NTLMSSP_FEATURE_SIGN);
+       } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
+               /* Always implies both sign and seal for ntlmssp */
+               auth_ntlmssp_want_feature(auth_ntlmssp_state, NTLMSSP_FEATURE_SEAL);
+       } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
+               /* Default features */
+       } else {
+               DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
+                        auth_level));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       TALLOC_FREE(ans->server_info);
-       TALLOC_FREE(ans->ntlmssp_state);
-       return 0;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_generic_start(auth_ntlmssp_state, GENSEC_OID_NTLMSSP);
 }