~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/lib/secace.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
 *  Unix SMB/Netbios implementation.
3
 
 *  SEC_ACE handling functions
4
 
 *  Copyright (C) Andrew Tridgell              1992-1998,
5
 
 *  Copyright (C) Jeremy R. Allison            1995-2003.
6
 
 *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7
 
 *  Copyright (C) Paul Ashton                  1997-1998.
8
 
 *  
9
 
 *  This program is free software; you can redistribute it and/or modify
10
 
 *  it under the terms of the GNU General Public License as published by
11
 
 *  the Free Software Foundation; either version 2 of the License, or
12
 
 *  (at your option) any later version.
13
 
 *  
14
 
 *  This program is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *  
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this program; if not, write to the Free Software
21
 
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 
 */
23
 
 
24
 
#include "includes.h"
25
 
 
26
 
/*******************************************************************
27
 
 Check if ACE has OBJECT type.
28
 
********************************************************************/
29
 
 
30
 
BOOL sec_ace_object(uint8 type)
31
 
{
32
 
        if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
33
 
            type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
34
 
            type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
35
 
            type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
36
 
                return True;
37
 
        }
38
 
        return False;
39
 
}
40
 
 
41
 
/*******************************************************************
42
 
 copy a SEC_ACE structure.
43
 
********************************************************************/
44
 
void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
45
 
{
46
 
        ace_dest->type  = ace_src->type;
47
 
        ace_dest->flags = ace_src->flags;
48
 
        ace_dest->size  = ace_src->size;
49
 
        ace_dest->info.mask = ace_src->info.mask;
50
 
        ace_dest->obj_flags = ace_src->obj_flags;
51
 
        memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, sizeof(struct uuid));
52
 
        memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, sizeof(struct uuid));
53
 
        sid_copy(&ace_dest->trustee, &ace_src->trustee);
54
 
}
55
 
 
56
 
/*******************************************************************
57
 
 Sets up a SEC_ACE structure.
58
 
********************************************************************/
59
 
 
60
 
void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
61
 
{
62
 
        t->type = type;
63
 
        t->flags = flag;
64
 
        t->size = sid_size(sid) + 8;
65
 
        t->info = mask;
66
 
 
67
 
        ZERO_STRUCTP(&t->trustee);
68
 
        sid_copy(&t->trustee, sid);
69
 
}
70
 
 
71
 
/*******************************************************************
72
 
 adds new SID with its permissions to ACE list
73
 
********************************************************************/
74
 
 
75
 
NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask)
76
 
{
77
 
        unsigned int i = 0;
78
 
        
79
 
        if (!ctx || !pp_new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
80
 
 
81
 
        *num += 1;
82
 
        
83
 
        if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0)
84
 
                return NT_STATUS_NO_MEMORY;
85
 
 
86
 
        for (i = 0; i < *num - 1; i ++)
87
 
                sec_ace_copy(&(*pp_new)[i], &old[i]);
88
 
 
89
 
        (*pp_new)[i].type  = 0;
90
 
        (*pp_new)[i].flags = 0;
91
 
        (*pp_new)[i].size  = SEC_ACE_HEADER_SIZE + sid_size(sid);
92
 
        (*pp_new)[i].info.mask = mask;
93
 
        sid_copy(&(*pp_new)[i].trustee, sid);
94
 
        return NT_STATUS_OK;
95
 
}
96
 
 
97
 
/*******************************************************************
98
 
  modify SID's permissions at ACL 
99
 
********************************************************************/
100
 
 
101
 
NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
102
 
{
103
 
        unsigned int i = 0;
104
 
 
105
 
        if (!ace || !sid)  return NT_STATUS_INVALID_PARAMETER;
106
 
 
107
 
        for (i = 0; i < num; i ++) {
108
 
                if (sid_compare(&ace[i].trustee, sid) == 0) {
109
 
                        ace[i].info.mask = mask;
110
 
                        return NT_STATUS_OK;
111
 
                }
112
 
        }
113
 
        return NT_STATUS_NOT_FOUND;
114
 
}
115
 
 
116
 
/*******************************************************************
117
 
 delete SID from ACL
118
 
********************************************************************/
119
 
 
120
 
NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, uint32 *num, DOM_SID *sid)
121
 
{
122
 
        unsigned int i     = 0;
123
 
        unsigned int n_del = 0;
124
 
 
125
 
        if (!ctx || !pp_new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
126
 
 
127
 
        if((pp_new[0] = TALLOC_ZERO_ARRAY(ctx, SEC_ACE, *num )) == 0)
128
 
                return NT_STATUS_NO_MEMORY;
129
 
 
130
 
        for (i = 0; i < *num; i ++) {
131
 
                if (sid_compare(&old[i].trustee, sid) != 0)
132
 
                        sec_ace_copy(&(*pp_new)[i], &old[i]);
133
 
                else
134
 
                        n_del ++;
135
 
        }
136
 
        if (n_del == 0)
137
 
                return NT_STATUS_NOT_FOUND;
138
 
        else {
139
 
                *num -= n_del;
140
 
                return NT_STATUS_OK;
141
 
        }
142
 
}
143
 
 
144
 
/*******************************************************************
145
 
 Compares two SEC_ACE structures
146
 
********************************************************************/
147
 
 
148
 
BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
149
 
{
150
 
        /* Trivial case */
151
 
 
152
 
        if (!s1 && !s2) {
153
 
                return True;
154
 
        }
155
 
 
156
 
        if (!s1 || !s2) {
157
 
                return False;
158
 
        }
159
 
 
160
 
        /* Check top level stuff */
161
 
 
162
 
        if (s1->type != s2->type || s1->flags != s2->flags ||
163
 
            s1->info.mask != s2->info.mask) {
164
 
                return False;
165
 
        }
166
 
 
167
 
        /* Check SID */
168
 
 
169
 
        if (!sid_equal(&s1->trustee, &s2->trustee)) {
170
 
                return False;
171
 
        }
172
 
 
173
 
        return True;
174
 
}
175
 
 
176
 
int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
177
 
{
178
 
        int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
179
 
        int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
180
 
 
181
 
        if (a1_inh == a2_inh)
182
 
                return 0;
183
 
 
184
 
        if (!a1_inh && a2_inh)
185
 
                return -1;
186
 
        return 1;
187
 
}
188
 
 
189
 
/*******************************************************************
190
 
  Comparison function to apply the order explained below in a group.
191
 
*******************************************************************/
192
 
 
193
 
int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
194
 
{
195
 
        if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
196
 
                                (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
197
 
                return -1;
198
 
 
199
 
        if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
200
 
                                (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
201
 
                return 1;
202
 
 
203
 
        /* Both access denied or access allowed. */
204
 
 
205
 
        /* 1. ACEs that apply to the object itself */
206
 
 
207
 
        if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
208
 
                        (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
209
 
                return -1;
210
 
        else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
211
 
                        (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
212
 
                return 1;
213
 
 
214
 
        /* 2. ACEs that apply to a subobject of the object, such as
215
 
         * a property set or property. */
216
 
 
217
 
        if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
218
 
                        !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
219
 
                return -1;
220
 
        else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
221
 
                        !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
222
 
                return 1;
223
 
 
224
 
        return 0;
225
 
}
226
 
 
227
 
/*******************************************************************
228
 
 Functions to convert a SEC_DESC ACE DACL list into canonical order.
229
 
 JRA.
230
 
 
231
 
--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
232
 
 
233
 
The following describes the preferred order:
234
 
 
235
 
 To ensure that noninherited ACEs have precedence over inherited ACEs,
236
 
 place all noninherited ACEs in a group before any inherited ACEs.
237
 
 This ordering ensures, for example, that a noninherited access-denied ACE
238
 
 is enforced regardless of any inherited ACE that allows access.
239
 
 
240
 
 Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
241
 
        1. Access-denied ACEs that apply to the object itself
242
 
        2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
243
 
        3. Access-allowed ACEs that apply to the object itself
244
 
        4. Access-allowed ACEs that apply to a subobject of the object"
245
 
 
246
 
********************************************************************/
247
 
 
248
 
void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
249
 
{
250
 
        unsigned int i;
251
 
 
252
 
        if (!srclist || num_aces == 0)
253
 
                return;
254
 
 
255
 
        /* Sort so that non-inherited ACE's come first. */
256
 
        qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
257
 
 
258
 
        /* Find the boundary between non-inherited ACEs. */
259
 
        for (i = 0; i < num_aces; i++ ) {
260
 
                SEC_ACE *curr_ace = &srclist[i];
261
 
 
262
 
                if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
263
 
                        break;
264
 
        }
265
 
 
266
 
        /* i now points at entry number of the first inherited ACE. */
267
 
 
268
 
        /* Sort the non-inherited ACEs. */
269
 
        if (i)
270
 
                qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
271
 
 
272
 
        /* Now sort the inherited ACEs. */
273
 
        if (num_aces - i)
274
 
                qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
275
 
}
276
 
 
277
 
/*******************************************************************
278
 
 Check if this ACE has a SID in common with the token.
279
 
********************************************************************/
280
 
 
281
 
BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
282
 
{
283
 
        size_t i;
284
 
 
285
 
        for (i = 0; i < token->num_sids; i++) {
286
 
                if (sid_equal(&ace->trustee, &token->user_sids[i]))
287
 
                        return True;
288
 
        }
289
 
 
290
 
        return False;
291
 
}