#include "includes.h"
#include "../lib/util/tevent_ntstatus.h"
#include "librpc/gen_ndr/ndr_epmapper_c.h"
-#include "../librpc/gen_ndr/ndr_schannel.h"
#include "../librpc/gen_ndr/ndr_dssetup.h"
#include "../libcli/auth/schannel.h"
-#include "../libcli/auth/spnego.h"
-#include "../auth/ntlmssp/ntlmssp.h"
#include "auth_generic.h"
#include "librpc/gen_ndr/ndr_dcerpc.h"
#include "librpc/gen_ndr/ndr_netlogon_c.h"
return gensec_update(gensec_security, mem_ctx, NULL, null_blob, auth_token);
}
-/*******************************************************************
- Creates schannel auth bind.
- ********************************************************************/
-
-static NTSTATUS create_schannel_auth_rpc_bind_req(struct rpc_pipe_client *cli,
- DATA_BLOB *auth_token)
-{
- NTSTATUS status;
- struct NL_AUTH_MESSAGE r;
-
- /* Use lp_workgroup() if domain not specified */
-
- if (!cli->auth->domain || !cli->auth->domain[0]) {
- cli->auth->domain = talloc_strdup(cli, lp_workgroup());
- if (cli->auth->domain == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- }
-
- /*
- * Now marshall the data into the auth parse_struct.
- */
-
- r.MessageType = NL_NEGOTIATE_REQUEST;
- r.Flags = NL_FLAG_OEM_NETBIOS_DOMAIN_NAME |
- NL_FLAG_OEM_NETBIOS_COMPUTER_NAME;
- r.oem_netbios_domain.a = cli->auth->domain;
- r.oem_netbios_computer.a = lp_netbios_name();
-
- status = dcerpc_push_schannel_bind(cli, &r, auth_token);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- return NT_STATUS_OK;
-}
-
/*******************************************************************
Creates the internals of a DCE/RPC bind request or alter context PDU.
********************************************************************/
switch (auth->auth_type) {
case DCERPC_AUTH_TYPE_SCHANNEL:
- ret = create_schannel_auth_rpc_bind_req(cli, &auth_token);
- if (!NT_STATUS_IS_OK(ret)) {
- return ret;
- }
- break;
-
case DCERPC_AUTH_TYPE_NTLMSSP:
case DCERPC_AUTH_TYPE_KRB5:
case DCERPC_AUTH_TYPE_SPNEGO:
DATA_BLOB rpc_out;
bool auth3;
uint32_t rpc_call_id;
- struct netr_Authenticator auth;
- struct netr_Authenticator return_auth;
- struct netlogon_creds_CredentialState *creds;
- union netr_Capabilities capabilities;
- struct netr_LogonGetCapabilities r;
};
static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq);
-static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req);
static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
struct rpc_pipe_bind_state *state,
DATA_BLOB *credentials);
case DCERPC_AUTH_TYPE_NONE:
case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
+ case DCERPC_AUTH_TYPE_SCHANNEL:
/* Bind complete. */
tevent_req_done(req);
return;
- case DCERPC_AUTH_TYPE_SCHANNEL:
- rpc_pipe_bind_step_two_trigger(req);
- return;
-
case DCERPC_AUTH_TYPE_NTLMSSP:
case DCERPC_AUTH_TYPE_SPNEGO:
case DCERPC_AUTH_TYPE_KRB5:
tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
}
-static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq);
-
-static void rpc_pipe_bind_step_two_trigger(struct tevent_req *req)
-{
- struct rpc_pipe_bind_state *state =
- tevent_req_data(req,
- struct rpc_pipe_bind_state);
- struct dcerpc_binding_handle *b = state->cli->binding_handle;
- struct schannel_state *schannel_auth =
- talloc_get_type_abort(state->cli->auth->auth_ctx,
- struct schannel_state);
- struct tevent_req *subreq;
-
- if (schannel_auth == NULL ||
- !ndr_syntax_id_equal(&state->cli->abstract_syntax,
- &ndr_table_netlogon.syntax_id)) {
- tevent_req_done(req);
- return;
- }
-
- ZERO_STRUCT(state->return_auth);
-
- state->creds = netlogon_creds_copy(state, schannel_auth->creds);
- if (state->creds == NULL) {
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
-
- netlogon_creds_client_authenticator(state->creds, &state->auth);
-
- state->r.in.server_name = state->cli->srv_name_slash;
- state->r.in.computer_name = state->creds->computer_name;
- state->r.in.credential = &state->auth;
- state->r.in.query_level = 1;
- state->r.in.return_authenticator = &state->return_auth;
-
- state->r.out.capabilities = &state->capabilities;
- state->r.out.return_authenticator = &state->return_auth;
-
- subreq = dcerpc_netr_LogonGetCapabilities_r_send(talloc_tos(),
- state->ev,
- b,
- &state->r);
- if (subreq == NULL) {
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
-
- tevent_req_set_callback(subreq, rpc_pipe_bind_step_two_done, req);
- return;
-}
-
-static void rpc_pipe_bind_step_two_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq,
- struct tevent_req);
- struct rpc_pipe_bind_state *state =
- tevent_req_data(req,
- struct rpc_pipe_bind_state);
- NTSTATUS status;
-
- status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, talloc_tos());
- TALLOC_FREE(subreq);
- if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
- if (state->cli->dc && state->cli->dc->negotiate_flags &
- NETLOGON_NEG_SUPPORTS_AES) {
- DEBUG(5, ("AES is not supported and the error was %s\n",
- nt_errstr(status)));
- tevent_req_nterror(req,
- NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
- }
-
- /* This is probably NT */
- DEBUG(5, ("We are checking against an NT - %s\n",
- nt_errstr(status)));
- tevent_req_done(req);
- return;
- } else if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n",
- nt_errstr(status)));
- tevent_req_nterror(req, status);
- return;
- }
-
- if (NT_STATUS_EQUAL(state->r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
- if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
- /* This means AES isn't supported. */
- DEBUG(5, ("AES is not supported and the error was %s\n",
- nt_errstr(state->r.out.result)));
- tevent_req_nterror(req,
- NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
- }
-
- /* This is probably an old Samba version */
- DEBUG(5, ("We are checking against an old Samba version - %s\n",
- nt_errstr(state->r.out.result)));
- tevent_req_done(req);
- return;
- }
-
- /* We need to check the credential state here, cause win2k3 and earlier
- * returns NT_STATUS_NOT_IMPLEMENTED */
- if (!netlogon_creds_client_check(state->creds,
- &state->r.out.return_authenticator->cred)) {
- /*
- * Server replied with bad credential. Fail.
- */
- DEBUG(0,("rpc_pipe_bind_step_two_done: server %s "
- "replied with bad credential\n",
- state->cli->desthost));
- tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
- return;
- }
-
- TALLOC_FREE(state->cli->dc);
- state->cli->dc = talloc_steal(state->cli, state->creds);
-
- if (!NT_STATUS_IS_OK(state->r.out.result)) {
- DEBUG(0, ("dcerpc_netr_LogonGetCapabilities_r_recv failed with %s\n",
- nt_errstr(state->r.out.result)));
- tevent_req_nterror(req, state->r.out.result);
- return;
- }
-
- if (state->creds->negotiate_flags !=
- state->r.out.capabilities->server_capabilities) {
- DEBUG(0, ("The client capabilities don't match the server "
- "capabilities: local[0x%08X] remote[0x%08X]\n",
- state->creds->negotiate_flags,
- state->capabilities.server_capabilities));
- tevent_req_nterror(req,
- NT_STATUS_INVALID_NETWORK_RESPONSE);
- return;
- }
-
- /* TODO: Add downgrade dectection. */
-
- tevent_req_done(req);
- return;
-}
-
static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
struct rpc_pipe_bind_state *state,
DATA_BLOB *auth_token)
return rpccli_set_timeout(hs->rpc_cli, timeout);
}
+static void rpccli_bh_auth_info(struct dcerpc_binding_handle *h,
+ enum dcerpc_AuthType *auth_type,
+ enum dcerpc_AuthLevel *auth_level)
+{
+ struct rpccli_bh_state *hs = dcerpc_binding_handle_data(h,
+ struct rpccli_bh_state);
+
+ if (hs->rpc_cli == NULL) {
+ return;
+ }
+
+ if (hs->rpc_cli->auth == NULL) {
+ return;
+ }
+
+ *auth_type = hs->rpc_cli->auth->auth_type;
+ *auth_level = hs->rpc_cli->auth->auth_level;
+}
+
struct rpccli_bh_raw_call_state {
DATA_BLOB in_data;
DATA_BLOB out_data;
.name = "rpccli",
.is_connected = rpccli_bh_is_connected,
.set_timeout = rpccli_bh_set_timeout,
+ .auth_info = rpccli_bh_auth_info,
.raw_call_send = rpccli_bh_raw_call_send,
.raw_call_recv = rpccli_bh_raw_call_recv,
.disconnect_send = rpccli_bh_disconnect_send,
};
/* initialise a rpc_pipe_client binding handle */
-struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c)
+struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
+ const struct GUID *object,
+ const struct ndr_interface_table *table)
{
struct dcerpc_binding_handle *h;
struct rpccli_bh_state *hs;
h = dcerpc_binding_handle_create(c,
&rpccli_bh_ops,
- NULL,
- NULL, /* TODO */
+ object,
+ table,
&hs,
struct rpccli_bh_state,
__location__);
const char *username,
const char *password,
enum credentials_use_kerberos use_kerberos,
+ struct netlogon_creds_CredentialState *creds,
struct pipe_auth_data **presult)
{
struct auth_generic_state *auth_generic_ctx;
}
cli_credentials_set_kerberos_state(auth_generic_ctx->credentials, use_kerberos);
+ cli_credentials_set_netlogon_creds(auth_generic_ctx->credentials, creds);
status = auth_generic_client_start_by_authtype(auth_generic_ctx, auth_type, auth_level);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
- enum dcerpc_AuthLevel auth_level,
- struct netlogon_creds_CredentialState *creds,
- struct pipe_auth_data **presult)
-{
- struct schannel_state *schannel_auth;
- struct pipe_auth_data *result;
-
- result = talloc(mem_ctx, struct pipe_auth_data);
- if (result == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- result->auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
- result->auth_level = auth_level;
-
- result->user_name = talloc_strdup(result, "");
- result->domain = talloc_strdup(result, domain);
- if ((result->user_name == NULL) || (result->domain == NULL)) {
- goto fail;
- }
-
- schannel_auth = talloc_zero(result, struct schannel_state);
- if (schannel_auth == NULL) {
- goto fail;
- }
-
- schannel_auth->state = SCHANNEL_STATE_START;
- schannel_auth->initiator = true;
- schannel_auth->creds = netlogon_creds_copy(result, creds);
-
- result->auth_ctx = schannel_auth;
- *presult = result;
- return NT_STATUS_OK;
-
- fail:
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
-}
-
/**
* Create an rpc pipe client struct, connecting to a tcp port.
*/
static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host,
const struct sockaddr_storage *ss_addr,
uint16_t port,
- const struct ndr_syntax_id *abstract_syntax,
+ const struct ndr_interface_table *table,
struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
return NT_STATUS_NO_MEMORY;
}
- result->abstract_syntax = *abstract_syntax;
+ result->abstract_syntax = table->syntax_id;
result->transfer_syntax = ndr_transfer_syntax_ndr;
result->desthost = talloc_strdup(result, host);
result->transport->transport = NCACN_IP_TCP;
- result->binding_handle = rpccli_bh_create(result);
+ result->binding_handle = rpccli_bh_create(result, NULL, table);
if (result->binding_handle == NULL) {
TALLOC_FREE(result);
return NT_STATUS_NO_MEMORY;
*/
static NTSTATUS rpc_pipe_get_tcp_port(const char *host,
const struct sockaddr_storage *addr,
- const struct ndr_syntax_id *abstract_syntax,
+ const struct ndr_interface_table *table,
uint16_t *pport)
{
NTSTATUS status;
goto done;
}
- if (ndr_syntax_id_equal(abstract_syntax,
+ if (ndr_syntax_id_equal(&table->syntax_id,
&ndr_table_epmapper.syntax_id)) {
*pport = 135;
return NT_STATUS_OK;
/* open the connection to the endpoint mapper */
status = rpc_pipe_open_tcp_port(tmp_ctx, host, addr, 135,
- &ndr_table_epmapper.syntax_id,
+ &ndr_table_epmapper,
&epm_pipe);
if (!NT_STATUS_IS_OK(status)) {
}
map_binding->transport = NCACN_IP_TCP;
- map_binding->object = *abstract_syntax;
+ map_binding->object = table->syntax_id;
map_binding->host = host; /* needed? */
map_binding->endpoint = "0"; /* correct? needed? */
status = dcerpc_epm_Map(epm_handle,
tmp_ctx,
discard_const_p(struct GUID,
- &(abstract_syntax->uuid)),
+ &(table->syntax_id.uuid)),
map_tower,
entry_handle,
max_towers,
*/
NTSTATUS rpc_pipe_open_tcp(TALLOC_CTX *mem_ctx, const char *host,
const struct sockaddr_storage *addr,
- const struct ndr_syntax_id *abstract_syntax,
+ const struct ndr_interface_table *table,
struct rpc_pipe_client **presult)
{
NTSTATUS status;
uint16_t port = 0;
- status = rpc_pipe_get_tcp_port(host, addr, abstract_syntax, &port);
+ status = rpc_pipe_get_tcp_port(host, addr, table, &port);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return rpc_pipe_open_tcp_port(mem_ctx, host, addr, port,
- abstract_syntax, presult);
+ table, presult);
}
/********************************************************************
result->transport->transport = NCALRPC;
- result->binding_handle = rpccli_bh_create(result);
+ result->binding_handle = rpccli_bh_create(result, NULL, table);
if (result->binding_handle == NULL) {
TALLOC_FREE(result);
return NT_STATUS_NO_MEMORY;
****************************************************************************/
static NTSTATUS rpc_pipe_open_np(struct cli_state *cli,
- const struct ndr_syntax_id *abstract_syntax,
+ const struct ndr_interface_table *table,
struct rpc_pipe_client **presult)
{
struct rpc_pipe_client *result;
return NT_STATUS_NO_MEMORY;
}
- result->abstract_syntax = *abstract_syntax;
+ result->abstract_syntax = table->syntax_id;
result->transfer_syntax = ndr_transfer_syntax_ndr;
result->desthost = talloc_strdup(result, smbXcli_conn_remote_name(cli->conn));
result->srv_name_slash = talloc_asprintf_strupper_m(
return NT_STATUS_NO_MEMORY;
}
- status = rpc_transport_np_init(result, cli, abstract_syntax,
+ status = rpc_transport_np_init(result, cli, table,
&result->transport);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(result);
DLIST_ADD(np_ref->cli->pipe_list, np_ref->pipe);
talloc_set_destructor(np_ref, rpc_pipe_client_np_ref_destructor);
- result->binding_handle = rpccli_bh_create(result);
+ result->binding_handle = rpccli_bh_create(result, NULL, table);
if (result->binding_handle == NULL) {
TALLOC_FREE(result);
return NT_STATUS_NO_MEMORY;
static NTSTATUS cli_rpc_pipe_open(struct cli_state *cli,
enum dcerpc_transport_t transport,
- const struct ndr_syntax_id *interface,
+ const struct ndr_interface_table *table,
struct rpc_pipe_client **presult)
{
switch (transport) {
return rpc_pipe_open_tcp(NULL,
smbXcli_conn_remote_name(cli->conn),
smbXcli_conn_remote_sockaddr(cli->conn),
- interface, presult);
+ table, presult);
case NCACN_NP:
- return rpc_pipe_open_np(cli, interface, presult);
+ return rpc_pipe_open_np(cli, table, presult);
default:
return NT_STATUS_NOT_IMPLEMENTED;
}
NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
enum dcerpc_transport_t transport,
- const struct ndr_syntax_id *interface,
+ const struct ndr_interface_table *table,
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);
+ status = cli_rpc_pipe_open(cli, transport, table, &result);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = rpc_pipe_bind(result, auth);
if (!NT_STATUS_IS_OK(status)) {
int lvl = 0;
- if (ndr_syntax_id_equal(interface,
+ if (ndr_syntax_id_equal(&table->syntax_id,
&ndr_table_dssetup.syntax_id)) {
/* non AD domains just don't have this pipe, avoid
* level 0 statement in that case - gd */
}
DEBUG(lvl, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe "
"%s failed with error %s\n",
- get_pipe_name_from_syntax(talloc_tos(), interface),
+ table->name,
nt_errstr(status) ));
TALLOC_FREE(result);
return status;
DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine "
"%s and bound anonymously.\n",
- get_pipe_name_from_syntax(talloc_tos(), interface),
+ table->name,
result->desthost));
*presult = result;
****************************************************************************/
NTSTATUS cli_rpc_pipe_open_noauth(struct cli_state *cli,
- const struct ndr_syntax_id *interface,
+ const struct ndr_interface_table *table,
struct rpc_pipe_client **presult)
{
return cli_rpc_pipe_open_noauth_transport(cli, NCACN_NP,
- interface, presult);
+ table, presult);
}
/****************************************************************************
NTSTATUS status;
- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
+ status = cli_rpc_pipe_open(cli, transport, table, &result);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
server, target_service,
domain, username, password,
CRED_AUTO_USE_KERBEROS,
+ NULL,
&auth);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
enum dcerpc_AuthLevel auth_level,
const char *domain,
struct netlogon_creds_CredentialState **pdc,
- struct rpc_pipe_client **presult)
+ struct rpc_pipe_client **_rpccli)
{
- struct rpc_pipe_client *result;
- struct pipe_auth_data *auth;
+ struct rpc_pipe_client *rpccli;
+ struct pipe_auth_data *rpcauth;
NTSTATUS status;
+ NTSTATUS result;
+ struct netlogon_creds_CredentialState save_creds;
+ struct netr_Authenticator auth;
+ struct netr_Authenticator return_auth;
+ union netr_Capabilities capabilities;
+ const char *target_service = table->authservices->names[0];
- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
+ status = cli_rpc_pipe_open(cli, transport, table, &rpccli);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = rpccli_schannel_bind_data(result, domain, auth_level,
- *pdc, &auth);
+ status = rpccli_generic_bind_data(rpccli,
+ DCERPC_AUTH_TYPE_SCHANNEL,
+ auth_level,
+ NULL,
+ target_service,
+ domain,
+ (*pdc)->computer_name,
+ NULL,
+ CRED_AUTO_USE_KERBEROS,
+ *pdc,
+ &rpcauth);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("rpccli_schannel_bind_data returned %s\n",
+ DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
nt_errstr(status)));
- TALLOC_FREE(result);
+ TALLOC_FREE(rpccli);
return status;
}
- status = rpc_pipe_bind(result, auth);
+ /*
+ * The credentials on a new netlogon pipe are the ones we are passed
+ * in - copy them over
+ *
+ * This may get overwritten... in rpc_pipe_bind()...
+ */
+ rpccli->dc = netlogon_creds_copy(rpccli, *pdc);
+ if (rpccli->dc == NULL) {
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = rpc_pipe_bind(rpccli, rpcauth);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: "
"cli_rpc_pipe_bind failed with error %s\n",
nt_errstr(status) ));
- TALLOC_FREE(result);
+ TALLOC_FREE(rpccli);
+ return status;
+ }
+
+ if (!ndr_syntax_id_equal(&table->syntax_id, &ndr_table_netlogon.syntax_id)) {
+ goto done;
+ }
+
+ save_creds = *rpccli->dc;
+ ZERO_STRUCT(return_auth);
+ ZERO_STRUCT(capabilities);
+
+ netlogon_creds_client_authenticator(&save_creds, &auth);
+
+ status = dcerpc_netr_LogonGetCapabilities(rpccli->binding_handle,
+ talloc_tos(),
+ rpccli->srv_name_slash,
+ save_creds.computer_name,
+ &auth, &return_auth,
+ 1, &capabilities,
+ &result);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
+ if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+ DEBUG(5, ("AES was negotiated and the error was %s - "
+ "downgrade detected\n",
+ nt_errstr(status)));
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ /* This is probably an old Samba Version */
+ DEBUG(5, ("We are checking against an NT or old Samba - %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
+ nt_errstr(status)));
+ TALLOC_FREE(rpccli);
return status;
}
+ if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_IMPLEMENTED)) {
+ if (save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
+ /* This means AES isn't supported. */
+ DEBUG(5, ("AES was negotiated and the result was %s - "
+ "downgrade detected\n",
+ nt_errstr(result)));
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ /* This is probably an old Windows version */
+ DEBUG(5, ("We are checking against an win2k3 or Samba - %s\n",
+ nt_errstr(result)));
+ goto done;
+ }
+
/*
- * The credentials on a new netlogon pipe are the ones we are passed
- * in - copy them over
+ * We need to check the credential state here, cause win2k3 and earlier
+ * returns NT_STATUS_NOT_IMPLEMENTED
*/
- if (result->dc == NULL) {
- result->dc = netlogon_creds_copy(result, *pdc);
- if (result->dc == NULL) {
- TALLOC_FREE(result);
- return NT_STATUS_NO_MEMORY;
- }
+ if (!netlogon_creds_client_check(&save_creds, &return_auth.cred)) {
+ /*
+ * Server replied with bad credential. Fail.
+ */
+ DEBUG(0,("cli_rpc_pipe_open_schannel_with_key: server %s "
+ "replied with bad credential\n",
+ rpccli->desthost));
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
+ *rpccli->dc = save_creds;
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0, ("dcerpc_netr_LogonGetCapabilities failed with %s\n",
+ nt_errstr(result)));
+ TALLOC_FREE(rpccli);
+ return result;
+ }
+
+ if (!(save_creds.negotiate_flags & NETLOGON_NEG_SUPPORTS_AES)) {
+ /* This means AES isn't supported. */
+ DEBUG(5, ("AES is not negotiated, but netr_LogonGetCapabilities "
+ "was OK - downgrade detected\n"));
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+ if (save_creds.negotiate_flags != capabilities.server_capabilities) {
+ DEBUG(0, ("The client capabilities don't match the server "
+ "capabilities: local[0x%08X] remote[0x%08X]\n",
+ save_creds.negotiate_flags,
+ capabilities.server_capabilities));
+ TALLOC_FREE(rpccli);
+ return NT_STATUS_INVALID_NETWORK_RESPONSE;
+ }
+
+done:
DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
"for domain %s and bound using schannel.\n",
- get_pipe_name_from_syntax(talloc_tos(), &table->syntax_id),
- result->desthost, domain));
+ table->name,
+ rpccli->desthost, domain));
- *presult = result;
+ *_rpccli = rpccli;
return NT_STATUS_OK;
}
return NT_STATUS_INVALID_PARAMETER;
}
- status = cli_rpc_pipe_open(cli, transport, &table->syntax_id, &result);
+ status = cli_rpc_pipe_open(cli, transport, table, &result);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
DCERPC_AUTH_TYPE_SPNEGO, auth_level,
server, target_service,
domain, username, password,
- use_kerberos,
+ use_kerberos, NULL,
&auth);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("rpccli_generic_bind_data returned %s\n",
{
NTSTATUS status;
struct pipe_auth_data *a;
- struct schannel_state *schannel_auth;
struct gensec_security *gensec_security;
DATA_BLOB sk = data_blob_null;
bool make_dup = false;
}
switch (cli->auth->auth_type) {
- case DCERPC_AUTH_TYPE_SCHANNEL:
- schannel_auth = talloc_get_type_abort(a->auth_ctx,
- struct schannel_state);
- sk = data_blob_const(schannel_auth->creds->session_key, 16);
- make_dup = true;
- break;
case DCERPC_AUTH_TYPE_SPNEGO:
case DCERPC_AUTH_TYPE_NTLMSSP:
case DCERPC_AUTH_TYPE_KRB5: