From 078cced5ec1026432f5df275a7023db70a62693e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Feb 2004 10:22:12 +0000 Subject: - modified the dcerpc client security code to be generic, so ntlmssp and schannel are both instances of possible security modules - added schannel sign and sign/seal support to the dcerpc client code. You select it with binding options of "schannel,sign" or "schannel,seal". (This used to be commit 05db0b9d942cad8f1dd574dc35b759e5e79d4195) --- source4/librpc/idl/dcerpc.idl | 7 +- source4/librpc/rpc/dcerpc.c | 42 +++---- source4/librpc/rpc/dcerpc.h | 27 +++-- source4/librpc/rpc/dcerpc_auth.c | 121 ------------------- source4/librpc/rpc/dcerpc_ntlm.c | 197 +++++++++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_schannel.c | 219 +++++++++++++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_smb.c | 1 - source4/librpc/rpc/dcerpc_util.c | 15 ++- 8 files changed, 473 insertions(+), 156 deletions(-) create mode 100644 source4/librpc/rpc/dcerpc_ntlm.c create mode 100644 source4/librpc/rpc/dcerpc_schannel.c (limited to 'source4/librpc') diff --git a/source4/librpc/idl/dcerpc.idl b/source4/librpc/idl/dcerpc.idl index 4d09a9ec4f..334ae8ce5d 100644 --- a/source4/librpc/idl/dcerpc.idl +++ b/source4/librpc/idl/dcerpc.idl @@ -99,9 +99,10 @@ interface dcerpc } dcerpc_fault; - const uint8 DCERPC_AUTH_TYPE_NONE = 0; - const uint8 DCERPC_AUTH_TYPE_KRB5 = 1; - const uint8 DCERPC_AUTH_TYPE_NTLMSSP = 10; + const uint8 DCERPC_AUTH_TYPE_NONE = 0; + const uint8 DCERPC_AUTH_TYPE_KRB5 = 1; + const uint8 DCERPC_AUTH_TYPE_NTLMSSP = 10; + const uint8 DCERPC_AUTH_TYPE_SCHANNEL = 68; const uint8 DCERPC_AUTH_LEVEL_NONE = 1; const uint8 DCERPC_AUTH_LEVEL_CONNECT = 2; diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index d00f2c2986..8987cead92 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -42,7 +42,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(void) p->mem_ctx = mem_ctx; p->call_id = 1; p->auth_info = NULL; - p->ntlmssp_state = NULL; + p->security_state = NULL; p->flags = 0; p->srv_max_xmit_frag = 0; p->srv_max_recv_frag = 0; @@ -56,8 +56,8 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p) if (!p) return; p->reference_count--; if (p->reference_count <= 0) { - if (p->ntlmssp_state) { - ntlmssp_end(&p->ntlmssp_state); + if (p->security_state) { + p->security_state->security_end(p->security_state); } p->transport.shutdown_pipe(p); talloc_destroy(p->mem_ctx); @@ -128,7 +128,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, DATA_BLOB auth_blob; /* non-signed packets are simpler */ - if (!p->auth_info || !p->ntlmssp_state) { + if (!p->auth_info || !p->security_state) { return dcerpc_pull(blob, mem_ctx, pkt); } @@ -182,17 +182,17 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, /* check signature or unseal the packet */ switch (p->auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = ntlmssp_unseal_packet(p->ntlmssp_state, - pkt->u.response.stub_and_verifier.data, - pkt->u.response.stub_and_verifier.length, - &auth.credentials); + status = p->security_state->unseal_packet(p->security_state, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = ntlmssp_check_packet(p->ntlmssp_state, - pkt->u.response.stub_and_verifier.data, - pkt->u.response.stub_and_verifier.length, - &auth.credentials); + status = p->security_state->check_packet(p->security_state, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); break; case DCERPC_AUTH_LEVEL_NONE: @@ -224,7 +224,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, struct ndr_push *ndr; /* non-signed packets are simpler */ - if (!p->auth_info || !p->ntlmssp_state) { + if (!p->auth_info || !p->security_state) { return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info); } @@ -249,17 +249,17 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* sign or seal the packet */ switch (p->auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = ntlmssp_seal_packet(p->ntlmssp_state, - ndr->data + DCERPC_REQUEST_LENGTH, - ndr->offset - DCERPC_REQUEST_LENGTH, - &p->auth_info->credentials); + status = p->security_state->seal_packet(p->security_state, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->auth_info->credentials); break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = ntlmssp_sign_packet(p->ntlmssp_state, - ndr->data + DCERPC_REQUEST_LENGTH, - ndr->offset - DCERPC_REQUEST_LENGTH, - &p->auth_info->credentials); + status = p->security_state->sign_packet(p->security_state, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->auth_info->credentials); break; case DCERPC_AUTH_LEVEL_NONE: diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index c5cf07ddba..55c81c374e 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -20,16 +20,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - see http://www.opengroup.org/onlinepubs/9629399/chap12.htm for details - of these structures +enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP}; - note that the structure definitions here don't include some of the - fields that are wire-artifacts. Those are put on the wire by the - marshalling/unmarshalling routines in decrpc.c +/* + this defines a generic security context for signed/sealed dcerpc pipes. */ - -enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP}; +struct dcerpc_security { + void *private; + NTSTATUS (*unseal_packet)(struct dcerpc_security *, + uchar *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*check_packet)(struct dcerpc_security *, + const uchar *data, size_t length, const DATA_BLOB *sig); + NTSTATUS (*seal_packet)(struct dcerpc_security *, + uchar *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*sign_packet)(struct dcerpc_security *, + const uchar *data, size_t length, DATA_BLOB *sig); + void (*security_end)(struct dcerpc_security *); +}; struct dcerpc_pipe { @@ -39,7 +46,7 @@ struct dcerpc_pipe { uint32 srv_max_xmit_frag; uint32 srv_max_recv_frag; unsigned flags; - struct ntlmssp_state *ntlmssp_state; + struct dcerpc_security *security_state; struct dcerpc_auth *auth_info; const char *binding_string; @@ -73,6 +80,8 @@ struct dcerpc_pipe { #define DCERPC_PUSH_BIGENDIAN 64 #define DCERPC_PULL_BIGENDIAN 128 +#define DCERPC_SCHANNEL 256 + /* this is used to find pointers to calls */ diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 99ea03c216..2b01ad2d4e 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -22,127 +22,6 @@ #include "includes.h" -/* - do a simple ntlm style authentication on a dcerpc pipe -*/ -NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, - const char *uuid, unsigned version, - const char *domain, - const char *username, - const char *password) -{ - NTSTATUS status; - struct ntlmssp_state *state; - TALLOC_CTX *mem_ctx; - DATA_BLOB credentials; - - mem_ctx = talloc_init("dcerpc_bind_auth_ntlm"); - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - status = ntlmssp_client_start(&state); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = ntlmssp_set_domain(state, domain); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - status = ntlmssp_set_username(state, username); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - status = ntlmssp_set_password(state, password); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - p->auth_info = talloc(p->mem_ctx, sizeof(*p->auth_info)); - if (!p->auth_info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - p->auth_info->auth_type = DCERPC_AUTH_TYPE_NTLMSSP; - - if (p->flags & DCERPC_SEAL) { - p->auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; - state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL; - } else if (p->flags & DCERPC_SIGN) { - state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - p->auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; - } else { - state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL); - p->auth_info->auth_level = DCERPC_AUTH_LEVEL_NONE; - } - p->auth_info->auth_pad_length = 0; - p->auth_info->auth_reserved = 0; - p->auth_info->auth_context_id = random(); - p->auth_info->credentials = data_blob(NULL, 0); - p->ntlmssp_state = NULL; - - status = ntlmssp_update(state, - p->auth_info->credentials, - &credentials); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto done; - } - - p->auth_info->credentials = data_blob_talloc(mem_ctx, - credentials.data, - credentials.length); - data_blob_free(&credentials); - - status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - - status = ntlmssp_update(state, - p->auth_info->credentials, - &credentials); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto done; - } - - p->auth_info->credentials = data_blob_talloc(mem_ctx, - credentials.data, - credentials.length); - data_blob_free(&credentials); - - status = dcerpc_auth3(p, mem_ctx); - - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - p->ntlmssp_state = state; - - switch (p->auth_info->auth_level) { - case DCERPC_AUTH_LEVEL_PRIVACY: - case DCERPC_AUTH_LEVEL_INTEGRITY: - /* setup for signing */ - status = ntlmssp_sign_init(state); - break; - } - -done: - talloc_destroy(mem_ctx); - - if (!NT_STATUS_IS_OK(status)) { - p->ntlmssp_state = NULL; - p->auth_info = NULL; - } - - return status; -} - - /* do a non-athenticated dcerpc bind */ diff --git a/source4/librpc/rpc/dcerpc_ntlm.c b/source4/librpc/rpc/dcerpc_ntlm.c new file mode 100644 index 0000000000..8bfe0cb5ee --- /dev/null +++ b/source4/librpc/rpc/dcerpc_ntlm.c @@ -0,0 +1,197 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc authentication operations + + Copyright (C) Andrew Tridgell 2003 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + wrappers for the ntlmssp_*() functions +*/ +static NTSTATUS ntlm_unseal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_unseal_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_check_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + const DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_check_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_seal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_seal_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_sign_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_sign_packet(ntlmssp_state, data, length, sig); +} + +static void ntlm_security_end(struct dcerpc_security *dcerpc_security) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_end(&ntlmssp_state); +} + + + +/* + do ntlm style authentication on a dcerpc pipe +*/ +NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, + const char *uuid, unsigned version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + struct ntlmssp_state *state; + TALLOC_CTX *mem_ctx; + DATA_BLOB credentials; + + mem_ctx = talloc_init("dcerpc_bind_auth_ntlm"); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + status = ntlmssp_client_start(&state); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = ntlmssp_set_domain(state, domain); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = ntlmssp_set_username(state, username); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = ntlmssp_set_password(state, password); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->auth_info = talloc(p->mem_ctx, sizeof(*p->auth_info)); + if (!p->auth_info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->auth_info->auth_type = DCERPC_AUTH_TYPE_NTLMSSP; + + if (p->flags & DCERPC_SEAL) { + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL; + } else { + /* ntlmssp does not work on dcerpc with + AUTH_LEVEL_NONE */ + state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } + p->auth_info->auth_pad_length = 0; + p->auth_info->auth_reserved = 0; + p->auth_info->auth_context_id = random(); + p->auth_info->credentials = data_blob(NULL, 0); + p->security_state = NULL; + + status = ntlmssp_update(state, + p->auth_info->credentials, + &credentials); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + goto done; + } + + p->auth_info->credentials = data_blob_talloc(mem_ctx, + credentials.data, + credentials.length); + data_blob_free(&credentials); + + status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + + status = ntlmssp_update(state, + p->auth_info->credentials, + &credentials); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + goto done; + } + + p->auth_info->credentials = data_blob_talloc(mem_ctx, + credentials.data, + credentials.length); + data_blob_free(&credentials); + + status = dcerpc_auth3(p, mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->security_state = talloc_p(p->mem_ctx, struct dcerpc_security); + if (!p->security_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->security_state->private = state; + p->security_state->unseal_packet = ntlm_unseal_packet; + p->security_state->check_packet = ntlm_check_packet; + p->security_state->seal_packet = ntlm_seal_packet; + p->security_state->sign_packet = ntlm_sign_packet; + p->security_state->security_end = ntlm_security_end; + + switch (p->auth_info->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + case DCERPC_AUTH_LEVEL_INTEGRITY: + /* setup for signing */ + status = ntlmssp_sign_init(state); + break; + } + +done: + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + p->security_state = NULL; + p->auth_info = NULL; + } + + return status; +} + + diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c new file mode 100644 index 0000000000..9ef16a0d5c --- /dev/null +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -0,0 +1,219 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc schannel operations + + Copyright (C) Andrew Tridgell 2004 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + wrappers for the schannel_*() functions +*/ +static NTSTATUS schan_unseal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_unseal_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_check_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + const DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_check_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_seal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_seal_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_sign_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_sign_packet(schannel_state, data, length, sig); +} + +static void schan_security_end(struct dcerpc_security *dcerpc_security) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_end(&schannel_state); +} + + +/* + do a schannel style bind on a dcerpc pipe. The username is usually + of the form HOSTNAME$ and the password is the domain trust password +*/ +NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p, + const char *uuid, unsigned version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + struct dcerpc_pipe *p2; + struct netr_ServerReqChallenge r; + struct netr_ServerAuthenticate2 a; + uint8 mach_pwd[16]; + uint8 session_key[16]; + struct netr_CredentialState creds; + struct schannel_state *schannel_state; + const char *workgroup, *workstation; + uint32 negotiate_flags = 0; + + workstation = username; + workgroup = domain; + + /* + step 1 - establish a netlogon connection, with no authentication + */ + status = dcerpc_secondary_smb(p, &p2, + DCERPC_NETLOGON_NAME, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION); + + + /* + step 2 - request a netlogon challenge + */ + r.in.server_name = talloc_asprintf(p->mem_ctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = workstation; + generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False); + + status = dcerpc_netr_ServerReqChallenge(p2, p->mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + step 3 - authenticate on the netlogon pipe + */ + E_md4hash(password, mach_pwd); + creds_client_init(&creds, &r.in.credentials, &r.out.credentials, mach_pwd, + &a.in.credentials); + + a.in.server_name = r.in.server_name; + a.in.username = talloc_asprintf(p->mem_ctx, "%s$", workstation); + if (lp_server_role() == ROLE_DOMAIN_BDC) { + a.in.secure_channel_type = SEC_CHAN_BDC; + } else { + a.in.secure_channel_type = SEC_CHAN_WKSTA; + } + a.in.computer_name = workstation; + a.in.negotiate_flags = &negotiate_flags; + a.out.negotiate_flags = &negotiate_flags; + + status = dcerpc_netr_ServerAuthenticate2(p2, p->mem_ctx, &a); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!creds_client_check(&creds, &a.out.credentials)) { + return NT_STATUS_UNSUCCESSFUL; + } + + /* + the schannel session key is now in creds.session_key + */ + + + /* + step 4 - perform a bind with security type schannel + */ + p->auth_info = talloc(p->mem_ctx, sizeof(*p->auth_info)); + if (!p->auth_info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->auth_info->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; + + if (p->flags & DCERPC_SEAL) { + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + } else { + /* note that DCERPC_AUTH_LEVEL_NONE does not make any + sense, and would be rejected by the server */ + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } + p->auth_info->auth_pad_length = 0; + p->auth_info->auth_reserved = 0; + p->auth_info->auth_context_id = 1; + p->security_state = NULL; + + p->auth_info->credentials = data_blob_talloc(p->mem_ctx, + NULL, + 8 + + strlen(workgroup)+1 + + strlen(workstation)+1); + if (!p->auth_info->credentials.data) { + return NT_STATUS_NO_MEMORY; + } + + /* oh, this is ugly! */ + SIVAL(p->auth_info->credentials.data, 0, 0); + SIVAL(p->auth_info->credentials.data, 4, 3); + memcpy(p->auth_info->credentials.data+8, workgroup, strlen(workgroup)+1); + memcpy(p->auth_info->credentials.data+8+strlen(workgroup)+1, + workstation, strlen(workstation)+1); + + /* send the authenticated bind request */ + status = dcerpc_bind_byuuid(p, p->mem_ctx, uuid, version); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->security_state = talloc_p(p->mem_ctx, struct dcerpc_security); + if (!p->security_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + schannel_state = talloc_p(p->mem_ctx, struct schannel_state); + if (!schannel_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + memcpy(session_key, creds.session_key, 8); + memset(session_key+8, 0, 8); + + status = schannel_start(&schannel_state, session_key, True); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + dump_data_pw("session key:\n", schannel_state->session_key, 16); + + p->security_state->private = schannel_state; + p->security_state->unseal_packet = schan_unseal_packet; + p->security_state->check_packet = schan_check_packet; + p->security_state->seal_packet = schan_seal_packet; + p->security_state->sign_packet = schan_sign_packet; + p->security_state->security_end = schan_security_end; + +done: + return status; +} + diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index a79e5adb10..7822231b82 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -295,7 +295,6 @@ static const char *smb_peer_name(struct dcerpc_pipe *p) return smb->tree->session->transport->called.name; } - /* open a rpc connection to a named pipe */ diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 96f0b959e7..ba61f28c95 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -275,6 +275,7 @@ static const struct { } ncacn_options[] = { {"sign", DCERPC_SIGN}, {"seal", DCERPC_SEAL}, + {"schannel", DCERPC_SCHANNEL}, {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, {"print", DCERPC_DEBUG_PRINT_BOTH}, {"bigendian", DCERPC_PUSH_BIGENDIAN} @@ -481,11 +482,23 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, (*p)->flags = binding->flags; - if (binding->flags & (DCERPC_SIGN | DCERPC_SEAL)) { + if (binding->flags & DCERPC_SCHANNEL) { + const char *trust_password = secrets_fetch_machine_password(); + if (!trust_password) { + DEBUG(0,("Unable to fetch machine password\n")); + goto done; + } + status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + lp_workgroup(), + lp_netbios_name(), + trust_password); + } else if (binding->flags & (DCERPC_SIGN | DCERPC_SEAL)) { status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); } else { status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); } + +done: if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); dcerpc_pipe_close(*p); -- cgit