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/rpc_server | |
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/rpc_server')
-rw-r--r-- | source3/rpc_server/dcesrv_spnego.c | 297 | ||||
-rw-r--r-- | source3/rpc_server/dcesrv_spnego.h | 38 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 82 | ||||
-rwxr-xr-x | source3/rpc_server/wscript_build | 2 |
4 files changed, 3 insertions, 416 deletions
diff --git a/source3/rpc_server/dcesrv_spnego.c b/source3/rpc_server/dcesrv_spnego.c deleted file mode 100644 index ed7d772d59..0000000000 --- a/source3/rpc_server/dcesrv_spnego.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * SPNEGO Encapsulation - * DCERPC Server functions - * 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/>. - */ - -#include "includes.h" -#include "../libcli/auth/spnego.h" -#include "../lib/tsocket/tsocket.h" -#include "dcesrv_auth_generic.h" -#include "dcesrv_spnego.h" -#include "auth/gensec/gensec.h" - -static NTSTATUS spnego_init_server(TALLOC_CTX *mem_ctx, - bool do_sign, bool do_seal, - bool is_dcerpc, - const struct tsocket_address *remote_address, - struct spnego_context **spnego_ctx) -{ - struct spnego_context *sp_ctx = NULL; - - sp_ctx = talloc_zero(mem_ctx, struct spnego_context); - if (!sp_ctx) { - return NT_STATUS_NO_MEMORY; - } - - sp_ctx->remote_address = tsocket_address_copy(remote_address, sp_ctx); - if (sp_ctx->remote_address == NULL) { - return NT_STATUS_NO_MEMORY; - } - - sp_ctx->do_sign = do_sign; - sp_ctx->do_seal = do_seal; - sp_ctx->is_dcerpc = is_dcerpc; - - *spnego_ctx = sp_ctx; - return NT_STATUS_OK; -} - -static NTSTATUS spnego_server_mech_init(struct spnego_context *sp_ctx, - DATA_BLOB *token_in, - DATA_BLOB *token_out) -{ - struct gensec_security *gensec_security; - NTSTATUS status; - const char *oid; - - switch (sp_ctx->mech) { - case SPNEGO_KRB5: - oid = GENSEC_OID_KERBEROS5; - break; - case SPNEGO_NTLMSSP: - oid = GENSEC_OID_NTLMSSP; - break; - default: - DEBUG(3, ("No known mechanisms available\n")); - return NT_STATUS_INVALID_PARAMETER; - } - - status = auth_generic_server_start(sp_ctx, - oid, - sp_ctx->do_sign, - sp_ctx->do_seal, - sp_ctx->is_dcerpc, - token_in, - token_out, - sp_ctx->remote_address, - &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to init ntlmssp server " - "(%s)\n", nt_errstr(status))); - return status; - } - - sp_ctx->gensec_security = gensec_security; - - return NT_STATUS_OK; -} - -NTSTATUS spnego_server_step(struct spnego_context *sp_ctx, - TALLOC_CTX *mem_ctx, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out) -{ - DATA_BLOB token_in = data_blob_null; - DATA_BLOB token_out = data_blob_null; - DATA_BLOB signature = data_blob_null; - DATA_BLOB MICblob = data_blob_null; - struct spnego_data sp_in; - ssize_t len_in = 0; - NTSTATUS status; - bool ret; - - len_in = spnego_read_data(mem_ctx, *spnego_in, &sp_in); - if (len_in == -1) { - DEBUG(1, (__location__ ": invalid SPNEGO blob.\n")); - dump_data(10, spnego_in->data, spnego_in->length); - status = NT_STATUS_INVALID_PARAMETER; - sp_ctx->state = SPNEGO_CONV_AUTH_DONE; - goto done; - } - if (sp_in.type != SPNEGO_NEG_TOKEN_TARG) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - token_in = sp_in.negTokenTarg.responseToken; - signature = sp_in.negTokenTarg.mechListMIC; - - switch (sp_ctx->state) { - case SPNEGO_CONV_NEGO: - /* still to initialize */ - status = spnego_server_mech_init(sp_ctx, - &token_in, - &token_out); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - /* server always need at least one reply from client */ - status = NT_STATUS_MORE_PROCESSING_REQUIRED; - sp_ctx->state = SPNEGO_CONV_AUTH_MORE; - break; - - case SPNEGO_CONV_AUTH_MORE: - - status = auth_generic_server_step( - sp_ctx->gensec_security, - mem_ctx, &token_in, &token_out); - break; - - case SPNEGO_CONV_AUTH_DONE: - /* we are already done, can't step further */ - /* fall thorugh and return error */ - default: - /* wrong case */ - return NT_STATUS_INVALID_PARAMETER; - } - - if (NT_STATUS_IS_OK(status) && signature.length != 0) { - /* last packet and requires signature check */ - ret = spnego_mech_list_blob(talloc_tos(), - sp_ctx->oid_list, &MICblob); - if (ret) { - status = spnego_sigcheck(talloc_tos(), sp_ctx, - &MICblob, &MICblob, - &signature); - } else { - status = NT_STATUS_UNSUCCESSFUL; - } - } - if (NT_STATUS_IS_OK(status) && signature.length != 0) { - /* if signature was good, sign our own packet too */ - status = spnego_sign(talloc_tos(), sp_ctx, - &MICblob, &MICblob, &signature); - } - -done: - *spnego_out = spnego_gen_auth_response_and_mic(mem_ctx, status, - sp_ctx->mech_oid, - &token_out, - &signature); - if (!spnego_out->data) { - DEBUG(1, ("SPNEGO wrapping failed!\n")); - status = NT_STATUS_UNSUCCESSFUL; - } - - if (NT_STATUS_IS_OK(status) || - !NT_STATUS_EQUAL(status, - NT_STATUS_MORE_PROCESSING_REQUIRED)) { - sp_ctx->state = SPNEGO_CONV_AUTH_DONE; - } - - data_blob_free(&token_in); - data_blob_free(&token_out); - return status; -} - -NTSTATUS spnego_server_auth_start(TALLOC_CTX *mem_ctx, - bool do_sign, - bool do_seal, - bool is_dcerpc, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out, - const struct tsocket_address *remote_address, - struct spnego_context **spnego_ctx) -{ - struct spnego_context *sp_ctx; - DATA_BLOB token_in = data_blob_null; - DATA_BLOB token_out = data_blob_null; - unsigned int i; - NTSTATUS status; - bool ret; - - if (!spnego_in->length) { - return NT_STATUS_INVALID_PARAMETER; - } - - status = spnego_init_server(mem_ctx, - do_sign, - do_seal, - is_dcerpc, - remote_address, - &sp_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - ret = spnego_parse_negTokenInit(sp_ctx, *spnego_in, - sp_ctx->oid_list, NULL, &token_in); - if (!ret || sp_ctx->oid_list[0] == NULL) { - DEBUG(3, ("Invalid SPNEGO message\n")); - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* try for krb auth first */ - for (i = 0; sp_ctx->oid_list[i] && sp_ctx->mech == SPNEGO_NONE; i++) { - if (strcmp(OID_KERBEROS5, sp_ctx->oid_list[i]) == 0 || - strcmp(OID_KERBEROS5_OLD, sp_ctx->oid_list[i]) == 0) { - - if (lp_security() == SEC_ADS || USE_KERBEROS_KEYTAB) { - sp_ctx->mech = SPNEGO_KRB5; - sp_ctx->mech_oid = sp_ctx->oid_list[i]; - } - } - } - - /* if auth type still undetermined, try for NTLMSSP */ - for (i = 0; sp_ctx->oid_list[i] && sp_ctx->mech == SPNEGO_NONE; i++) { - if (strcmp(OID_NTLMSSP, sp_ctx->oid_list[i]) == 0) { - sp_ctx->mech = SPNEGO_NTLMSSP; - sp_ctx->mech_oid = sp_ctx->oid_list[i]; - } - } - - if (!sp_ctx->mech_oid) { - DEBUG(3, ("No known mechanisms available\n")); - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - if (DEBUGLEVEL >= 10) { - DEBUG(10, ("Client Provided OIDs:\n")); - for (i = 0; sp_ctx->oid_list[i]; i++) { - DEBUG(10, (" %d: %s\n", i, sp_ctx->oid_list[i])); - } - DEBUG(10, ("Chosen OID: %s\n", sp_ctx->mech_oid)); - } - - /* If it is not the first OID, then token_in is not valid for the - * choosen mech */ - if (sp_ctx->mech_oid != sp_ctx->oid_list[0]) { - /* request more and send back empty token */ - status = NT_STATUS_MORE_PROCESSING_REQUIRED; - sp_ctx->state = SPNEGO_CONV_NEGO; - goto done; - } - - status = spnego_server_mech_init(sp_ctx, &token_in, &token_out); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - DEBUG(10, ("SPNEGO(%d) auth started\n", sp_ctx->mech)); - - /* server always need at least one reply from client */ - status = NT_STATUS_MORE_PROCESSING_REQUIRED; - sp_ctx->state = SPNEGO_CONV_AUTH_MORE; - -done: - *spnego_out = spnego_gen_auth_response(mem_ctx, &token_out, - status, sp_ctx->mech_oid); - if (!spnego_out->data) { - status = NT_STATUS_INVALID_PARAMETER; - TALLOC_FREE(sp_ctx); - } else { - status = NT_STATUS_OK; - *spnego_ctx = sp_ctx; - } - - data_blob_free(&token_in); - data_blob_free(&token_out); - - return status; -} diff --git a/source3/rpc_server/dcesrv_spnego.h b/source3/rpc_server/dcesrv_spnego.h deleted file mode 100644 index e6187f64f4..0000000000 --- a/source3/rpc_server/dcesrv_spnego.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPNEGO Encapsulation - * Server 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 _DCESRV_SPNEGO_H_ -#define _DCESRV_SPENGO_H_ - -#include "librpc/crypto/spnego.h" - -NTSTATUS spnego_server_auth_start(TALLOC_CTX *mem_ctx, - bool do_sign, - bool do_seal, - bool is_dcerpc, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out, - const struct tsocket_address *remote_address, - struct spnego_context **spnego_ctx); -NTSTATUS spnego_server_step(struct spnego_context *sp_ctx, - TALLOC_CTX *mem_ctx, - DATA_BLOB *spnego_in, - DATA_BLOB *spnego_out); - -#endif /* _DCESRV_SPENGO_H_ */ diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 879b6deabd..9be2bc8d72 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -34,7 +34,6 @@ #include "../libcli/auth/schannel.h" #include "../libcli/auth/spnego.h" #include "dcesrv_auth_generic.h" -#include "dcesrv_spnego.h" #include "rpc_server.h" #include "rpc_dce.h" #include "smbd/smbd.h" @@ -423,45 +422,6 @@ bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax) } /******************************************************************* - Handle the first part of a SPNEGO bind auth. -*******************************************************************/ - -static bool pipe_spnego_auth_bind(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, - struct dcerpc_auth *auth_info, - DATA_BLOB *response) -{ - struct spnego_context *spnego_ctx; - NTSTATUS status; - - status = spnego_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, - p->remote_address, - &spnego_ctx); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed SPNEGO negotiate (%s)\n", - nt_errstr(status))); - return false; - } - - /* Make sure data is bound to the memctx, to be freed the caller */ - talloc_steal(mem_ctx, response->data); - - p->auth.auth_ctx = spnego_ctx; - p->auth.auth_type = DCERPC_AUTH_TYPE_SPNEGO; - - DEBUG(10, ("SPNEGO auth started\n")); - - return true; -} - -/******************************************************************* Handle an schannel bind auth. *******************************************************************/ @@ -678,12 +638,11 @@ static bool pipe_auth_generic_verify_final(TALLOC_CTX *mem_ctx, static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) { struct gensec_security *gensec_security; - struct spnego_context *spnego_ctx; - NTSTATUS status; switch (p->auth.auth_type) { case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: gensec_security = talloc_get_type_abort(p->auth.auth_ctx, struct gensec_security); if (!pipe_auth_generic_verify_final(p, gensec_security, @@ -692,21 +651,6 @@ static NTSTATUS pipe_auth_verify_final(struct pipes_struct *p) return NT_STATUS_ACCESS_DENIED; } break; - case DCERPC_AUTH_TYPE_SPNEGO: - spnego_ctx = talloc_get_type_abort(p->auth.auth_ctx, - struct spnego_context); - status = spnego_get_negotiated_mech(spnego_ctx, &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Bad SPNEGO state (%s)\n", - nt_errstr(status))); - return status; - } - if (!pipe_auth_generic_verify_final(p, gensec_security, - p->auth.auth_level, - &p->session_info)) { - return NT_STATUS_ACCESS_DENIED; - } - break; default: DEBUG(0, (__location__ ": incorrect auth type (%u).\n", (unsigned int)p->auth.auth_type)); @@ -883,12 +827,6 @@ static bool api_pipe_bind_req(struct pipes_struct *p, break; case DCERPC_AUTH_TYPE_SPNEGO: - if (!pipe_spnego_auth_bind(p, pkt, - &auth_info, &auth_resp)) { - goto err_exit; - } - break; - case DCERPC_AUTH_TYPE_KRB5: if (!pipe_auth_generic_bind(p, pkt, &auth_info, &auth_resp)) { @@ -1033,7 +971,6 @@ 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 gensec_security *gensec_security; - struct spnego_context *spnego_ctx; NTSTATUS status; DEBUG(5, ("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); @@ -1080,19 +1017,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: + case DCERPC_AUTH_TYPE_SPNEGO: 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_SPNEGO: - 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; default: DEBUG(0, (__location__ ": incorrect auth type (%u).\n", (unsigned int)auth_info.auth_type)); @@ -1145,7 +1076,6 @@ static bool api_pipe_alter_context(struct pipes_struct *p, DATA_BLOB auth_blob = data_blob_null; int pad_len = 0; struct gensec_security *gensec_security; - struct spnego_context *spnego_ctx; DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); @@ -1223,14 +1153,6 @@ static bool api_pipe_alter_context(struct pipes_struct *p, switch (auth_info.auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: - 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: case DCERPC_AUTH_TYPE_NTLMSSP: gensec_security = talloc_get_type_abort(p->auth.auth_ctx, diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build index 57c76a2817..bd96b92b25 100755 --- a/source3/rpc_server/wscript_build +++ b/source3/rpc_server/wscript_build @@ -38,7 +38,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_SERVICE', deps='samba-util') bld.SAMBA3_SUBSYSTEM('RPC_CRYPTO', - source='dcesrv_auth_generic.c dcesrv_spnego.c', + source='dcesrv_auth_generic.c', deps = 'KRB5_PAC') bld.SAMBA3_SUBSYSTEM('RPC_PIPE_REGISTER', |