* RPC Pipe client routines
* Largely rewritten by Jeremy Allison 2005.
* Heavily modified by Simo Sorce 2010.
+ * Copyright 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
#include "../libcli/auth/schannel.h"
#include "../libcli/auth/spnego.h"
#include "../auth/ntlmssp/ntlmssp.h"
-#include "ntlmssp_wrap.h"
+#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"
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.
********************************************************************/
-static NTSTATUS create_ntlmssp_auth_rpc_bind_req(struct rpc_pipe_client *cli,
+static NTSTATUS create_generic_auth_rpc_bind_req(struct rpc_pipe_client *cli,
TALLOC_CTX *mem_ctx,
DATA_BLOB *auth_token)
{
gensec_security = talloc_get_type_abort(cli->auth->auth_ctx,
struct gensec_security);
- DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
+ DEBUG(5, ("create_generic_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
status = gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
return status;
}
- DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
- dump_data(5, auth_token->data, auth_token->length);
-
return NT_STATUS_OK;
}
break;
case DCERPC_AUTH_TYPE_NTLMSSP:
- ret = create_ntlmssp_auth_rpc_bind_req(cli, mem_ctx, &auth_token);
+ 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;
}
}
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",
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;
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,
}
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;
}
return NT_STATUS_OK;
}
-static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
- enum dcerpc_AuthType auth_type,
- enum dcerpc_AuthLevel auth_level,
- const char *domain,
- const char *username,
- const char *password,
- struct pipe_auth_data **presult)
+static NTSTATUS rpccli_generic_bind_data(TALLOC_CTX *mem_ctx,
+ enum dcerpc_AuthType auth_type,
+ enum dcerpc_AuthLevel auth_level,
+ const char *server,
+ const char *target_service,
+ const char *domain,
+ const char *username,
+ const char *password,
+ struct pipe_auth_data **presult)
{
- struct auth_generic_state *ntlmssp_ctx;
+ struct auth_generic_state *auth_generic_ctx;
struct pipe_auth_data *result;
NTSTATUS status;
goto fail;
}
- status = auth_ntlmssp_client_prepare(result,
- &ntlmssp_ctx);
+ status = auth_generic_client_prepare(result,
+ &auth_generic_ctx);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- status = auth_ntlmssp_set_username(ntlmssp_ctx, username);
+ status = auth_generic_set_username(auth_generic_ctx, username);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- status = auth_ntlmssp_set_domain(ntlmssp_ctx, domain);
+ status = auth_generic_set_domain(auth_generic_ctx, domain);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- status = auth_ntlmssp_set_password(ntlmssp_ctx, password);
+ status = auth_generic_set_password(auth_generic_ctx, password);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
- gensec_want_feature(ntlmssp_ctx->gensec_security, GENSEC_FEATURE_SIGN);
- } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
- gensec_want_feature(ntlmssp_ctx->gensec_security, GENSEC_FEATURE_SEAL);
+ status = gensec_set_target_service(auth_generic_ctx->gensec_security, target_service);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
}
- status = auth_ntlmssp_client_start(ntlmssp_ctx);
+ status = gensec_set_target_hostname(auth_generic_ctx->gensec_security, server);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- result->auth_ctx = talloc_move(result, &ntlmssp_ctx->gensec_security);
- talloc_free(ntlmssp_ctx);
+ status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ result->auth_ctx = talloc_move(result, &auth_generic_ctx->gensec_security);
+ talloc_free(auth_generic_ctx);
*presult = result;
return NT_STATUS_OK;
}
/****************************************************************************
- Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
+ Open a named pipe to an SMB server and bind using the mech specified
****************************************************************************/
-NTSTATUS cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
- const struct ndr_syntax_id *interface,
- enum dcerpc_transport_t transport,
- enum dcerpc_AuthLevel auth_level,
- const char *domain,
- const char *username,
- const char *password,
- struct rpc_pipe_client **presult)
+NTSTATUS cli_rpc_pipe_open_generic_auth(struct cli_state *cli,
+ const struct ndr_syntax_id *interface,
+ enum dcerpc_transport_t transport,
+ enum dcerpc_AuthType auth_type,
+ enum dcerpc_AuthLevel auth_level,
+ const char *server,
+ const char *domain,
+ const char *username,
+ const char *password,
+ struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
struct pipe_auth_data *auth = NULL;
- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
+ const char *target_service = "cifs"; /* TODO: Determine target service from the bindings or interface table */
NTSTATUS status;
status = cli_rpc_pipe_open(cli, transport, interface, &result);
return status;
}
- status = rpccli_ntlmssp_bind_data(result,
+ status = rpccli_generic_bind_data(result,
auth_type, auth_level,
+ server, target_service,
domain, username, password,
&auth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_ntlmssp_bind_data returned %s\n",
+ DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
nt_errstr(status)));
goto err;
}
status = rpc_pipe_bind(result, auth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
+ DEBUG(0, ("cli_rpc_pipe_open_generic_auth: cli_rpc_pipe_bind failed with error %s\n",
nt_errstr(status) ));
goto err;
}
- DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to "
- "machine %s and bound NTLMSSP as user %s\\%s.\n",
+ DEBUG(10,("cli_rpc_pipe_open_generic_auth: opened pipe %s to "
+ "machine %s and bound as user %s\\%s.\n",
get_pipe_name_from_syntax(talloc_tos(), interface),
result->desthost, domain, username));
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,
- 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 spnego_context *spnego_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_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;
- }
-
- /* Fixme, should we fetch/set the Realm ? */
- auth->domain = talloc_strdup(auth, "");
- if (!auth->domain) {
- status = NT_STATUS_NO_MEMORY;
- goto err_out;
- }
-
- status = spnego_gssapi_init_client(auth,
- (auth->auth_level ==
- DCERPC_AUTH_LEVEL_INTEGRITY),
- (auth->auth_level ==
- DCERPC_AUTH_LEVEL_PRIVACY),
- true,
- NULL, server, "cifs",
- username, password,
- &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)) {
- 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_ntlmssp(struct cli_state *cli,
- const struct ndr_syntax_id *interface,
- enum dcerpc_transport_t transport,
- enum dcerpc_AuthLevel auth_level,
- const char *domain,
- const char *username,
- const char *password,
- struct rpc_pipe_client **presult)
+NTSTATUS cli_rpc_pipe_open_spnego(struct cli_state *cli,
+ const struct ndr_syntax_id *interface,
+ enum dcerpc_transport_t transport,
+ const char *oid,
+ enum dcerpc_AuthLevel auth_level,
+ const char *server,
+ const char *domain,
+ const char *username,
+ const char *password,
+ struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
struct pipe_auth_data *auth;
struct spnego_context *spnego_ctx;
NTSTATUS status;
+ const char *target_service = "cifs"; /* TODO: Determine target service from the bindings or interface table */
status = cli_rpc_pipe_open(cli, transport, interface, &result);
if (!NT_STATUS_IS_OK(status)) {
goto err_out;
}
- status = spnego_ntlmssp_init_client(auth,
+ 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);
if (!NT_STATUS_IS_OK(status)) {
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;
case DCERPC_AUTH_TYPE_SPNEGO:
spnego_ctx = talloc_get_type_abort(a->auth_ctx,
struct spnego_context);
- sk = spnego_get_session_key(mem_ctx, spnego_ctx);
+ 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,
struct gensec_security);
status = gensec_session_key(gensec_security, mem_ctx, &sk);
}
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,