s4:rpc_server: add dcesrv_iface_state_{store,find}_{assoc,conn}() helpers
authorStefan Metzmacher <metze@samba.org>
Mon, 10 Dec 2018 21:41:31 +0000 (22:41 +0100)
committerJeremy Allison <jra@samba.org>
Sat, 12 Jan 2019 02:13:38 +0000 (03:13 +0100)
They can be used instead of
dcesrv_connection_context->private_data and
dcesrv_assoc_group->proxied_id.

This is the first step to hide internal details of
the core dcerpc server from the interface implementations.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=7113
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11892

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source4/rpc_server/dcerpc_server.h
source4/rpc_server/handles.c

index 5578830..ad97b0e 100644 (file)
@@ -38,6 +38,7 @@ struct dcesrv_connection;
 struct dcesrv_call_state;
 struct dcesrv_auth;
 struct dcesrv_connection_context;
+struct dcesrv_iface_state;
 
 struct dcesrv_interface {
        const char *name;
@@ -353,6 +354,11 @@ struct dcesrv_assoc_group {
        /* list of handles in this association group */
        struct dcesrv_handle *handles;
 
+       /*
+        * list of iface states per assoc/conn
+        */
+       struct dcesrv_iface_state *iface_states;
+
        /* parent context */
        struct dcesrv_context *dce_ctx;
 
@@ -536,4 +542,36 @@ _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state
 _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
                                                      const struct dcesrv_interface *iface);
 
+_PUBLIC_ NTSTATUS _dcesrv_iface_state_store_assoc(
+               struct dcesrv_call_state *call,
+               uint64_t magic,
+               void *ptr,
+               const char *location);
+#define dcesrv_iface_state_store_assoc(call, magic, ptr) \
+       _dcesrv_iface_state_store_assoc((call), (magic), (ptr), \
+                                       __location__)
+_PUBLIC_ void *_dcesrv_iface_state_find_assoc(
+               struct dcesrv_call_state *call,
+               uint64_t magic);
+#define dcesrv_iface_state_find_assoc(call, magic, _type) \
+       talloc_get_type( \
+               _dcesrv_iface_state_find_assoc((call), (magic)), \
+               _type)
+
+_PUBLIC_ NTSTATUS _dcesrv_iface_state_store_conn(
+               struct dcesrv_call_state *call,
+               uint64_t magic,
+               void *_pptr,
+               const char *location);
+#define dcesrv_iface_state_store_conn(call, magic, ptr) \
+       _dcesrv_iface_state_store_conn((call), (magic), (ptr), \
+                                       __location__)
+_PUBLIC_ void *_dcesrv_iface_state_find_conn(
+               struct dcesrv_call_state *call,
+               uint64_t magic);
+#define dcesrv_iface_state_find_conn(call, magic, _type) \
+       talloc_get_type( \
+               _dcesrv_iface_state_find_conn((call), (magic)), \
+               _type)
+
 #endif /* SAMBA_DCERPC_SERVER_H */
index 68bacef..91bfaf9 100644 (file)
@@ -137,3 +137,226 @@ struct dcesrv_handle *dcesrv_handle_lookup(struct dcesrv_call_state *call,
 
        return NULL;
 }
+
+struct dcesrv_iface_state {
+       struct dcesrv_iface_state *prev, *next;
+       struct dcesrv_assoc_group *assoc;
+       const struct dcesrv_interface *iface;
+       struct dom_sid owner;
+       const struct dcesrv_connection *conn;
+       const struct dcesrv_auth *auth;
+       const struct dcesrv_connection_context *pres;
+       uint64_t magic;
+       void *ptr;
+       const char *location;
+};
+
+static int dcesrv_iface_state_destructor(struct dcesrv_iface_state *istate)
+{
+       DLIST_REMOVE(istate->assoc->iface_states, istate);
+       return 0;
+}
+
+static void *dcesrv_iface_state_find(struct dcesrv_assoc_group *assoc,
+                       const struct dcesrv_interface *iface,
+                       const struct dom_sid *owner,
+                       const struct dcesrv_connection *conn,
+                       const struct dcesrv_auth *auth,
+                       const struct dcesrv_connection_context *pres,
+                       uint64_t magic,
+                       const void *ptr)
+{
+       struct dcesrv_iface_state *cur = NULL;
+
+       for (cur = assoc->iface_states; cur != NULL; cur = cur->next) {
+               bool match;
+
+               SMB_ASSERT(cur->assoc == assoc);
+
+               if (cur->ptr == ptr) {
+                       return cur->ptr;
+               }
+
+               if (cur->iface != iface) {
+                       continue;
+               }
+
+               match = dom_sid_equal(&cur->owner, owner);
+               if (!match) {
+                       continue;
+               }
+
+               if (cur->conn != conn) {
+                       continue;
+               }
+
+               if (cur->auth != auth) {
+                       continue;
+               }
+
+               if (cur->pres != pres) {
+                       continue;
+               }
+
+               if (cur->magic != magic) {
+                       continue;
+               }
+
+               return cur->ptr;
+       }
+
+       return NULL;
+}
+
+static NTSTATUS dcesrv_iface_state_store(struct dcesrv_assoc_group *assoc,
+                               const struct dcesrv_interface *iface,
+                               const struct dom_sid *owner,
+                               const struct dcesrv_connection *conn,
+                               const struct dcesrv_auth *auth,
+                               const struct dcesrv_connection_context *pres,
+                               uint64_t magic,
+                               TALLOC_CTX *mem_ctx,
+                               void *ptr,
+                               const char *location)
+{
+       struct dcesrv_iface_state *istate = NULL;
+       void *optr = NULL;
+
+       optr = dcesrv_iface_state_find(assoc,
+                                      iface,
+                                      owner,
+                                      conn,
+                                      auth,
+                                      pres,
+                                      magic,
+                                      ptr);
+       if (optr != NULL) {
+               return NT_STATUS_OBJECTID_EXISTS;
+       }
+
+       istate = talloc_zero(ptr, struct dcesrv_iface_state);
+       if (istate == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *istate = (struct dcesrv_iface_state) {
+               .assoc = assoc,
+               .iface = iface,
+               .owner = *owner,
+               .conn  = conn,
+               .auth  = auth,
+               .pres  = pres,
+               .magic = magic,
+               .location = location,
+       };
+
+       istate->ptr = talloc_steal(mem_ctx, ptr);
+
+       talloc_set_destructor(istate, dcesrv_iface_state_destructor);
+
+       DLIST_ADD_END(assoc->iface_states, istate);
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS _dcesrv_iface_state_store_assoc(struct dcesrv_call_state *call,
+                               uint64_t magic,
+                               void *ptr,
+                               const char *location)
+{
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(call);
+       const struct dom_sid *owner =
+               &session_info->security_token->sids[0];
+       NTSTATUS status;
+
+       status = dcesrv_iface_state_store(call->conn->assoc_group,
+                                         call->context->iface,
+                                         owner,
+                                         NULL, /* conn */
+                                         NULL, /* auth */
+                                         NULL, /* pres */
+                                         magic,
+                                         call->conn->assoc_group, /* mem_ctx */
+                                         ptr,
+                                         location);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+void *_dcesrv_iface_state_find_assoc(struct dcesrv_call_state *call, uint64_t magic)
+{
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(call);
+       const struct dom_sid *owner =
+               &session_info->security_token->sids[0];
+       void *ptr = NULL;
+
+       ptr = dcesrv_iface_state_find(call->conn->assoc_group,
+                                     call->context->iface,
+                                     owner,
+                                     NULL, /* conn */
+                                     NULL, /* auth */
+                                     NULL, /* pres */
+                                     magic,
+                                     NULL); /* ptr */
+       if (ptr == NULL) {
+               return NULL;
+       }
+
+       return ptr;
+}
+
+NTSTATUS _dcesrv_iface_state_store_conn(struct dcesrv_call_state *call,
+                                       uint64_t magic,
+                                       void *ptr,
+                                       const char *location)
+{
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(call);
+       const struct dom_sid *owner =
+               &session_info->security_token->sids[0];
+       NTSTATUS status;
+
+       status = dcesrv_iface_state_store(call->conn->assoc_group,
+                                         call->context->iface,
+                                         owner,
+                                         call->conn,
+                                         call->auth_state,
+                                         call->context,
+                                         magic,
+                                         call->conn, /* mem_ctx */
+                                         ptr,
+                                         location);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+void *_dcesrv_iface_state_find_conn(struct dcesrv_call_state *call, uint64_t magic)
+{
+       struct auth_session_info *session_info =
+               dcesrv_call_session_info(call);
+       const struct dom_sid *owner =
+               &session_info->security_token->sids[0];
+       void *ptr = NULL;
+
+       ptr = dcesrv_iface_state_find(call->conn->assoc_group,
+                                     call->context->iface,
+                                     owner,
+                                     call->conn,
+                                     call->auth_state,
+                                     call->context,
+                                     magic,
+                                     NULL); /* ptr */
+       if (ptr == NULL) {
+               return NULL;
+       }
+
+       return ptr;
+}