From be081037e09bb78c0308cd6c7a5d7ae563678b7c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 20 Jun 2004 00:58:09 +0000 Subject: r1200: Add 'gensec', our generic security layer. This layer is used for DCERPC security, as well as ntlm_auth at this time. It expect things like SASL and the CIFS layer to use it as well. The particular purpose of this layer is to introduce SPENGO, which needs generic access to the actual implementation mechanisms. Schannel, due to it's 'interesting' setup properties is in GENSEC, but is only in the RPC code. Andrew Bartlett (This used to be commit 902af49006fb8cfecaadd3cc0c10e2e542083fb1) --- source4/librpc/rpc/dcerpc.c | 58 ++++++----- source4/librpc/rpc/dcerpc.h | 30 +----- source4/librpc/rpc/dcerpc_auth.c | 63 +++++------- source4/librpc/rpc/dcerpc_ntlm.c | 132 ++---------------------- source4/librpc/rpc/dcerpc_schannel.c | 194 +++++++++++++++++------------------ source4/librpc/rpc/dcerpc_util.c | 4 +- 6 files changed, 162 insertions(+), 319 deletions(-) (limited to 'source4/librpc/rpc') diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 82b6fa9a4e..5d5469da7f 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -42,9 +42,9 @@ struct dcerpc_pipe *dcerpc_pipe_init(void) p->mem_ctx = mem_ctx; p->call_id = 1; p->security_state.auth_info = NULL; - ZERO_STRUCT(p->security_state.user); - p->security_state.private_data = NULL; - p->security_state.ops = NULL; + ZERO_STRUCT(p->security_state.generic_state.user); + p->security_state.generic_state.private_data = NULL; + p->security_state.generic_state.ops = NULL; p->binding_string = NULL; p->flags = 0; p->srv_max_xmit_frag = 0; @@ -60,8 +60,8 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p) if (!p) return; p->reference_count--; if (p->reference_count <= 0) { - if (p->security_state.ops) { - p->security_state.ops->end(&p->security_state); + if (p->security_state.generic_state.ops) { + p->security_state.generic_state.ops->end(&p->security_state.generic_state); } p->transport.shutdown_pipe(p); talloc_destroy(p->mem_ctx); @@ -132,7 +132,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, DATA_BLOB auth_blob; /* non-signed packets are simpler */ - if (!p->security_state.auth_info || !p->security_state.ops) { + if (!p->security_state.auth_info || !p->security_state.generic_state.ops) { return dcerpc_pull(blob, mem_ctx, pkt); } @@ -186,19 +186,21 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, /* check signature or unseal the packet */ switch (p->security_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = p->security_state.ops->unseal(&p->security_state, - mem_ctx, - pkt->u.response.stub_and_verifier.data, - pkt->u.response.stub_and_verifier.length, - &auth.credentials); + status = p->security_state + .generic_state.ops->unseal(&p->security_state.generic_state, + mem_ctx, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = p->security_state.ops->check_sig(&p->security_state, - mem_ctx, - pkt->u.response.stub_and_verifier.data, - pkt->u.response.stub_and_verifier.length, - &auth.credentials); + status = p->security_state + .generic_state.ops->check_sig(&p->security_state.generic_state, + mem_ctx, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); break; case DCERPC_AUTH_LEVEL_NONE: @@ -230,7 +232,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, struct ndr_push *ndr; /* non-signed packets are simpler */ - if (!p->security_state.auth_info || !p->security_state.ops) { + if (!p->security_state.auth_info || !p->security_state.generic_state.ops) { return dcerpc_push_auth(blob, mem_ctx, pkt, p->security_state.auth_info); } @@ -255,19 +257,21 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* sign or seal the packet */ switch (p->security_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: - status = p->security_state.ops->seal(&p->security_state, - mem_ctx, - ndr->data + DCERPC_REQUEST_LENGTH, - ndr->offset - DCERPC_REQUEST_LENGTH, - &p->security_state.auth_info->credentials); + status = p->security_state + .generic_state.ops->seal(&p->security_state.generic_state, + mem_ctx, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->security_state.auth_info->credentials); break; case DCERPC_AUTH_LEVEL_INTEGRITY: - status = p->security_state.ops->sign(&p->security_state, - mem_ctx, - ndr->data + DCERPC_REQUEST_LENGTH, - ndr->offset - DCERPC_REQUEST_LENGTH, - &p->security_state.auth_info->credentials); + status = p->security_state + .generic_state.ops->sign(&p->security_state.generic_state, + mem_ctx, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->security_state.auth_info->credentials); break; case DCERPC_AUTH_LEVEL_NONE: diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 7694a9c230..a513b72a16 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -25,38 +25,10 @@ enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP}; /* this defines a generic security context for signed/sealed dcerpc pipes. */ -struct dcerpc_security; struct dcerpc_pipe; - -struct dcerpc_user { - const char *domain; - const char *name; - const char *password; -}; - -struct dcesrv_security_ops { - const char *name; - uint8 auth_type; - NTSTATUS (*start)(struct dcerpc_pipe *dce_pipe, struct dcerpc_security *dce_sec); - NTSTATUS (*update)(struct dcerpc_security *dce_sec, TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out); - NTSTATUS (*seal)(struct dcerpc_security *dce_sec, TALLOC_CTX *sig_mem_ctx, - uint8_t *data, size_t length, DATA_BLOB *sig); - NTSTATUS (*sign)(struct dcerpc_security *dce_sec, TALLOC_CTX *sig_mem_ctx, - const uint8_t *data, size_t length, DATA_BLOB *sig); - NTSTATUS (*check_sig)(struct dcerpc_security *dce_sec, TALLOC_CTX *sig_mem_ctx, - const uint8_t *data, size_t length, const DATA_BLOB *sig); - NTSTATUS (*unseal)(struct dcerpc_security *dce_sec, TALLOC_CTX *sig_mem_ctx, - uint8_t *data, size_t length, DATA_BLOB *sig); - NTSTATUS (*session_key)(struct dcerpc_security *, DATA_BLOB *session_key); - void (*end)(struct dcerpc_security *dce_sec); -}; - struct dcerpc_security { struct dcerpc_auth *auth_info; - struct dcerpc_user user; - void *private_data; - const struct dcesrv_security_ops *ops; + struct gensec_security generic_state; }; struct dcerpc_pipe { diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 021249847a..e5fad1f082 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -1,9 +1,11 @@ /* Unix SMB/CIFS implementation. - dcerpc authentication operations + Generic Authentication Interface Copyright (C) Andrew Tridgell 2003 + Copyright (C) Andrew Bartlett 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 @@ -42,24 +44,8 @@ NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p, return status; } -const struct dcesrv_security_ops *dcerpc_security_by_authtype(uint8_t auth_type) -{ - switch (auth_type) { - case DCERPC_AUTH_TYPE_SCHANNEL: - return dcerpc_schannel_security_get_ops(); - - case DCERPC_AUTH_TYPE_NTLMSSP: - return dcerpc_ntlmssp_security_get_ops(); - } - - return NULL; -} - NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, - const char *uuid, uint_t version, - const char *domain, - const char *username, - const char *password) + const char *uuid, uint_t version) { NTSTATUS status; TALLOC_CTX *mem_ctx; @@ -69,20 +55,19 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } - - p->security_state.ops = dcerpc_security_by_authtype(auth_type); - if (!p->security_state.ops) { - status = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - p->security_state.user.domain = domain; - p->security_state.user.name = username; - p->security_state.user.password = password; - - status = p->security_state.ops->start(p, &p->security_state); - if (!NT_STATUS_IS_OK(status)) { - return status; + + if (!p->security_state.generic_state.ops) { + + p->security_state.generic_state.ops = gensec_security_by_authtype(auth_type); + if (!p->security_state.generic_state.ops) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + status = p->security_state.generic_state.ops->client_start(&p->security_state.generic_state); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } p->security_state.auth_info = talloc(p->mem_ctx, sizeof(*p->security_state.auth_info)); @@ -105,9 +90,9 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, p->security_state.auth_info->auth_level = DCERPC_AUTH_LEVEL_NONE; } - status = p->security_state.ops->update(&p->security_state, mem_ctx, - p->security_state.auth_info->credentials, - &credentials); + status = p->security_state.generic_state.ops->update(&p->security_state.generic_state, mem_ctx, + p->security_state.auth_info->credentials, + &credentials); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; @@ -120,9 +105,9 @@ NTSTATUS dcerpc_bind_auth(struct dcerpc_pipe *p, uint8_t auth_type, goto done; } - status = p->security_state.ops->update(&p->security_state, mem_ctx, - p->security_state.auth_info->credentials, - &credentials); + status = p->security_state.generic_state.ops->update(&p->security_state.generic_state, mem_ctx, + p->security_state.auth_info->credentials, + &credentials); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto done; @@ -140,3 +125,5 @@ done: return status; } + + diff --git a/source4/librpc/rpc/dcerpc_ntlm.c b/source4/librpc/rpc/dcerpc_ntlm.c index 2cfecd939f..398e3f1aa3 100644 --- a/source4/librpc/rpc/dcerpc_ntlm.c +++ b/source4/librpc/rpc/dcerpc_ntlm.c @@ -23,127 +23,7 @@ #include "includes.h" /* - wrappers for the ntlmssp_*() functions -*/ -static NTSTATUS dcerpc_ntlmssp_unseal(struct dcerpc_security *dcerpc_security, - TALLOC_CTX *mem_ctx, - uint8_t *data, size_t length, DATA_BLOB *sig) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - return ntlmssp_unseal_packet(ntlmssp_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_ntlmssp_check_sig(struct dcerpc_security *dcerpc_security, - TALLOC_CTX *mem_ctx, - const uint8_t *data, size_t length, - const DATA_BLOB *sig) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - return ntlmssp_check_packet(ntlmssp_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_ntlmssp_seal(struct dcerpc_security *dcerpc_security, - TALLOC_CTX *mem_ctx, - uint8_t *data, size_t length, - DATA_BLOB *sig) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - return ntlmssp_seal_packet(ntlmssp_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_ntlmssp_sign(struct dcerpc_security *dcerpc_security, - TALLOC_CTX *mem_ctx, - const uint8_t *data, size_t length, - DATA_BLOB *sig) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - return ntlmssp_sign_packet(ntlmssp_state, mem_ctx, data, length, sig); -} - -static NTSTATUS dcerpc_ntlmssp_session_key(struct dcerpc_security *dcerpc_security, - DATA_BLOB *session_key) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - if (!ntlmssp_state->session_key.data) { - return NT_STATUS_NO_USER_SESSION_KEY; - } - *session_key = ntlmssp_state->session_key; - - return NT_STATUS_OK; -} - -static NTSTATUS dcerpc_ntlmssp_start(struct dcerpc_pipe *dce_pipe, struct dcerpc_security *dcerpc_security) -{ - struct ntlmssp_state *ntlmssp_state = NULL; - NTSTATUS status; - - status = ntlmssp_client_start(&ntlmssp_state); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = ntlmssp_set_domain(ntlmssp_state, dcerpc_security->user.domain); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = ntlmssp_set_username(ntlmssp_state, dcerpc_security->user.name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = ntlmssp_set_password(ntlmssp_state, dcerpc_security->user.password); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - dcerpc_security->private_data = ntlmssp_state; - - return status; -} - -static NTSTATUS dcerpc_ntlmssp_update(struct dcerpc_security *dcerpc_security, TALLOC_CTX *out_mem_ctx, - const DATA_BLOB in, DATA_BLOB *out) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - return ntlmssp_update(ntlmssp_state, out_mem_ctx, in, out); -} - -static void dcerpc_ntlmssp_end(struct dcerpc_security *dcerpc_security) -{ - struct ntlmssp_state *ntlmssp_state = dcerpc_security->private_data; - - ntlmssp_end(&ntlmssp_state); - - dcerpc_security->private_data = NULL; -} - -static const struct dcesrv_security_ops dcerpc_ntlmssp_security_ops = { - .name = "ntlmssp", - .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, - .start = dcerpc_ntlmssp_start, - .update = dcerpc_ntlmssp_update, - .seal = dcerpc_ntlmssp_seal, - .sign = dcerpc_ntlmssp_sign, - .check_sig = dcerpc_ntlmssp_check_sig, - .unseal = dcerpc_ntlmssp_unseal, - .session_key = dcerpc_ntlmssp_session_key, - .end = dcerpc_ntlmssp_end -}; - -const struct dcesrv_security_ops *dcerpc_ntlmssp_security_get_ops(void) -{ - return &dcerpc_ntlmssp_security_ops; -} - -/* - do ntlm style authentication on a dcerpc pipe + do ntlm style authentication on a gensec pipe */ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, const char *uuid, uint_t version, @@ -153,12 +33,12 @@ NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, { NTSTATUS status; + p->security_state.generic_state.user.domain = domain; + p->security_state.generic_state.user.name = username; + p->security_state.generic_state.user.password = password; + status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_NTLMSSP, - uuid, version, - domain, username, - password); + uuid, version); return status; } - - diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index df15edfb6f..b43dd0788a 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -32,109 +32,68 @@ struct dcerpc_schannel_state { struct schannel_state *schannel_state; }; +static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, + const char *domain, + const char *username, + const char *password, + int chan_type, + uint8_t new_session_key[16]); + /* wrappers for the schannel_*() functions + + These will become static again, when we get dynamic registration, and + decrpc_schannel_security_ops come back here. */ -static NTSTATUS dcerpc_schannel_unseal(struct dcerpc_security *dcerpc_security, +static NTSTATUS dcerpc_schannel_unseal(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; return schannel_unseal_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); } -static NTSTATUS dcerpc_schannel_check_sig(struct dcerpc_security *dcerpc_security, +static NTSTATUS dcerpc_schannel_check_sig(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, const DATA_BLOB *sig) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; return schannel_check_packet(dce_schan_state->schannel_state, data, length, sig); } -static NTSTATUS dcerpc_schannel_seal(struct dcerpc_security *dcerpc_security, +static NTSTATUS dcerpc_schannel_seal(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; return schannel_seal_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); } -static NTSTATUS dcerpc_schannel_sign(struct dcerpc_security *dcerpc_security, +static NTSTATUS dcerpc_schannel_sign(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, const uint8_t *data, size_t length, DATA_BLOB *sig) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; return schannel_sign_packet(dce_schan_state->schannel_state, mem_ctx, data, length, sig); } -static NTSTATUS dcerpc_schannel_session_key(struct dcerpc_security *dcerpc_security, +static NTSTATUS dcerpc_schannel_session_key(struct gensec_security *gensec_security, DATA_BLOB *session_key) { return NT_STATUS_NOT_IMPLEMENTED; } -static NTSTATUS dcerpc_schannel_start(struct dcerpc_pipe *p, struct dcerpc_security *dcerpc_security) -{ - struct dcerpc_schannel_state *dce_schan_state; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - uint8_t session_key[16]; - int chan_type = 0; - - if (p->flags & DCERPC_SCHANNEL_BDC) { - chan_type = SEC_CHAN_BDC; - } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) { - chan_type = SEC_CHAN_WKSTA; - } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) { - chan_type = SEC_CHAN_DOMAIN; - } - - status = dcerpc_schannel_key(p, dcerpc_security->user.domain, - dcerpc_security->user.name, - dcerpc_security->user.password, - chan_type, session_key); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - mem_ctx = talloc_init("dcerpc_schannel_start"); - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - dce_schan_state = talloc_p(mem_ctx, struct dcerpc_schannel_state); - if (!dce_schan_state) { - talloc_destroy(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - - dce_schan_state->mem_ctx = mem_ctx; - - status = schannel_start(&dce_schan_state->schannel_state, session_key, True); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - dce_schan_state->state = DCERPC_SCHANNEL_STATE_START; - - dcerpc_security->private_data = dce_schan_state; - - dump_data_pw("session key:\n", dce_schan_state->schannel_state->session_key, 16); - - return status; -} - -static NTSTATUS dcerpc_schannel_update(struct dcerpc_security *dcerpc_security, TALLOC_CTX *out_mem_ctx, +static NTSTATUS dcerpc_schannel_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, const DATA_BLOB in, DATA_BLOB *out) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; NTSTATUS status; struct schannel_bind bind_schannel; @@ -148,14 +107,14 @@ static NTSTATUS dcerpc_schannel_update(struct dcerpc_security *dcerpc_security, #if 0 /* to support this we'd need to have access to the full domain name */ bind_schannel.bind_type = 23; - bind_schannel.u.info23.domain = dcerpc_security->user.domain; - bind_schannel.u.info23.account_name = dcerpc_security->user.name; + bind_schannel.u.info23.domain = gensec_security->user.domain; + bind_schannel.u.info23.account_name = gensec_security->user.name; bind_schannel.u.info23.dnsdomain = str_format_nbt_domain(dce_schan_state->mem_ctx, fulldomainname); - bind_schannel.u.info23.workstation = str_format_nbt_domain(dce_schan_state->mem_ctx, dcerpc_security->user.name); + bind_schannel.u.info23.workstation = str_format_nbt_domain(dce_schan_state->mem_ctx, gensec_security->user.name); #else bind_schannel.bind_type = 3; - bind_schannel.u.info3.domain = dcerpc_security->user.domain; - bind_schannel.u.info3.account_name = dcerpc_security->user.name; + bind_schannel.u.info3.domain = gensec_security->user.domain; + bind_schannel.u.info3.account_name = gensec_security->user.name; #endif status = ndr_push_struct_blob(out, dce_schan_state->mem_ctx, &bind_schannel, @@ -167,27 +126,39 @@ static NTSTATUS dcerpc_schannel_update(struct dcerpc_security *dcerpc_security, return NT_STATUS_MORE_PROCESSING_REQUIRED; } -static void dcerpc_schannel_end(struct dcerpc_security *dcerpc_security) +static void dcerpc_schannel_end(struct gensec_security *gensec_security) { - struct dcerpc_schannel_state *dce_schan_state = dcerpc_security->private_data; + struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data; schannel_end(&dce_schan_state->schannel_state); talloc_destroy(dce_schan_state->mem_ctx); - dcerpc_security->private_data = NULL; + gensec_security->private_data = NULL; } +static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = { + .name = "dcerpc_schannel", + .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, + .update = dcerpc_schannel_update, + .seal = dcerpc_schannel_seal, + .sign = dcerpc_schannel_sign, + .check_sig = dcerpc_schannel_check_sig, + .unseal = dcerpc_schannel_unseal, + .session_key = dcerpc_schannel_session_key, + .end = dcerpc_schannel_end +}; + /* get a schannel key using a netlogon challenge on a secondary pipe */ -NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, - const char *domain, - const char *username, - const char *password, - int chan_type, - uint8_t new_session_key[16]) +static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, + const char *domain, + const char *username, + const char *password, + int chan_type, + uint8_t new_session_key[16]) { NTSTATUS status; struct dcerpc_pipe *p2; @@ -269,24 +240,6 @@ NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, return NT_STATUS_OK; } -const struct dcesrv_security_ops dcerpc_schannel_security_ops = { - .name = "schannel", - .auth_type = DCERPC_AUTH_TYPE_SCHANNEL, - .start = dcerpc_schannel_start, - .update = dcerpc_schannel_update, - .seal = dcerpc_schannel_seal, - .sign = dcerpc_schannel_sign, - .check_sig = dcerpc_schannel_check_sig, - .unseal = dcerpc_schannel_unseal, - .session_key = dcerpc_schannel_session_key, - .end = dcerpc_schannel_end -}; - -const struct dcesrv_security_ops *dcerpc_schannel_security_get_ops(void) -{ - return &dcerpc_schannel_security_ops; -} - /* 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 @@ -298,11 +251,58 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p, const char *password) { NTSTATUS status; + struct dcerpc_schannel_state *dce_schan_state; + TALLOC_CTX *mem_ctx; + uint8_t session_key[16]; + int chan_type = 0; + + if (p->flags & DCERPC_SCHANNEL_BDC) { + chan_type = SEC_CHAN_BDC; + } else if (p->flags & DCERPC_SCHANNEL_WORKSTATION) { + chan_type = SEC_CHAN_WKSTA; + } else if (p->flags & DCERPC_SCHANNEL_DOMAIN) { + chan_type = SEC_CHAN_DOMAIN; + } + + status = dcerpc_schannel_key(p, domain, + username, + password, + chan_type, session_key); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + mem_ctx = talloc_init("dcerpc_schannel_start"); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + dce_schan_state = talloc_p(mem_ctx, struct dcerpc_schannel_state); + if (!dce_schan_state) { + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + dce_schan_state->mem_ctx = mem_ctx; + + status = schannel_start(&dce_schan_state->schannel_state, session_key, True); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + dce_schan_state->state = DCERPC_SCHANNEL_STATE_START; + + p->security_state.generic_state.user.domain = domain; + p->security_state.generic_state.user.name = username; + p->security_state.generic_state.user.password = password; + + p->security_state.generic_state.ops = &gensec_dcerpc_schannel_security_ops; + p->security_state.generic_state.private_data = dce_schan_state; + + dump_data_pw("session key:\n", dce_schan_state->schannel_state->session_key, 16); status = dcerpc_bind_auth(p, DCERPC_AUTH_TYPE_SCHANNEL, - uuid, version, - domain, username, - password); + uuid, version); return status; } diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 8c9b273896..82aa5aa1f3 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -697,8 +697,8 @@ NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p, { struct cli_tree *tree; - if (p->security_state.ops) { - return p->security_state.ops->session_key(&p->security_state, session_key); + if (p->security_state.generic_state.ops) { + return p->security_state.generic_state.ops->session_key(&p->security_state.generic_state, session_key); } tree = dcerpc_smb_tree(p); -- cgit