diff options
Diffstat (limited to 'source4/librpc/rpc')
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 58 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 30 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_auth.c | 63 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_ntlm.c | 132 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_schannel.c | 194 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 4 |
6 files changed, 162 insertions, 319 deletions
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 <abartlet@samba.org> 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); |