source: trunk/lib/winsec.c @ 133

Last change on this file since 133 was 133, checked in by tim, 15 years ago

minor changes to winsec library

fixed major bug with data_in_offset values

  • Property svn:keywords set to Id
File size: 14.2 KB
Line 
1/*
2 * This file contains refactored Samba code used to interpret Windows
3 * Security Descriptors. See:
4 *   http://websvn.samba.org/cgi-bin/viewcvs.cgi/trunk/source/
5 *
6 * Copyright (C) 2005-2006,2009 Timothy D. Morgan
7 * Copyright (C) 1992-2005 Samba development team
8 *               (see individual files under Subversion for details.)
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; version 3 of the License.
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 * $Id: winsec.c 133 2009-01-12 17:07:58Z tim $
24 */
25
26#include "../include/winsec.h"
27
28
29
30/*******************************************************************
31 * Parses a SEC_DESC structure.
32 *******************************************************************/
33bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
34{
35  uint32 old_offset;
36  uint32 max_offset = 0; /* after we're done, move offset to end */
37  uint32 tmp_offset = 0;
38
39  SEC_DESC *psd;
40
41  if (ppsd == NULL || ps == NULL)
42    return false;
43
44  psd = *ppsd;
45  if (psd == NULL) 
46  {
47    if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
48      return false;
49    *ppsd = psd;
50  }
51
52  depth++;
53
54  /* start of security descriptor stored for back-calc offset purposes */
55  old_offset = ps->data_offset;
56
57  if(!prs_uint16("revision ", ps, depth, &psd->revision)
58     || !prs_uint16("type     ", ps, depth, &psd->type))
59  {
60    free(psd);
61    *ppsd = NULL;
62    return false;
63  }
64
65  if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)
66     || !prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid)
67     || !prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl)
68     || !prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
69  {
70    free(psd);
71    *ppsd = NULL;   
72    return false;
73  }
74  max_offset = MAX(max_offset, ps->data_offset);
75
76  if (psd->off_owner_sid != 0) 
77  {
78    tmp_offset = ps->data_offset;
79    if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
80    {
81      free(psd);
82      *ppsd = NULL;
83      return false;
84    }
85
86    /* reading */
87    if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
88    {
89      free(psd);
90      *ppsd = NULL;
91      return false;
92    }
93
94    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
95    {
96      free(psd->owner_sid);
97      free(psd);
98      *ppsd = NULL;
99      return false;
100    }
101
102    max_offset = MAX(max_offset, ps->data_offset);
103
104    if (!prs_set_offset(ps,tmp_offset))
105    {
106      free(psd->owner_sid);
107      free(psd);
108      *ppsd = NULL;
109      return false;
110    }
111  }
112
113  if (psd->off_grp_sid != 0) 
114  {
115    tmp_offset = ps->data_offset;
116    if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
117    {
118      free(psd->owner_sid);
119      free(psd);
120      *ppsd = NULL;
121      return false;
122    }
123
124    /* reading */
125    if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
126    {
127      free(psd->owner_sid);
128      free(psd);
129      *ppsd = NULL;
130      return false;
131    }
132
133    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
134    {
135      free(psd->grp_sid);
136      free(psd->owner_sid);
137      free(psd);
138      *ppsd = NULL;
139      return false;
140    }
141                       
142    max_offset = MAX(max_offset, ps->data_offset);
143
144    if (!prs_set_offset(ps,tmp_offset))
145    {
146      free(psd->grp_sid);
147      free(psd->owner_sid);
148      free(psd);
149      *ppsd = NULL;
150      return false;
151    }
152  }
153
154  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
155  {
156    tmp_offset = ps->data_offset;
157    if(!prs_set_offset(ps, old_offset + psd->off_sacl)
158       || !sec_io_acl("sacl", &psd->sacl, ps, depth))
159    {
160      free(psd->grp_sid);
161      free(psd->owner_sid);
162      free(psd);
163      *ppsd = NULL;
164      return false;
165    }
166    max_offset = MAX(max_offset, ps->data_offset);
167    if (!prs_set_offset(ps,tmp_offset))
168    {
169      free(psd->grp_sid);
170      free(psd->owner_sid);
171      free(psd);
172      *ppsd = NULL;
173      return false;
174    }
175  }
176
177  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
178  {
179    tmp_offset = ps->data_offset;
180    if(!prs_set_offset(ps, old_offset + psd->off_dacl)
181       || !sec_io_acl("dacl", &psd->dacl, ps, depth))
182    {
183      free(psd->grp_sid);
184      free(psd->owner_sid);
185      free(psd);
186      *ppsd = NULL;
187      return false;
188    }
189    max_offset = MAX(max_offset, ps->data_offset);
190    if (!prs_set_offset(ps,tmp_offset))
191    {
192      free(psd->grp_sid);
193      free(psd->owner_sid);
194      free(psd);
195      *ppsd = NULL;
196      return false;
197    }
198  }
199
200  if(!prs_set_offset(ps, max_offset))
201  {
202    free(psd->grp_sid);
203    free(psd->owner_sid);
204    free(psd);
205    *ppsd = NULL;
206    return false;
207  }
208
209  return true;
210}
211
212
213/*******************************************************************
214 Reads or writes a DOM_SID structure.
215********************************************************************/
216bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
217{
218  int i;
219
220  if (sid == NULL)
221    return false;
222  depth++;
223
224  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
225    return false;
226
227  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
228    return false;
229
230  for (i = 0; i < 6; i++)
231  {
232    fstring tmp;
233    snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
234    if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
235      return false;
236  }
237
238  /* oops! XXXX should really issue a warning here... */
239  if (sid->num_auths > MAXSUBAUTHS)
240    sid->num_auths = MAXSUBAUTHS;
241
242  if(!prs_uint32s("sub_auths ", ps, depth, 
243                  sid->sub_auths, sid->num_auths))
244  { return false; }
245
246  return true;
247}
248
249
250
251/*******************************************************************
252 Reads or writes a SEC_ACCESS structure.
253********************************************************************/
254bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
255{
256  if (t == NULL)
257    return false;
258
259  depth++;
260       
261  if(!prs_uint32("mask", ps, depth, &t->mask))
262    return false;
263
264  return true;
265}
266
267
268/*******************************************************************
269 Reads or writes a SEC_ACE structure.
270********************************************************************/
271bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
272{
273  uint32 old_offset;
274  uint32 offset_ace_size;
275
276  if (psa == NULL)
277    return false;
278
279  depth++;
280       
281  old_offset = ps->data_offset;
282
283  if(!prs_uint8("type ", ps, depth, &psa->type))
284    return false;
285
286  if(!prs_uint8("flags", ps, depth, &psa->flags))
287    return false;
288
289  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
290    return false;
291
292  if(!sec_io_access("info ", &psa->info, ps, depth))
293    return false;
294
295  /* check whether object access is present */
296  if (!sec_ace_object(psa->type)) 
297  {
298    if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
299      return false;
300  } 
301  else 
302  {
303    if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
304      return false;
305
306    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
307      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
308        return false;
309
310    if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
311      if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
312        return false;
313
314    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
315      return false;
316  }
317
318  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
319                      offset_ace_size, old_offset))
320  { return false; }
321
322  return true;
323}
324
325
326/*******************************************************************
327 Reads or writes a SEC_ACL structure. 
328
329 First of the xx_io_xx functions that allocates its data structures
330 for you as it reads them.
331********************************************************************/
332bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
333{
334  unsigned int i;
335  uint32 old_offset;
336  uint32 offset_acl_size;
337  SEC_ACL* psa;
338
339  /*
340   * Note that the size is always a multiple of 4 bytes due to the
341   * nature of the data structure.  Therefore the prs_align() calls
342   * have been removed as they through us off when doing two-layer
343   * marshalling such as in the printing code (RPC_BUFFER).  --jerry
344   */
345
346  if (ppsa == NULL || ps == NULL)
347    return false;
348
349  psa = *ppsa;
350
351  if(psa == NULL) 
352  {
353    /*
354     * This is a read and we must allocate the stuct to read into.
355     */
356    if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
357      return false;
358    *ppsa = psa;
359  }
360
361  depth++;     
362  old_offset = ps->data_offset;
363
364  if(!prs_uint16("revision", ps, depth, &psa->revision)
365     || !prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size)
366     || !prs_uint32("num_aces ", ps, depth, &psa->num_aces))
367  {
368    free(psa);
369    *ppsa = NULL;
370    return false;
371  }
372
373  /*
374   * Even if the num_aces is zero, allocate memory as there's a difference
375   * between a non-present DACL (allow all access) and a DACL with no ACE's
376   * (allow no access).
377   */
378  if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
379  {
380    free(psa);
381    *ppsa = NULL;
382    return false;
383  }
384
385  for (i = 0; i < psa->num_aces; i++) 
386  {
387    fstring tmp;
388    snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
389    if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
390    {
391      free(psa);
392      *ppsa = NULL;
393      return false;
394    }
395  }
396
397  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
398                      offset_acl_size, old_offset))
399  { 
400    free(psa);
401    *ppsa = NULL;
402    return false; 
403  }
404
405  return true;
406}
407
408
409/*****************************************************************
410 Calculates size of a sid.
411*****************************************************************/ 
412size_t sid_size(const DOM_SID *sid)
413{
414  if (sid == NULL)
415    return 0;
416
417  return sid->num_auths * sizeof(uint32) + 8;
418}
419
420
421/*****************************************************************
422 Compare the auth portion of two sids.
423*****************************************************************/ 
424int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
425{
426  int i;
427
428  if (sid1 == sid2)
429    return 0;
430  if (!sid1)
431    return -1;
432  if (!sid2)
433    return 1;
434
435  if (sid1->sid_rev_num != sid2->sid_rev_num)
436    return sid1->sid_rev_num - sid2->sid_rev_num;
437
438  for (i = 0; i < 6; i++)
439    if (sid1->id_auth[i] != sid2->id_auth[i])
440      return sid1->id_auth[i] - sid2->id_auth[i];
441
442  return 0;
443}
444
445
446/*****************************************************************
447 Compare two sids.
448*****************************************************************/ 
449int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
450{
451  int i;
452
453  if (sid1 == sid2)
454    return 0;
455  if (!sid1)
456    return -1;
457  if (!sid2)
458    return 1;
459
460  /* Compare most likely different rids, first: i.e start at end */
461  if (sid1->num_auths != sid2->num_auths)
462    return sid1->num_auths - sid2->num_auths;
463
464  for (i = sid1->num_auths-1; i >= 0; --i)
465    if (sid1->sub_auths[i] != sid2->sub_auths[i])
466      return sid1->sub_auths[i] - sid2->sub_auths[i];
467
468  return sid_compare_auth(sid1, sid2);
469}
470
471
472/*****************************************************************
473 Compare two sids.
474*****************************************************************/ 
475bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
476{
477  return sid_compare(sid1, sid2) == 0;
478}
479
480
481
482/*******************************************************************
483 Check if ACE has OBJECT type.
484********************************************************************/
485bool sec_ace_object(uint8 type)
486{
487  if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
488      type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
489      type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
490      type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
491    return true;
492  }
493  return false;
494}
495
496
497/*******************************************************************
498 Compares two SEC_ACE structures
499********************************************************************/
500bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
501{
502  /* Trivial cases */
503  if (!s1 && !s2) 
504    return true;
505  if (!s1 || !s2) 
506    return false;
507
508  /* Check top level stuff */
509  if (s1->type != s2->type || s1->flags != s2->flags ||
510      s1->info.mask != s2->info.mask) 
511  { return false; }
512
513  /* Check SID */
514  if (!sid_equal(&s1->trustee, &s2->trustee))
515    return false;
516
517  return true;
518}
519
520
521/*******************************************************************
522 Compares two SEC_ACL structures
523********************************************************************/
524bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
525{
526  unsigned int i, j;
527
528  /* Trivial cases */
529  if (!s1 && !s2) 
530    return true;
531  if (!s1 || !s2) 
532    return false;
533
534  /* Check top level stuff */
535  if (s1->revision != s2->revision)
536    return false;
537
538  if (s1->num_aces != s2->num_aces)
539    return false;
540
541  /* The ACEs could be in any order so check each ACE in s1 against
542     each ACE in s2. */
543
544  for (i = 0; i < s1->num_aces; i++) 
545  {
546    bool found = false;
547
548    for (j = 0; j < s2->num_aces; j++) 
549    {
550      if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) 
551      {
552        found = true;
553        break;
554      }
555    }
556
557    if (!found)
558      return false;
559  }
560
561  return true;
562}
563
564
565/*******************************************************************
566 Compares two SEC_DESC structures
567********************************************************************/
568bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
569{
570  /* Trivial cases */
571  if (!s1 && !s2)
572    return true;
573  if (!s1 || !s2)
574    return false;
575
576  /* Check top level stuff */
577  if (s1->revision != s2->revision)
578    return false;
579
580  if (s1->type!= s2->type)
581    return false;
582
583  /* Check owner and group */
584  if (!sid_equal(s1->owner_sid, s2->owner_sid))
585    return false;
586
587  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
588    return false;
589
590  /* Check ACLs present in one but not the other */
591  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
592      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
593  { return false; }
594
595  /* Sigh - we have to do it the hard way by iterating over all
596     the ACEs in the ACLs */
597  if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) 
598    return false;
599
600  return true;
601}
Note: See TracBrowser for help on using the repository browser.