s3: Fix some DEBUG messages
[ira/wip.git] / source3 / rpc_server / srv_lsa_hnd.c
index 839833ce542fd839c4ffb8d7180b8c30cc8f845c..4348fb8d4a7b115b15af60ec40a919120c90b887 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
+/*
+ * Handle database - stored per pipe.
+ */
+
+struct policy {
+       struct policy *next, *prev;
+
+       struct policy_handle pol_hnd;
+
+       uint32_t access_granted;
+
+       void *data_ptr;
+};
+
+struct handle_list {
+       struct policy *Policy;  /* List of policies. */
+       size_t count;                   /* Current number of handles. */
+       size_t pipe_ref_count;  /* Number of pipe handles referring to this list. */
+};
+
 /* This is the max handles across all instances of a pipe name. */
 #ifndef MAX_OPEN_POLS
-#define MAX_OPEN_POLS 1024
+#define MAX_OPEN_POLS 2048
 #endif
 
 /****************************************************************************
  pipe is open. JRA.
 ****************************************************************************/
 
-static bool is_samr_lsa_pipe(const char *pipe_name)
+static bool is_samr_lsa_pipe(const struct ndr_syntax_id *syntax)
 {
-       return (strstr(pipe_name, "samr") || strstr(pipe_name, "lsa"));
+       return (ndr_syntax_id_equal(syntax, &ndr_table_samr.syntax_id)
+               || ndr_syntax_id_equal(syntax, &ndr_table_lsarpc.syntax_id));
+}
+
+size_t num_pipe_handles(struct handle_list *list)
+{
+       if (list == NULL) {
+               return 0;
+       }
+       return list->count;
 }
 
 /****************************************************************************
@@ -44,40 +73,45 @@ static bool is_samr_lsa_pipe(const char *pipe_name)
  pipes of the same name.
 ****************************************************************************/
 
-bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name)
+bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax)
 {
-       pipes_struct *plist = get_first_internal_pipe();
-       struct handle_list *hl = NULL;
-
-       for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) {
-               if (strequal( plist->name, pipe_name) ||
-                               (is_samr_lsa_pipe(plist->name) && is_samr_lsa_pipe(pipe_name))) {
-                       if (!plist->pipe_handles) {
-                               char *msg;
-                               if (asprintf(&msg, "init_pipe_handles: NULL "
-                                                "pipe_handle pointer in pipe %s",
-                                                pipe_name) != -1) {
-                                       smb_panic(msg);
-                               } else {
-                                       smb_panic("init_pipe_handle_list");
-                               }
-                       }
-                       hl = plist->pipe_handles;
+       pipes_struct *plist;
+       struct handle_list *hl;
+
+       for (plist = get_first_internal_pipe();
+            plist;
+            plist = get_next_internal_pipe(plist)) {
+               if (ndr_syntax_id_equal(syntax, &plist->syntax)) {
+                       break;
+               }
+               if (is_samr_lsa_pipe(&plist->syntax)
+                   && is_samr_lsa_pipe(syntax)) {
+                       /*
+                        * samr and lsa share a handle space (same process
+                        * under Windows?)
+                        */
                        break;
                }
        }
 
-       if (!hl) {
+       if (plist != NULL) {
+               hl = plist->pipe_handles;
+               if (hl == NULL) {
+                       return false;
+               }
+       } else {
                /*
-                * No handle list for this pipe (first open of pipe).
-                * Create list.
+                * First open, we have to create the handle list
                 */
-
-               if ((hl = SMB_MALLOC_P(struct handle_list)) == NULL)
-                       return False;
+               hl = SMB_MALLOC_P(struct handle_list);
+               if (hl == NULL) {
+                       return false;
+               }
                ZERO_STRUCTP(hl);
 
-               DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name ));
+               DEBUG(10,("init_pipe_handle_list: created handle list for "
+                         "pipe %s\n",
+                         get_pipe_name_from_syntax(talloc_tos(), syntax)));
        }
 
        /*
@@ -92,17 +126,24 @@ bool init_pipe_handle_list(pipes_struct *p, const char *pipe_name)
 
        p->pipe_handles = hl;
 
-       DEBUG(10,("init_pipe_handles: pipe_handles ref count = %lu for pipe %s\n",
-                 (unsigned long)p->pipe_handles->pipe_ref_count, pipe_name ));
+       DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for "
+                 "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count,
+                 get_pipe_name_from_syntax(talloc_tos(), syntax)));
 
        return True;
 }
 
 /****************************************************************************
   find first available policy slot.  creates a policy handle for you.
+
+  If "data_ptr" is given, this must be a talloc'ed object, create_policy_hnd
+  talloc_moves this into the handle. If the policy_hnd is closed,
+  data_ptr is TALLOC_FREE()'ed
 ****************************************************************************/
 
-bool create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *), void *data_ptr)
+static struct policy *create_policy_hnd_internal(pipes_struct *p,
+                                                struct policy_handle *hnd,
+                                                void *data_ptr)
 {
        static uint32 pol_hnd_low  = 0;
        static uint32 pol_hnd_high = 0;
@@ -113,19 +154,18 @@ bool create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
        if (p->pipe_handles->count > MAX_OPEN_POLS) {
                DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
                                (int)p->pipe_handles->count));
-               return False;
+               return NULL;
        }
 
-       pol = SMB_MALLOC_P(struct policy);
+       pol = TALLOC_ZERO_P(NULL, struct policy);
        if (!pol) {
                DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
-               return False;
+               return NULL;
        }
 
