diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-02-06 12:40:38 +1100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2012-02-16 15:18:42 +0100 |
commit | 2b511f0e9280e0b918265bac8090d79d3c9d5115 (patch) | |
tree | b2c8db285a6a6e588ac309ea395d6ebdc23bbafb /source3/librpc | |
parent | 5c9b6db68e0f535ed2b42bbfee310b7cebf65ca4 (diff) | |
download | samba-2b511f0e9280e0b918265bac8090d79d3c9d5115.tar.gz samba-2b511f0e9280e0b918265bac8090d79d3c9d5115.tar.bz2 samba-2b511f0e9280e0b918265bac8090d79d3c9d5115.zip |
s3-librpc: Use gensec_spnego for DCE/RPC authentication
This ensures that we use the same SPNEGO code on session setup and on
DCE/RPC binds, and simplfies the calling code as spnego is no longer
a special case in cli_pipe.c
A special case wrapper function remains to avoid changing the
application layer callers in this patch.
Andrew Bartlett
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source3/librpc')
-rw-r--r-- | source3/librpc/crypto/cli_spnego.c | 334 | ||||
-rw-r--r-- | source3/librpc/crypto/spnego.h | 92 | ||||
-rw-r--r-- | source3/librpc/rpc/dcerpc_helpers.c | 42 |
3 files changed, 0 insertions, 468 deletions
diff --git a/source3/librpc/crypto/cli_spnego.c b/source3/librpc/crypto/cli_spnego.c deleted file mode 100644 index e676703c6b..0000000000 --- a/source3/librpc/crypto/cli_spnego.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * SPNEGO Encapsulation - * Client functions - * Copyright (C) Simo Sorce 2010. - * Copyright (C) Andrew Bartlett 2011. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "includes.h" -#include "../libcli/auth/spnego.h" -#include "include/auth_generic.h" -#include "librpc/gen_ndr/ntlmssp.h" -#include "auth/ntlmssp/ntlmssp.h" -#include "librpc/crypto/gse.h" -#include "librpc/crypto/spnego.h" -#include "auth/gensec/gensec.h" - -static NTSTATUS spnego_context_init(TALLOC_CTX *mem_ctx, - bool do_sign, bool do_seal, - struct spnego_context **spnego_ctx) -{ - struct spnego_context *sp_ctx; - - sp_ctx = talloc_zero(mem_ctx, struct spnego_context); - if (!sp_ctx) { - return NT_STATUS_NO_MEMORY; - } - - sp_ctx->do_sign = do_sign; - sp_ctx->do_seal = do_seal; - sp_ctx->state = SPNEGO_CONV_INIT; - - *spnego_ctx = sp_ctx; - return NT_STATUS_OK; -} - -NTSTATUS spnego_generic_init_client(TALLOC_CTX *mem_ctx, - const char *oid, - bool do_sign, bool do_seal, - bool is_dcerpc, - const char *server, - const char *target_service, - const char *domain, - const char *username, - const char *password, - struct spnego_context **spnego_ctx) -{ - struct spnego_context *sp_ctx = NULL; - struct auth_generic_state *auth_generic_state; - NTSTATUS status; - - status = spnego_context_init(mem_ctx, do_sign, do_seal, &sp_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) { - sp_ctx->mech = SPNEGO_NTLMSSP; - } else if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) { - sp_ctx->mech = SPNEGO_KRB5; - } else { - return NT_STATUS_INVALID_PARAMETER; - } - - status = auth_generic_client_prepare(sp_ctx, - &auth_generic_state); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - status = auth_generic_set_username(auth_generic_state, - username); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - status = auth_generic_set_domain(auth_generic_state, - domain); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - status = auth_generic_set_password(auth_generic_state, - password); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - if (do_sign) { - gensec_want_feature(auth_generic_state->gensec_security, - GENSEC_FEATURE_SIGN); - } else if (do_seal) { - gensec_want_feature(auth_generic_state->gensec_security, - GENSEC_FEATURE_SEAL); - } - - if (is_dcerpc) { - gensec_want_feature(auth_generic_state->gensec_security, - GENSEC_FEATURE_DCE_STYLE); - } - - status = gensec_set_target_service(auth_generic_state->gensec_security, target_service); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - status = gensec_set_target_hostname(auth_generic_state->gensec_security, server); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - status = auth_generic_client_start(auth_generic_state, oid); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(sp_ctx); - return status; - } - - sp_ctx->gensec_security = talloc_move(sp_ctx, &auth_generic_state->gensec_security); - TALLOC_FREE(auth_generic_state); - *spnego_ctx = sp_ctx; - return NT_STATUS_OK; -} - -NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out) -{ - struct gensec_security *gensec_security; - struct spnego_data sp_in, sp_out; - DATA_BLOB token_in = data_blob_null; - DATA_BLOB token_out = data_blob_null; - const char *mech_oids[2] = { NULL, NULL }; - char *principal = NULL; - ssize_t len_in = 0; - ssize_t len_out = 0; - NTSTATUS status; - - if (!spnego_in->length) { - /* server didn't send anything, is init ? */ - if (sp_ctx->state != SPNEGO_CONV_INIT) { - return NT_STATUS_INVALID_PARAMETER; - } - } else { - len_in = spnego_read_data(mem_ctx, *spnego_in, &sp_in); - if (len_in == -1) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - if (sp_in.type != SPNEGO_NEG_TOKEN_TARG) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - if (sp_in.negTokenTarg.negResult == SPNEGO_REJECT) { - status = NT_STATUS_ACCESS_DENIED; - goto done; - } - token_in = sp_in.negTokenTarg.responseToken; - } - - if (sp_ctx->state == SPNEGO_CONV_AUTH_CONFIRM) { - if (sp_in.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) { - sp_ctx->state = SPNEGO_CONV_AUTH_DONE; - *spnego_out = data_blob_null; - status = NT_STATUS_OK; - } else { - status = NT_STATUS_ACCESS_DENIED; - } - goto done; - } - - switch (sp_ctx->mech) { - case SPNEGO_KRB5: - mech_oids[0] = OID_KERBEROS5; - break; - - case SPNEGO_NTLMSSP: - mech_oids[0] = OID_NTLMSSP; - break; - - default: - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - gensec_security = sp_ctx->gensec_security; - status = gensec_update(gensec_security, mem_ctx, NULL, - token_in, &token_out); - sp_ctx->more_processing = false; - if (NT_STATUS_EQUAL(status, - NT_STATUS_MORE_PROCESSING_REQUIRED)) { - sp_ctx->more_processing = true; - } else if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - switch (sp_ctx->state) { - case SPNEGO_CONV_INIT: - *spnego_out = spnego_gen_negTokenInit(mem_ctx, mech_oids, - &token_out, principal); - if (!spnego_out->data) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - sp_ctx->state = SPNEGO_CONV_AUTH_MORE; - break; - - case SPNEGO_CONV_AUTH_MORE: - /* server says it's done and we do not seem to agree */ - if (sp_in.negTokenTarg.negResult == - SPNEGO_ACCEPT_COMPLETED) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - sp_out.type = SPNEGO_NEG_TOKEN_TARG; - sp_out.negTokenTarg.negResult = SPNEGO_NONE_RESULT; - sp_out.negTokenTarg.supportedMech = NULL; - sp_out.negTokenTarg.responseToken = token_out; - sp_out.negTokenTarg.mechListMIC = data_blob_null; - - len_out = spnego_write_data(mem_ctx, spnego_out, &sp_out); - if (len_out == -1) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - if (!sp_ctx->more_processing) { - /* we still need to get an ack from the server */ - sp_ctx->state = SPNEGO_CONV_AUTH_CONFIRM; - } - - break; - - default: - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - status = NT_STATUS_OK; - -done: - if (len_in > 0) { - spnego_free_data(&sp_in); - } - data_blob_free(&token_out); - return status; -} - -bool spnego_require_more_processing(struct spnego_context *sp_ctx) -{ - - /* see if spnego processing itself requires more */ - if (sp_ctx->state == SPNEGO_CONV_AUTH_MORE || - sp_ctx->state == SPNEGO_CONV_AUTH_CONFIRM) { - return true; - } - - return sp_ctx->more_processing; -} - -NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, - struct gensec_security **auth_context) -{ - *auth_context = sp_ctx->gensec_security; - return NT_STATUS_OK; -} - -NTSTATUS spnego_sign(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature) -{ - return gensec_sign_packet( - sp_ctx->gensec_security, - mem_ctx, - data->data, data->length, - full_data->data, full_data->length, - signature); -} - -NTSTATUS spnego_sigcheck(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature) -{ - return gensec_check_packet( - sp_ctx->gensec_security, - data->data, data->length, - full_data->data, full_data->length, - signature); -} - -NTSTATUS spnego_seal(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature) -{ - return gensec_seal_packet( - sp_ctx->gensec_security, - mem_ctx, - data->data, data->length, - full_data->data, full_data->length, - signature); -} - -NTSTATUS spnego_unseal(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature) -{ - return gensec_unseal_packet( - sp_ctx->gensec_security, - data->data, data->length, - full_data->data, full_data->length, - signature); -} diff --git a/source3/librpc/crypto/spnego.h b/source3/librpc/crypto/spnego.h deleted file mode 100644 index b66ef4d152..0000000000 --- a/source3/librpc/crypto/spnego.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPNEGO Encapsulation - * RPC Pipe client routines - * Copyright (C) Simo Sorce 2010. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _CLI_SPNEGO_H_ -#define _CLI_SPENGO_H_ - -enum spnego_mech { - SPNEGO_NONE = 0, - SPNEGO_KRB5, - SPNEGO_NTLMSSP -}; - -struct spnego_context { - enum spnego_mech mech; - - struct gensec_security *gensec_security; - - char *oid_list[ASN1_MAX_OIDS]; - char *mech_oid; - - enum { - SPNEGO_CONV_INIT = 0, - SPNEGO_CONV_NEGO, - SPNEGO_CONV_AUTH_MORE, - SPNEGO_CONV_AUTH_CONFIRM, - SPNEGO_CONV_AUTH_DONE - } state; - - bool do_sign; - bool do_seal; - bool is_dcerpc; - - struct tsocket_address *remote_address; - - bool more_processing; /* Current mech state requires more processing */ -}; - -NTSTATUS spnego_generic_init_client(TALLOC_CTX *mem_ctx, - const char *oid, - bool do_sign, bool do_seal, - bool is_dcerpc, - const char *server, - const char *target_service, - const char *domain, - const char *username, - const char *password, - struct spnego_context **spnego_ctx); - -NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out); - -bool spnego_require_more_processing(struct spnego_context *sp_ctx); - -NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, - struct gensec_security **auth_context); - -NTSTATUS spnego_sign(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature); -NTSTATUS spnego_sigcheck(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature); -NTSTATUS spnego_seal(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature); -NTSTATUS spnego_unseal(TALLOC_CTX *mem_ctx, - struct spnego_context *sp_ctx, - DATA_BLOB *data, DATA_BLOB *full_data, - DATA_BLOB *signature); - -#endif /* _CLI_SPENGO_H_ */ diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 212c98fb1a..5f8c793191 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -25,7 +25,6 @@ #include "../libcli/auth/schannel.h" #include "../libcli/auth/spnego.h" #include "librpc/crypto/gse.h" -#include "librpc/crypto/spnego.h" #include "auth/gensec/gensec.h" #undef DBGC_CLASS @@ -267,8 +266,6 @@ NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth, size_t mod_len; struct gensec_security *gensec_security; struct schannel_state *schannel_auth; - struct spnego_context *spnego_ctx; - NTSTATUS status; /* no auth token cases first */ switch (auth->auth_level) { @@ -300,15 +297,6 @@ 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: - spnego_ctx = talloc_get_type_abort(auth->auth_ctx, - struct spnego_context); - status = spnego_get_negotiated_mech(spnego_ctx, &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - *auth_len = gensec_sig_size(gensec_security, max_len); - break; - case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(auth->auth_ctx, @@ -557,7 +545,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; char pad[CLIENT_NDR_PADDING_SIZE] = { 0, }; DATA_BLOB auth_info; DATA_BLOB auth_blob; @@ -606,17 +593,6 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, status = NT_STATUS_OK; break; case DCERPC_AUTH_TYPE_SPNEGO: - spnego_ctx = talloc_get_type_abort(auth->auth_ctx, - struct spnego_context); - status = spnego_get_negotiated_mech(spnego_ctx, &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = add_generic_auth_footer(gensec_security, - 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, @@ -661,7 +637,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; NTSTATUS status; struct dcerpc_auth auth_info; uint32_t auth_length; @@ -728,23 +703,6 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, return NT_STATUS_OK; case DCERPC_AUTH_TYPE_SPNEGO: - spnego_ctx = talloc_get_type_abort(auth->auth_ctx, - struct spnego_context); - status = spnego_get_negotiated_mech(spnego_ctx, &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = get_generic_auth_footer(gensec_security, - auth->auth_level, - &data, &full_pkt, - &auth_info.credentials); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - break; - case DCERPC_AUTH_TYPE_KRB5: case DCERPC_AUTH_TYPE_NTLMSSP: |