summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/rpc_server/dcerpc_server.c71
-rw-r--r--source4/rpc_server/dcesrv_auth.c15
2 files changed, 80 insertions, 6 deletions
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index 808cad94d9..925004b191 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -599,6 +599,56 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
return NT_STATUS_OK;
}
+
+/*
+ handle a bind request
+*/
+static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32 context_id)
+{
+ uint32_t if_version, transfer_syntax_version;
+ const char *uuid, *transfer_syntax;
+ struct dcesrv_connection_context *context;
+ const struct dcesrv_interface *iface;
+
+ if_version = call->pkt.u.alter.ctx_list[0].abstract_syntax.if_version;
+ uuid = GUID_string(call, &call->pkt.u.alter.ctx_list[0].abstract_syntax.uuid);
+ if (!uuid) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ transfer_syntax_version = call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].if_version;
+ transfer_syntax = GUID_string(call,
+ &call->pkt.u.alter.ctx_list[0].transfer_syntaxes[0].uuid);
+ if (!transfer_syntax ||
+ strcasecmp(NDR_GUID, transfer_syntax) != 0 ||
+ NDR_GUID_VERSION != transfer_syntax_version) {
+ /* we only do NDR encoded dcerpc */
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ iface = find_interface_by_uuid(call->conn->endpoint, uuid, if_version);
+ if (iface == NULL) {
+ DEBUG(2,("Request for unknown dcerpc interface %s/%d\n", uuid, if_version));
+ return NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED;
+ }
+
+ /* add this context to the list of available context_ids */
+ context = talloc(call->conn, struct dcesrv_connection_context);
+ if (context == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ context->conn = call->conn;
+ context->iface = iface;
+ context->context_id = context_id;
+ context->private = NULL;
+ context->handles = NULL;
+ DLIST_ADD(call->conn->contexts, context);
+ call->context = context;
+
+ return NT_STATUS_OK;
+}
+
+
/*
handle a bind request
*/
@@ -608,14 +658,28 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
struct dcesrv_call_reply *rep;
NTSTATUS status;
uint32_t result=0, reason=0;
+ uint32_t context_id;
/* handle any authentication that is being requested */
if (!dcesrv_auth_alter(call)) {
/* TODO: work out the right reject code */
- return dcesrv_bind_nak(call, 0);
+ result = DCERPC_BIND_PROVIDER_REJECT;
+ reason = DCERPC_BIND_REASON_ASYNTAX;
+ }
+
+ context_id = call->pkt.u.alter.ctx_list[0].context_id;
+
+ /* see if they are asking for a new interface */
+ if (result == 0 &&
+ dcesrv_find_context(call->conn, context_id) == NULL) {
+ status = dcesrv_alter_new_context(call, context_id);
+ if (!NT_STATUS_IS_OK(status)) {
+ result = DCERPC_BIND_PROVIDER_REJECT;
+ reason = DCERPC_BIND_REASON_ASYNTAX;
+ }
}
- /* setup a alter_ack */
+ /* setup a alter_resp */
dcesrv_init_hdr(&pkt);
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
@@ -623,7 +687,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
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.assoc_group_id = call->pkt.u.alter.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);
@@ -635,6 +699,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
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);
+ pkt.u.alter_resp.secondary_address = "";
if (!dcesrv_auth_alter_ack(call, &pkt)) {
return dcesrv_bind_nak(call, 0);
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 71332b557d..91b579b9e4 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -204,9 +204,13 @@ BOOL dcesrv_auth_alter(struct dcesrv_call_state *call)
struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
- /* We can't work without an existing gensec state, and an new blob to feed it */
- if (!dce_conn->auth_state.gensec_security ||
- pkt->u.alter.auth_info.length == 0) {
+ /* on a pure interface change there is no auth blob */
+ if (pkt->u.alter.auth_info.length == 0) {
+ return True;
+ }
+
+ /* We can't work without an existing gensec state */
+ if (!dce_conn->auth_state.gensec_security) {
return False;
}
@@ -235,6 +239,11 @@ BOOL dcesrv_auth_alter_ack(struct dcesrv_call_state *call, struct dcerpc_packet
struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
+ /* on a pure interface change there is no auth blob */
+ if (pkt->u.alter.auth_info.length == 0) {
+ return True;
+ }
+
if (!call->conn->auth_state.gensec_security) {
return False;
}