s3:auth Change auth_ntlmssp_server_info API to return NTSTATUS
[kamenim/samba.git] / source3 / smbd / smb2_sesssetup.c
index 7ac003fad6e17dd98dad063dc0109e56e7541030..6586a454395d431a9c561ca24a2197ba3dc5dfe9 100644 (file)
@@ -23,7 +23,7 @@
 #include "smbd/globals.h"
 #include "../libcli/smb/smb_common.h"
 #include "../libcli/auth/spnego.h"
-#include "ntlmssp.h"
+#include "../libcli/auth/ntlmssp.h"
 
 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
                                        uint64_t in_session_id,
@@ -170,7 +170,6 @@ static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
        fstring tmp;
        bool username_was_mapped = false;
        bool map_domainuser_to_guest = false;
-       struct smbd_server_connection *sconn = smbd_server_conn;
 
        if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
                status = NT_STATUS_LOGON_FAILURE;
@@ -265,7 +264,7 @@ static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
 
        /* lookup the passwd struct, create a new user if necessary */
 
-       username_was_mapped = map_username(sconn, user);
+       username_was_mapped = map_username(user);
 
        pw = smb_getpwnam(talloc_tos(), user, real_username, true );
        if (pw) {
@@ -345,6 +344,7 @@ static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
                        DEBUG(10, ("smb2: found user %s in passdb, calling "
                                "make_server_info_sam\n", real_username));
                        status = make_server_info_sam(&tmp_server_info, sampass);
+                       TALLOC_FREE(sampass);
                } else {
                        /*
                         * User not in passdb, make it up artificially
@@ -444,7 +444,8 @@ static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
                        register_homes_share(session->server_info->unix_name);
        }
 
-       if (!session_claim(session->compat_vuser)) {
+       if (!session_claim(sconn_server_id(session->sconn),
+                          session->compat_vuser)) {
                DEBUG(1, ("smb2: Failed to claim session "
                        "for vuid=%d\n",
                        session->compat_vuser->vuid));
@@ -553,15 +554,25 @@ static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
        }
 #endif
 
-       /* Fall back to NTLMSSP. */
-       status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
+       if (kerb_mech) {
+               /* The mechtoken is a krb5 ticket, but
+                * we need to fall back to NTLM. */
 
-       status = auth_ntlmssp_update(session->auth_ntlmssp_state,
-                                    secblob_in,
-                                    &chal_out);
+               DEBUG(3,("smb2: Got krb5 ticket in SPNEGO "
+                       "but set to downgrade to NTLMSSP\n"));
+
+               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+       } else {
+               /* Fall back to NTLMSSP. */
+               status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+
+               status = auth_ntlmssp_update(session->auth_ntlmssp_state,
+                                            secblob_in,
+                                            &chal_out);
+       }
 
        if (!NT_STATUS_IS_OK(status) &&
                        !NT_STATUS_EQUAL(status,
@@ -604,13 +615,20 @@ static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *s
                                        uint64_t *out_session_id)
 {
        fstring tmp;
+       NTSTATUS status = auth_ntlmssp_server_info(session, session->auth_ntlmssp_state,
+                                                  &session->server_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               auth_ntlmssp_end(&session->auth_ntlmssp_state);
+               TALLOC_FREE(session);
+               return status;
+       }
 
        if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
            lp_server_signing() == Required) {
                session->do_signing = true;
        }
 
-       if (session->auth_ntlmssp_state->server_info->guest) {
+       if (session->server_info->guest) {
                /* we map anonymous to guest internally */
                *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
                *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
@@ -618,20 +636,6 @@ static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *s
                session->do_signing = false;
        }
 
-       session->server_info = session->auth_ntlmssp_state->server_info;
-       data_blob_free(&session->server_info->user_session_key);
-       session->server_info->user_session_key =
-               data_blob_talloc(
-                       session->server_info,
-                       session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
-                       session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
-       if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
-               if (session->server_info->user_session_key.data == NULL) {
-                       auth_ntlmssp_end(&session->auth_ntlmssp_state);
-                       TALLOC_FREE(session);
-                       return NT_STATUS_NO_MEMORY;
-               }
-       }
        session->session_key = session->server_info->user_session_key;
 
        session->compat_vuser = talloc_zero(session, user_struct);
@@ -649,18 +653,19 @@ static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *s
 
        /* This is a potentially untrusted username */
        alpha_strcpy(tmp,
-               session->auth_ntlmssp_state->ntlmssp_state->user,
-               ". _-$",
-               sizeof(tmp));
+                    auth_ntlmssp_get_username(session->auth_ntlmssp_state),
+                    ". _-$",
+                    sizeof(tmp));
        session->server_info->sanitized_username = talloc_strdup(
-                       session->server_info, tmp);
+               session->server_info, tmp);
 
        if (!session->compat_vuser->server_info->guest) {
                session->compat_vuser->homes_snum =
                        register_homes_share(session->server_info->unix_name);
        }
 
-       if (!session_claim(session->compat_vuser)) {
+       if (!session_claim(sconn_server_id(session->sconn),
+                          session->compat_vuser)) {
                DEBUG(1, ("smb2: Failed to claim session "
                        "for vuid=%d\n",
                        session->compat_vuser->vuid));
@@ -752,12 +757,24 @@ static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
                        SAFE_FREE(kerb_mech);
                        return NT_STATUS_LOGON_FAILURE;
                }
+
+               data_blob_free(&secblob_in);
+       }
+
+       if (session->auth_ntlmssp_state == NULL) {
+               status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       data_blob_free(&auth);
+                       TALLOC_FREE(session);
+                       return status;
+               }
        }
 
        status = auth_ntlmssp_update(session->auth_ntlmssp_state,
                                     auth,
                                     &auth_out);
-       if (!NT_STATUS_IS_OK(status)) {
+       if (!NT_STATUS_IS_OK(status) &&
+                       !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                auth_ntlmssp_end(&session->auth_ntlmssp_state);
                data_blob_free(&auth);
                TALLOC_FREE(session);
@@ -780,6 +797,11 @@ static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
 
        *out_session_id = session->vuid;
 
+       if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       }
+
+       /* We're done - claim the session. */
        return smbd_smb2_common_ntlmssp_auth_return(session,
                                                smb2req,
                                                in_security_mode,