-       ZERO_STRUCTP(pol);
-
-       pol->data_ptr = data_ptr;
-       pol->free_fn = free_fn;
+       if (data_ptr != NULL) {
+               pol->data_ptr = talloc_move(pol, &data_ptr);
+       }
 
        pol_hnd_low++;
        if (pol_hnd_low == 0)
@@ -151,14 +191,22 @@ bool create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
        DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
        dump_data(4, (uint8 *)hnd, sizeof(*hnd));
 
-       return True;
+       return pol;
+}
+
+bool create_policy_hnd(pipes_struct *p, struct policy_handle *hnd,
+                      void *data_ptr)
+{
+       return create_policy_hnd_internal(p, hnd, data_ptr) != NULL;
 }
 
 /****************************************************************************
   find policy by handle - internal version.
 ****************************************************************************/
 
-static struct policy *find_policy_by_hnd_internal(pipes_struct *p, POLICY_HND *hnd, void **data_p)
+static struct policy *find_policy_by_hnd_internal(pipes_struct *p,
+                                                 const struct policy_handle *hnd,
+                                                 void **data_p)
 {
        struct policy *pol;
        size_t i;
@@ -188,7 +236,8 @@ static struct policy *find_policy_by_hnd_internal(pipes_struct *p, POLICY_HND *h
   find policy by handle
 ****************************************************************************/
 
-bool find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p)
+bool find_policy_by_hnd(pipes_struct *p, const struct policy_handle *hnd,
+                       void **data_p)
 {
        return find_policy_by_hnd_internal(p, hnd, data_p) == NULL ? False : True;
 }
@@ -197,7 +246,7 @@ bool find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p)
   Close a policy.
 ****************************************************************************/
 
-bool close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
+bool close_policy_hnd(pipes_struct *p, struct policy_handle *hnd)
 {
        struct policy *pol = find_policy_by_hnd_internal(p, hnd, NULL);
 
@@ -208,16 +257,11 @@ bool close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
 
        DEBUG(3,("Closed policy\n"));
 
-       if (pol->free_fn && pol->data_ptr)
-               (*pol->free_fn)(pol->data_ptr);
-
        p->pipe_handles->count--;
 
        DLIST_REMOVE(p->pipe_handles->Policy, pol);
 
-       ZERO_STRUCTP(pol);
-
-       SAFE_FREE(pol);
+       TALLOC_FREE(pol);
 
        return True;
 }
@@ -241,7 +285,9 @@ void close_policy_by_pipe(pipes_struct *p)
                p->pipe_handles->count = 0;
 
                SAFE_FREE(p->pipe_handles);
-               DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name ));
+               DEBUG(10,("close_policy_by_pipe: deleted handle list for "
+                         "pipe %s\n",
+                         get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
        }
 }
 
@@ -272,3 +318,81 @@ bool pipe_access_check(pipes_struct *p)
 
        return True;
 }
+
+void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd,
+                           uint32_t access_granted, size_t data_size,
+                           const char *type, NTSTATUS *pstatus)
+{
+       struct policy *pol;
+       void *data;
+
+       if (p->pipe_handles->count > MAX_OPEN_POLS) {
+               DEBUG(0, ("policy_handle_create: ERROR: too many handles (%d) "
+                         "on pipe %s.\n", (int)p->pipe_handles->count,
+                         get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
+               *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
+               return NULL;
+       }
+
+       data = talloc_size(talloc_tos(), data_size);
+       if (data == NULL) {
+               *pstatus = NT_STATUS_NO_MEMORY;
+               return NULL;
+       }
+       talloc_set_name_const(data, type);
+
+       pol = create_policy_hnd_internal(p, hnd, data);
+       if (pol == NULL) {
+               TALLOC_FREE(data);
+               *pstatus = NT_STATUS_NO_MEMORY;
+               return NULL;
+       }
+       pol->access_granted = access_granted;
+       *pstatus = NT_STATUS_OK;
+       return data;
+}
+
+void *_policy_handle_find(struct pipes_struct *p,
+                         const struct policy_handle *hnd,
+                         uint32_t access_required,
+                         uint32_t *paccess_granted,
+                         const char *name, const char *location,
+                         NTSTATUS *pstatus)
+{
+       struct policy *pol;
+       void *data;
+
+       pol = find_policy_by_hnd_internal(p, hnd, &data);
+       if (pol == NULL) {
+               *pstatus = NT_STATUS_INVALID_HANDLE;
+               return NULL;
+       }
+       if (strcmp(name, talloc_get_name(data)) != 0) {
+               DEBUG(10, ("expected %s, got %s\n", name,
+                          talloc_get_name(data)));
+               *pstatus = NT_STATUS_INVALID_HANDLE;
+               return NULL;
+       }
+       if ((access_required & pol->access_granted) != access_required) {
+               if (geteuid() == sec_initial_uid()) {
+                       DEBUG(4, ("%s: ACCESS should be DENIED (granted: "
+                                 "%#010x; required: %#010x)\n", location,
+                                 pol->access_granted, access_required));
+                       DEBUGADD(4,("but overwritten by euid == 0\n"));
+                       goto okay;
+               }
+               DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: "
+                        "%#010x)\n", location, pol->access_granted,
+                        access_required));
+               *pstatus = NT_STATUS_ACCESS_DENIED;
+               return NULL;
+       }
+
+ okay:
+       DEBUG(10, ("found handle of type %s\n", talloc_get_name(data)));
+       if (paccess_granted != NULL) {
+               *paccess_granted = pol->access_granted;
+       }
+       *pstatus = NT_STATUS_OK;
+       return data;
+}