• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/libcli/security/
1/*
2   Unix SMB/CIFS implementation.
3
4   security access checking routines
5
6   Copyright (C) Andrew Tridgell 2004
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#include "includes.h"
23#include "libcli/security/security.h"
24
25
26/*
27  perform a SEC_FLAG_MAXIMUM_ALLOWED access check
28*/
29static uint32_t access_check_max_allowed(const struct security_descriptor *sd,
30					 const struct security_token *token)
31{
32	uint32_t denied = 0, granted = 0;
33	unsigned i;
34
35	if (security_token_has_sid(token, sd->owner_sid)) {
36		granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE;
37	} else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
38		granted |= SEC_STD_DELETE;
39	}
40
41	if (sd->dacl == NULL) {
42		return granted & ~denied;
43	}
44
45	for (i = 0;i<sd->dacl->num_aces; i++) {
46		struct security_ace *ace = &sd->dacl->aces[i];
47
48		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
49			continue;
50		}
51
52		if (!security_token_has_sid(token, &ace->trustee)) {
53			continue;
54		}
55
56		switch (ace->type) {
57		case SEC_ACE_TYPE_ACCESS_ALLOWED:
58			granted |= ace->access_mask;
59			break;
60		case SEC_ACE_TYPE_ACCESS_DENIED:
61		case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
62			denied |= ace->access_mask;
63			break;
64		default:	/* Other ACE types not handled/supported */
65			break;
66		}
67	}
68
69	return granted & ~denied;
70}
71
72static const struct GUID *get_ace_object_type(struct security_ace *ace)
73{
74        struct GUID *type;
75
76        if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT)
77                type = &ace->object.object.type.type;
78        else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT)
79                type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */
80        else
81                type = NULL;
82
83        return type;
84
85}
86
87/*
88  the main entry point for access checking.
89*/
90NTSTATUS sec_access_check(const struct security_descriptor *sd,
91			  const struct security_token *token,
92			  uint32_t access_desired,
93			  uint32_t *access_granted)
94{
95	int i;
96	uint32_t bits_remaining;
97
98	*access_granted = access_desired;
99	bits_remaining = access_desired;
100
101	/* handle the maximum allowed flag */
102	if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
103		access_desired |= access_check_max_allowed(sd, token);
104		access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
105		*access_granted = access_desired;
106		bits_remaining = access_desired & ~SEC_STD_DELETE;
107	}
108
109	if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
110		if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
111			bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
112		} else {
113			return NT_STATUS_PRIVILEGE_NOT_HELD;
114		}
115	}
116
117	/* a NULL dacl allows access */
118	if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
119		*access_granted = access_desired;
120		return NT_STATUS_OK;
121	}
122
123	/* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
124	if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
125	    security_token_has_sid(token, sd->owner_sid)) {
126		bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
127	}
128	if ((bits_remaining & SEC_STD_DELETE) &&
129	    security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
130		bits_remaining &= ~SEC_STD_DELETE;
131	}
132
133	if (sd->dacl == NULL) {
134		goto done;
135	}
136
137	/* check each ace in turn. */
138	for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
139		struct security_ace *ace = &sd->dacl->aces[i];
140
141		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
142			continue;
143		}
144
145		if (!security_token_has_sid(token, &ace->trustee)) {
146			continue;
147		}
148
149		switch (ace->type) {
150		case SEC_ACE_TYPE_ACCESS_ALLOWED:
151			bits_remaining &= ~ace->access_mask;
152			break;
153		case SEC_ACE_TYPE_ACCESS_DENIED:
154		case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
155			if (bits_remaining & ace->access_mask) {
156				return NT_STATUS_ACCESS_DENIED;
157			}
158			break;
159		default:	/* Other ACE types not handled/supported */
160			break;
161		}
162	}
163
164done:
165	if (bits_remaining != 0) {
166		return NT_STATUS_ACCESS_DENIED;
167	}
168
169	return NT_STATUS_OK;
170}
171
172/* modified access check for the purposes of DS security
173 * Lots of code duplication, it will ve united in just one
174 * function eventually */
175
176NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
177			     const struct security_token *token,
178			     uint32_t access_desired,
179			     uint32_t *access_granted,
180			     struct object_tree *tree)
181{
182        int i;
183        uint32_t bits_remaining;
184        struct object_tree *node;
185        struct GUID *type;
186
187        *access_granted = access_desired;
188        bits_remaining = access_desired;
189
190        /* handle the maximum allowed flag */
191        if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
192                access_desired |= access_check_max_allowed(sd, token);
193                access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
194                *access_granted = access_desired;
195                bits_remaining = access_desired & ~SEC_STD_DELETE;
196        }
197
198        if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
199                if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
200                        bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
201                } else {
202                        return NT_STATUS_PRIVILEGE_NOT_HELD;
203                }
204        }
205
206        /* a NULL dacl allows access */
207        if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
208		*access_granted = access_desired;
209                return NT_STATUS_OK;
210        }
211
212        /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */
213        if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) &&
214            security_token_has_sid(token, sd->owner_sid)) {
215                bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE);
216        }
217        if ((bits_remaining & SEC_STD_DELETE) &&
218            security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
219                bits_remaining &= ~SEC_STD_DELETE;
220        }
221
222        if (sd->dacl == NULL) {
223                goto done;
224        }
225
226        /* check each ace in turn. */
227        for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
228		struct security_ace *ace = &sd->dacl->aces[i];
229
230                if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
231                        continue;
232                }
233
234                if (!security_token_has_sid(token, &ace->trustee)) {
235                        continue;
236                }
237
238                switch (ace->type) {
239                case SEC_ACE_TYPE_ACCESS_ALLOWED:
240                        if (tree)
241                                object_tree_modify_access(tree, ace->access_mask);
242
243                        bits_remaining &= ~ace->access_mask;
244                        break;
245                case SEC_ACE_TYPE_ACCESS_DENIED:
246                        if (bits_remaining & ace->access_mask) {
247                                return NT_STATUS_ACCESS_DENIED;
248                        }
249                        break;
250                case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
251                case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
252                        /* check only in case we have provided a tree,
253                         * the ACE has an object type and that type
254                         * is in the tree                           */
255                        type = get_ace_object_type(ace);
256
257                        if (!tree)
258                                continue;
259
260                        if (!type)
261                                node = tree;
262                        else
263                                if (!(node = get_object_tree_by_GUID(tree, type)))
264                                        continue;
265
266                        if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT){
267                                object_tree_modify_access(node, ace->access_mask);
268                        }
269                        else {
270                                if (node->remaining_access & ace->access_mask){
271                                        return NT_STATUS_ACCESS_DENIED;
272                                }
273                        }
274                        break;
275                default:        /* Other ACE types not handled/supported */
276                        break;
277                }
278        }
279
280done:
281        if (bits_remaining != 0) {
282                return NT_STATUS_ACCESS_DENIED;
283        }
284
285        return NT_STATUS_OK;
286}
287
288
289
290
291