source: trunk/lib/winsec.c @ 132

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

separated ACL parsing code from smb_deps into new winsec library

  • Property svn:keywords set to Id
File size: 16.8 KB
Line 
1/*
2 * This file contains miscellaneous pieces of code which regfio.c
3 * depends upon, from the Samba Subversion tree.  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 $
24 */
25
26#include "../include/winsec.h"
27
28
29
30/* From rpc_parse/parse_misc.c */
31
32/*******************************************************************
33 Reads or writes a DOM_SID structure.
34********************************************************************/
35bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
36{
37  int i;
38
39  if (sid == NULL)
40    return false;
41  depth++;
42
43  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
44    return false;
45
46  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
47    return false;
48
49  for (i = 0; i < 6; i++)
50  {
51    fstring tmp;
52    snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
53    if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
54      return false;
55  }
56
57  /* oops! XXXX should really issue a warning here... */
58  if (sid->num_auths > MAXSUBAUTHS)
59    sid->num_auths = MAXSUBAUTHS;
60
61  if(!prs_uint32s("sub_auths ", ps, depth, 
62                  sid->sub_auths, sid->num_auths))
63  { return false; }
64
65  return true;
66}
67
68/* End of stuff from rpc_parse/parse_misc.c */
69
70/* From lib/util_sid.c */
71
72/*****************************************************************
73 Calculates size of a sid.
74*****************************************************************/ 
75size_t sid_size(const DOM_SID *sid)
76{
77  if (sid == NULL)
78    return 0;
79
80  return sid->num_auths * sizeof(uint32) + 8;
81}
82
83
84/*****************************************************************
85 Compare the auth portion of two sids.
86*****************************************************************/ 
87int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
88{
89  int i;
90
91  if (sid1 == sid2)
92    return 0;
93  if (!sid1)
94    return -1;
95  if (!sid2)
96    return 1;
97
98  if (sid1->sid_rev_num != sid2->sid_rev_num)
99    return sid1->sid_rev_num - sid2->sid_rev_num;
100
101  for (i = 0; i < 6; i++)
102    if (sid1->id_auth[i] != sid2->id_auth[i])
103      return sid1->id_auth[i] - sid2->id_auth[i];
104
105  return 0;
106}
107
108
109/*****************************************************************
110 Compare two sids.
111*****************************************************************/ 
112int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
113{
114  int i;
115
116  if (sid1 == sid2)
117    return 0;
118  if (!sid1)
119    return -1;
120  if (!sid2)
121    return 1;
122
123  /* Compare most likely different rids, first: i.e start at end */
124  if (sid1->num_auths != sid2->num_auths)
125    return sid1->num_auths - sid2->num_auths;
126
127  for (i = sid1->num_auths-1; i >= 0; --i)
128    if (sid1->sub_auths[i] != sid2->sub_auths[i])
129      return sid1->sub_auths[i] - sid2->sub_auths[i];
130
131  return sid_compare_auth(sid1, sid2);
132}
133
134
135/*****************************************************************
136 Compare two sids.
137*****************************************************************/ 
138bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
139{
140  return sid_compare(sid1, sid2) == 0;
141}
142
143/* End of stuff from lib/util_sid.c */
144
145/* From lib/secace.c */
146
147/*******************************************************************
148 Check if ACE has OBJECT type.
149********************************************************************/
150
151bool sec_ace_object(uint8 type)
152{
153  if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
154      type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
155      type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
156      type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
157    return true;
158  }
159  return false;
160}
161
162/* End of stuff from lib/secace.c */
163
164/* From rpc_parse/parse_sec.c */
165
166/*******************************************************************
167 Reads or writes a SEC_ACCESS structure.
168********************************************************************/
169bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
170{
171  if (t == NULL)
172    return false;
173
174  depth++;
175       
176  if(!prs_uint32("mask", ps, depth, &t->mask))
177    return false;
178
179  return true;
180}
181
182
183/*******************************************************************
184 Reads or writes a SEC_ACE structure.
185********************************************************************/
186bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
187{
188  uint32 old_offset;
189  uint32 offset_ace_size;
190
191  if (psa == NULL)
192    return false;
193
194  depth++;
195       
196  old_offset = ps->data_offset;
197
198  if(!prs_uint8("type ", ps, depth, &psa->type))
199    return false;
200
201  if(!prs_uint8("flags", ps, depth, &psa->flags))
202    return false;
203
204  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
205    return false;
206
207  if(!sec_io_access("info ", &psa->info, ps, depth))
208    return false;
209
210  /* check whether object access is present */
211  if (!sec_ace_object(psa->type)) 
212  {
213    if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
214      return false;
215  } 
216  else 
217  {
218    if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
219      return false;
220
221    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
222      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
223        return false;
224
225    if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
226      if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
227        return false;
228
229    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
230      return false;
231  }
232
233  /* Theorectically an ACE can have a size greater than the
234   * sum of its components. When marshalling, pad with extra null bytes
235   * up to the
236   * correct size.
237   */
238  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
239  {
240    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
241    uint32 i;
242    uint8 c = 0;
243
244    for (i = 0; i < extra_len; i++) 
245    {
246      if (!prs_uint8("ace extra space", ps, depth, &c))
247        return false;
248    }
249  }
250
251  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
252                      offset_ace_size, old_offset))
253  { return false; }
254
255  return true;
256}
257
258
259/*******************************************************************
260 Reads or writes a SEC_ACL structure. 
261
262 First of the xx_io_xx functions that allocates its data structures
263 for you as it reads them.
264********************************************************************/
265bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
266{
267  unsigned int i;
268  uint32 old_offset;
269  uint32 offset_acl_size;
270  SEC_ACL* psa;
271
272  /*
273   * Note that the size is always a multiple of 4 bytes due to the
274   * nature of the data structure.  Therefore the prs_align() calls
275   * have been removed as they through us off when doing two-layer
276   * marshalling such as in the printing code (RPC_BUFFER).  --jerry
277   */
278
279  if (ppsa == NULL || ps == NULL)
280    return false;
281
282  psa = *ppsa;
283
284  if(ps->io && psa == NULL) 
285  {
286    /*
287     * This is a read and we must allocate the stuct to read into.
288     */
289    if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
290      return false;
291    *ppsa = psa;
292  }
293
294  depth++;     
295  old_offset = ps->data_offset;
296
297  if(!prs_uint16("revision", ps, depth, &psa->revision)
298     || !prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size)
299     || !prs_uint32("num_aces ", ps, depth, &psa->num_aces))
300  {
301    free(psa);
302    *ppsa = NULL;
303    return false;
304  }
305
306  if (ps->io) 
307  {
308    /*
309     * Even if the num_aces is zero, allocate memory as there's a difference
310     * between a non-present DACL (allow all access) and a DACL with no ACE's
311     * (allow no access).
312     */
313    if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
314    {
315      free(psa);
316      *ppsa = NULL;
317      return false;
318    }
319  }
320
321  for (i = 0; i < psa->num_aces; i++) 
322  {
323    fstring tmp;
324    snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
325    if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
326    {
327      free(psa);
328      *ppsa = NULL;
329      return false;
330    }
331  }
332
333  /* Theoretically an ACL can have a size greater than the
334   *  sum of its components. When marshalling, pad with extra null
335   *  bytes up to the
336   *  correct size.
337   */
338  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
339  {
340    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
341    uint8 c = 0;
342
343    for (i = 0; i < extra_len; i++) 
344    {
345      if (!prs_uint8("acl extra space", ps, depth, &c))
346      {
347        free(psa);
348        *ppsa = NULL;
349        return false;
350      }
351    }
352  }
353
354  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
355                      offset_acl_size, old_offset))
356  { 
357    free(psa);
358    *ppsa = NULL;
359    return false; 
360  }
361
362  return true;
363}
364
365
366/*******************************************************************
367 Reads or writes a SEC_DESC structure.
368 If reading and the *ppsd = NULL, allocates the structure.
369********************************************************************/
370bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
371{
372  uint32 old_offset;
373  uint32 max_offset = 0; /* after we're done, move offset to end */
374  uint32 tmp_offset = 0;
375
376  SEC_DESC *psd;
377
378  if (ppsd == NULL || ps == NULL)
379    return false;
380
381  psd = *ppsd;
382  if (psd == NULL) 
383  {
384    if(ps->io) 
385    {
386      if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
387        return false;
388      *ppsd = psd;
389    } 
390    else 
391    {
392      /* Marshalling - just ignore. */
393      return true;
394    }
395  }
396
397  depth++;
398
399  /* start of security descriptor stored for back-calc offset purposes */
400  old_offset = ps->data_offset;
401
402  if(!prs_uint16("revision ", ps, depth, &psd->revision)
403     || !prs_uint16("type     ", ps, depth, &psd->type))
404  {
405    free(psd);
406    *ppsd = NULL;
407    return false;
408  }
409
410  if (!ps->io)
411  {
412    uint32 offset = SEC_DESC_HEADER_SIZE;
413
414    /*
415     * Work out the offsets here, as we write it out.
416     */
417
418    if (psd->sacl != NULL) 
419    {
420      psd->off_sacl = offset;
421      offset += psd->sacl->size;
422    } 
423    else
424      psd->off_sacl = 0;
425
426    if (psd->dacl != NULL) 
427    {
428      psd->off_dacl = offset;
429      offset += psd->dacl->size;
430    } 
431    else 
432      psd->off_dacl = 0;
433
434    if (psd->owner_sid != NULL) 
435    {
436      psd->off_owner_sid = offset;
437      offset += sid_size(psd->owner_sid);
438    } 
439    else
440      psd->off_owner_sid = 0;
441
442    if (psd->grp_sid != NULL) 
443    {
444      psd->off_grp_sid = offset;
445      offset += sid_size(psd->grp_sid);
446    } 
447    else
448      psd->off_grp_sid = 0;
449  }
450
451  if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)
452     || !prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid)
453     || !prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl)
454     || !prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
455  {
456    free(psd);
457    *ppsd = NULL;   
458    return false;
459  }
460  max_offset = MAX(max_offset, ps->data_offset);
461
462  if (psd->off_owner_sid != 0) 
463  {
464    tmp_offset = ps->data_offset;
465    if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
466    {
467      free(psd);
468      *ppsd = NULL;
469      return false;
470    }
471
472    if (ps->io) 
473    {
474      /* reading */
475      if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
476      {
477        free(psd);
478        *ppsd = NULL;
479        return false;
480      }
481    }
482
483    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
484    {
485      if(ps->io)
486        free(psd->owner_sid);
487      free(psd);
488      *ppsd = NULL;
489      return false;
490    }
491
492    max_offset = MAX(max_offset, ps->data_offset);
493
494    if (!prs_set_offset(ps,tmp_offset))
495    {
496      if(ps->io)
497        free(psd->owner_sid);
498      free(psd);
499      *ppsd = NULL;
500      return false;
501    }
502  }
503
504  if (psd->off_grp_sid != 0) 
505  {
506    tmp_offset = ps->data_offset;
507    if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
508    {
509      if(ps->io)
510        free(psd->owner_sid);
511      free(psd);
512      *ppsd = NULL;
513      return false;
514    }
515
516    if (ps->io) 
517    {
518      /* reading */
519      if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
520      {
521        free(psd->owner_sid);
522        free(psd);
523        *ppsd = NULL;
524        return false;
525      }
526    }
527
528    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
529    {
530      if(ps->io)
531      {
532        free(psd->grp_sid);
533        free(psd->owner_sid);
534      }
535      free(psd);
536      *ppsd = NULL;
537      return false;
538    }
539                       
540    max_offset = MAX(max_offset, ps->data_offset);
541
542    if (!prs_set_offset(ps,tmp_offset))
543    {
544      if(ps->io)
545      {
546        free(psd->grp_sid);
547        free(psd->owner_sid);
548      }
549      free(psd);
550      *ppsd = NULL;
551      return false;
552    }
553  }
554
555  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
556  {
557    tmp_offset = ps->data_offset;
558    if(!prs_set_offset(ps, old_offset + psd->off_sacl)
559       || !sec_io_acl("sacl", &psd->sacl, ps, depth))
560    {
561      if(ps->io)
562      {
563        free(psd->grp_sid);
564        free(psd->owner_sid);
565      }
566      free(psd);
567      *ppsd = NULL;
568      return false;
569    }
570    max_offset = MAX(max_offset, ps->data_offset);
571    if (!prs_set_offset(ps,tmp_offset))
572    {
573      if(ps->io)
574      {
575        free(psd->grp_sid);
576        free(psd->owner_sid);
577      }
578      free(psd);
579      *ppsd = NULL;
580      return false;
581    }
582  }
583
584  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
585  {
586    tmp_offset = ps->data_offset;
587    if(!prs_set_offset(ps, old_offset + psd->off_dacl)
588       || !sec_io_acl("dacl", &psd->dacl, ps, depth))
589    {
590      if(ps->io)
591      {
592        free(psd->grp_sid);
593        free(psd->owner_sid);
594      }
595      free(psd);
596      *ppsd = NULL;
597      return false;
598    }
599    max_offset = MAX(max_offset, ps->data_offset);
600    if (!prs_set_offset(ps,tmp_offset))
601    {
602      if(ps->io)
603      {
604        free(psd->grp_sid);
605        free(psd->owner_sid);
606      }
607      free(psd);
608      *ppsd = NULL;
609      return false;
610    }
611  }
612
613  if(!prs_set_offset(ps, max_offset))
614  {
615      if(ps->io)
616      {
617        free(psd->grp_sid);
618        free(psd->owner_sid);
619      }
620      free(psd);
621      *ppsd = NULL;
622      return false;
623  }
624
625  return true;
626}
627
628/* End of stuff from rpc_parse/parse_sec.c */
629
630/* From lib/secace.c */
631
632/*******************************************************************
633 Compares two SEC_ACE structures
634********************************************************************/
635bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
636{
637  /* Trivial cases */
638  if (!s1 && !s2) 
639    return true;
640  if (!s1 || !s2) 
641    return false;
642
643  /* Check top level stuff */
644  if (s1->type != s2->type || s1->flags != s2->flags ||
645      s1->info.mask != s2->info.mask) 
646  { return false; }
647
648  /* Check SID */
649  if (!sid_equal(&s1->trustee, &s2->trustee))
650    return false;
651
652  return true;
653}
654
655/* End of stuff from lib/secace.c */
656
657/* From lib/secacl.c */
658
659/*******************************************************************
660 Compares two SEC_ACL structures
661********************************************************************/
662
663bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
664{
665  unsigned int i, j;
666
667  /* Trivial cases */
668  if (!s1 && !s2) 
669    return true;
670  if (!s1 || !s2) 
671    return false;
672
673  /* Check top level stuff */
674  if (s1->revision != s2->revision)
675    return false;
676
677  if (s1->num_aces != s2->num_aces)
678    return false;
679
680  /* The ACEs could be in any order so check each ACE in s1 against
681     each ACE in s2. */
682
683  for (i = 0; i < s1->num_aces; i++) 
684  {
685    bool found = false;
686
687    for (j = 0; j < s2->num_aces; j++) 
688    {
689      if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) 
690      {
691        found = true;
692        break;
693      }
694    }
695
696    if (!found)
697      return false;
698  }
699
700  return true;
701}
702
703/* End of stuff from lib/secacl.c */
704
705/* From lib/secdesc.c */
706
707/*******************************************************************
708 Compares two SEC_DESC structures
709********************************************************************/
710bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
711{
712  /* Trivial cases */
713  if (!s1 && !s2)
714    return true;
715  if (!s1 || !s2)
716    return false;
717
718  /* Check top level stuff */
719  if (s1->revision != s2->revision)
720    return false;
721
722  if (s1->type!= s2->type)
723    return false;
724
725  /* Check owner and group */
726  if (!sid_equal(s1->owner_sid, s2->owner_sid))
727    return false;
728
729  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
730    return false;
731
732  /* Check ACLs present in one but not the other */
733  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
734      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
735  { return false; }
736
737  /* Sigh - we have to do it the hard way by iterating over all
738     the ACEs in the ACLs */
739  if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) 
740    return false;
741
742  return true;
743}
744
745/* End of stuff from lib/secdesc.c */
Note: See TracBrowser for help on using the repository browser.