Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : fast routines for getting the wire size of security objects
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Stefan Metzmacher 2006-2008
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 :
24 : #include "includes.h"
25 : #include "librpc/gen_ndr/ndr_security.h"
26 : #include "../libcli/security/security.h"
27 :
28 : /*
29 : return the wire size of a security_ace
30 : */
31 42805098 : size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
32 : {
33 : size_t ret;
34 :
35 42805098 : if (!ace) return 0;
36 :
37 42805098 : ret = 8 + ndr_size_dom_sid(&ace->trustee, flags);
38 :
39 42805098 : switch (ace->type) {
40 23554887 : case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
41 : case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
42 : case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT:
43 : case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT:
44 23554887 : ret += 4; /* uint32 bitmap ace->object.object.flags */
45 23554887 : if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
46 20926027 : ret += 16; /* GUID ace->object.object.type.type */
47 : }
48 23554887 : if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
49 16083434 : ret += 16; /* GUID ace->object.object.inherited_typeinherited_type */
50 : }
51 23554887 : break;
52 19250211 : default:
53 19250211 : break;
54 : }
55 :
56 42805098 : return ret;
57 : }
58 :
59 229430694 : enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, struct security_ace *r)
60 : {
61 229430694 : if (ndr_flags & NDR_SCALARS) {
62 114715347 : uint32_t start_ofs = ndr->offset;
63 114715347 : uint32_t size = 0;
64 114715347 : uint32_t pad = 0;
65 114715347 : NDR_CHECK(ndr_pull_align(ndr, 4));
66 114715347 : NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type));
67 114715347 : NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags));
68 114715347 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size));
69 114715347 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask));
70 114715347 : NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
71 114715347 : NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object));
72 114715347 : NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee));
73 114715347 : size = ndr->offset - start_ofs;
74 114715347 : if (r->size < size) {
75 0 : return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
76 : "ndr_pull_security_ace: r->size %u < size %u",
77 : (unsigned)r->size, size);
78 : }
79 114715347 : pad = r->size - size;
80 114715347 : NDR_PULL_NEED_BYTES(ndr, pad);
81 114715347 : ndr->offset += pad;
82 : }
83 229430694 : if (ndr_flags & NDR_BUFFERS) {
84 114715347 : NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
85 114715347 : NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object));
86 : }
87 229430694 : return NDR_ERR_SUCCESS;
88 : }
89 :
90 : /*
91 : return the wire size of a security_acl
92 : */
93 2978523 : size_t ndr_size_security_acl(const struct security_acl *theacl, int flags)
94 : {
95 : size_t ret;
96 : int i;
97 2978523 : if (!theacl) return 0;
98 2950498 : ret = 8;
99 24398715 : for (i=0;i<theacl->num_aces;i++) {
100 21448217 : ret += ndr_size_security_ace(&theacl->aces[i], flags);
101 : }
102 2950498 : return ret;
103 : }
104 :
105 : /*
106 : return the wire size of a security descriptor
107 : */
108 27914 : size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
109 : {
110 : size_t ret;
111 27914 : if (!sd) return 0;
112 :
113 27718 : ret = 20;
114 27718 : ret += ndr_size_dom_sid(sd->owner_sid, flags);
115 27718 : ret += ndr_size_dom_sid(sd->group_sid, flags);
116 27718 : ret += ndr_size_security_acl(sd->dacl, flags);
117 27718 : ret += ndr_size_security_acl(sd->sacl, flags);
118 27718 : return ret;
119 : }
120 :
121 : /*
122 : return the wire size of a dom_sid
123 : */
124 52772776 : size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
125 : {
126 52772776 : if (!sid) return 0;
127 52743337 : return 8 + 4*sid->num_auths;
128 : }
129 :
130 2643419 : size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags)
131 : {
132 2643419 : if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
133 2355798 : return 0;
134 : }
135 287621 : return ndr_size_dom_sid(sid, flags);
136 : }
137 :
138 498 : size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags)
139 : {
140 498 : return ndr_size_dom_sid28(sid, flags);
141 : }
142 :
143 : /*
144 : print a dom_sid
145 : */
146 26761 : void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
147 : {
148 : struct dom_sid_buf buf;
149 26761 : ndr->print(ndr, "%-25s: %s", name, dom_sid_str_buf(sid, &buf));
150 26761 : }
151 :
152 11323 : void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
153 : {
154 11323 : ndr_print_dom_sid(ndr, name, sid);
155 11323 : }
156 :
157 14756 : void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
158 : {
159 14756 : ndr_print_dom_sid(ndr, name, sid);
160 14756 : }
161 :
162 0 : void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
163 : {
164 0 : ndr_print_dom_sid(ndr, name, sid);
165 0 : }
166 :
167 :
168 : /*
169 : parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
170 : */
171 200298 : enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
172 : {
173 : uint32_t num_auths;
174 200298 : if (!(ndr_flags & NDR_SCALARS)) {
175 0 : return NDR_ERR_SUCCESS;
176 : }
177 200298 : NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &num_auths));
178 200298 : NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
179 200298 : if (sid->num_auths != num_auths) {
180 0 : return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
181 : "Bad num_auths %u; should equal %u",
182 : num_auths, sid->num_auths);
183 : }
184 200298 : return NDR_ERR_SUCCESS;
185 : }
186 :
187 : /*
188 : parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
189 : */
190 176018 : enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
191 : {
192 176018 : if (!(ndr_flags & NDR_SCALARS)) {
193 0 : return NDR_ERR_SUCCESS;
194 : }
195 176018 : NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
196 176018 : return ndr_push_dom_sid(ndr, ndr_flags, sid);
197 : }
198 :
199 : /*
200 : parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only up to 5 sub_auth
201 : */
202 2338342 : enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
203 : {
204 : enum ndr_err_code status;
205 : struct ndr_pull *subndr;
206 :
207 2338342 : if (!(ndr_flags & NDR_SCALARS)) {
208 1169171 : return NDR_ERR_SUCCESS;
209 : }
210 :
211 1169171 : subndr = talloc_zero(ndr, struct ndr_pull);
212 1169171 : NDR_ERR_HAVE_NO_MEMORY(subndr);
213 1169171 : subndr->flags = ndr->flags;
214 1169171 : subndr->current_mem_ctx = ndr->current_mem_ctx;
215 :
216 1169171 : subndr->data = ndr->data + ndr->offset;
217 1169171 : subndr->data_size = 28;
218 1169171 : subndr->offset = 0;
219 :
220 1169171 : NDR_CHECK(ndr_pull_advance(ndr, 28));
221 :
222 1169171 : status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
223 1169171 : if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
224 : /* handle a w2k bug which send random data in the buffer */
225 0 : ZERO_STRUCTP(sid);
226 1169171 : } else if (sid->num_auths == 0) {
227 1052785 : ZERO_STRUCT(sid->sub_auths);
228 : }
229 :
230 1169171 : return NDR_ERR_SUCCESS;
231 : }
232 :
233 : /*
234 : push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
235 : */
236 5286022 : enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
237 : {
238 : uint32_t old_offset;
239 : uint32_t padding;
240 :
241 5286022 : if (!(ndr_flags & NDR_SCALARS)) {
242 2643011 : return NDR_ERR_SUCCESS;
243 : }
244 :
245 2643011 : if (sid->num_auths > 5) {
246 0 : return ndr_push_error(ndr, NDR_ERR_RANGE,
247 : "dom_sid28 allows only up to 5 sub auth [%u]",
248 : sid->num_auths);
249 : }
250 :
251 2643011 : old_offset = ndr->offset;
252 2643011 : NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
253 :
254 2643011 : padding = 28 - (ndr->offset - old_offset);
255 :
256 2643011 : if (padding > 0) {
257 2417079 : NDR_CHECK(ndr_push_zero(ndr, padding));
258 : }
259 :
260 2643011 : return NDR_ERR_SUCCESS;
261 : }
262 :
263 : /*
264 : parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
265 : */
266 5 : enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
267 : {
268 5 : if (!(ndr_flags & NDR_SCALARS)) {
269 0 : return NDR_ERR_SUCCESS;
270 : }
271 :
272 5 : if (ndr->data_size == ndr->offset) {
273 0 : ZERO_STRUCTP(sid);
274 0 : return NDR_ERR_SUCCESS;
275 : }
276 :
277 5 : return ndr_pull_dom_sid(ndr, ndr_flags, sid);
278 : }
279 :
280 : /*
281 : push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
282 : */
283 4 : enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
284 : {
285 4 : if (!(ndr_flags & NDR_SCALARS)) {
286 0 : return NDR_ERR_SUCCESS;
287 : }
288 :
289 4 : if (!sid) {
290 0 : return NDR_ERR_SUCCESS;
291 : }
292 :
293 4 : if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
294 0 : return NDR_ERR_SUCCESS;
295 : }
296 :
297 4 : return ndr_push_dom_sid(ndr, ndr_flags, sid);
298 : }
299 :
300 34078378 : _PUBLIC_ enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
301 : {
302 : uint32_t cntr_sub_auths_0;
303 34078378 : if (ndr_flags & NDR_SCALARS) {
304 34078378 : NDR_CHECK(ndr_push_align(ndr, 4));
305 34078378 : NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
306 34078378 : NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
307 34078378 : NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
308 34078378 : if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
309 0 : return ndr_push_error(ndr, NDR_ERR_RANGE, "value out of range");
310 : }
311 124916884 : for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
312 90838506 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
313 : }
314 : }
315 34078378 : return NDR_ERR_SUCCESS;
316 : }
317 :
318 137571045 : _PUBLIC_ enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
319 : {
320 : uint32_t cntr_sub_auths_0;
321 137571045 : if (ndr_flags & NDR_SCALARS) {
322 137571045 : NDR_CHECK(ndr_pull_align(ndr, 4));
323 137571045 : NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
324 137571045 : NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
325 137571045 : if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
326 4 : return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
327 : }
328 137571041 : NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
329 137571041 : ZERO_STRUCT(r->sub_auths);
330 482504563 : for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
331 344933522 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
332 : }
333 : }
334 137571041 : return NDR_ERR_SUCCESS;
335 : }
|