~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to libcli/security/secace.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 *  Unix SMB/Netbios implementation.
 
3
 *  struct security_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 3 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, see <http://www.gnu.org/licenses/>.
 
21
 */
 
22
 
 
23
#include "includes.h"
 
24
#include "librpc/gen_ndr/ndr_security.h"
 
25
#include "libcli/security/dom_sid.h"
 
26
 
 
27
#define  SEC_ACE_HEADER_SIZE (2 * sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t))
 
28
 
 
29
/**
 
30
 * Check if ACE has OBJECT type.
 
31
 */
 
32
bool sec_ace_object(uint8_t type)
 
33
{
 
34
        if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
 
35
            type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
 
36
            type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
 
37
            type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
 
38
                return true;
 
39
        }
 
40
        return false;
 
41
}
 
42
 
 
43
/**
 
44
 * copy a struct security_ace structure.
 
45
 */
 
46
void sec_ace_copy(struct security_ace *ace_dest, struct security_ace *ace_src)
 
47
{
 
48
        ace_dest->type  = ace_src->type;
 
49
        ace_dest->flags = ace_src->flags;
 
50
        ace_dest->size  = ace_src->size;
 
51
        ace_dest->access_mask = ace_src->access_mask;
 
52
        ace_dest->object = ace_src->object;
 
53
        ace_dest->trustee = ace_src->trustee;
 
54
}
 
55
 
 
56
/*******************************************************************
 
57
 Sets up a struct security_ace structure.
 
58
********************************************************************/
 
59
 
 
60
void init_sec_ace(struct security_ace *t, const struct dom_sid *sid, enum security_ace_type type,
 
61
                  uint32_t mask, uint8_t flag)
 
62
{
 
63
        t->type = type;
 
64
        t->flags = flag;
 
65
        t->size = ndr_size_dom_sid(sid, NULL, 0) + 8;
 
66
        t->access_mask = mask;
 
67
 
 
68
        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, struct security_ace **pp_new, struct security_ace *old, unsigned *num, struct dom_sid *sid, uint32_t 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, struct security_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  = SEC_ACE_TYPE_ACCESS_ALLOWED;
 
90
        (*pp_new)[i].flags = 0;
 
91
        (*pp_new)[i].size  = SEC_ACE_HEADER_SIZE + ndr_size_dom_sid(sid, NULL, 0);
 
92
        (*pp_new)[i].access_mask = mask;
 
93
        (*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(struct security_ace *ace, size_t num, struct dom_sid *sid, uint32_t 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 (dom_sid_equal(&ace[i].trustee, sid)) {
 
109
                        ace[i].access_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, struct security_ace **pp_new, struct security_ace *old, uint32_t *num, struct 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 (*num) {
 
128
                if((pp_new[0] = talloc_zero_array(ctx, struct security_ace, *num )) == 0)
 
129
                        return NT_STATUS_NO_MEMORY;
 
130
        } else {
 
131
                pp_new[0] = NULL;
 
132
        }
 
133
 
 
134
        for (i = 0; i < *num; i ++) {
 
135
                if (!dom_sid_equal(&old[i].trustee, sid))
 
136
                        sec_ace_copy(&(*pp_new)[i], &old[i]);
 
137
                else
 
138
                        n_del ++;
 
139
        }
 
140
        if (n_del == 0)
 
141
                return NT_STATUS_NOT_FOUND;
 
142
        else {
 
143
                *num -= n_del;
 
144
                return NT_STATUS_OK;
 
145
        }
 
146
}
 
147
 
 
148
/*******************************************************************
 
149
 Compares two struct security_ace structures
 
150
********************************************************************/
 
151
 
 
152
bool sec_ace_equal(struct security_ace *s1, struct security_ace *s2)
 
153
{
 
154
        /* Trivial case */
 
155
 
 
156
        if (!s1 && !s2) {
 
157
                return true;
 
158
        }
 
159
 
 
160
        if (!s1 || !s2) {
 
161
                return false;
 
162
        }
 
163
 
 
164
        /* Check top level stuff */
 
165
 
 
166
        if (s1->type != s2->type || s1->flags != s2->flags ||
 
167
            s1->access_mask != s2->access_mask) {
 
168
                return false;
 
169
        }
 
170
 
 
171
        /* Check SID */
 
172
 
 
173
        if (!dom_sid_equal(&s1->trustee, &s2->trustee)) {
 
174
                return false;
 
175
        }
 
176
 
 
177
        return true;
 
178
}
 
179
 
 
180
int nt_ace_inherit_comp( struct security_ace *a1, struct security_ace *a2)
 
181
{
 
182
        int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
 
183
        int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
 
184
 
 
185
        if (a1_inh == a2_inh)
 
186
                return 0;
 
187
 
 
188
        if (!a1_inh && a2_inh)
 
189
                return -1;
 
190
        return 1;
 
191
}
 
192
 
 
193
/*******************************************************************
 
194
  Comparison function to apply the order explained below in a group.
 
195
*******************************************************************/
 
196
 
 
197
int nt_ace_canon_comp( struct security_ace *a1, struct security_ace *a2)
 
198
{
 
199
        if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
 
200
                                (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
 
201
                return -1;
 
202
 
 
203
        if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
 
204
                                (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
 
205
                return 1;
 
206
 
 
207
        /* Both access denied or access allowed. */
 
208
 
 
209
        /* 1. ACEs that apply to the object itself */
 
210
 
 
211
        if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
 
212
                        (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
 
213
                return -1;
 
214
        else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
 
215
                        (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
 
216
                return 1;
 
217
 
 
218
        /* 2. ACEs that apply to a subobject of the object, such as
 
219
         * a property set or property. */
 
220
 
 
221
        if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
 
222
                        !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
 
223
                return -1;
 
224
        else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
 
225
                        !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
 
226
                return 1;
 
227
 
 
228
        return 0;
 
229
}
 
230
 
 
231
/*******************************************************************
 
232
 Functions to convert a SEC_DESC ACE DACL list into canonical order.
 
233
 JRA.
 
234
 
 
235
--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
 
236
 
 
237
The following describes the preferred order:
 
238
 
 
239
 To ensure that noninherited ACEs have precedence over inherited ACEs,
 
240
 place all noninherited ACEs in a group before any inherited ACEs.
 
241
 This ordering ensures, for example, that a noninherited access-denied ACE
 
242
 is enforced regardless of any inherited ACE that allows access.
 
243
 
 
244
 Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
 
245
        1. Access-denied ACEs that apply to the object itself
 
246
        2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
 
247
        3. Access-allowed ACEs that apply to the object itself
 
248
        4. Access-allowed ACEs that apply to a subobject of the object"
 
249
 
 
250
********************************************************************/
 
251
 
 
252
void dacl_sort_into_canonical_order(struct security_ace *srclist, unsigned int num_aces)
 
253
{
 
254
        unsigned int i;
 
255
 
 
256
        if (!srclist || num_aces == 0)
 
257
                return;
 
258
 
 
259
        /* Sort so that non-inherited ACE's come first. */
 
260
        qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
 
261
 
 
262
        /* Find the boundary between non-inherited ACEs. */
 
263
        for (i = 0; i < num_aces; i++ ) {
 
264
                struct security_ace *curr_ace = &srclist[i];
 
265
 
 
266
                if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
 
267
                        break;
 
268
        }
 
269
 
 
270
        /* i now points at entry number of the first inherited ACE. */
 
271
 
 
272
        /* Sort the non-inherited ACEs. */
 
273
        if (i)
 
274
                qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
 
275
 
 
276
        /* Now sort the inherited ACEs. */
 
277
        if (num_aces - i)
 
278
                qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
 
279
}
 
280
 
 
281