security descriptors
[samba.git] / source3 / rpc_parse / parse_sec.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-1998,
6  *  Copyright (C) Jeremy R. Allison            1995-1998
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8  *  Copyright (C) Paul Ashton                  1997-1998.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27
28 extern int DEBUGLEVEL;
29
30
31 /*******************************************************************
32 makes a structure.
33 ********************************************************************/
34 void make_sec_access(SEC_ACCESS *t, uint32 mask)
35 {
36         t->mask = mask;
37 }
38
39 /*******************************************************************
40 reads or writes a structure.
41 ********************************************************************/
42 void sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
43 {
44         if (t == NULL) return;
45
46         prs_debug(ps, depth, desc, "sec_io_access");
47         depth++;
48
49         prs_align(ps);
50         
51         prs_uint32("mask", ps, depth, &(t->mask));
52 }
53
54
55 /*******************************************************************
56 makes a structure.
57 ********************************************************************/
58 void make_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
59 {
60         t->type = type;
61         t->flags = flag;
62         t->size = sid_size(sid) + 8;
63         t->info = mask;
64
65         sid_copy(&t->sid, sid);
66 }
67
68 /*******************************************************************
69 reads or writes a structure.
70 ********************************************************************/
71 void sec_io_ace(char *desc, SEC_ACE *t, prs_struct *ps, int depth)
72 {
73         uint32 old_offset;
74         uint32 offset_ace_size;
75         if (t == NULL) return;
76
77         prs_debug(ps, depth, desc, "sec_io_ace");
78         depth++;
79
80         prs_align(ps);
81         
82         old_offset = ps->offset;
83
84         prs_uint8     ("type ", ps, depth, &(t->type));
85         prs_uint8     ("flags", ps, depth, &(t->flags));
86         prs_uint16_pre("size ", ps, depth, &(t->size ), &offset_ace_size);
87
88         sec_io_access   ("info ", &t->info, ps, depth);
89         prs_align(ps);
90         smb_io_dom_sid("sid  ", &t->sid , ps, depth);
91
92         prs_uint16_post("size ", ps, depth, &t->size, offset_ace_size, old_offset);
93 }
94
95 /*******************************************************************
96 makes a structure.  
97 ********************************************************************/
98 void make_sec_acl(SEC_ACL *t, uint16 revision, int num_aces, SEC_ACE *ace)
99 {
100         int i;
101         t->revision = revision;
102         t->num_aces = num_aces;
103         t->size = 4;
104         t->ace = ace;
105
106         for (i = 0; i < num_aces; i++)
107         {
108                 t->size += ace[i].size;
109         }
110 }
111
112 /*******************************************************************
113 frees a structure.  
114 ********************************************************************/
115 void free_sec_acl(SEC_ACL *t)
116 {
117         if (t->ace != NULL)
118         {
119                 free(t->ace);
120         }
121 }
122
123 /*******************************************************************
124 reads or writes a structure.  
125
126 first of the xx_io_xx functions that allocates its data structures
127 for you as it reads them.
128 ********************************************************************/
129 void sec_io_acl(char *desc, SEC_ACL *t, prs_struct *ps, int depth)
130 {
131         int i;
132         uint32 old_offset;
133         uint32 offset_acl_size;
134
135         if (t == NULL) return;
136
137         prs_debug(ps, depth, desc, "sec_io_acl");
138         depth++;
139
140         prs_align(ps);
141         
142         old_offset = ps->offset;
143
144         prs_uint16("revision", ps, depth, &(t->revision));
145         prs_uint16_pre("size     ", ps, depth, &(t->size     ), &offset_acl_size);
146         prs_uint32("num_aces ", ps, depth, &(t->num_aces ));
147
148         if (ps->io && t->num_aces != 0)
149         {
150                 /* reading */
151                 t->ace = malloc(sizeof(t->ace[0]) * t->num_aces);
152                 ZERO_STRUCTPN(t->ace);
153         }
154
155         if (t->ace == NULL && t->num_aces != 0)
156         {
157                 DEBUG(0,("INVALID ACL\n"));
158                 ps->offset = 0xfffffffe;
159                 return;
160         }
161
162         for (i = 0; i < MIN(t->num_aces, MAX_SEC_ACES); i++)
163         {
164                 fstring tmp;
165                 snprintf(tmp, sizeof(tmp), "ace[%02d]: ", i);
166                 sec_io_ace(tmp, &t->ace[i], ps, depth);
167         }
168
169         prs_align(ps);
170
171         prs_uint16_post("size     ", ps, depth, &t->size    , offset_acl_size, old_offset);
172 }
173
174
175 /*******************************************************************
176 makes a structure
177 ********************************************************************/
178 int make_sec_desc(SEC_DESC *t, uint16 revision, uint16 type,
179                                 DOM_SID *owner_sid, DOM_SID *grp_sid,
180                                 SEC_ACL *sacl, SEC_ACL *dacl)
181 {
182         uint32 offset;
183
184         t->revision = revision;
185         t->type     = type;
186
187         t->off_owner_sid = 0;
188         t->off_grp_sid   = 0;
189         t->off_sacl      = 0;
190         t->off_dacl      = 0;
191
192         t->dacl      = dacl;
193         t->sacl      = sacl;
194         t->owner_sid = owner_sid;
195         t->grp_sid   = grp_sid;
196
197         offset = 0x0;
198
199         if (dacl != NULL)
200         {
201                 if (offset == 0)
202                 {
203                         offset = 0x14;
204                 }
205                 t->off_dacl = offset;
206                 offset += dacl->size;
207         }
208
209         if (sacl != NULL)
210         {
211                 if (offset == 0)
212                 {
213                         offset = 0x14;
214                 }
215                 t->off_dacl = offset;
216                 offset += dacl->size;
217         }
218
219         if (owner_sid != NULL)
220         {
221                 if (offset == 0)
222                 {
223                         offset = 0x14;
224                 }
225                 t->off_owner_sid = offset;
226                 offset += sid_size(owner_sid);
227         }
228
229         if (grp_sid != NULL)
230         {
231                 if (offset == 0)
232                 {
233                         offset = 0x14;
234                 }
235                 t->off_grp_sid = offset;
236                 offset += sid_size(grp_sid);
237         }
238
239         return (offset == 0) ? 0x14 : offset;
240 }
241
242
243 /*******************************************************************
244 frees a structure
245 ********************************************************************/
246 void free_sec_desc(SEC_DESC *t)
247 {
248         if (t->dacl != NULL)
249         {
250                 free_sec_acl(t->dacl);
251         }
252
253         if (t->sacl != NULL)
254         {
255                 free_sec_acl(t->dacl);
256         }
257
258         if (t->owner_sid != NULL)
259         {
260                 free(t->owner_sid);
261         }
262
263         if (t->grp_sid != NULL)
264         {
265                 free(t->grp_sid);
266         }
267 }
268
269
270 /*******************************************************************
271 reads or writes a structure.
272 ********************************************************************/
273 static void sec_io_desc(char *desc, SEC_DESC *t, prs_struct *ps, int depth)
274 {
275 #if 0
276         uint32 off_owner_sid;
277         uint32 off_grp_sid  ;
278         uint32 off_sacl     ;
279         uint32 off_dacl     ;
280 #endif
281         uint32 old_offset;
282         uint32 max_offset = 0; /* after we're done, move offset to end */
283
284         if (t == NULL) return;
285
286         prs_debug(ps, depth, desc, "sec_io_desc");
287         depth++;
288
289         prs_align(ps);
290         
291         /* start of security descriptor stored for back-calc offset purposes */
292         old_offset = ps->offset;
293
294         prs_uint16("revision ", ps, depth, &(t->revision ));
295         prs_uint16("type     ", ps, depth, &(t->type     ));
296
297         prs_uint32("off_owner_sid", ps, depth, &(t->off_owner_sid));
298         prs_uint32("off_grp_sid  ", ps, depth, &(t->off_grp_sid  ));
299         prs_uint32("off_sacl     ", ps, depth, &(t->off_sacl     ));
300         prs_uint32("off_dacl     ", ps, depth, &(t->off_dacl     ));
301 #if 0
302         prs_uint32_pre("off_owner_sid", ps, depth, &(t->off_owner_sid), &off_owner_sid);
303         prs_uint32_pre("off_grp_sid  ", ps, depth, &(t->off_grp_sid  ), &off_grp_sid  );
304         prs_uint32_pre("off_sacl     ", ps, depth, &(t->off_sacl     ), &off_sacl     );
305         prs_uint32_pre("off_dacl     ", ps, depth, &(t->off_dacl     ), &off_dacl     );
306 #endif
307         max_offset = MAX(max_offset, ps->offset);
308
309         if (IS_BITS_SET_ALL(t->type, SEC_DESC_DACL_PRESENT))
310         {
311 #if 0
312                 prs_uint32_post("off_dacl    ", ps, depth, &(t->off_dacl     ), off_dacl     , ps->offset - old_offset);
313 #endif
314                 ps->offset = old_offset + t->off_dacl;
315                 if (ps->io)
316                 {
317                         /* reading */
318                         t->dacl = malloc(sizeof(*t->dacl));
319                         ZERO_STRUCTPN(t->dacl);
320                 }
321
322                 if (t->dacl == NULL)
323                 {
324                         DEBUG(0,("INVALID DACL\n"));
325                         ps->offset = 0xfffffffe;
326                         return;
327                 }
328
329                 sec_io_acl     ("dacl"        , t->dacl       , ps, depth);
330                 prs_align(ps);
331         }
332 #if 0
333         else
334         {
335                 prs_uint32_post("off_dacl    ", ps, depth, &(t->off_dacl     ), off_dacl     , 0);
336         }
337 #endif
338
339         max_offset = MAX(max_offset, ps->offset);
340
341         if (IS_BITS_SET_ALL(t->type, SEC_DESC_SACL_PRESENT))
342         {
343 #if 0
344                 prs_uint32_post("off_sacl  ", ps, depth, &(t->off_sacl  ), off_sacl  , ps->offset - old_offset);
345 #endif
346                 ps->offset = old_offset + t->off_sacl;
347                 if (ps->io)
348                 {
349                         /* reading */
350                         t->sacl = malloc(sizeof(*t->sacl));
351                         ZERO_STRUCTPN(t->sacl);
352                 }
353
354                 if (t->sacl == NULL)
355                 {
356                         DEBUG(0,("INVALID SACL\n"));
357                         ps->offset = 0xfffffffe;
358                         return;
359                 }
360
361                 sec_io_acl     ("sacl"      , t->sacl       , ps, depth);
362                 prs_align(ps);
363         }
364 #if 0
365         else
366         {
367                 prs_uint32_post("off_sacl  ", ps, depth, &(t->off_sacl  ), off_sacl  , 0);
368         }
369 #endif
370
371         max_offset = MAX(max_offset, ps->offset);
372
373 #if 0
374         prs_uint32_post("off_owner_sid", ps, depth, &(t->off_owner_sid), off_owner_sid, ps->offset - old_offset);
375 #endif
376         if (t->off_owner_sid != 0)
377         {
378                 if (ps->io)
379                 {
380                         ps->offset = old_offset + t->off_owner_sid;
381                 }
382                 if (ps->io)
383                 {
384                         /* reading */
385                         t->owner_sid = malloc(sizeof(*t->owner_sid));
386                         ZERO_STRUCTPN(t->owner_sid);
387                 }
388
389                 if (t->owner_sid == NULL)
390                 {
391                         DEBUG(0,("INVALID OWNER SID\n"));
392                         ps->offset = 0xfffffffe;
393                         return;
394                 }
395
396                 smb_io_dom_sid("owner_sid ", t->owner_sid , ps, depth);
397                 prs_align(ps);
398         }
399
400         max_offset = MAX(max_offset, ps->offset);
401
402 #if 0
403         prs_uint32_post("off_grp_sid  ", ps, depth, &(t->off_grp_sid  ), off_grp_sid  , ps->offset - old_offset);
404 #endif
405         if (t->off_grp_sid != 0)
406         {
407                 if (ps->io)
408                 {
409                         ps->offset = old_offset + t->off_grp_sid;
410                 }
411                 if (ps->io)
412                 {
413                         /* reading */
414                         t->grp_sid = malloc(sizeof(*t->grp_sid));
415                         ZERO_STRUCTPN(t->grp_sid);
416                 }
417
418                 if (t->grp_sid == NULL)
419                 {
420                         DEBUG(0,("INVALID GROUP SID\n"));
421                         ps->offset = 0xfffffffe;
422                         return;
423                 }
424
425                 smb_io_dom_sid("grp_sid", t->grp_sid, ps, depth);
426                 prs_align(ps);
427         }
428
429         max_offset = MAX(max_offset, ps->offset);
430
431         ps->offset = max_offset;
432 }
433
434 /*******************************************************************
435 creates a SEC_DESC_BUF structure.
436 ********************************************************************/
437 void make_sec_desc_buf(SEC_DESC_BUF *buf, int len, SEC_DESC *data)
438 {
439         ZERO_STRUCTP(buf);
440
441         /* max buffer size (allocated size) */
442         buf->max_len = len;
443         buf->undoc       = 0;
444         buf->len = data != NULL ? len : 0;
445         buf->sec = data;
446 }
447
448 /*******************************************************************
449 frees a SEC_DESC_BUF structure.
450 ********************************************************************/
451 void free_sec_desc_buf(SEC_DESC_BUF *buf)
452 {
453         if (buf->sec != NULL)
454         {
455                 free_sec_desc(buf->sec);
456                 free(buf->sec);
457         }
458 }
459
460
461 /*******************************************************************
462 reads or writes a SEC_DESC_BUF structure.
463 ********************************************************************/
464 void sec_io_desc_buf(char *desc, SEC_DESC_BUF *sec, prs_struct *ps, int depth)
465 {
466         uint32 off_len;
467         uint32 off_max_len;
468         uint32 old_offset;
469         uint32 size;
470
471         if (sec == NULL) return;
472
473         prs_debug(ps, depth, desc, "sec_io_desc_buf");
474         depth++;
475
476         prs_align(ps);
477         
478         prs_uint32_pre("max_len", ps, depth, &(sec->max_len), &off_max_len);
479         prs_uint32    ("undoc  ", ps, depth, &(sec->undoc  ));
480         prs_uint32_pre("len    ", ps, depth, &(sec->len    ), &off_len);
481
482         old_offset = ps->offset;
483
484         if (sec->len != 0 && ps->io)
485         {
486                 /* reading */
487                 sec->sec = malloc(sizeof(*sec->sec));
488                 ZERO_STRUCTPN(sec->sec);
489
490                 if (sec->sec == NULL)
491                 {
492                         DEBUG(0,("INVALID SEC_DESC\n"));
493                         ps->offset = 0xfffffffe;
494                         return;
495                 }
496         }
497
498         /* reading, length is non-zero; writing, descriptor is non-NULL */
499         if ((sec->len != 0 || (!ps->io)) && sec->sec != NULL)
500         {
501                 sec_io_desc("sec   ", sec->sec, ps, depth);
502         }
503
504         size = ps->offset - old_offset;
505         prs_uint32_post("max_len", ps, depth, &(sec->max_len), off_max_len, size == 0 ? sec->max_len : size);
506         prs_uint32_post("len    ", ps, depth, &(sec->len    ), off_len    , size);
507 }
508