From 3453bc7b1108390354c0825ee6b2b0bb28fca2f3 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 3 Sep 2010 16:27:47 -0400 Subject: [PATCH] s3-dcerpc: make auth context opaque MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This way we always double check in advance that the context is of the right type with talloc_get_type_abort instead of potentially accessing random memory by addressing the wrong structure in the union. Signed-off-by: Günther Deschner --- source3/include/ntdomain.h | 7 +- source3/librpc/rpc/dcerpc_helpers.c | 57 ++++++++---- source3/rpc_client/cli_pipe.c | 133 ++++++++++++++++++---------- source3/rpc_server/srv_netlog_nt.c | 8 +- source3/rpc_server/srv_pipe.c | 110 ++++++++++++----------- 5 files changed, 189 insertions(+), 126 deletions(-) diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 9fdb794fd39..b0a462399f8 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -101,12 +101,7 @@ struct pipe_auth_data { enum dcerpc_AuthType auth_type; enum dcerpc_AuthLevel auth_level; - union { - struct schannel_state *schannel_auth; - struct auth_ntlmssp_state *auth_ntlmssp_state; - struct gse_context *gssapi_state; - struct spnego_context *spnego_state; - } a_u; + void *auth_ctx; /* Only the client code uses these 3 for now */ char *domain; diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index c83668f9b8e..7af2bbc8540 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -266,6 +266,7 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, { size_t max_len; size_t mod_len; + struct spnego_context *spnego_ctx; struct gse_context *gse_ctx; enum spnego_mech auth_type; void *auth_ctx; @@ -303,8 +304,9 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, /* Treat the same for all authenticated rpc requests. */ switch (auth->auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: - - status = spnego_get_negotiated_mech(auth->a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(auth->auth_ctx, + struct spnego_context); + status = spnego_get_negotiated_mech(spnego_ctx, &auth_type, &auth_ctx); if (!NT_STATUS_IS_OK(status)) { return status; @@ -315,8 +317,8 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, break; case SPNEGO_KRB5: - gse_ctx = talloc_get_type(auth_ctx, - struct gse_context); + gse_ctx = talloc_get_type_abort(auth_ctx, + struct gse_context); if (!gse_ctx) { return NT_STATUS_INVALID_PARAMETER; } @@ -338,7 +340,9 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, break; case DCERPC_AUTH_TYPE_KRB5: - *auth_len = gse_get_signature_length(auth->a_u.gssapi_state, + gse_ctx = talloc_get_type_abort(auth->auth_ctx, + struct gse_context); + *auth_len = gse_get_signature_length(gse_ctx, seal, max_len); break; @@ -755,6 +759,10 @@ static NTSTATUS get_spnego_auth_footer(TALLOC_CTX *mem_ctx, NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, size_t pad_len, DATA_BLOB *rpc_out) { + struct schannel_state *schannel_auth; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; char pad[CLIENT_NDR_PADDING_SIZE] = { 0, }; DATA_BLOB auth_info; DATA_BLOB auth_blob; @@ -801,21 +809,29 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, status = NT_STATUS_OK; break; case DCERPC_AUTH_TYPE_SPNEGO: - status = add_spnego_auth_footer(auth->a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(auth->auth_ctx, + struct spnego_context); + status = add_spnego_auth_footer(spnego_ctx, auth->auth_level, rpc_out); break; case DCERPC_AUTH_TYPE_NTLMSSP: - status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state, + ntlmssp_ctx = talloc_get_type_abort(auth->auth_ctx, + struct auth_ntlmssp_state); + status = add_ntlmssp_auth_footer(ntlmssp_ctx, auth->auth_level, rpc_out); break; case DCERPC_AUTH_TYPE_SCHANNEL: - status = add_schannel_auth_footer(auth->a_u.schannel_auth, + schannel_auth = talloc_get_type_abort(auth->auth_ctx, + struct schannel_state); + status = add_schannel_auth_footer(schannel_auth, auth->auth_level, rpc_out); break; case DCERPC_AUTH_TYPE_KRB5: - status = add_gssapi_auth_footer(auth->a_u.gssapi_state, + gse_ctx = talloc_get_type_abort(auth->auth_ctx, + struct gse_context); + status = add_gssapi_auth_footer(gse_ctx, auth->auth_level, rpc_out); break; @@ -846,6 +862,10 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DATA_BLOB *raw_pkt, size_t *pad_len) { + struct schannel_state *schannel_auth; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; NTSTATUS status; struct dcerpc_auth auth_info; uint32_t auth_length; @@ -911,8 +931,9 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, return NT_STATUS_OK; case DCERPC_AUTH_TYPE_SPNEGO: - - status = get_spnego_auth_footer(pkt, auth->a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(auth->auth_ctx, + struct spnego_context); + status = get_spnego_auth_footer(pkt, spnego_ctx, auth->auth_level, &data, &full_pkt, &auth_info.credentials); @@ -925,7 +946,9 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DEBUG(10, ("NTLMSSP auth\n")); - status = get_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state, + ntlmssp_ctx = talloc_get_type_abort(auth->auth_ctx, + struct auth_ntlmssp_state); + status = get_ntlmssp_auth_footer(ntlmssp_ctx, auth->auth_level, &data, &full_pkt, &auth_info.credentials); @@ -938,8 +961,9 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DEBUG(10, ("SCHANNEL auth\n")); - status = get_schannel_auth_footer(pkt, - auth->a_u.schannel_auth, + schannel_auth = talloc_get_type_abort(auth->auth_ctx, + struct schannel_state); + status = get_schannel_auth_footer(pkt, schannel_auth, auth->auth_level, &data, &full_pkt, &auth_info.credentials); @@ -952,8 +976,9 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, DEBUG(10, ("KRB5 auth\n")); - status = get_gssapi_auth_footer(pkt, - auth->a_u.gssapi_state, + gse_ctx = talloc_get_type_abort(auth->auth_ctx, + struct gse_context); + status = get_gssapi_auth_footer(pkt, gse_ctx, auth->auth_level, &data, &full_pkt, &auth_info.credentials); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index fa139f4f89b..b59e9db9fd4 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -985,12 +985,15 @@ static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx, struct pipe_auth_data *auth, DATA_BLOB *auth_token) { + struct spnego_context *spnego_ctx; DATA_BLOB in_token = data_blob_null; NTSTATUS status; + spnego_ctx = talloc_get_type_abort(auth->auth_ctx, + struct spnego_context); + /* Negotiate the initial auth token */ - status = spnego_get_client_auth_token(mem_ctx, - auth->a_u.spnego_state, + status = spnego_get_client_auth_token(mem_ctx, spnego_ctx, &in_token, auth_token); if (!NT_STATUS_IS_OK(status)) { return status; @@ -1010,12 +1013,15 @@ static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx, struct pipe_auth_data *auth, DATA_BLOB *auth_token) { + struct gse_context *gse_ctx; DATA_BLOB in_token = data_blob_null; NTSTATUS status; + gse_ctx = talloc_get_type_abort(auth->auth_ctx, + struct gse_context); + /* Negotiate the initial auth token */ - status = gse_get_client_auth_token(mem_ctx, - auth->a_u.gssapi_state, + status = gse_get_client_auth_token(mem_ctx, gse_ctx, &in_token, auth_token); if (!NT_STATUS_IS_OK(status)) { @@ -1035,12 +1041,15 @@ static NTSTATUS create_gssapi_auth_bind_req(TALLOC_CTX *mem_ctx, static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli, DATA_BLOB *auth_token) { - NTSTATUS status; + struct auth_ntlmssp_state *ntlmssp_ctx; DATA_BLOB null_blob = data_blob_null; + NTSTATUS status; + + ntlmssp_ctx = talloc_get_type_abort(cli->auth->auth_ctx, + struct auth_ntlmssp_state); DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n")); - status = auth_ntlmssp_update(cli->auth->a_u.auth_ntlmssp_state, - null_blob, auth_token); + status = auth_ntlmssp_update(ntlmssp_ctx, null_blob, auth_token); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { data_blob_free(auth_token); @@ -1676,6 +1685,9 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) struct rpc_pipe_bind_state *state = tevent_req_data( req, struct rpc_pipe_bind_state); struct pipe_auth_data *pauth = state->cli->auth; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; struct ncacn_packet *pkt; struct dcerpc_auth auth; DATA_BLOB auth_token = data_blob_null; @@ -1752,7 +1764,9 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) return; case DCERPC_AUTH_TYPE_NTLMSSP: - status = auth_ntlmssp_update(pauth->a_u.auth_ntlmssp_state, + ntlmssp_ctx = talloc_get_type_abort(pauth->auth_ctx, + struct auth_ntlmssp_state); + status = auth_ntlmssp_update(ntlmssp_ctx, auth.credentials, &auth_token); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { @@ -1765,8 +1779,10 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) break; case DCERPC_AUTH_TYPE_SPNEGO: + spnego_ctx = talloc_get_type_abort(pauth->auth_ctx, + struct spnego_context); status = spnego_get_client_auth_token(state, - pauth->a_u.spnego_state, + spnego_ctx, &auth.credentials, &auth_token); if (!NT_STATUS_IS_OK(status)) { @@ -1777,7 +1793,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) tevent_req_done(req); return; } - if (spnego_require_more_processing(pauth->a_u.spnego_state)) { + if (spnego_require_more_processing(spnego_ctx)) { status = rpc_bind_next_send(req, state, &auth_token); } else { @@ -1787,15 +1803,17 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) break; case DCERPC_AUTH_TYPE_KRB5: + gse_ctx = talloc_get_type_abort(pauth->auth_ctx, + struct gse_context); status = gse_get_client_auth_token(state, - pauth->a_u.gssapi_state, + gse_ctx, &auth.credentials, &auth_token); if (!NT_STATUS_IS_OK(status)) { break; } - if (gse_require_more_processing(pauth->a_u.gssapi_state)) { + if (gse_require_more_processing(gse_ctx)) { status = rpc_bind_next_send(req, state, &auth_token); } else { status = rpc_bind_finish_send(req, state, &auth_token); @@ -2189,22 +2207,25 @@ bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16]) struct cli_state *cli; if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) { - a = rpc_cli->auth->a_u.auth_ntlmssp_state; + a = talloc_get_type_abort(rpc_cli->auth->auth_ctx, + struct auth_ntlmssp_state); } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) { + struct spnego_context *spnego_ctx; enum spnego_mech auth_type; void *auth_ctx; NTSTATUS status; - status = spnego_get_negotiated_mech( - rpc_cli->auth->a_u.spnego_state, - &auth_type, &auth_ctx); + spnego_ctx = talloc_get_type_abort(rpc_cli->auth->auth_ctx, + struct spnego_context); + status = spnego_get_negotiated_mech(spnego_ctx, + &auth_type, &auth_ctx); if (!NT_STATUS_IS_OK(status)) { return false; } if (auth_type == SPNEGO_NTLMSSP) { - a = talloc_get_type(auth_ctx, - struct auth_ntlmssp_state); + a = talloc_get_type_abort(auth_ctx, + struct auth_ntlmssp_state); } } @@ -2247,7 +2268,7 @@ NTSTATUS rpccli_anon_bind_data(TALLOC_CTX *mem_ctx, static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth) { - TALLOC_FREE(auth->a_u.auth_ntlmssp_state); + TALLOC_FREE(auth->auth_ctx); return 0; } @@ -2259,6 +2280,7 @@ static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, const char *password, struct pipe_auth_data **presult) { + struct auth_ntlmssp_state *ntlmssp_ctx; struct pipe_auth_data *result; NTSTATUS status; @@ -2281,27 +2303,24 @@ static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, global_myname(), lp_workgroup(), lp_client_ntlmv2_auth(), - &result->a_u.auth_ntlmssp_state); + &ntlmssp_ctx); if (!NT_STATUS_IS_OK(status)) { goto fail; } talloc_set_destructor(result, cli_auth_ntlmssp_data_destructor); - status = auth_ntlmssp_set_username(result->a_u.auth_ntlmssp_state, - username); + status = auth_ntlmssp_set_username(ntlmssp_ctx, username); if (!NT_STATUS_IS_OK(status)) { goto fail; } - status = auth_ntlmssp_set_domain(result->a_u.auth_ntlmssp_state, - domain); + status = auth_ntlmssp_set_domain(ntlmssp_ctx, domain); if (!NT_STATUS_IS_OK(status)) { goto fail; } - status = auth_ntlmssp_set_password(result->a_u.auth_ntlmssp_state, - password); + status = auth_ntlmssp_set_password(ntlmssp_ctx, password); if (!NT_STATUS_IS_OK(status)) { goto fail; } @@ -2309,19 +2328,17 @@ static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, /* * Turn off sign+seal to allow selected auth level to turn it back on. */ - auth_ntlmssp_and_flags(result->a_u.auth_ntlmssp_state, - ~(NTLMSSP_NEGOTIATE_SIGN | - NTLMSSP_NEGOTIATE_SEAL)); + auth_ntlmssp_and_flags(ntlmssp_ctx, ~(NTLMSSP_NEGOTIATE_SIGN | + NTLMSSP_NEGOTIATE_SEAL)); if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { - auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state, - NTLMSSP_NEGOTIATE_SIGN); + auth_ntlmssp_or_flags(ntlmssp_ctx, NTLMSSP_NEGOTIATE_SIGN); } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { - auth_ntlmssp_or_flags(result->a_u.auth_ntlmssp_state, - NTLMSSP_NEGOTIATE_SEAL | - NTLMSSP_NEGOTIATE_SIGN); + auth_ntlmssp_or_flags(ntlmssp_ctx, NTLMSSP_NEGOTIATE_SEAL | + NTLMSSP_NEGOTIATE_SIGN); } + result->auth_ctx = ntlmssp_ctx; *presult = result; return NT_STATUS_OK; @@ -2335,6 +2352,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, struct netlogon_creds_CredentialState *creds, struct pipe_auth_data **presult) { + struct schannel_state *schannel_auth; struct pipe_auth_data *result; result = talloc(mem_ctx, struct pipe_auth_data); @@ -2351,16 +2369,17 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain, goto fail; } - result->a_u.schannel_auth = talloc(result, struct schannel_state); - if (result->a_u.schannel_auth == NULL) { + schannel_auth = talloc(result, struct schannel_state); + if (schannel_auth == NULL) { goto fail; } - result->a_u.schannel_auth->state = SCHANNEL_STATE_START; - result->a_u.schannel_auth->seq_num = 0; - result->a_u.schannel_auth->initiator = true; - result->a_u.schannel_auth->creds = netlogon_creds_copy(result, creds); + schannel_auth->state = SCHANNEL_STATE_START; + schannel_auth->seq_num = 0; + schannel_auth->initiator = true; + schannel_auth->creds = netlogon_creds_copy(result, creds); + result->auth_ctx = schannel_auth; *presult = result; return NT_STATUS_OK; @@ -2977,6 +2996,7 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, { struct rpc_pipe_client *result; struct pipe_auth_data *auth; + struct gse_context *gse_ctx; NTSTATUS status; status = cli_rpc_pipe_open(cli, transport, interface, &result); @@ -3012,13 +3032,13 @@ NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY), (auth_level == DCERPC_AUTH_LEVEL_PRIVACY), NULL, server, "cifs", username, password, - GSS_C_DCE_STYLE, &auth->a_u.gssapi_state); - + GSS_C_DCE_STYLE, &gse_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("gse_init_client returned %s\n", nt_errstr(status))); goto err_out; } + auth->auth_ctx = gse_ctx; status = rpc_pipe_bind(result, auth); if (!NT_STATUS_IS_OK(status)) { @@ -3046,6 +3066,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli, { struct rpc_pipe_client *result; struct pipe_auth_data *auth; + struct spnego_context *spnego_ctx; NTSTATUS status; status = cli_rpc_pipe_open(cli, transport, interface, &result); @@ -3085,12 +3106,13 @@ NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli, true, NULL, server, "cifs", username, password, - &auth->a_u.spnego_state); + &spnego_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("spnego_init_client returned %s\n", nt_errstr(status))); goto err_out; } + auth->auth_ctx = spnego_ctx; status = rpc_pipe_bind(result, auth); if (!NT_STATUS_IS_OK(status)) { @@ -3118,6 +3140,7 @@ NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli, { struct rpc_pipe_client *result; struct pipe_auth_data *auth; + struct spnego_context *spnego_ctx; NTSTATUS status; status = cli_rpc_pipe_open(cli, transport, interface, &result); @@ -3158,12 +3181,13 @@ NTSTATUS cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli, DCERPC_AUTH_LEVEL_PRIVACY), true, domain, username, password, - &auth->a_u.spnego_state); + &spnego_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("spnego_init_client returned %s\n", nt_errstr(status))); goto err_out; } + auth->auth_ctx = spnego_ctx; status = rpc_pipe_bind(result, auth); if (!NT_STATUS_IS_OK(status)) { @@ -3185,6 +3209,10 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, DATA_BLOB *session_key) { struct pipe_auth_data *a = cli->auth; + struct schannel_state *schannel_auth; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; DATA_BLOB sk = data_blob_null; bool make_dup = false; @@ -3198,20 +3226,27 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, switch (cli->auth->auth_type) { case DCERPC_AUTH_TYPE_SCHANNEL: - sk = data_blob_const(a->a_u.schannel_auth->creds->session_key, - 16); + schannel_auth = talloc_get_type_abort(a->auth_ctx, + struct schannel_state); + sk = data_blob_const(schannel_auth->creds->session_key, 16); make_dup = true; break; case DCERPC_AUTH_TYPE_SPNEGO: - sk = spnego_get_session_key(mem_ctx, a->a_u.spnego_state); + spnego_ctx = talloc_get_type_abort(a->auth_ctx, + struct spnego_context); + sk = spnego_get_session_key(mem_ctx, spnego_ctx); make_dup = false; break; case DCERPC_AUTH_TYPE_NTLMSSP: - sk = auth_ntlmssp_get_session_key(a->a_u.auth_ntlmssp_state); + ntlmssp_ctx = talloc_get_type_abort(a->auth_ctx, + struct auth_ntlmssp_state); + sk = auth_ntlmssp_get_session_key(ntlmssp_ctx); make_dup = true; break; case DCERPC_AUTH_TYPE_KRB5: - sk = gse_get_session_key(mem_ctx, a->a_u.gssapi_state); + gse_ctx = talloc_get_type_abort(a->auth_ctx, + struct gse_context); + sk = gse_get_session_key(mem_ctx, gse_ctx); make_dup = false; break; case DCERPC_AUTH_TYPE_NONE: diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 76da1d00d66..d821b04cdc5 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -1426,12 +1426,16 @@ static NTSTATUS _netr_LogonSamLogon_base(struct pipes_struct *p, /* Get the pipe session key from the creds. */ memcpy(pipe_session_key, creds->session_key, 16); } else { + struct schannel_state *schannel_auth; /* Get the pipe session key from the schannel. */ if ((p->auth.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) - || (p->auth.a_u.schannel_auth == NULL)) { + || (p->auth.auth_ctx == NULL)) { return NT_STATUS_INVALID_HANDLE; } - memcpy(pipe_session_key, p->auth.a_u.schannel_auth->creds->session_key, 16); + + schannel_auth = talloc_get_type_abort(p->auth.auth_ctx, + struct schannel_state); + memcpy(pipe_session_key, schannel_auth->creds->session_key, 16); } switch (r->in.validation_level) { diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index fab7383ce33..e5d2a1c6dad 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -86,32 +86,9 @@ static void dump_pdu_region(const char *name, int v, TALLOC_FREE(fname); } -static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth) -{ - TALLOC_FREE(auth->a_u.auth_ntlmssp_state); -} - -static void free_pipe_schannel_auth_data(struct pipe_auth_data *auth) -{ - TALLOC_FREE(auth->a_u.schannel_auth); -} - -static void free_pipe_gssapi_auth_data(struct pipe_auth_data *auth) -{ - TALLOC_FREE(auth->a_u.gssapi_state); -} - -static void free_pipe_spnego_auth_data(struct pipe_auth_data *auth) -{ - TALLOC_FREE(auth->a_u.spnego_state); -} - static void free_pipe_auth_data(struct pipe_auth_data *auth) { - if (auth->auth_data_free_func) { - (*auth->auth_data_free_func)(auth); - auth->auth_data_free_func = NULL; - } + TALLOC_FREE(auth->auth_ctx); } static DATA_BLOB generic_session_key(void) @@ -466,8 +443,8 @@ static bool pipe_spnego_auth_bind(struct pipes_struct *p, /* Make sure data is bound to the memctx, to be freed the caller */ talloc_steal(mem_ctx, response->data); - p->auth.a_u.spnego_state = spnego_ctx; - p->auth.auth_data_free_func = &free_pipe_spnego_auth_data; + p->auth.auth_ctx = spnego_ctx; + p->auth.auth_data_free_func = &free_pipe_auth_data; p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO; DEBUG(10, ("SPNEGO auth started\n")); @@ -491,6 +468,7 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, struct netlogon_creds_CredentialState *creds; DATA_BLOB session_key; enum ndr_err_code ndr_err; + struct schannel_state *schannel_auth; ndr_err = ndr_pull_struct_blob( &auth_info->credentials, mem_ctx, &neg, @@ -525,16 +503,16 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, return False; } - p->auth.a_u.schannel_auth = talloc(p, struct schannel_state); - if (!p->auth.a_u.schannel_auth) { + schannel_auth = talloc(p, struct schannel_state); + if (!schannel_auth) { TALLOC_FREE(creds); return False; } - p->auth.a_u.schannel_auth->state = SCHANNEL_STATE_START; - p->auth.a_u.schannel_auth->seq_num = 0; - p->auth.a_u.schannel_auth->initiator = false; - p->auth.a_u.schannel_auth->creds = creds; + schannel_auth->state = SCHANNEL_STATE_START; + schannel_auth->seq_num = 0; + schannel_auth->initiator = false; + schannel_auth->creds = creds; /* * JRA. Should we also copy the schannel session key into the pipe session key p->session_key @@ -586,7 +564,8 @@ static bool pipe_schannel_auth_bind(struct pipes_struct *p, neg.oem_netbios_domain.a, neg.oem_netbios_computer.a)); /* We're finished with this bind - no more packets. */ - p->auth.auth_data_free_func = &free_pipe_schannel_auth_data; + p->auth.auth_ctx = schannel_auth; + p->auth.auth_data_free_func = &free_pipe_auth_data; p->auth.auth_type = DCERPC_AUTH_TYPE_SCHANNEL; p->pipe_bound = True; @@ -603,6 +582,7 @@ static bool pipe_ntlmssp_auth_bind(struct pipes_struct *p, struct dcerpc_auth *auth_info, DATA_BLOB *response) { + struct auth_ntlmssp_state *ntlmssp_state = NULL; NTSTATUS status; if (strncmp((char *)auth_info->credentials.data, "NTLMSSP", 7) != 0) { @@ -619,7 +599,7 @@ static bool pipe_ntlmssp_auth_bind(struct pipes_struct *p, true, &auth_info->credentials, response, - &p->auth.a_u.auth_ntlmssp_state); + &ntlmssp_state); if (!NT_STATUS_EQUAL(status, NT_STATUS_OK)) { DEBUG(0, (__location__ ": auth_ntlmssp_start failed: %s\n", nt_errstr(status))); @@ -629,7 +609,8 @@ static bool pipe_ntlmssp_auth_bind(struct pipes_struct *p, /* Make sure data is bound to the memctx, to be freed the caller */ talloc_steal(mem_ctx, response->data); - p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data; + p->auth.auth_ctx = ntlmssp_state; + p->auth.auth_data_free_func = &free_pipe_auth_data; p->auth.auth_type = DCERPC_AUTH_TYPE_NTLMSSP; DEBUG(10, (__location__ ": NTLMSSP auth started\n")); @@ -740,8 +721,8 @@ static bool pipe_gssapi_auth_bind(struct pipes_struct *p, /* Make sure data is bound to the memctx, to be freed the caller */ talloc_steal(mem_ctx, response->data); - p->auth.a_u.gssapi_state = gse_ctx; - p->auth.auth_data_free_func = &free_pipe_gssapi_auth_data; + p->auth.auth_ctx = gse_ctx; + p->auth.auth_data_free_func = &free_pipe_auth_data; p->auth.auth_type = DCERPC_AUTH_TYPE_KRB5; DEBUG(10, ("KRB5 auth started\n")); @@ -816,25 +797,28 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) { enum spnego_mech auth_type; struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; struct gse_context *gse_ctx; void *mech_ctx; NTSTATUS status; switch (p->auth.auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: - if (!pipe_ntlmssp_verify_final(p, - p->auth.a_u.auth_ntlmssp_state, - p->auth.auth_level, - p->client_id, &p->syntax, - &p->server_info)) { + ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct auth_ntlmssp_state); + if (!pipe_ntlmssp_verify_final(p, ntlmssp_ctx, + p->auth.auth_level, + p->client_id, &p->syntax, + &p->server_info)) { return NT_STATUS_ACCESS_DENIED; } break; case DCERPC_AUTH_TYPE_KRB5: - status = pipe_gssapi_verify_final(p, - p->auth.a_u.gssapi_state, - p->client_id, - &p->server_info); + gse_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct gse_context); + status = pipe_gssapi_verify_final(p, gse_ctx, + p->client_id, + &p->server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("gssapi bind failed with: %s", nt_errstr(status))); @@ -842,7 +826,9 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) } break; case DCERPC_AUTH_TYPE_SPNEGO: - status = spnego_get_negotiated_mech(p->auth.a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct spnego_context); + status = spnego_get_negotiated_mech(spnego_ctx, &auth_type, &mech_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Bad SPNEGO state (%s)\n", @@ -1185,6 +1171,9 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt) { struct dcerpc_auth auth_info; DATA_BLOB response = data_blob_null; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; NTSTATUS status; DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); @@ -1223,17 +1212,23 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt) switch (auth_info.auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: - status = ntlmssp_server_step(p->auth.a_u.auth_ntlmssp_state, + ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct auth_ntlmssp_state); + status = ntlmssp_server_step(ntlmssp_ctx, pkt, &auth_info.credentials, &response); break; case DCERPC_AUTH_TYPE_KRB5: - status = gssapi_server_step(p->auth.a_u.gssapi_state, + gse_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct gse_context); + status = gssapi_server_step(gse_ctx, pkt, &auth_info.credentials, &response); break; case DCERPC_AUTH_TYPE_SPNEGO: - status = spnego_server_step(p->auth.a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct spnego_context); + status = spnego_server_step(spnego_ctx, pkt, &auth_info.credentials, &response); break; @@ -1288,6 +1283,9 @@ static bool api_pipe_alter_context(struct pipes_struct *p, DATA_BLOB auth_resp = data_blob_null; DATA_BLOB auth_blob = data_blob_null; int pad_len = 0; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct spnego_context *spnego_ctx; + struct gse_context *gse_ctx; DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); @@ -1357,20 +1355,26 @@ static bool api_pipe_alter_context(struct pipes_struct *p, switch (auth_info.auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: - status = spnego_server_step(p->auth.a_u.spnego_state, + spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct spnego_context); + status = spnego_server_step(spnego_ctx, pkt, &auth_info.credentials, &auth_resp); break; case DCERPC_AUTH_TYPE_KRB5: - status = gssapi_server_step(p->auth.a_u.gssapi_state, + gse_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct gse_context); + status = gssapi_server_step(gse_ctx, pkt, &auth_info.credentials, &auth_resp); break; case DCERPC_AUTH_TYPE_NTLMSSP: - status = ntlmssp_server_step(p->auth.a_u.auth_ntlmssp_state, + ntlmssp_ctx = talloc_get_type_abort(p->auth.auth_ctx, + struct auth_ntlmssp_state); + status = ntlmssp_server_step(ntlmssp_ctx, pkt, &auth_info.credentials, &auth_resp); -- 2.34.1