From e74b3ed6f195e66cb5fa0f387cea0f59fb66711b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 9 Jan 2005 11:32:12 +0000 Subject: r4618: - tidied up the alter_context client code a bit - there is no alter_nak or alter_ack packet, its all done in an alter_response - auto-allocated the contex_ids - tried to fix up the dcom code to work again with alter_context. Jelmer, please take a look :) (This used to be commit dd1c54add8884376601f2f8a56c01bfb8add030c) --- source4/include/nterr.h | 1 + source4/lib/dcom/common/main.c | 48 +++++++++++++------- source4/libcli/util/nterr.c | 1 + source4/librpc/idl/dcerpc.idl | 20 ++++----- source4/librpc/rpc/dcerpc.c | 35 ++++++++++----- source4/librpc/rpc/dcerpc.h | 3 ++ source4/librpc/rpc/dcerpc_auth.c | 89 ------------------------------------- source4/librpc/rpc/dcerpc_spnego.c | 5 ++- source4/librpc/rpc/dcerpc_util.c | 6 +-- source4/rpc_server/dcerpc_server.c | 26 +++++------ source4/torture/rpc/alter_context.c | 9 +++- 11 files changed, 100 insertions(+), 143 deletions(-) diff --git a/source4/include/nterr.h b/source4/include/nterr.h index 9cf9e0f086..6680b7ecec 100644 --- a/source4/include/nterr.h +++ b/source4/include/nterr.h @@ -563,6 +563,7 @@ #define NT_STATUS_NOT_A_REPARSE_POINT NT_STATUS(0xC0000000 | 0x0275) #define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */ #define NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED NT_STATUS(0xC0000000 | 0x20004) +#define NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX NT_STATUS(0xC0000000 | 0x20026) /* I use NT_STATUS_FOOBAR when I have no idea what error code to use - diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 02e1dea139..b9f6127c6c 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -341,41 +341,54 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const return WERR_OK; } -NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) +NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding binding; struct GUID iid; HYPER_T oxid; NTSTATUS status; int i; + struct dcerpc_pipe *p; + TALLOC_CTX *tmp_ctx; + const char *uuid; + + tmp_ctx = talloc_new(NULL); - *p = NULL; + p = iface->ox->pipe; oxid = iface->ox->oxid; iid = iface->interface->iid; -#warning "dcerpc_alter needed" -#if 0 - if (iface->ox->pipe) { - if (!GUID_equal(&iface->ox->pipe->syntax.uuid, &iid)) { + uuid = GUID_string(tmp_ctx, &iid); + + if (p) { + if (!GUID_equal(&p->syntax.uuid, &iid)) { + struct dcerpc_pipe *p2; iface->ox->pipe->syntax.uuid = iid; - status = dcerpc_alter(iface->ox->pipe, iface->ctx); - if (NT_STATUS_IS_ERR(status)) { - return status; + status = dcerpc_secondary_context(p, &p2, uuid, 0); + if (NT_STATUS_IS_OK(status)) { + p = p2; } + } else { + p = talloc_reference(NULL, p); } - *p = iface->ox->pipe; - return NT_STATUS_OK; + *pp = p; + talloc_free(tmp_ctx); + return status; } -#endif + i = 0; do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]); - if (NT_STATUS_IS_ERR(status)) { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, + iface->ox->bindings.stringbindings[i]); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Error parsing string binding")); } else { binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&iface->ox->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); + status = dcerpc_pipe_connect_b(&p, &binding, + uuid, 0.0, + iface->ctx->domain, iface->ctx->user, + iface->ctx->password); } i++; @@ -383,12 +396,15 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) if (NT_STATUS_IS_ERR(status)) { DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); + talloc_free(tmp_ctx); return status; } DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); - *p = iface->ox->pipe; + *pp = p; + talloc_free(tmp_ctx); + return NT_STATUS_OK; } diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c index d2d87eeb1c..9317f0e37a 100644 --- a/source4/libcli/util/nterr.c +++ b/source4/libcli/util/nterr.c @@ -537,6 +537,7 @@ static const nt_err_code_struct nt_errs[] = { "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE }, { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES }, { "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED }, + { "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX }, { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES }, { "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED }, { NULL, NT_STATUS(0) } diff --git a/source4/librpc/idl/dcerpc.idl b/source4/librpc/idl/dcerpc.idl index d9ed119abd..d4fb026c8c 100644 --- a/source4/librpc/idl/dcerpc.idl +++ b/source4/librpc/idl/dcerpc.idl @@ -160,7 +160,7 @@ interface dcerpc DCERPC_PKT_BIND_ACK = 12, DCERPC_PKT_BIND_NAK = 13, DCERPC_PKT_ALTER = 14, - DCERPC_PKT_ALTER_ACK = 15, + DCERPC_PKT_ALTER_RESP = 15, DCERPC_PKT_AUTH3 = 16, DCERPC_PKT_SHUTDOWN = 17, DCERPC_PKT_CO_CANCEL = 18, @@ -168,15 +168,15 @@ interface dcerpc } dcerpc_pkt_type; typedef [nodiscriminant] union { - [case(DCERPC_PKT_REQUEST)] dcerpc_request request; - [case(DCERPC_PKT_RESPONSE)] dcerpc_response response; - [case(DCERPC_PKT_BIND)] dcerpc_bind bind; - [case(DCERPC_PKT_BIND_ACK)] dcerpc_bind_ack bind_ack; - [case(DCERPC_PKT_ALTER)] dcerpc_bind alter; - [case(DCERPC_PKT_ALTER_ACK)] dcerpc_bind_ack alter_ack; - [case(DCERPC_PKT_FAULT)] dcerpc_fault fault; - [case(DCERPC_PKT_AUTH3)] dcerpc_auth3 auth3; - [case(DCERPC_PKT_BIND_NAK)] dcerpc_bind_nak bind_nak; + [case(DCERPC_PKT_REQUEST)] dcerpc_request request; + [case(DCERPC_PKT_RESPONSE)] dcerpc_response response; + [case(DCERPC_PKT_BIND)] dcerpc_bind bind; + [case(DCERPC_PKT_BIND_ACK)] dcerpc_bind_ack bind_ack; + [case(DCERPC_PKT_ALTER)] dcerpc_bind alter; + [case(DCERPC_PKT_ALTER_RESP)] dcerpc_bind_ack alter_resp; + [case(DCERPC_PKT_FAULT)] dcerpc_fault fault; + [case(DCERPC_PKT_AUTH3)] dcerpc_auth3 auth3; + [case(DCERPC_PKT_BIND_NAK)] dcerpc_bind_nak bind_nak; } dcerpc_payload; diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index d75f6db935..e133c77d07 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -562,6 +562,18 @@ static NTSTATUS full_request(struct dcerpc_connection *c, return state->status; } +/* + map a bind nak reason to a NTSTATUS +*/ +static NTSTATUS dcerpc_map_reason(uint16_t reason) +{ + switch (reason) { + case DCERPC_BIND_REASON_ASYNTAX: + return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX; + } + return NT_STATUS_UNSUCCESSFUL; +} + /* perform a bind using the given syntax @@ -622,7 +634,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, if (pkt.ptype == DCERPC_PKT_BIND_NAK) { DEBUG(2,("dcerpc: bind_nak reason %d\n", pkt.u.bind_nak.reject_reason)); - return NT_STATUS_ACCESS_DENIED; + return dcerpc_map_reason(pkt.u.bind_nak.reject_reason); } if ((pkt.ptype != DCERPC_PKT_BIND_ACK) || @@ -1387,20 +1399,23 @@ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p, return status; } - if (pkt.ptype == DCERPC_PKT_BIND_NAK) { - DEBUG(2,("dcerpc: alter_nak reason %d\n", pkt.u.bind_nak.reject_reason)); - return NT_STATUS_ACCESS_DENIED; + if (pkt.ptype == DCERPC_PKT_ALTER_RESP && + pkt.u.alter_resp.num_results == 1 && + pkt.u.alter_resp.ctx_list[0].result != 0) { + DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", + pkt.u.alter_resp.ctx_list[0].reason)); + return dcerpc_map_reason(pkt.u.alter_resp.ctx_list[0].reason); } - if ((pkt.ptype != DCERPC_PKT_ALTER_ACK) || - pkt.u.alter_ack.num_results == 0 || - pkt.u.alter_ack.ctx_list[0].result != 0) { + if (pkt.ptype != DCERPC_PKT_ALTER_RESP || + pkt.u.alter_resp.num_results == 0 || + pkt.u.alter_resp.ctx_list[0].result != 0) { return NT_STATUS_UNSUCCESSFUL; } - /* the alter_ack might contain a reply set of credentials */ - if (p->conn->security_state.auth_info && pkt.u.alter_ack.auth_info.length) { - status = ndr_pull_struct_blob(&pkt.u.alter_ack.auth_info, + /* the alter_resp might contain a reply set of credentials */ + if (p->conn->security_state.auth_info && pkt.u.alter_resp.auth_info.length) { + status = ndr_pull_struct_blob(&pkt.u.alter_resp.auth_info, mem_ctx, p->conn->security_state.auth_info, (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index 00f1fb6488..f5ed637d0b 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -76,6 +76,9 @@ struct dcerpc_connection { /* private pointer for pending full requests */ void *full_request_private; + + /* the next context_id to be assigned */ + uint32_t next_context_id; }; /* diff --git a/source4/librpc/rpc/dcerpc_auth.c b/source4/librpc/rpc/dcerpc_auth.c index 9d43218e4b..4ff8fe549e 100644 --- a/source4/librpc/rpc/dcerpc_auth.c +++ b/source4/librpc/rpc/dcerpc_auth.c @@ -123,92 +123,3 @@ done: return status; } - -#warning "bind_alter not implemented" -#if 0 -NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level, - const char *uuid, uint_t version) -{ - NTSTATUS status; - TALLOC_CTX *mem_ctx; - DATA_BLOB credentials; - DATA_BLOB null_data_blob = data_blob(NULL, 0); - - mem_ctx = talloc_init("dcerpc_bind_auth"); - if (!mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - if (!p->conn->security_state.generic_state) { - status = gensec_client_start(p, &p->conn->security_state.generic_state); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, - auth_type, auth_level); - - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } - - p->conn->security_state.auth_info = talloc_p(p, struct dcerpc_auth); - if (!p->conn->security_state.auth_info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - p->conn->security_state.auth_info->auth_type = auth_type; - p->conn->security_state.auth_info->auth_level = auth_level; - p->conn->security_state.auth_info->auth_pad_length = 0; - p->conn->security_state.auth_info->auth_reserved = 0; - p->conn->security_state.auth_info->auth_context_id = random(); - p->conn->security_state.auth_info->credentials = null_data_blob; - - status = gensec_update(p->conn->security_state.generic_state, mem_ctx, - null_data_blob, - &credentials); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto done; - } - - p->conn->security_state.auth_info->credentials = credentials; - - status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - while(1) { - status = gensec_update(p->conn->security_state.generic_state, mem_ctx, - p->conn->security_state.auth_info->credentials, - &credentials); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto done; - } - - p->conn->security_state.auth_info->credentials = credentials; - - status = dcerpc_alter(p, mem_ctx); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - } - -done: - talloc_destroy(mem_ctx); - - if (!NT_STATUS_IS_OK(status)) { - talloc_free(p->conn->security_state.generic_state); - ZERO_STRUCT(p->conn->security_state); - } else { - /* Authenticated connections use the generic session key */ - p->conn->security_state.session_key = dcerpc_generic_session_key; - } - - return status; -} -#endif diff --git a/source4/librpc/rpc/dcerpc_spnego.c b/source4/librpc/rpc/dcerpc_spnego.c index cab8865d6b..f67dd2c7cb 100644 --- a/source4/librpc/rpc/dcerpc_spnego.c +++ b/source4/librpc/rpc/dcerpc_spnego.c @@ -24,8 +24,11 @@ #include "includes.h" -#warning "this needs dcerpc_alter" #if 0 +/* + metze, can you tell me what you're trying to do with this? +*/ + /* do spnego style authentication on a gensec pipe */ diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 702a1f6ecf..305c1c7725 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -1272,8 +1272,8 @@ void dcerpc_log_packet(const struct dcerpc_interface_table *ndr, this uses dcerpc_alter_context() to create a new dcerpc context_id */ -NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, struct dcerpc_pipe **pp2, - uint32_t context_id, +NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, + struct dcerpc_pipe **pp2, const char *pipe_uuid, uint32_t pipe_version) { @@ -1286,7 +1286,7 @@ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, struct dcerpc_pipe **pp } p2->conn = talloc_reference(p2, p->conn); - p2->context_id = context_id; + p2->context_id = ++p->conn->next_context_id; status = GUID_from_string(pipe_uuid, &p2->syntax.uuid); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index f0791e5928..c86ffb2cd0 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -580,22 +580,22 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call) dcesrv_init_hdr(&pkt); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; - pkt.ptype = DCERPC_PKT_ALTER_ACK; + pkt.ptype = DCERPC_PKT_ALTER_RESP; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; - pkt.u.alter_ack.max_xmit_frag = 0x2000; - pkt.u.alter_ack.max_recv_frag = 0x2000; - pkt.u.alter_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id; - pkt.u.alter_ack.secondary_address = NULL; - pkt.u.alter_ack.num_results = 1; - pkt.u.alter_ack.ctx_list = talloc_p(call, struct dcerpc_ack_ctx); - if (!pkt.u.alter_ack.ctx_list) { + pkt.u.alter_resp.max_xmit_frag = 0x2000; + pkt.u.alter_resp.max_recv_frag = 0x2000; + pkt.u.alter_resp.assoc_group_id = call->pkt.u.bind.assoc_group_id; + pkt.u.alter_resp.secondary_address = NULL; + pkt.u.alter_resp.num_results = 1; + pkt.u.alter_resp.ctx_list = talloc_p(call, struct dcerpc_ack_ctx); + if (!pkt.u.alter_resp.ctx_list) { return NT_STATUS_NO_MEMORY; } - pkt.u.alter_ack.ctx_list[0].result = result; - pkt.u.alter_ack.ctx_list[0].reason = reason; - GUID_from_string(NDR_GUID, &pkt.u.alter_ack.ctx_list[0].syntax.uuid); - pkt.u.alter_ack.ctx_list[0].syntax.if_version = NDR_GUID_VERSION; - pkt.u.alter_ack.auth_info = data_blob(NULL, 0); + pkt.u.alter_resp.ctx_list[0].result = result; + pkt.u.alter_resp.ctx_list[0].reason = reason; + GUID_from_string(NDR_GUID, &pkt.u.alter_resp.ctx_list[0].syntax.uuid); + pkt.u.alter_resp.ctx_list[0].syntax.if_version = NDR_GUID_VERSION; + pkt.u.alter_resp.auth_info = data_blob(NULL, 0); if (!dcesrv_auth_alter_ack(call, &pkt)) { return dcesrv_bind_nak(call, 0); diff --git a/source4/torture/rpc/alter_context.c b/source4/torture/rpc/alter_context.c index d10604fa04..2c6f209404 100644 --- a/source4/torture/rpc/alter_context.c +++ b/source4/torture/rpc/alter_context.c @@ -49,12 +49,19 @@ BOOL torture_rpc_alter_context(void) } printf("Opening secondary DSSETUP context\n"); - status = dcerpc_secondary_context(p, &p2, 1, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION); + status = dcerpc_secondary_context(p, &p2, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION); if (!NT_STATUS_IS_OK(status)) { printf("dcerpc_alter_context failed - %s\n", nt_errstr(status)); return False; } + printf("Opening bad secondary connection\n"); + status = dcerpc_secondary_context(p, &p2, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION+100); + if (NT_STATUS_IS_OK(status)) { + printf("dcerpc_alter_context with wrong version should fail\n"); + return False; + } + printf("testing DSSETUP pipe operations\n"); ret &= test_DsRoleGetPrimaryDomainInformation(p2, mem_ctx); -- cgit