summaryrefslogtreecommitdiff
path: root/source4/librpc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc')
-rw-r--r--source4/librpc/idl/dcerpc.idl7
-rw-r--r--source4/librpc/rpc/dcerpc.c42
-rw-r--r--source4/librpc/rpc/dcerpc.h27
-rw-r--r--source4/librpc/rpc/dcerpc_auth.c121
-rw-r--r--source4/librpc/rpc/dcerpc_ntlm.c197
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c219
-rw-r--r--source4/librpc/rpc/dcerpc_smb.c1
-rw-r--r--source4/librpc/rpc/dcerpc_util.c15
8 files changed, 473 insertions, 156 deletions
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
@@ -23,127 +23,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
*/
NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p,
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);