From 3b706865f6bae7a2b04590da160bda939a3bafe5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 25 May 2010 15:34:06 +1000 Subject: s3:auth Make AUTH_NTLMSSP_STATE a private structure. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it a little easier for it to writen in terms of GENSEC in future. Andrew Bartlett Signed-off-by: Stefan Metzmacher Signed-off-by: Günther Deschner --- source3/auth/auth_ntlmssp.c | 87 +++++++++++++++++++++++++++++++++++++++++++ source3/include/auth.h | 7 +--- source3/include/proto.h | 31 +++++++++++++-- source3/rpc_server/srv_pipe.c | 53 +++++++++++++------------- source3/smbd/seal.c | 9 +++-- source3/smbd/sesssetup.c | 27 ++++++-------- source3/smbd/smb2_sesssetup.c | 30 ++++++--------- 7 files changed, 171 insertions(+), 73 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index 762411702f..cdc00d80c0 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -23,6 +23,93 @@ #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 diff --git a/source3/include/auth.h b/source3/include/auth.h index fbd73ae48d..cb849f542f 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -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 diff --git a/source3/include/proto.h b/source3/include/proto.h index bd39973727..d97ef520d5 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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 */ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 272b5360ad..bd09386dc0 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -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; } diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c index 700d7ea02e..4662507c90 100644 --- a/source3/smbd/seal.c +++ b/source3/smbd/seal.c @@ -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; } } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 9d0c68512c..ec82406349 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -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 ); diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index d8972156a1..b659f2e2ef 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -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 = -- cgit