From 186f93633b4890c444115ac4eed109aa24f20b44 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 29 Jul 2010 19:55:44 -0400 Subject: s3-dcerpc: use common spengo wrapper code for client SPNEGO/NTLMSSP --- source3/include/ntdomain.h | 2 +- source3/librpc/rpc/dcerpc_helpers.c | 110 ++++++++++++---- source3/librpc/rpc/dcerpc_spnego.c | 108 ++++++++++++++- source3/librpc/rpc/dcerpc_spnego.h | 7 + source3/rpc_client/cli_pipe.c | 256 ++++++++++++++++++------------------ 5 files changed, 321 insertions(+), 162 deletions(-) diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 98f2df9445..f42ff587ff 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -105,7 +105,7 @@ struct gse_context; struct pipe_auth_data { enum dcerpc_AuthType auth_type; - enum pipe_auth_type_spnego spnego_type; + enum pipe_auth_type_spnego spnego_type; /* used by server only */ enum dcerpc_AuthLevel auth_level; union { diff --git a/source3/librpc/rpc/dcerpc_helpers.c b/source3/librpc/rpc/dcerpc_helpers.c index 592832bdd8..26b44de5ea 100644 --- a/source3/librpc/rpc/dcerpc_helpers.c +++ b/source3/librpc/rpc/dcerpc_helpers.c @@ -524,6 +524,7 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx, { enum dcerpc_AuthType auth_type; struct gse_context *gse_ctx; + struct auth_ntlmssp_state *ntlmssp_ctx; void *auth_ctx; NTSTATUS status; @@ -548,8 +549,15 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx, auth_level, rpc_out); break; - case DCERPC_AUTH_LEVEL_INTEGRITY: - status = NT_STATUS_NOT_IMPLEMENTED; + case DCERPC_AUTH_TYPE_NTLMSSP: + ntlmssp_ctx = talloc_get_type(auth_ctx, + struct auth_ntlmssp_state); + if (!ntlmssp_ctx) { + status = NT_STATUS_INTERNAL_ERROR; + break; + } + status = add_ntlmssp_auth_footer(ntlmssp_ctx, + auth_level, rpc_out); break; default: @@ -560,6 +568,55 @@ static NTSTATUS add_spnego_auth_footer(struct spnego_context *spnego_ctx, return status; } +static NTSTATUS get_spnego_auth_footer(TALLOC_CTX *mem_ctx, + struct spnego_context *sp_ctx, + enum dcerpc_AuthLevel auth_level, + DATA_BLOB *data, DATA_BLOB *full_pkt, + DATA_BLOB *auth_token) +{ + enum dcerpc_AuthType auth_type; + struct auth_ntlmssp_state *ntlmssp_ctx; + struct gse_context *gse_ctx; + void *auth_ctx; + NTSTATUS status; + + status = spnego_get_negotiated_mech(sp_ctx, &auth_type, &auth_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + switch (auth_type) { + case DCERPC_AUTH_TYPE_KRB5: + gse_ctx = talloc_get_type(auth_ctx, + struct gse_context); + if (!gse_ctx) { + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10, ("KRB5 auth\n")); + + return get_gssapi_auth_footer(mem_ctx, gse_ctx, + auth_level, + data, full_pkt, + auth_token); + case DCERPC_AUTH_TYPE_NTLMSSP: + ntlmssp_ctx = talloc_get_type(auth_ctx, + struct auth_ntlmssp_state); + if (!ntlmssp_ctx) { + return NT_STATUS_INVALID_PARAMETER; + } + + DEBUG(10, ("NTLMSSP auth\n")); + + return get_ntlmssp_auth_footer(ntlmssp_ctx, + auth_level, + data, full_pkt, + auth_token); + default: + return NT_STATUS_INVALID_PARAMETER; + } +} + /** * @brief Append an auth footer according to what is the current mechanism * @@ -618,12 +675,16 @@ NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth, status = NT_STATUS_OK; break; case DCERPC_AUTH_TYPE_SPNEGO: - if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { - return add_spnego_auth_footer(auth->a_u.spnego_state, - auth->auth_level, - rpc_out); + if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { + /* compat for server code */ + return add_ntlmssp_auth_footer( + auth->a_u.auth_ntlmssp_state, + auth->auth_level, + rpc_out); } - /* fall thorugh */ + status = add_spnego_auth_footer(auth->a_u.spnego_state, + auth->auth_level, rpc_out); + break; case DCERPC_AUTH_TYPE_NTLMSSP: status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state, auth->auth_level, @@ -731,26 +792,12 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, return NT_STATUS_OK; case DCERPC_AUTH_TYPE_SPNEGO: - if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { - enum dcerpc_AuthType auth_type; - struct gse_context *gse_ctx; - void *auth_ctx; - - status = spnego_get_negotiated_mech( - auth->a_u.spnego_state, - &auth_type, &auth_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - gse_ctx = talloc_get_type(auth_ctx, - struct gse_context); - if (!gse_ctx) { - return NT_STATUS_INVALID_PARAMETER; - } + if (auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { + /* compat for server code */ + DEBUG(10, ("NTLMSSP auth\n")); - DEBUG(10, ("KRB5 auth\n")); - - status = get_gssapi_auth_footer(pkt, gse_ctx, + status = get_ntlmssp_auth_footer( + auth->a_u.auth_ntlmssp_state, auth->auth_level, &data, &full_pkt, &auth_info.credentials); @@ -759,7 +806,16 @@ NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth, } break; } - /* fall through */ + + status = get_spnego_auth_footer(pkt, auth->a_u.spnego_state, + auth->auth_level, + &data, &full_pkt, + &auth_info.credentials); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + break; + case DCERPC_AUTH_TYPE_NTLMSSP: DEBUG(10, ("NTLMSSP auth\n")); diff --git a/source3/librpc/rpc/dcerpc_spnego.c b/source3/librpc/rpc/dcerpc_spnego.c index e733469ac3..a0832ce09f 100644 --- a/source3/librpc/rpc/dcerpc_spnego.c +++ b/source3/librpc/rpc/dcerpc_spnego.c @@ -19,6 +19,8 @@ #include "includes.h" #include "../libcli/auth/spnego.h" +#include "include/ntlmssp_wrap.h" +#include "librpc/gen_ndr/ntlmssp.h" #include "dcerpc_spnego.h" #include "dcerpc_gssapi.h" @@ -26,7 +28,7 @@ struct spnego_context { enum dcerpc_AuthType auth_type; union { - struct auth_ntlmssp_state *auth_ntlmssp_state; + struct auth_ntlmssp_state *ntlmssp_state; struct gse_context *gssapi_state; } mech_ctx; @@ -88,12 +90,80 @@ NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } +NTSTATUS spnego_ntlmssp_init_client(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthLevel auth_level, + const char *domain, + const char *username, + const char *password, + struct spnego_context **spnego_ctx) +{ + struct spnego_context *sp_ctx; + NTSTATUS status; + + status = spnego_context_init(mem_ctx, + DCERPC_AUTH_TYPE_NTLMSSP, &sp_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = auth_ntlmssp_client_start(sp_ctx, + global_myname(), + lp_workgroup(), + lp_client_ntlmv2_auth(), + &sp_ctx->mech_ctx.ntlmssp_state); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_username(sp_ctx->mech_ctx.ntlmssp_state, + username); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_domain(sp_ctx->mech_ctx.ntlmssp_state, + domain); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + status = auth_ntlmssp_set_password(sp_ctx->mech_ctx.ntlmssp_state, + password); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(sp_ctx); + return status; + } + + /* + * Turn off sign+seal to allow selected auth level to turn it back on. + */ + auth_ntlmssp_and_flags(sp_ctx->mech_ctx.ntlmssp_state, + ~(NTLMSSP_NEGOTIATE_SIGN | + NTLMSSP_NEGOTIATE_SEAL)); + + if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { + auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state, + NTLMSSP_NEGOTIATE_SIGN); + } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + auth_ntlmssp_or_flags(sp_ctx->mech_ctx.ntlmssp_state, + NTLMSSP_NEGOTIATE_SEAL | + NTLMSSP_NEGOTIATE_SIGN); + } + + *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 gse_context *gse_ctx; + struct auth_ntlmssp_state *ntlmssp_ctx; struct spnego_data sp_in, sp_out; DATA_BLOB token_in = data_blob_null; DATA_BLOB token_out = data_blob_null; @@ -129,6 +199,7 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, 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; @@ -152,8 +223,21 @@ NTSTATUS spnego_get_client_auth_token(TALLOC_CTX *mem_ctx, break; case DCERPC_AUTH_TYPE_NTLMSSP: - status = NT_STATUS_NOT_IMPLEMENTED; - goto done; + + ntlmssp_ctx = sp_ctx->mech_ctx.ntlmssp_state; + status = auth_ntlmssp_update(ntlmssp_ctx, + token_in, &token_out); + if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + mech_wants_more = true; + } else if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + mech_oids[0] = OID_NTLMSSP; + + break; + default: status = NT_STATUS_INTERNAL_ERROR; goto done; @@ -227,6 +311,8 @@ bool spnego_require_more_processing(struct spnego_context *sp_ctx) case DCERPC_AUTH_TYPE_KRB5: gse_ctx = sp_ctx->mech_ctx.gssapi_state; return gse_require_more_processing(gse_ctx); + case DCERPC_AUTH_TYPE_NTLMSSP: + return false; default: DEBUG(0, ("Unsupported type in request!\n")); return false; @@ -242,7 +328,7 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, *auth_context = sp_ctx->mech_ctx.gssapi_state; break; case DCERPC_AUTH_TYPE_NTLMSSP: - *auth_context = sp_ctx->mech_ctx.auth_ntlmssp_state; + *auth_context = sp_ctx->mech_ctx.ntlmssp_state; break; default: return NT_STATUS_INTERNAL_ERROR; @@ -252,3 +338,17 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, return NT_STATUS_OK; } +DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx) +{ + switch (sp_ctx->auth_type) { + case DCERPC_AUTH_TYPE_KRB5: + return gse_get_session_key(sp_ctx->mech_ctx.gssapi_state); + case DCERPC_AUTH_TYPE_NTLMSSP: + return auth_ntlmssp_get_session_key( + sp_ctx->mech_ctx.ntlmssp_state); + default: + DEBUG(0, ("Unsupported type in request!\n")); + return data_blob_null; + } +} + diff --git a/source3/librpc/rpc/dcerpc_spnego.h b/source3/librpc/rpc/dcerpc_spnego.h index 08458b246f..58363fd072 100644 --- a/source3/librpc/rpc/dcerpc_spnego.h +++ b/source3/librpc/rpc/dcerpc_spnego.h @@ -31,6 +31,12 @@ NTSTATUS spnego_gssapi_init_client(TALLOC_CTX *mem_ctx, const char *password, uint32_t add_gss_c_flags, struct spnego_context **spengo_ctx); +NTSTATUS spnego_ntlmssp_init_client(TALLOC_CTX *mem_ctx, + enum dcerpc_AuthLevel auth_level, + 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, @@ -43,4 +49,5 @@ NTSTATUS spnego_get_negotiated_mech(struct spnego_context *sp_ctx, enum dcerpc_AuthType *auth_type, void **auth_context); +DATA_BLOB spnego_get_session_key(struct spnego_context *sp_ctx); #endif /* _DCERPC_SPENGO_H_ */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index e41966f6fb..5fdfb6374e 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1247,20 +1247,7 @@ static NTSTATUS create_rpc_bind_req(TALLOC_CTX *mem_ctx, break; case DCERPC_AUTH_TYPE_SPNEGO: - switch (auth->spnego_type) { - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, - auth->auth_level, - &auth_info); - break; - - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - ret = create_spnego_auth_bind_req(cli, auth, - &auth_info); - break; - default: - return NT_STATUS_INTERNAL_ERROR; - } + ret = create_spnego_auth_bind_req(cli, auth, &auth_info); if (!NT_STATUS_IS_OK(ret)) { return ret; } @@ -1331,17 +1318,17 @@ static NTSTATUS calculate_data_len_tosend(struct rpc_pipe_client *cli, /* Treat the same for all authenticated rpc requests. */ switch(cli->auth->auth_type) { case DCERPC_AUTH_TYPE_SPNEGO: - switch (cli->auth->spnego_type) { - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + status = spnego_get_negotiated_mech( + cli->auth->a_u.spnego_state, + &auth_type, &auth_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + switch (auth_type) { + case DCERPC_AUTH_TYPE_NTLMSSP: *p_auth_len = NTLMSSP_SIG_SIZE; break; - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - status = spnego_get_negotiated_mech( - cli->auth->a_u.spnego_state, - &auth_type, &auth_ctx); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + case DCERPC_AUTH_TYPE_KRB5: gse_ctx = talloc_get_type(auth_ctx, struct gse_context); if (!gse_ctx) { @@ -1986,36 +1973,24 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq) break; case DCERPC_AUTH_TYPE_SPNEGO: - switch (pauth->spnego_type) { - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - /* Need to send alter context request and reply. */ - status = rpc_finish_spnego_ntlmssp_bind_send(req, - state, &auth.credentials); - break; - - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - status = spnego_get_client_auth_token(state, + status = spnego_get_client_auth_token(state, pauth->a_u.spnego_state, &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(pauth->a_u.spnego_state)) { - status = rpc_bind_next_send(req, state, - &auth_token); - } else { - status = rpc_bind_finish_send(req, state, - &auth_token); - } + if (!NT_STATUS_IS_OK(status)) { break; - default: - status = NT_STATUS_INTERNAL_ERROR; + } + if (auth_token.length == 0) { + /* Bind complete. */ + tevent_req_done(req); + return; + } + if (spnego_require_more_processing(pauth->a_u.spnego_state)) { + status = rpc_bind_next_send(req, state, + &auth_token); + } else { + status = rpc_bind_finish_send(req, state, + &auth_token); } break; @@ -2358,12 +2333,31 @@ bool rpccli_is_connected(struct rpc_pipe_client *rpc_cli) bool rpccli_get_pwd_hash(struct rpc_pipe_client *rpc_cli, uint8_t nt_hash[16]) { + struct auth_ntlmssp_state *a = NULL; struct cli_state *cli; - if ((rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) - || ((rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO - && rpc_cli->auth->spnego_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { - memcpy(nt_hash, auth_ntlmssp_get_nt_hash(rpc_cli->auth->a_u.auth_ntlmssp_state), 16); + if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_NTLMSSP) { + a = rpc_cli->auth->a_u.auth_ntlmssp_state; + } else if (rpc_cli->auth->auth_type == DCERPC_AUTH_TYPE_SPNEGO) { + enum dcerpc_AuthType auth_type; + void *auth_ctx; + NTSTATUS status; + + status = spnego_get_negotiated_mech( + rpc_cli->auth->a_u.spnego_state, + &auth_type, &auth_ctx); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + + if (auth_type == DCERPC_AUTH_TYPE_NTLMSSP) { + a = talloc_get_type(auth_ctx, + struct auth_ntlmssp_state); + } + } + + if (a) { + memcpy(nt_hash, auth_ntlmssp_get_nt_hash(a), 16); return true; } @@ -2408,7 +2402,6 @@ static int cli_auth_ntlmssp_data_destructor(struct pipe_auth_data *auth) static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, enum dcerpc_AuthType auth_type, - enum pipe_auth_type_spnego spnego_type, enum dcerpc_AuthLevel auth_level, const char *domain, const char *username, @@ -2424,7 +2417,6 @@ static NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx, } result->auth_type = auth_type; - result->spnego_type = spnego_type; result->auth_level = auth_level; result->user_name = talloc_strdup(result, username); @@ -3056,20 +3048,18 @@ NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli, Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP ****************************************************************************/ -static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli, - const struct ndr_syntax_id *interface, - enum dcerpc_transport_t transport, - bool use_spnego, - enum dcerpc_AuthLevel auth_level, - const char *domain, - const char *username, - const char *password, - struct rpc_pipe_client **presult) +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) { struct rpc_pipe_client *result; struct pipe_auth_data *auth; enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NTLMSSP; - enum pipe_auth_type_spnego spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE; NTSTATUS status; status = cli_rpc_pipe_open(cli, transport, interface, &result); @@ -3077,13 +3067,8 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli, return status; } - if (use_spnego) { - auth_type = DCERPC_AUTH_TYPE_SPNEGO; - spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; - } - status = rpccli_ntlmssp_bind_data(result, - auth_type, spnego_type, auth_level, + auth_type, auth_level, domain, username, password, &auth); if (!NT_STATUS_IS_OK(status)) { @@ -3113,56 +3098,6 @@ static NTSTATUS cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli, return status; } -/**************************************************************************** - External interface. - Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10) - ****************************************************************************/ - -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) -{ - return cli_rpc_pipe_open_ntlmssp_internal(cli, - interface, - transport, - false, - auth_level, - domain, - username, - password, - presult); -} - -/**************************************************************************** - External interface. - Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9) - ****************************************************************************/ - -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) -{ - return cli_rpc_pipe_open_ntlmssp_internal(cli, - interface, - transport, - true, - auth_level, - domain, - username, - password, - presult); -} - /**************************************************************************** Get a the schannel session key out of an already opened netlogon pipe. ****************************************************************************/ @@ -3562,6 +3497,74 @@ err_out: 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) +{ + struct rpc_pipe_client *result; + struct pipe_auth_data *auth; + 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; + } + + if (!domain) { + domain = ""; + } + auth->domain = talloc_strdup(auth, domain); + if (!auth->domain) { + status = NT_STATUS_NO_MEMORY; + goto err_out; + } + + status = spnego_ntlmssp_init_client(auth, auth->auth_level, + domain, username, password, + &auth->a_u.spnego_state); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("spnego_init_client returned %s\n", + nt_errstr(status))); + goto err_out; + } + + 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_get_session_key(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *cli, DATA_BLOB *session_key) @@ -3583,15 +3586,8 @@ NTSTATUS cli_get_session_key(TALLOC_CTX *mem_ctx, 16); break; case DCERPC_AUTH_TYPE_SPNEGO: - switch (cli->auth->spnego_type) { - case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: - sk = auth_ntlmssp_get_session_key( - a->a_u.auth_ntlmssp_state); - break; - case PIPE_AUTH_TYPE_SPNEGO_KRB5: - sk = gse_get_session_key(a->a_u.gssapi_state); - break; - default: + sk = spnego_get_session_key(a->a_u.spnego_state); + if (sk.length == 0) { return NT_STATUS_NO_USER_SESSION_KEY; } break; -- cgit