85b407913c518d340a03c52f522f6480c737e925
[sfrench/samba-autobuild/.git] / source4 / libcli / security / object_tree.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    security access checking routines
5
6    Copyright (C) Nadezhda Ivanova 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23  *  Description: Contains data handler functions for
24  *               the object tree that must be constructed to perform access checks.
25  *               The object tree is an unbalanced tree of depth 3, indexed by
26  *               object type guid. Perhaps a different data structure
27  *               should be concidered later to improve performance
28  *
29  *  Author: Nadezhda Ivanova
30  */
31 #include "includes.h"
32 #include "libcli/security/security.h"
33 #include "lib/util/dlinklist.h"
34 #include "librpc/ndr/libndr.h"
35
36 /* Adds a new node to the object tree. If attributeSecurityGUID is not zero and
37  * has already been added to the tree, the new node is added as a child of that node
38  * In all other cases as a child of the root
39  */
40
41 struct object_tree * insert_in_object_tree(TALLOC_CTX *mem_ctx,
42                                            const struct GUID *schemaGUIDID,
43                                            const struct GUID *attributeSecurityGUID,
44                                            uint32_t init_access,
45                                            struct object_tree *root)
46 {
47         struct object_tree * parent = NULL;
48         struct object_tree * new_node;
49
50         new_node = talloc(mem_ctx, struct object_tree);
51         if (!new_node)
52                 return NULL;
53         memset(new_node, 0, sizeof(struct object_tree));
54         new_node->remaining_access = init_access;
55
56         if (!root){
57                 memcpy(&new_node->guid, schemaGUIDID, sizeof(struct GUID));
58                 return new_node;
59         }
60
61         if (attributeSecurityGUID && !GUID_all_zero(attributeSecurityGUID)){
62                 parent = get_object_tree_by_GUID(root, attributeSecurityGUID);
63                 memcpy(&new_node->guid, attributeSecurityGUID, sizeof(struct GUID));
64         }
65         else
66                 memcpy(&new_node->guid, schemaGUIDID, sizeof(struct GUID));
67
68         if (!parent)
69                 parent = root;
70
71         new_node->remaining_access = init_access;
72         DLIST_ADD(parent, new_node);
73         return new_node;
74 }
75
76 /* search by GUID */
77 struct object_tree * get_object_tree_by_GUID(struct object_tree *root,
78                                              const struct GUID *guid)
79 {
80         struct object_tree *p;
81         struct object_tree *result = NULL;
82
83         if (!root || GUID_equal(&root->guid, guid))
84                 result = root;
85         else{
86         for (p = root->children; p != NULL; p = p->next)
87                 if ((result = get_object_tree_by_GUID(p, guid)))
88                         break;
89         }
90
91         return result;
92 }
93
94 /* Change the granted access per each ACE */
95
96 void object_tree_modify_access(struct object_tree *root,
97                                uint32_t access_mask)
98 {
99         struct object_tree *p;
100         if (root){
101                 root->remaining_access &= ~access_mask;
102         }
103
104         for (p = root->children; p != NULL; p = p->next)
105                 object_tree_modify_access(p, access_mask);
106 }