From e012ad9d8b7cea3a86841fe92b80627a6d07d459 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 Jan 2012 13:06:29 +1100 Subject: s3-librpc Call GSSAPI via the auth_generic layer and gensec This simplifies a lot of code, as we know we are always dealing with a struct gensec_security, and allows the gensec module being used to implement GSSAPI to be swapped when required for AD-server operation. Andrew Bartlett Signed-off-by: Stefan Metzmacher --- source3/auth/auth_generic.c | 7 +- source3/librpc/rpc/dcerpc_helpers.c | 111 +--------------------------- source3/rpc_client/cli_pipe.c | 142 +----------------------------------- source3/rpc_server/srv_pipe.c | 76 +------------------ source3/rpcclient/rpcclient.c | 10 +-- 5 files changed, 17 insertions(+), 329 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index e73c27b5eb..b2b862ee1c 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -29,6 +29,7 @@ #ifdef HAVE_KRB5 #include "libcli/auth/krb5_wrap.h" #endif +#include "librpc/crypto/gse.h" static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, TALLOC_CTX *mem_ctx, @@ -196,7 +197,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - gensec_settings->backends = talloc_zero_array(gensec_settings, struct gensec_security_ops *, 2); + gensec_settings->backends = talloc_zero_array(gensec_settings, struct gensec_security_ops *, 3); if (gensec_settings->backends == NULL) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; @@ -204,6 +205,10 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, gensec_settings->backends[0] = &gensec_ntlmssp3_server_ops; +#if defined(HAVE_KRB5) && defined(HAVE_GSS_WRAP_IOV) + gensec_settings->backends[1] = &gensec_gse_krb5_security_ops; +#endif + nt_status = gensec_server_start(tmp_ctx, gensec_settings, auth4_context, &gensec_security); diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 026b1fa32f..4cfe7933fe 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -335,6 +335,7 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, break; case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(auth->auth_ctx, struct gensec_security); *auth_len = gensec_sig_size(gensec_security, max_len); @@ -345,14 +346,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, struct schannel_state); *auth_len = netsec_outgoing_sig_size(schannel_auth); break; - - case DCERPC_AUTH_TYPE_KRB5: - gse_ctx = talloc_get_type_abort(auth->auth_ctx, - struct gse_context); - *auth_len = gse_get_signature_length(gse_ctx, - seal, max_len); - break; - default: return NT_STATUS_INVALID_PARAMETER; } @@ -575,82 +568,6 @@ static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx, } } -/******************************************************************* - Create and add the gssapi sign/seal auth data. - ********************************************************************/ - -static NTSTATUS add_gssapi_auth_footer(struct gse_context *gse_ctx, - enum dcerpc_AuthLevel auth_level, - DATA_BLOB *rpc_out) -{ - DATA_BLOB data; - DATA_BLOB auth_blob; - NTSTATUS status; - - if (!gse_ctx) { - return NT_STATUS_INVALID_PARAMETER; - } - - data.data = rpc_out->data + DCERPC_RESPONSE_LENGTH; - data.length = rpc_out->length - DCERPC_RESPONSE_LENGTH - - DCERPC_AUTH_TRAILER_LENGTH; - - switch (auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - status = gse_seal(talloc_tos(), gse_ctx, &data, &auth_blob); - break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = gse_sign(talloc_tos(), gse_ctx, &data, &auth_blob); - break; - default: - status = NT_STATUS_INTERNAL_ERROR; - break; - } - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("Failed to process packet: %s\n", - nt_errstr(status))); - return status; - } - - /* Finally attach the blob. */ - if (!data_blob_append(NULL, rpc_out, - auth_blob.data, auth_blob.length)) { - return NT_STATUS_NO_MEMORY; - } - - data_blob_free(&auth_blob); - - return NT_STATUS_OK; -} - -/******************************************************************* - Check/unseal the gssapi auth data. (Unseal in place). - ********************************************************************/ - -static NTSTATUS get_gssapi_auth_footer(TALLOC_CTX *mem_ctx, - struct gse_context *gse_ctx, - enum dcerpc_AuthLevel auth_level, - DATA_BLOB *data, DATA_BLOB *full_pkt, - DATA_BLOB *auth_token) -{ - /* TODO: pass in full_pkt when - * DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN is set */ - switch (auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - /* Data portion is encrypted. */ - return gse_unseal(mem_ctx, gse_ctx, - data, auth_token); - - case DCERPC_AUTH_LEVEL_INTEGRITY: - /* Data is signed. */ - return gse_sigcheck(mem_ctx, gse_ctx, - data, auth_token); - default: - return NT_STATUS_INVALID_PARAMETER; - } -} - /******************************************************************* Create and add the spnego-negotiated sign/seal auth data. ********************************************************************/ @@ -752,7 +669,6 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, struct schannel_state *schannel_auth; struct gensec_security *gensec_security; 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; @@ -806,6 +722,7 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, status = add_spnego_auth_footer(spnego_ctx, auth->auth_level, rpc_out); break; + case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_NTLMSSP: gensec_security = talloc_get_type_abort(auth->auth_ctx, struct gensec_security); @@ -820,13 +737,6 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, auth->auth_level, rpc_out); break; - case DCERPC_AUTH_TYPE_KRB5: - 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; default: status = NT_STATUS_INVALID_PARAMETER; break; @@ -857,7 +767,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, struct schannel_state *schannel_auth; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; NTSTATUS status; struct dcerpc_auth auth_info; uint32_t auth_length; @@ -935,6 +844,7 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, } break; + case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_NTLMSSP: DEBUG(10, ("GENSEC auth\n")); @@ -965,21 +875,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, } break; - case DCERPC_AUTH_TYPE_KRB5: - - DEBUG(10, ("KRB5 auth\n")); - - 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); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - break; - default: DEBUG(0, ("process_request_pdu: " "unknown auth type %u set.\n", diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ca8655cab1..ce8ab819c5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -30,7 +30,6 @@ #include "auth_generic.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/rpc/dcerpc.h" -#include "librpc/crypto/gse.h" #include "librpc/crypto/spnego.h" #include "rpc_dce.h" #include "cli_pipe.h" @@ -1005,35 +1004,6 @@ static NTSTATUS create_spnego_auth_bind_req(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* - Creates krb5 auth bind. - ********************************************************************/ - -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, gse_ctx, - &in_token, - auth_token); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - DEBUG(5, ("Created GSS Authentication Token:\n")); - dump_data(5, auth_token->data, auth_token->length); - - return NT_STATUS_OK; -} - /******************************************************************* Creates NTLMSSP auth bind. ********************************************************************/ @@ -1171,6 +1141,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, break; case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token); if (!NT_STATUS_IS_OK(ret)) { return ret; @@ -1184,13 +1155,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, } break; - case DCERPC_AUTH_TYPE_KRB5: - ret = create_gssapi_auth_bind_req(mem_ctx, auth, &auth_token); - if (!NT_STATUS_IS_OK(ret)) { - return ret; - } - break; - case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM: auth_token = data_blob_talloc(mem_ctx, "NCALRPC_AUTH_TOKEN", @@ -1691,7 +1655,6 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) struct pipe_auth_data *pauth = state->cli->auth; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; struct ncacn_packet *pkt = NULL; struct dcerpc_auth auth; DATA_BLOB auth_token = data_blob_null; @@ -1770,6 +1733,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) return; case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(pauth->auth_ctx, struct gensec_security); status = gensec_update(gensec_security, state, NULL, @@ -1808,24 +1772,6 @@ 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, - gse_ctx, - &auth.credentials, - &auth_token); - if (!NT_STATUS_IS_OK(status)) { - break; - } - - 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); - } - break; - default: goto err_out; } @@ -2980,82 +2926,6 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, return NT_STATUS_OK; } -/**************************************************************************** - Open a named pipe to an SMB server and bind using krb5 (bind type 16). - The idea is this can be called with service_princ, username and password all - NULL so long as the caller has a TGT. - ****************************************************************************/ - -NTSTATUS cli_rpc_pipe_open_krb5(struct cli_state *cli, - const struct ndr_syntax_id *interface, - enum dcerpc_transport_t transport, - enum dcerpc_AuthLevel auth_level, - const char *server, - const char *username, - const char *password, - struct rpc_pipe_client **presult) -{ - 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); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - auth = talloc(result, struct pipe_auth_data); - if (auth == NULL) { - status = NT_STATUS_NO_MEMORY; - goto err_out; - } - auth->auth_type = DCERPC_AUTH_TYPE_KRB5; - auth->auth_level = auth_level; - - if (!username) { - username = ""; - } - auth->user_name = talloc_strdup(auth, username); - if (!auth->user_name) { - status = NT_STATUS_NO_MEMORY; - goto err_out; - } - - /* Fixme, should we fetch/set the Realm ? */ - auth->domain = talloc_strdup(auth, ""); - if (!auth->domain) { - status = NT_STATUS_NO_MEMORY; - goto err_out; - } - - status = gse_init_client(auth, - (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY), - (auth_level == DCERPC_AUTH_LEVEL_PRIVACY), - NULL, server, "cifs", username, password, - 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)) { - DEBUG(0, ("cli_rpc_pipe_bind failed with error %s\n", - nt_errstr(status))); - goto err_out; - } - - *presult = result; - return NT_STATUS_OK; - -err_out: - TALLOC_FREE(result); - return status; -} - NTSTATUS cli_rpc_pipe_open_spnego_krb5(struct cli_state *cli, const struct ndr_syntax_id *interface, enum dcerpc_transport_t transport, @@ -3218,7 +3088,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct schannel_state *schannel_auth; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; DATA_BLOB sk = data_blob_null; bool make_dup = false; @@ -3246,6 +3115,7 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, make_dup = false; break; case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(a->auth_ctx, struct gensec_security); status = gensec_session_key(gensec_security, mem_ctx, &sk); @@ -3254,12 +3124,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, } make_dup = false; break; - case DCERPC_AUTH_TYPE_KRB5: - 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_NCALRPC_AS_SYSTEM: case DCERPC_AUTH_TYPE_NONE: sk = data_blob_const(a->user_session_key.data, diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 61e306c199..605ed5420c 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -676,48 +676,6 @@ static bool pipe_auth_generic_verify_final(TALLOC_CTX *mem_ctx, return true; } -/******************************************************************* - Handle a GSSAPI bind auth. -*******************************************************************/ - -static bool pipe_gssapi_auth_bind(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, - struct dcerpc_auth *auth_info, - DATA_BLOB *response) -{ - NTSTATUS status; - struct gse_context *gse_ctx = NULL; - - status = gssapi_server_auth_start(p, - (auth_info->auth_level == - DCERPC_AUTH_LEVEL_INTEGRITY), - (auth_info->auth_level == - DCERPC_AUTH_LEVEL_PRIVACY), - true, - &auth_info->credentials, - response, - &gse_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to init dcerpc gssapi server (%s)\n", - nt_errstr(status))); - goto err; - } - - /* Make sure data is bound to the memctx, to be freed the caller */ - talloc_steal(mem_ctx, response->data); - - p->auth.auth_ctx = gse_ctx; - p->auth.auth_type = DCERPC_AUTH_TYPE_KRB5; - - DEBUG(10, ("KRB5 auth started\n")); - - return true; - -err: - TALLOC_FREE(gse_ctx); - return false; -} - static NTSTATUS pipe_gssapi_verify_final(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, const struct tsocket_address *remote_address, @@ -769,6 +727,7 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) switch (p->auth.auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(p->auth.auth_ctx, struct gensec_security); if (!pipe_auth_generic_verify_final(p, gensec_security, @@ -777,18 +736,6 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) return NT_STATUS_ACCESS_DENIED; } break; - case DCERPC_AUTH_TYPE_KRB5: - gse_ctx = talloc_get_type_abort(p->auth.auth_ctx, - struct gse_context); - status = pipe_gssapi_verify_final(p, gse_ctx, - p->remote_address, - &p->session_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("gssapi bind failed with: %s", - nt_errstr(status))); - return status; - } - break; case DCERPC_AUTH_TYPE_SPNEGO: spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, struct spnego_context); @@ -1010,8 +957,8 @@ static bool api_pipe_bind_req(struct pipes_struct *p, break; case DCERPC_AUTH_TYPE_KRB5: - if (!pipe_gssapi_auth_bind(p, pkt, - &auth_info, &auth_resp)) { + if (!pipe_auth_generic_bind(p, pkt, + &auth_info, &auth_resp)) { goto err_exit; } break; @@ -1154,7 +1101,6 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt) DATA_BLOB response = data_blob_null; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; NTSTATUS status; DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); @@ -1200,19 +1146,13 @@ bool api_pipe_bind_auth3(struct pipes_struct *p, struct ncacn_packet *pkt) switch (auth_info.auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(p->auth.auth_ctx, struct gensec_security); status = auth_generic_server_step(gensec_security, pkt, &auth_info.credentials, &response); break; - case DCERPC_AUTH_TYPE_KRB5: - 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: spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, struct spnego_context); @@ -1273,7 +1213,6 @@ static bool api_pipe_alter_context(struct pipes_struct *p, int pad_len = 0; struct gensec_security *gensec_security; struct spnego_context *spnego_ctx; - struct gse_context *gse_ctx; DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); @@ -1360,13 +1299,6 @@ static bool api_pipe_alter_context(struct pipes_struct *p, break; case DCERPC_AUTH_TYPE_KRB5: - 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: gensec_security = talloc_get_type_abort(p->auth.auth_ctx, struct gensec_security); diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 1f74f7e9e9..27deff56ff 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -715,6 +715,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, } break; case DCERPC_AUTH_TYPE_NTLMSSP: + case DCERPC_AUTH_TYPE_KRB5: ntresult = cli_rpc_pipe_open_generic_auth( cli, cmd_entry->interface, default_transport, @@ -734,15 +735,6 @@ static NTSTATUS do_cmd(struct cli_state *cli, get_cmdline_auth_info_domain(auth_info), &cmd_entry->rpc_pipe); break; - case DCERPC_AUTH_TYPE_KRB5: - ntresult = cli_rpc_pipe_open_krb5( - cli, cmd_entry->interface, - default_transport, - pipe_default_auth_level, - cli_state_remote_name(cli), - NULL, NULL, - &cmd_entry->rpc_pipe); - break; default: DEBUG(0, ("Could not initialise %s. Invalid " "auth type %u\n", -- cgit