s3:auth Make AUTH_NTLMSSP_STATE a private structure.
authorAndrew Bartlett <abartlet@samba.org>
Tue, 25 May 2010 05:34:06 +0000 (15:34 +1000)
committerGünther Deschner <gd@samba.org>
Mon, 31 May 2010 13:10:33 +0000 (15:10 +0200)
This makes it a little easier for it to writen in terms of GENSEC in future.

Andrew Bartlett

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Günther Deschner <gd@samba.org>
source3/auth/auth_ntlmssp.c
source3/include/auth.h
source3/include/proto.h
source3/rpc_server/srv_pipe.c
source3/smbd/seal.c
source3/smbd/sesssetup.c
source3/smbd/smb2_sesssetup.c

index 762411702f245806a9713266e096ca475999a78a..cdc00d80c0801f2b8250b279c34c19568d3bdece 100644 (file)
 #include "includes.h"
 #include "ntlmssp.h"
 
+struct auth_ntlmssp_state {
+       TALLOC_CTX *mem_ctx;
+       struct auth_context *auth_context;
+       struct auth_serversupplied_info *server_info;
+       struct ntlmssp_state *ntlmssp_state;
+};
+
+NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 const uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig)
+{
+       return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                  const uint8_t *data, size_t length,
+                                  const uint8_t *whole_pdu, size_t pdu_length,
+                                  const DATA_BLOB *sig)
+{
+       return ntlmssp_check_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig)
+{
+       return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                   uint8_t *data, size_t length,
+                                   const uint8_t *whole_pdu, size_t pdu_length,
+                                   const DATA_BLOB *sig)
+{
+       return ntlmssp_unseal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN;
+}
+
+bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL;
+}
+
+struct auth_serversupplied_info *auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
+                                                         struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       struct auth_serversupplied_info *server_info = auth_ntlmssp_state->server_info;
+       data_blob_free(&server_info->user_session_key);
+       server_info->user_session_key =
+               data_blob_talloc(
+                       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 && !server_info->user_session_key.data) {
+               return NULL;
+       }
+       auth_ntlmssp_state->server_info = NULL;
+       return talloc_steal(mem_ctx, server_info);
+}
+
+struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state;
+}
+
+/* Needed for 'map to guest' and 'smb username' processing */
+const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state->user;
+}
+
+const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state->domain;
+}
+
+const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+       return auth_ntlmssp_state->ntlmssp_state->client.netbios_name;
+}
+
 /**
  * Return the challenge as determined by the authentication subsystem 
  * @return an 8 byte random challenge
index fbd73ae48d6d0d4b2cb478c9785ea507f098ace8..cb849f542f754f0ba7771bd8558650889f15ac35 100644 (file)
@@ -143,12 +143,7 @@ struct auth_init_function_entry {
        struct auth_init_function_entry *prev, *next;
 };
 
-typedef struct auth_ntlmssp_state {
-       TALLOC_CTX *mem_ctx;
-       struct auth_context *auth_context;
-       struct auth_serversupplied_info *server_info;
-       struct ntlmssp_state *ntlmssp_state;
-} AUTH_NTLMSSP_STATE;
+typedef struct auth_ntlmssp_state AUTH_NTLMSSP_STATE;
 
 /* Changed from 1 -> 2 to add the logon_parameters field. */
 #define AUTH_INTERFACE_VERSION 2
index bd3997372752409fd6b4f3e24e8c43b1b492c8cf..d97ef520d5f0cfeadf7044904fc3a0682c7480da 100644 (file)
@@ -54,10 +54,35 @@ NTSTATUS auth_netlogond_init(void);
 
 /* The following definitions come from auth/auth_ntlmssp.c  */
 
-NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state);
-void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state);
-NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state, 
+struct auth_serversupplied_info *auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
+                                                         struct auth_ntlmssp_state *auth_ntlmssp_state);
+struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state);
+bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state);
+bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state);
+
+NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state);
+void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state);
+NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
                             const DATA_BLOB request, DATA_BLOB *reply) ;
+NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 const uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig);
+NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                  const uint8_t *data, size_t length,
+                                  const uint8_t *whole_pdu, size_t pdu_length,
+                                  const DATA_BLOB *sig) ;
+NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 uint8_t *data, size_t length,
+                                 const uint8_t *whole_pdu, size_t pdu_length,
+                                 DATA_BLOB *sig);
+NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                   uint8_t *data, size_t length,
+                                   const uint8_t *whole_pdu, size_t pdu_length,
+                                   const DATA_BLOB *sig);
 
 /* The following definitions come from auth/auth_sam.c  */
 
index 272b5360ad2e1c01165dadbe024982054804860f..bd09386dc0449512def72c688dae5c7d84322d21 100644 (file)
@@ -225,8 +225,8 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
        switch (p->auth.auth_level) {
                case DCERPC_AUTH_LEVEL_PRIVACY:
                        /* Data portion is encrypted. */
-                       status = ntlmssp_seal_packet(
-                               a->ntlmssp_state,
+                       status = auth_ntlmssp_seal_packet(
+                               a,
                                (uint8_t *)prs_data_p(&p->out_data.frag)
                                + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                data_len + ss_padding_len,
@@ -241,8 +241,8 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
                        break;
                case DCERPC_AUTH_LEVEL_INTEGRITY:
                        /* Data is signed. */
-                       status = ntlmssp_sign_packet(
-                               a->ntlmssp_state,
+                       status = auth_ntlmssp_sign_packet(
+                               a,
                                (unsigned char *)prs_data_p(&p->out_data.frag)
                                + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                data_len + ss_padding_len,
@@ -684,7 +684,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
           refuse the bind. */
 
        if (p->auth.auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
-               if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+               if (!auth_ntlmssp_negotiated_sign(a)) {
                        DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested "
                                "but client declined signing.\n",
                                 get_pipe_name_from_syntax(talloc_tos(),
@@ -693,7 +693,7 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
                }
        }
        if (p->auth.auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
-               if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+               if (!auth_ntlmssp_negotiated_seal(a)) {
                        DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested "
                                "but client declined sealing.\n",
                                 get_pipe_name_from_syntax(talloc_tos(),
@@ -703,23 +703,24 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
        }
 
        DEBUG(5, ("pipe_ntlmssp_verify_final: OK: user: %s domain: %s "
-                 "workstation: %s\n", a->ntlmssp_state->user,
-                 a->ntlmssp_state->domain,
-                 a->ntlmssp_state->client.netbios_name));
-
-       if (a->server_info->ptok == NULL) {
-               DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
-               return False;
-       }
+                 "workstation: %s\n",
+                 auth_ntlmssp_get_username(a),
+                 auth_ntlmssp_get_domain(a),
+                 auth_ntlmssp_get_client(a)));
 
        TALLOC_FREE(p->server_info);
 
-       p->server_info = copy_serverinfo(p, a->server_info);
+       p->server_info = auth_ntlmssp_server_info(p, a);
        if (p->server_info == NULL) {
-               DEBUG(0, ("copy_serverinfo failed\n"));
+               DEBUG(0, ("auth_ntlmssp_server_info failed to obtain the server info for authenticated user\n"));
                return false;
        }
 
+       if (p->server_info->ptok == NULL) {
+               DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
+               return False;
+       }
+
        /*
         * We're an authenticated bind over smb, so the session key needs to
         * be set to "SystemLibraryDTC". Weird, but this is what Windows
@@ -2324,22 +2325,22 @@ bool api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in,
        switch (p->auth.auth_level) {
                case DCERPC_AUTH_LEVEL_PRIVACY:
                        /* Data is encrypted. */
-                       *pstatus = ntlmssp_unseal_packet(a->ntlmssp_state,
-                                                       data, data_len,
-                                                       full_packet_data,
-                                                       full_packet_data_len,
-                                                       &auth_blob);
+                       *pstatus = auth_ntlmssp_unseal_packet(a,
+                                                             data, data_len,
+                                                             full_packet_data,
+                                                             full_packet_data_len,
+                                                             &auth_blob);
                        if (!NT_STATUS_IS_OK(*pstatus)) {
                                return False;
                        }
                        break;
                case DCERPC_AUTH_LEVEL_INTEGRITY:
                        /* Data is signed. */
-                       *pstatus = ntlmssp_check_packet(a->ntlmssp_state,
-                                                       data, data_len,
-                                                       full_packet_data,
-                                                       full_packet_data_len,
-                                                       &auth_blob);
+                       *pstatus = auth_ntlmssp_check_packet(a,
+                                                            data, data_len,
+                                                            full_packet_data,
+                                                            full_packet_data_len,
+                                                            &auth_blob);
                        if (!NT_STATUS_IS_OK(*pstatus)) {
                                return False;
                        }
index 700d7ea02e2e3d22be0403202fba276de8f996e9..4662507c90bac57d828dcdac118941ef1dc17609 100644 (file)
@@ -85,7 +85,7 @@ static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
         * We must remember to update the pointer copy for the common
         * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
         */
-       ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state;
+       ec->es->s.ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(ec->auth_ntlmssp_state);
        return status;
 }
 
@@ -710,8 +710,11 @@ static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec)
        }
 
        if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
-               if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) !=
-                               (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) {
+               if (!auth_ntlmssp_negotiated_sign((ec->auth_ntlmssp_state))) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (!auth_ntlmssp_negotiated_seal((ec->auth_ntlmssp_state))) {
                        return NT_STATUS_INVALID_PARAMETER;
                }
        }
index 9d0c68512c9ba9cac9b8f9f696dc1d6c430ada00..ec824063494f735e92222490e2d6a469ed309f90 100644 (file)
@@ -634,12 +634,16 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
        struct smbd_server_connection *sconn = smbd_server_conn;
 
        if (NT_STATUS_IS_OK(nt_status)) {
-               server_info = (*auth_ntlmssp_state)->server_info;
+               server_info = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state));
        } else {
+               /* Note that this server_info won't have a session
+                * key.  But for map to guest, that's exactly the right
+                * thing - we can't reasonably guess the key the
+                * client wants, as the password was wrong */
                nt_status = do_map_to_guest(nt_status,
-                           &server_info,
-                           (*auth_ntlmssp_state)->ntlmssp_state->user,
-                           (*auth_ntlmssp_state)->ntlmssp_state->domain);
+                                           &server_info,
+                                           auth_ntlmssp_get_username(*auth_ntlmssp_state),
+                                           auth_ntlmssp_get_domain(*auth_ntlmssp_state));
        }
 
        reply_outbuf(req, 4, 0);
