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 44573165 : size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
32 : {
33 : size_t ret;
34 :
35 44573165 : if (!ace) return 0;
36 :
37 44573165 : ret = 8 + ndr_size_dom_sid(&ace->trustee, flags);
38 :
39 44573165 : switch (ace->type) {
40 21908473 : 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 21908473 : ret += 4; /* uint32 bitmap ace->object.object.flags */
45 21908473 : if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) {
46 19464693 : ret += 16; /* GUID ace->object.object.type.type */
47 : }
48 21908473 : if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) {
49 14958821 : ret += 16; /* GUID ace->object.object.inherited_typeinherited_type */
50 : }
51 21908473 : break;
52 22664692 : default:
53 22664692 : break;
54 : }
55 :
56 44573165 : return ret;
57 : }
58 :
59 228797452 : enum ndr_err_code ndr_pull_security_ace(struct ndr_pull *ndr, int ndr_flags, struct security_ace *r)
60 : {
61 228797452 : if (ndr_flags & NDR_SCALARS) {
62 114398726 : uint32_t start_ofs = ndr->offset;
63 114398726 : uint32_t size = 0;
64 114398726 : uint32_t pad = 0;
65 114398726 : NDR_CHECK(ndr_pull_align(ndr, 4));
66 114398726 : NDR_CHECK(ndr_pull_security_ace_type(ndr, NDR_SCALARS, &r->type));
67 114398726 : NDR_CHECK(ndr_pull_security_ace_flags(ndr, NDR_SCALARS, &r->flags));
68 114398726 : NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &r->size));
69 114398726 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->access_mask));
70 114398726 : NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
71 114398726 : NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_SCALARS, &r->object));
72 114398726 : NDR_CHECK(ndr_pull_dom_sid(ndr, NDR_SCALARS, &r->trustee));
73 114398726 : size = ndr->offset - start_ofs;
74 114398726 : 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 114398726 : pad = r->size - size;
80 114398726 : NDR_PULL_NEED_BYTES(ndr, pad);
81 114398726 : ndr->offset += pad;
82 : }
83 228797452 : if (ndr_flags & NDR_BUFFERS) {
84 114398726 : NDR_CHECK(ndr_pull_set_switch_value(ndr, &r->object, r->type));
85 114398726 : NDR_CHECK(ndr_pull_security_ace_object_ctr(ndr, NDR_BUFFERS, &r->object));
86 : }
87 228797452 : return NDR_ERR_SUCCESS;
88 : }
89 :
90 : /*
91 : return the wire size of a security_acl
92 : */
93 3269458 : size_t ndr_size_security_acl(const struct security_acl *theacl, int flags)
94 : {
95 : size_t ret;
96 : int i;
97 3269458 : if (!theacl) return 0;
98 3241634 : ret = 8;
99 25573343 : for (i=0;i<theacl->num_aces;i++) {
100 22331709 : ret += ndr_size_security_ace(&theacl->aces[i], flags);
101 : }
102 3241634 : return ret;
103 : }
104 :
105 : /*
106 : return the wire size of a security descriptor
107 : */
108 27714 : size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
109 : {
110 : size_t ret;
111 27714 : if (!sd) return 0;
112 :
113 27518 : ret = 20;
114 27518 : ret += ndr_size_dom_sid(sd->owner_sid, flags);
115 27518 : ret += ndr_size_dom_sid(sd->group_sid, flags);
116 27518 : ret += ndr_size_security_acl(sd->dacl, flags);
117 27518 : ret += ndr_size_security_acl(sd->sacl, flags);
118 27518 : return ret;
119 : }
120 :
121 : /*
122 : return the wire size of a dom_sid
123 : */
124 54071127 : size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
125 : {
126 54071127 : if (!sid) return 0;
127 54041643 : return 8 + 4*sid->num_auths;
128 : }
129 :
130 2574287 : size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags)
131 : {
132 2574287 : if (!sid) return 0;
133 :
134 2574287 : if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
135 2298136 : return 0;
136 : }
137 :
138 276151 : return 8 + 4*sid->num_auths;
139 : }
140 :
141 498 : size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags)
142 : {
143 498 : return ndr_size_dom_sid28(sid, flags);
144 : }
145 :
146 : /*
147 : print a dom_sid
148 : */
149 26756 : void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
150 : {
151 : struct dom_sid_buf buf;
152 26756 : ndr->print(ndr, "%-25s: %s", name, dom_sid_str_buf(sid, &buf));
153 26756 : }
154 :
155 11319 : void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
156 : {
157 11319 : ndr_print_dom_sid(ndr, name, sid);
158 11319 : }
159 :
160 14756 : void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
161 : {
162 14756 : ndr_print_dom_sid(ndr, name, sid);
163 14756 : }
164 :
165 0 : void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
166 : {
167 0 : ndr_print_dom_sid(ndr, name, sid);
168 0 : }
169 :
170 :
171 : /*
172 : parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
173 : */
174 199960 : enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
175 : {
176 : uint32_t num_auths;
177 199960 : if (!(ndr_flags & NDR_SCALARS)) {
178 0 : return NDR_ERR_SUCCESS;
179 : }
180 199960 : NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &num_auths));
181 199960 : NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
182 199960 : if (sid->num_auths != num_auths) {
183 0 : return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
184 : "Bad array size %u should exceed %u",
185 : num_auths, sid->num_auths);
186 : }
187 199960 : return NDR_ERR_SUCCESS;
188 : }
189 :
190 : /*
191 : parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
192 : */
193 176536 : enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
194 : {
195 176536 : if (!(ndr_flags & NDR_SCALARS)) {
196 0 : return NDR_ERR_SUCCESS;
197 : }
198 176536 : NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, sid->num_auths));
199 176536 : return ndr_push_dom_sid(ndr, ndr_flags, sid);
200 : }
201 :
202 : /*
203 : 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
204 : */
205 2272814 : enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
206 : {
207 : enum ndr_err_code status;
208 : struct ndr_pull *subndr;
209 :
210 2272814 : if (!(ndr_flags & NDR_SCALARS)) {
211 1136407 : return NDR_ERR_SUCCESS;
212 : }
213 :
214 1136407 : subndr = talloc_zero(ndr, struct ndr_pull);
215 1136407 : NDR_ERR_HAVE_NO_MEMORY(subndr);
216 1136407 : subndr->flags = ndr->flags;
217 1136407 : subndr->current_mem_ctx = ndr->current_mem_ctx;
218 :
219 1136407 : subndr->data = ndr->data + ndr->offset;
220 1136407 : subndr->data_size = 28;
221 1136407 : subndr->offset = 0;
222 :
223 1136407 : NDR_CHECK(ndr_pull_advance(ndr, 28));
224 :
225 1136407 : status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
226 1136407 : if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
227 : /* handle a w2k bug which send random data in the buffer */
228 0 : ZERO_STRUCTP(sid);
229 1136407 : } else if (sid->num_auths == 0) {
230 1025130 : ZERO_STRUCT(sid->sub_auths);
231 : }
232 :
233 1136407 : return NDR_ERR_SUCCESS;
234 : }
235 :
236 : /*
237 : push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
238 : */
239 5147754 : enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
240 : {
241 : uint32_t old_offset;
242 : uint32_t padding;
243 :
244 5147754 : if (!(ndr_flags & NDR_SCALARS)) {
245 2573877 : return NDR_ERR_SUCCESS;
246 : }
247 :
248 2573877 : if (sid->num_auths > 5) {
249 0 : return ndr_push_error(ndr, NDR_ERR_RANGE,
250 : "dom_sid28 allows only up to 5 sub auth [%u]",
251 : sid->num_auths);
252 : }
253 :
254 2573877 : old_offset = ndr->offset;
255 2573877 : NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
256 :
257 2573877 : padding = 28 - (ndr->offset - old_offset);
258 :
259 2573877 : if (padding > 0) {
260 2358508 : NDR_CHECK(ndr_push_zero(ndr, padding));
261 : }
262 :
263 2573877 : return NDR_ERR_SUCCESS;
264 : }
265 :
266 : /*
267 : parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
268 : */
269 5 : enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
270 : {
271 5 : if (!(ndr_flags & NDR_SCALARS)) {
272 0 : return NDR_ERR_SUCCESS;
273 : }
274 :
275 5 : if (ndr->data_size == ndr->offset) {
276 0 : ZERO_STRUCTP(sid);
277 0 : return NDR_ERR_SUCCESS;
278 : }
279 :
280 5 : return ndr_pull_dom_sid(ndr, ndr_flags, sid);
281 : }
282 :
283 : /*
284 : push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
285 : */
286 4 : enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
287 : {
288 4 : if (!(ndr_flags & NDR_SCALARS)) {
289 0 : return NDR_ERR_SUCCESS;
290 : }
291 :
292 4 : if (!sid) {
293 0 : return NDR_ERR_SUCCESS;
294 : }
295 :
296 4 : if (all_zero((const uint8_t *)sid, sizeof(struct dom_sid))) {
297 0 : return NDR_ERR_SUCCESS;
298 : }
299 :
300 4 : return ndr_push_dom_sid(ndr, ndr_flags, sid);
301 : }
302 :
303 35042884 : _PUBLIC_ enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
304 : {
305 : uint32_t cntr_sub_auths_0;
306 35042884 : if (ndr_flags & NDR_SCALARS) {
307 35042884 : NDR_CHECK(ndr_push_align(ndr, 4));
308 35042884 : NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
309 35042884 : NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
310 35042884 : NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
311 35042884 : if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
312 0 : return ndr_push_error(ndr, NDR_ERR_RANGE, "value out of range");
313 : }
314 127259820 : for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
315 92216936 : NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
316 : }
317 : }
318 35042884 : return NDR_ERR_SUCCESS;
319 : }
320 :
321 137075257 : _PUBLIC_ enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
322 : {
323 : uint32_t cntr_sub_auths_0;
324 137075257 : if (ndr_flags & NDR_SCALARS) {
325 137075257 : NDR_CHECK(ndr_pull_align(ndr, 4));
326 137075257 : NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
327 137075257 : NDR_CHECK(ndr_pull_int8(ndr, NDR_SCALARS, &r->num_auths));
328 137075257 : if (r->num_auths < 0 || r->num_auths > ARRAY_SIZE(r->sub_auths)) {
329 4 : return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
330 : }
331 137075253 : NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
332 137075253 : ZERO_STRUCT(r->sub_auths);
333 476055805 : for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
334 338980552 : NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
335 : }
336 : }
337 137075253 : return NDR_ERR_SUCCESS;
338 : }
|