s4-rpcserver: added support for shared handles
authorAndrew Tridgell <tridge@samba.org>
Tue, 22 Sep 2009 07:18:03 +0000 (00:18 -0700)
committerAndrew Tridgell <tridge@samba.org>
Wed, 23 Sep 2009 00:10:05 +0000 (17:10 -0700)
This supports shared RPC handles across connections on all RPC
interfaces.

It turns out that w2k3 and w2k8 don't actually support this on all
pipes. We need to test which pipes we should enable this on.

source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcerpc_server.h
source4/rpc_server/handles.c

index a70c920f75ba66981bce42b12ded25885cfaec92..df0c2e73453a2f3106ea80ebfed5c684765112d4 100644 (file)
@@ -74,6 +74,17 @@ static struct dcesrv_assoc_group *dcesrv_assoc_group_reference(TALLOC_CTX *mem_c
        return talloc_reference(mem_ctx, assoc_group);
 }
 
+static int dcesrv_assoc_group_destructor(struct dcesrv_assoc_group *assoc_group)
+{
+       int ret;
+       ret = idr_remove(assoc_group->dce_ctx->assoc_groups_idr, assoc_group->id);
+       if (ret != 0) {
+               DEBUG(0,(__location__ ": Failed to remove assoc_group 0x%08x\n",
+                        assoc_group->id));
+       }
+       return 0;
+}
+
 /*
   allocate a new association group
  */
@@ -96,6 +107,10 @@ static struct dcesrv_assoc_group *dcesrv_assoc_group_new(TALLOC_CTX *mem_ctx,
        }
 
        assoc_group->id = id;
+       assoc_group->dce_ctx = dce_ctx;
+
+       talloc_set_destructor(assoc_group, dcesrv_assoc_group_destructor);
+
        return assoc_group;
 }
 
index a64b01fdc59c72b0506dc9e9976e9ae16d3b4f99..d273f6eca996fdf632c2fd04c819afeaee4110d0 100644 (file)
@@ -136,8 +136,10 @@ struct dcesrv_call_state {
 /* a dcerpc handle in internal format */
 struct dcesrv_handle {
        struct dcesrv_handle *next, *prev;
-       struct dcesrv_connection_context *context;
+       struct dcesrv_assoc_group *assoc_group;
        struct policy_handle wire_handle;
+       struct dom_sid *sid;
+       const struct dcesrv_interface *iface;
        void *data;
 };
 
@@ -255,6 +257,9 @@ struct dcesrv_assoc_group {
        
        /* list of handles in this association group */
        struct dcesrv_handle *handles;
+
+       /* parent context */
+       struct dcesrv_context *dce_ctx;
 };
 
 /* server-wide context information for the dcerpc server */
index 74b0ddc82e6f3f61ecd5f7ad13478bced084b9af..085703b3d4f02a37204abfc7af9f8c8918de32b7 100644 (file)
 #include "includes.h"
 #include "../lib/util/dlinklist.h"
 #include "rpc_server/dcerpc_server.h"
+#include "libcli/security/dom_sid.h"
+#include "auth/session.h"
 
 /*
   destroy a rpc handle
 */
 static int dcesrv_handle_destructor(struct dcesrv_handle *h)
 {
-       DLIST_REMOVE(h->context->assoc_group->handles, h);
+       DLIST_REMOVE(h->assoc_group->handles, h);
        return 0;
 }
 
@@ -37,17 +39,25 @@ static int dcesrv_handle_destructor(struct dcesrv_handle *h)
   allocate a new rpc handle
 */
 _PUBLIC_ struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_context *context, 
-                                       uint8_t handle_type)
+                                                uint8_t handle_type)
 {
        struct dcesrv_handle *h;
+       struct dom_sid *sid;
 
-       h = talloc(context, struct dcesrv_handle);
+       sid = context->conn->auth_state.session_info->security_token->user_sid;
+
+       h = talloc(context->assoc_group, struct dcesrv_handle);
        if (!h) {
                return NULL;
        }
        h->data = NULL;
-       h->context = context;
-
+       h->sid = dom_sid_dup(h, sid);
+       if (h->sid == NULL) {
+               talloc_free(h);
+               return NULL;
+       }
+       h->assoc_group = context->assoc_group;
+       h->iface = context->iface;
        h->wire_handle.handle_type = handle_type;
        h->wire_handle.uuid = GUID_random();
        
@@ -68,6 +78,9 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(
                                          uint8_t handle_type)
 {
        struct dcesrv_handle *h;
+       struct dom_sid *sid;
+
+       sid = context->conn->auth_state.session_info->security_token->user_sid;
 
        if (policy_handle_empty(p)) {
                /* TODO: we should probably return a NULL handle here */
@@ -83,6 +96,16 @@ _PUBLIC_ struct dcesrv_handle *dcesrv_handle_fetch(
                                         p->handle_type, handle_type));
                                return NULL;
                        }
+                       if (!dom_sid_equal(h->sid, sid)) {
+                               DEBUG(0,(__location__ ": Attempt to use invalid sid %s - %s\n",
+                                        dom_sid_string(context, h->sid),
+                                        dom_sid_string(context, sid)));
+                               return NULL;
+                       }
+                       if (h->iface != context->iface) {
+                               DEBUG(0,(__location__ ": Attempt to use invalid iface\n"));
+                               return NULL;
+                       }
                        return h;
                }
        }