@@ -654,24 +658,15 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
                        goto out;
                }
 
-               data_blob_free(&server_info->user_session_key);
-               server_info->user_session_key =
-                       data_blob_talloc(
-                       server_info,
-                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
-                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
-
                /* register_existing_vuid keeps the server info */
                if (register_existing_vuid(sconn, vuid,
-                               server_info, nullblob,
-                               (*auth_ntlmssp_state)->ntlmssp_state->user) !=
-                                       vuid) {
+                                          server_info, nullblob,
+                                          auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
+                                          vuid) {
                        nt_status = NT_STATUS_LOGON_FAILURE;
                        goto out;
                }
 
-               (*auth_ntlmssp_state)->server_info = NULL;
-
                /* current_user_info is changed on new vuid */
                reload_services( True );
 
index d8972156a196f353441798e3b868fcaf34de1c15..b659f2e2ef7bde5506bdf29271b49a99e5083549 100644 (file)
@@ -605,13 +605,19 @@ static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *s
                                        uint64_t *out_session_id)
 {
        fstring tmp;
+       session->server_info = auth_ntlmssp_server_info(session, session->auth_ntlmssp_state);
+       if (!session->server_info) {
+               auth_ntlmssp_end(&session->auth_ntlmssp_state);
+               TALLOC_FREE(session);
+               return NT_STATUS_NO_MEMORY;
+       }
 
        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;
@@ -619,20 +625,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);
@@ -650,11 +642,11 @@ 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 =