From 2b511f0e9280e0b918265bac8090d79d3c9d5115 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 6 Feb 2012 12:40:38 +1100 Subject: 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 --- source3/Makefile.in | 4 +- source3/librpc/crypto/cli_spnego.c | 334 ------------------------------------ source3/librpc/crypto/spnego.h | 92 ---------- source3/librpc/rpc/dcerpc_helpers.c | 42 ----- source3/rpc_client/cli_pipe.c | 159 ++++------------- source3/rpc_server/dcesrv_spnego.c | 297 -------------------------------- source3/rpc_server/dcesrv_spnego.h | 38 ---- source3/rpc_server/srv_pipe.c | 82 +-------- source3/rpc_server/wscript_build | 2 +- source3/wscript_build | 1 - 10 files changed, 42 insertions(+), 1009 deletions(-) delete mode 100644 source3/librpc/crypto/cli_spnego.c delete mode 100644 source3/librpc/crypto/spnego.h delete mode 100644 source3/rpc_server/dcesrv_spnego.c delete mode 100644 source3/rpc_server/dcesrv_spnego.h diff --git a/source3/Makefile.in b/source3/Makefile.in index 2920347639..e668dd1fa5 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -632,7 +632,6 @@ LIBMSRPC_OBJ = $(SCHANNEL_OBJ) \ librpc/crypto/gse.o \ ../auth/kerberos/gssapi_pac.o \ ../auth/kerberos/gssapi_parse.o \ - librpc/crypto/cli_spnego.o \ librpc/rpc/rpc_common.o \ rpc_client/rpc_transport_np.o \ rpc_client/rpc_transport_sock.o \ @@ -760,8 +759,7 @@ RPC_CONFIG = rpc_server/rpc_config.o RPC_SERVICE = rpc_server/rpc_server.o -RPC_CRYPTO = rpc_server/dcesrv_auth_generic.o \ - rpc_server/dcesrv_spnego.o +RPC_CRYPTO = rpc_server/dcesrv_auth_generic.o RPC_PIPE_OBJ = rpc_server/srv_pipe.o rpc_server/srv_pipe_hnd.o \ $(RPC_CONFIG) $(RPC_NCACN_NP) $(RPC_SERVICE) $(RPC_CRYPTO) 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 . - */ - -#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 . - */ - -#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: diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index d4607d89c8..7740fbc4bc 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -30,11 +30,11 @@ #include "auth_generic.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/rpc/dcerpc.h" -#include "librpc/crypto/spnego.h" #include "rpc_dce.h" #include "cli_pipe.h" #include "libsmb/libsmb.h" #include "auth/gensec/gensec.h" +#include "auth/credentials/credentials.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_CLI @@ -976,34 +976,6 @@ static NTSTATUS rpc_api_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* - Creates spnego auth bind. - ********************************************************************/ - -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, spnego_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. ********************************************************************/ @@ -1134,6 +1106,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: ret = create_generic_auth_rpc_bind_req(cli, mem_ctx, &auth_token); if (!NT_STATUS_IS_OK(ret) && @@ -1142,13 +1115,6 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, } break; - case DCERPC_AUTH_TYPE_SPNEGO: - ret = create_spnego_auth_bind_req(cli, 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", @@ -1649,7 +1615,6 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) req, struct rpc_pipe_bind_state); struct pipe_auth_data *pauth = state->cli->auth; struct gensec_security *gensec_security; - struct spnego_context *spnego_ctx; struct ncacn_packet *pkt = NULL; struct dcerpc_auth auth; DATA_BLOB auth_token = data_blob_null; @@ -1729,6 +1694,7 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: + case DCERPC_AUTH_TYPE_SPNEGO: gensec_security = talloc_get_type_abort(pauth->auth_ctx, struct gensec_security); status = gensec_update(gensec_security, state, NULL, @@ -1748,30 +1714,6 @@ 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, - spnego_ctx, - &auth.credentials, - &auth_token); - if (!NT_STATUS_IS_OK(status)) { - break; - } - if (auth_token.length == 0) { - /* Bind complete. */ - tevent_req_done(req); - return; - } - if (spnego_require_more_processing(spnego_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; } @@ -2209,6 +2151,7 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, const char *domain, const char *username, const char *password, + enum credentials_use_kerberos use_kerberos, struct pipe_auth_data **presult) { struct auth_generic_state *auth_generic_ctx; @@ -2261,6 +2204,8 @@ static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx, goto fail; } + cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos); + status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level); if (!NT_STATUS_IS_OK(status)) { goto fail; @@ -2825,6 +2770,7 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, struct rpc_pipe_client *result; struct pipe_auth_data *auth = NULL; const char *target_service = table->authservices->names[0]; + NTSTATUS status; status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result); @@ -2835,7 +2781,8 @@ NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli, status = rpccli_generic_bind_data(result, auth_type, auth_level, server, target_service, - domain, username, password, + domain, username, password, + CRED_AUTO_USE_KERBEROS, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("rpccli_generic_bind_data returned %s\n", @@ -2937,70 +2884,53 @@ NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result; - struct pipe_auth_data *auth; - struct spnego_context *spnego_ctx; - NTSTATUS status; + struct pipe_auth_data *auth = NULL; const char *target_service = table->authservices->names[0]; + + NTSTATUS status; + enum credentials_use_kerberos use_kerberos; + + if (strcmp(oid, GENSEC_OID_KERBEROS5) == 0) { + use_kerberos = CRED_MUST_USE_KERBEROS; + } else if (strcmp(oid, GENSEC_OID_NTLMSSP) == 0) { + use_kerberos = CRED_DONT_USE_KERBEROS; + } else { + return NT_STATUS_INVALID_PARAMETER; + } status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &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_SPNEGO; - 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; - } - - if (!domain) { - domain = ""; - } - auth->domain = talloc_strdup(auth, domain); - if (!auth->domain) { - status = NT_STATUS_NO_MEMORY; - goto err_out; - } - - status = spnego_generic_init_client(auth, - oid, - (auth->auth_level == - DCERPC_AUTH_LEVEL_INTEGRITY), - (auth->auth_level == - DCERPC_AUTH_LEVEL_PRIVACY), - true, - server, target_service, - domain, username, password, - &spnego_ctx); + status = rpccli_generic_bind_data(result, + DCERPC_AUTH_TYPE_SPNEGO, auth_level, + server, target_service, + domain, username, password, + use_kerberos, + &auth); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("spnego_init_client returned %s\n", + DEBUG(0, ("rpccli_generic_bind_data returned %s\n", nt_errstr(status))); - goto err_out; + goto err; } - auth->auth_ctx = spnego_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; + DEBUG(0, ("cli_rpc_pipe_open_spnego: cli_rpc_pipe_bind failed with error %s\n", + nt_errstr(status) )); + goto err; } + DEBUG(10,("cli_rpc_pipe_open_spnego: opened pipe %s to " + "machine %s.\n", table->name, + result->desthost)); + *presult = result; return NT_STATUS_OK; -err_out: + err: + TALLOC_FREE(result); return status; } @@ -3013,7 +2943,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, struct pipe_auth_data *a; struct schannel_state *schannel_auth; struct gensec_security *gensec_security; - struct spnego_context *spnego_ctx; DATA_BLOB sk = data_blob_null; bool make_dup = false; @@ -3035,18 +2964,6 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, make_dup = true; break; case DCERPC_AUTH_TYPE_SPNEGO: - spnego_ctx = talloc_get_type_abort(a->auth_ctx, - struct spnego_context); - status = spnego_get_negotiated_mech(spnego_ctx, &gensec_security); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = gensec_session_key(gensec_security, mem_ctx, &sk); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - make_dup = false; - break; case DCERPC_AUTH_TYPE_NTLMSSP: case DCERPC_AUTH_TYPE_KRB5: gensec_security = talloc_get_type_abort(a->auth_ctx, 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 . - */ - -#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 . - */ - -#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" @@ -422,45 +421,6 @@ bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax) return false; } -/******************************************************************* - 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', diff --git a/source3/wscript_build b/source3/wscript_build index 1e41953174..67b686bbef 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -143,7 +143,6 @@ LIBSMB_SRC = '''libsmb/clientgen.c libsmb/cliconnect.c libsmb/clifile.c LIBMSRPC_SRC = ''' rpc_client/cli_pipe.c - librpc/crypto/cli_spnego.c librpc/rpc/rpc_common.c rpc_client/rpc_transport_np.c rpc_client/rpc_transport_sock.c -- cgit