source: releases/0.4.0/lib/smb_deps.c @ 102

Last change on this file since 102 was 84, checked in by tim, 18 years ago

rearranged structure contents to reduce fragmentation on 64 bit systems.

make regfi interface return const structures to help enforce separation

removed a little cruft from some parsing functions

  • Property svn:keywords set to Id
File size: 29.1 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 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 2 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: smb_deps.c 84 2007-01-19 14:52:25Z tim $
24 */
25
26#include "../include/smb_deps.h"
27
28
29/* These act as replacements for numerous Samba memory allocation
30 *   functions.
31 */
32void* zalloc(size_t size)
33{
34  void* ret_val = NULL;
35  if((ret_val = (void*)malloc(size)) != NULL)
36    memset(ret_val, 0, size);
37  return ret_val;
38}
39
40void* zcalloc(size_t size, unsigned int count)
41{
42  return zalloc(size*count);
43}
44
45/* From lib/time.c */
46
47/****************************************************************************
48 Put a 8 byte filetime from a time_t
49 This takes real GMT as input and converts to kludge-GMT
50****************************************************************************/
51void unix_to_nt_time(NTTIME *nt, time_t t)
52{
53  double d;
54 
55  if (t==0) 
56  {
57    nt->low = 0;
58    nt->high = 0;
59    return;
60  }
61 
62  if (t == TIME_T_MAX) 
63  {
64    nt->low = 0xffffffff;
65    nt->high = 0x7fffffff;
66    return;
67  }             
68 
69  if (t == -1) 
70  {
71    nt->low = 0xffffffff;
72    nt->high = 0xffffffff;
73    return;
74  }             
75 
76  /* this converts GMT to kludge-GMT */
77  /* XXX: This was removed due to difficult dependency requirements. 
78   *      So far, times appear to be correct without this adjustment, but
79   *      that may be proven wrong with adequate testing.
80   */
81  /* t -= TimeDiff(t) - get_serverzone(); */
82 
83  d = (double)(t);
84  d += TIME_FIXUP_CONSTANT;
85  d *= 1.0e7;
86 
87  nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
88  nt->low  = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
89}
90
91
92/****************************************************************************
93 Interpret an 8 byte "filetime" structure to a time_t
94 It's originally in "100ns units since jan 1st 1601"
95
96 An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0.
97
98 It appears to be kludge-GMT (at least for file listings). This means
99 its the GMT you get by taking a localtime and adding the
100 serverzone. This is NOT the same as GMT in some cases. This routine
101 converts this to real GMT.
102****************************************************************************/
103time_t nt_time_to_unix(const NTTIME* nt)
104{
105  double d;
106  time_t ret;
107  /* The next two lines are a fix needed for the
108     broken SCO compiler. JRA. */
109  time_t l_time_min = TIME_T_MIN;
110  time_t l_time_max = TIME_T_MAX;
111 
112  if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff))
113    return(0);
114 
115  d = ((double)nt->high)*4.0*(double)(1<<30);
116  d += (nt->low&0xFFF00000);
117  d *= 1.0e-7;
118 
119  /* now adjust by 369 years to make the secs since 1970 */
120  d -= TIME_FIXUP_CONSTANT;
121 
122  if (d <= l_time_min)
123    return (l_time_min);
124 
125  if (d >= l_time_max)
126    return (l_time_max);
127 
128  ret = (time_t)(d+0.5);
129 
130  /* this takes us from kludge-GMT to real GMT */
131  /* XXX: This was removed due to difficult dependency requirements. 
132   *      So far, times appear to be correct without this adjustment, but
133   *      that may be proven wrong with adequate testing.
134   */
135  /*
136    ret -= get_serverzone();
137    ret += LocTimeDiff(ret);
138  */
139
140  return(ret);
141}
142
143/* End of stuff from lib/time.c */
144
145/* From parse_prs.c */
146
147/*******************************************************************
148 Attempt, if needed, to grow a data buffer.
149 Also depends on the data stream mode (io).
150 ********************************************************************/
151bool prs_grow(prs_struct *ps, uint32 extra_space)
152{
153  uint32 new_size;
154  char *new_data;
155 
156  ps->grow_size = MAX(ps->grow_size, ps->data_offset + extra_space);
157 
158  if(ps->data_offset + extra_space <= ps->buffer_size)
159    return true;
160 
161  /*
162   * We cannot grow the buffer if we're not reading
163   * into the prs_struct, or if we don't own the memory.
164   */
165 
166  if(ps->io || !ps->is_dynamic)
167    return false;
168 
169  /*
170   * Decide how much extra space we really need.
171   */
172  extra_space -= (ps->buffer_size - ps->data_offset);
173  if(ps->buffer_size == 0) 
174  {
175    /*
176     * Ensure we have at least a PDU's length, or extra_space,
177     * whichever is greater.
178     */ 
179    new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
180   
181    if((new_data = zalloc(new_size)) == NULL)
182      return false;
183  } 
184  else 
185  {
186    /*
187     * If the current buffer size is bigger than the space needed, just
188     * double it, else add extra_space.
189     */
190    new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);           
191   
192    if ((new_data = (char*)realloc(ps->data_p, new_size)) == NULL)
193      return false;
194   
195    memset(&new_data[ps->buffer_size], '\0', 
196           (size_t)(new_size - ps->buffer_size));
197  }
198  ps->buffer_size = new_size;
199  ps->data_p = new_data;
200 
201  return true;
202}
203
204
205/*******************************************************************
206 Align a the data_len to a multiple of align bytes - filling with
207 zeros.
208 ********************************************************************/
209bool prs_align(prs_struct *ps)
210{
211  uint32 mod = ps->data_offset & (ps->align-1);
212 
213  if (ps->align != 0 && mod != 0) 
214  {
215    uint32 extra_space = (ps->align - mod);
216    if(!prs_grow(ps, extra_space))
217      return false;
218    memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
219    ps->data_offset += extra_space;
220  }
221 
222  return true;
223}
224
225
226/**
227 * Initialise an expandable parse structure.
228 *
229 * @param size Initial buffer size.  If >0, a new buffer will be
230 * created with malloc().
231 *
232 * @return false if allocation fails, otherwise true.
233 **/
234
235bool prs_init(prs_struct *ps, uint32 size, void *ctx, bool io)
236{
237  if(ps == NULL)
238    return false;
239  memset(ps, 0, sizeof(prs_struct));
240
241  ps->io = io;
242  ps->bigendian_data = RPC_LITTLE_ENDIAN;
243  ps->align = RPC_PARSE_ALIGN;
244  ps->is_dynamic = false;
245  ps->data_offset = 0;
246  ps->buffer_size = 0;
247  ps->data_p = NULL;
248  ps->mem_ctx = ctx;
249 
250  if (size != 0) 
251  {
252    ps->buffer_size = size;
253    if((ps->data_p = (char *)zalloc((size_t)size)) == NULL)
254      return false;
255
256    ps->is_dynamic = true; /* We own this memory. */
257  }
258 
259  return true;
260}
261
262
263char *prs_mem_get(prs_struct *ps, uint32 extra_size)
264{
265  if(ps->io) 
266  {
267    /*
268     * If reading, ensure that we can read the requested size item.
269     */
270    if (ps->data_offset + extra_size > ps->buffer_size)
271      return NULL;
272  } 
273  else 
274  {
275    /*
276     * Writing - grow the buffer if needed.
277     */
278    if(!prs_grow(ps, extra_size))
279      return NULL;
280  }
281
282  return &ps->data_p[ps->data_offset];
283}
284
285
286/*******************************************************************
287 Stream a uint32.
288 ********************************************************************/
289bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32)
290{
291  char *q = prs_mem_get(ps, sizeof(uint32));
292  if (q == NULL)
293    return false;
294 
295  if (ps->io) 
296  {
297    if (ps->bigendian_data)
298      *data32 = RIVAL(q,0);
299    else
300      *data32 = IVAL(q,0);
301  } 
302  else 
303  {
304    if (ps->bigendian_data)
305      RSIVAL(q,0,*data32);
306    else
307      SIVAL(q,0,*data32);
308  }
309  ps->data_offset += sizeof(uint32);
310 
311  return true;
312}
313
314
315/******************************************************************
316 Stream an array of uint32s. Length is number of uint32s.
317 ********************************************************************/
318bool prs_uint32s(const char *name, prs_struct *ps, 
319                 int depth, uint32 *data32s, int len)
320{
321  int i;
322  char *q = prs_mem_get(ps, len * sizeof(uint32));
323  if (q == NULL)
324    return false;
325 
326  if (ps->io) 
327  {
328    if (ps->bigendian_data) 
329    {
330      for (i = 0; i < len; i++)
331        data32s[i] = RIVAL(q, 4*i);
332    } 
333    else 
334    {
335      for (i = 0; i < len; i++)
336        data32s[i] = IVAL(q, 4*i);
337    }
338  } 
339  else 
340  {
341    if (ps->bigendian_data) 
342    {
343      for (i = 0; i < len; i++)
344        RSIVAL(q, 4*i, data32s[i]);
345    } 
346    else 
347    {
348      for (i = 0; i < len; i++)
349        SIVAL(q, 4*i, data32s[i]);
350    }
351  }
352  ps->data_offset += (len * sizeof(uint32));
353 
354  return true;
355}
356
357
358/*******************************************************************
359 Stream a uint16.
360 ********************************************************************/
361bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16)
362{
363  char *q = prs_mem_get(ps, sizeof(uint16));
364  if (q == NULL)
365    return false;
366 
367  if (ps->io) 
368  {
369    if (ps->bigendian_data)
370      *data16 = RSVAL(q,0);
371    else
372      *data16 = SVAL(q,0);
373  } 
374  else 
375  {
376    if (ps->bigendian_data)
377      RSSVAL(q,0,*data16);
378    else
379      SSVAL(q,0,*data16);
380  }
381  ps->data_offset += sizeof(uint16);
382 
383  return true;
384}
385
386
387/*******************************************************************
388 prs_uint16 wrapper. Call this and it sets up a pointer to where the
389 uint16 should be stored, or gets the size if reading.
390 ********************************************************************/
391bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, 
392                    uint16 *data16, uint32 *offset)
393{
394  *offset = ps->data_offset;
395  if (ps->io) 
396  {
397    /* reading. */
398    return prs_uint16(name, ps, depth, data16);
399  } 
400  else 
401  {
402    char *q = prs_mem_get(ps, sizeof(uint16));
403    if(q ==NULL)
404      return false;
405    ps->data_offset += sizeof(uint16);
406  }
407  return true;
408}
409
410
411/*******************************************************************
412 prs_uint16 wrapper.  call this and it retrospectively stores the size.
413 does nothing on reading, as that is already handled by ...._pre()
414 ********************************************************************/
415bool prs_uint16_post(const char *name, prs_struct *ps, int depth, 
416                     uint16 *data16, uint32 ptr_uint16, uint32 start_offset)
417{
418  if (!ps->io) 
419  {
420    /*
421     * Writing - temporarily move the offset pointer.
422     */
423    uint16 data_size = ps->data_offset - start_offset;
424    uint32 old_offset = ps->data_offset;
425   
426    ps->data_offset = ptr_uint16;
427    if(!prs_uint16(name, ps, depth, &data_size)) 
428    {
429      ps->data_offset = old_offset;
430      return false;
431    }
432    ps->data_offset = old_offset;
433  } 
434  else 
435    ps->data_offset = start_offset + (uint32)(*data16);
436
437  return true;
438}
439
440
441/*******************************************************************
442 Stream a uint8.
443 ********************************************************************/
444bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
445{
446  char *q = prs_mem_get(ps, 1);
447  if (q == NULL)
448    return false;
449 
450  if (ps->io)
451    *data8 = CVAL(q,0);
452  else
453    SCVAL(q,0,*data8);
454 
455  ps->data_offset += 1;
456 
457  return true;
458}
459
460
461/******************************************************************
462 Stream an array of uint8s. Length is number of uint8s.
463 ********************************************************************/
464bool prs_uint8s(const char *name, prs_struct *ps, int depth, 
465                uint8* data8s, int len)
466{
467  int i;
468  char *q = prs_mem_get(ps, len);
469  if (q == NULL)
470    return false;
471 
472  if (ps->io) 
473  {
474    for (i = 0; i < len; i++)
475      data8s[i] = CVAL(q,i);
476  } 
477  else 
478  {
479    for (i = 0; i < len; i++)
480      SCVAL(q, i, data8s[i]);
481  }
482 
483  ps->data_offset += len;
484 
485  return true;
486}
487
488
489/*******************************************************************
490 Set the current offset (external interface).
491 ********************************************************************/
492bool prs_set_offset(prs_struct *ps, uint32 offset)
493{
494  if(offset <= ps->data_offset) 
495  {
496    ps->data_offset = offset;
497    return true;
498  }
499 
500  if(!prs_grow(ps, offset - ps->data_offset))
501    return false;
502 
503  ps->data_offset = offset;
504  return true;
505}
506
507/* End of stuff from parse_prs.c */
508
509/* From rpc_parse/parse_misc.c */
510
511/*******************************************************************
512 Reads or writes a struct uuid
513********************************************************************/
514bool smb_io_uuid(const char *desc, struct uuid *uuid, 
515                 prs_struct *ps, int depth)
516{
517  if (uuid == NULL)
518    return false;
519  depth++;
520 
521  if(!prs_uint32 ("data   ", ps, depth, &uuid->time_low))
522    return false;
523  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_mid))
524    return false;
525  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_hi_and_version))
526    return false;
527 
528  if(!prs_uint8s ("data   ", ps, depth, 
529                  uuid->clock_seq, sizeof(uuid->clock_seq)))
530    return false;
531
532  if(!prs_uint8s ("data   ", ps, depth, uuid->node, sizeof(uuid->node)))
533    return false;
534 
535  return true;
536}
537
538
539/*******************************************************************
540 Reads or writes an NTTIME structure.
541********************************************************************/
542bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
543{
544  if (nttime == NULL)
545    return false;
546  depth++;
547
548  if(!prs_align(ps))
549    return false;
550       
551  if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
552    return false;
553  if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
554    return false;
555
556  return true;
557}
558
559
560/*******************************************************************
561 Reads or writes a DOM_SID structure.
562********************************************************************/
563bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
564{
565  int i;
566
567  if (sid == NULL)
568    return false;
569  depth++;
570
571  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
572    return false;
573
574  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
575    return false;
576
577  for (i = 0; i < 6; i++)
578  {
579    fstring tmp;
580    snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
581    if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
582      return false;
583  }
584
585  /* oops! XXXX should really issue a warning here... */
586  if (sid->num_auths > MAXSUBAUTHS)
587    sid->num_auths = MAXSUBAUTHS;
588
589  if(!prs_uint32s("sub_auths ", ps, depth, 
590                  sid->sub_auths, sid->num_auths))
591  { return false; }
592
593  return true;
594}
595
596/* End of stuff from rpc_parse/parse_misc.c */
597
598/* From lib/util_sid.c */
599
600/*****************************************************************
601 Calculates size of a sid.
602*****************************************************************/ 
603size_t sid_size(const DOM_SID *sid)
604{
605  if (sid == NULL)
606    return 0;
607
608  return sid->num_auths * sizeof(uint32) + 8;
609}
610
611
612/*****************************************************************
613 Compare the auth portion of two sids.
614*****************************************************************/ 
615int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
616{
617  int i;
618
619  if (sid1 == sid2)
620    return 0;
621  if (!sid1)
622    return -1;
623  if (!sid2)
624    return 1;
625
626  if (sid1->sid_rev_num != sid2->sid_rev_num)
627    return sid1->sid_rev_num - sid2->sid_rev_num;
628
629  for (i = 0; i < 6; i++)
630    if (sid1->id_auth[i] != sid2->id_auth[i])
631      return sid1->id_auth[i] - sid2->id_auth[i];
632
633  return 0;
634}
635
636
637/*****************************************************************
638 Compare two sids.
639*****************************************************************/ 
640int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
641{
642  int i;
643
644  if (sid1 == sid2)
645    return 0;
646  if (!sid1)
647    return -1;
648  if (!sid2)
649    return 1;
650
651  /* Compare most likely different rids, first: i.e start at end */
652  if (sid1->num_auths != sid2->num_auths)
653    return sid1->num_auths - sid2->num_auths;
654
655  for (i = sid1->num_auths-1; i >= 0; --i)
656    if (sid1->sub_auths[i] != sid2->sub_auths[i])
657      return sid1->sub_auths[i] - sid2->sub_auths[i];
658
659  return sid_compare_auth(sid1, sid2);
660}
661
662
663/*****************************************************************
664 Compare two sids.
665*****************************************************************/ 
666bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
667{
668  return sid_compare(sid1, sid2) == 0;
669}
670
671/* End of stuff from lib/util_sid.c */
672
673/* From lib/secace.c */
674
675/*******************************************************************
676 Check if ACE has OBJECT type.
677********************************************************************/
678
679bool sec_ace_object(uint8 type)
680{
681  if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
682      type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
683      type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
684      type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
685    return true;
686  }
687  return false;
688}
689
690/* End of stuff from lib/secace.c */
691
692/* From rpc_parse/parse_sec.c */
693
694/*******************************************************************
695 Reads or writes a SEC_ACCESS structure.
696********************************************************************/
697bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
698{
699  if (t == NULL)
700    return false;
701
702  depth++;
703       
704  if(!prs_uint32("mask", ps, depth, &t->mask))
705    return false;
706
707  return true;
708}
709
710
711/*******************************************************************
712 Reads or writes a SEC_ACE structure.
713********************************************************************/
714bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
715{
716  uint32 old_offset;
717  uint32 offset_ace_size;
718
719  if (psa == NULL)
720    return false;
721
722  depth++;
723       
724  old_offset = ps->data_offset;
725
726  if(!prs_uint8("type ", ps, depth, &psa->type))
727    return false;
728
729  if(!prs_uint8("flags", ps, depth, &psa->flags))
730    return false;
731
732  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
733    return false;
734
735  if(!sec_io_access("info ", &psa->info, ps, depth))
736    return false;
737
738  /* check whether object access is present */
739  if (!sec_ace_object(psa->type)) 
740  {
741    if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
742      return false;
743  } 
744  else 
745  {
746    if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
747      return false;
748
749    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
750      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
751        return false;
752
753    if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
754      if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
755        return false;
756
757    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
758      return false;
759  }
760
761  /* Theorectically an ACE can have a size greater than the
762   * sum of its components. When marshalling, pad with extra null bytes
763   * up to the
764   * correct size.
765   */
766  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
767  {
768    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
769    uint32 i;
770    uint8 c = 0;
771
772    for (i = 0; i < extra_len; i++) 
773    {
774      if (!prs_uint8("ace extra space", ps, depth, &c))
775        return false;
776    }
777  }
778
779  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
780                      offset_ace_size, old_offset))
781  { return false; }
782
783  return true;
784}
785
786
787/*******************************************************************
788 Reads or writes a SEC_ACL structure. 
789
790 First of the xx_io_xx functions that allocates its data structures
791 for you as it reads them.
792********************************************************************/
793bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
794{
795  unsigned int i;
796  uint32 old_offset;
797  uint32 offset_acl_size;
798  SEC_ACL* psa;
799
800  /*
801   * Note that the size is always a multiple of 4 bytes due to the
802   * nature of the data structure.  Therefore the prs_align() calls
803   * have been removed as they through us off when doing two-layer
804   * marshalling such as in the printing code (RPC_BUFFER).  --jerry
805   */
806
807  if (ppsa == NULL || ps == NULL)
808    return false;
809
810  psa = *ppsa;
811
812  if(ps->io && psa == NULL) 
813  {
814    /*
815     * This is a read and we must allocate the stuct to read into.
816     */
817    if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
818      return false;
819    *ppsa = psa;
820  }
821
822  depth++;     
823  old_offset = ps->data_offset;
824
825  if(!prs_uint16("revision", ps, depth, &psa->revision)
826     || !prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size)
827     || !prs_uint32("num_aces ", ps, depth, &psa->num_aces))
828  {
829    free(psa);
830    *ppsa = NULL;
831    return false;
832  }
833
834  if (ps->io) 
835  {
836    /*
837     * Even if the num_aces is zero, allocate memory as there's a difference
838     * between a non-present DACL (allow all access) and a DACL with no ACE's
839     * (allow no access).
840     */
841    if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
842    {
843      free(psa);
844      *ppsa = NULL;
845      return false;
846    }
847  }
848
849  for (i = 0; i < psa->num_aces; i++) 
850  {
851    fstring tmp;
852    snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
853    if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
854    {
855      free(psa);
856      *ppsa = NULL;
857      return false;
858    }
859  }
860
861  /* Theoretically an ACL can have a size greater than the
862   *  sum of its components. When marshalling, pad with extra null
863   *  bytes up to the
864   *  correct size.
865   */
866  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
867  {
868    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
869    uint8 c = 0;
870
871    for (i = 0; i < extra_len; i++) 
872    {
873      if (!prs_uint8("acl extra space", ps, depth, &c))
874      {
875        free(psa);
876        *ppsa = NULL;
877        return false;
878      }
879    }
880  }
881
882  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
883                      offset_acl_size, old_offset))
884  { 
885    free(psa);
886    *ppsa = NULL;
887    return false; 
888  }
889
890  return true;
891}
892
893
894/*******************************************************************
895 Reads or writes a SEC_DESC structure.
896 If reading and the *ppsd = NULL, allocates the structure.
897********************************************************************/
898bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
899{
900  uint32 old_offset;
901  uint32 max_offset = 0; /* after we're done, move offset to end */
902  uint32 tmp_offset = 0;
903
904  SEC_DESC *psd;
905
906  if (ppsd == NULL || ps == NULL)
907    return false;
908
909  psd = *ppsd;
910  if (psd == NULL) 
911  {
912    if(ps->io) 
913    {
914      if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
915        return false;
916      *ppsd = psd;
917    } 
918    else 
919    {
920      /* Marshalling - just ignore. */
921      return true;
922    }
923  }
924
925  depth++;
926
927  /* start of security descriptor stored for back-calc offset purposes */
928  old_offset = ps->data_offset;
929
930  if(!prs_uint16("revision ", ps, depth, &psd->revision)
931     || !prs_uint16("type     ", ps, depth, &psd->type))
932  {
933    free(psd);
934    *ppsd = NULL;
935    return false;
936  }
937
938  if (!ps->io)
939  {
940    uint32 offset = SEC_DESC_HEADER_SIZE;
941
942    /*
943     * Work out the offsets here, as we write it out.
944     */
945
946    if (psd->sacl != NULL) 
947    {
948      psd->off_sacl = offset;
949      offset += psd->sacl->size;
950    } 
951    else
952      psd->off_sacl = 0;
953
954    if (psd->dacl != NULL) 
955    {
956      psd->off_dacl = offset;
957      offset += psd->dacl->size;
958    } 
959    else 
960      psd->off_dacl = 0;
961
962    if (psd->owner_sid != NULL) 
963    {
964      psd->off_owner_sid = offset;
965      offset += sid_size(psd->owner_sid);
966    } 
967    else
968      psd->off_owner_sid = 0;
969
970    if (psd->grp_sid != NULL) 
971    {
972      psd->off_grp_sid = offset;
973      offset += sid_size(psd->grp_sid);
974    } 
975    else
976      psd->off_grp_sid = 0;
977  }
978
979  if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)
980     || !prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid)
981     || !prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl)
982     || !prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
983  {
984    free(psd);
985    *ppsd = NULL;   
986    return false;
987  }
988  max_offset = MAX(max_offset, ps->data_offset);
989
990  if (psd->off_owner_sid != 0) 
991  {
992    tmp_offset = ps->data_offset;
993    if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
994    {
995      free(psd);
996      *ppsd = NULL;
997      return false;
998    }
999
1000    if (ps->io) 
1001    {
1002      /* reading */
1003      if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
1004      {
1005        free(psd);
1006        *ppsd = NULL;
1007        return false;
1008      }
1009    }
1010
1011    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
1012    {
1013      if(ps->io)
1014        free(psd->owner_sid);
1015      free(psd);
1016      *ppsd = NULL;
1017      return false;
1018    }
1019
1020    max_offset = MAX(max_offset, ps->data_offset);
1021
1022    if (!prs_set_offset(ps,tmp_offset))
1023    {
1024      if(ps->io)
1025        free(psd->owner_sid);
1026      free(psd);
1027      *ppsd = NULL;
1028      return false;
1029    }
1030  }
1031
1032  if (psd->off_grp_sid != 0) 
1033  {
1034    tmp_offset = ps->data_offset;
1035    if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
1036    {
1037      if(ps->io)
1038        free(psd->owner_sid);
1039      free(psd);
1040      *ppsd = NULL;
1041      return false;
1042    }
1043
1044    if (ps->io) 
1045    {
1046      /* reading */
1047      if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
1048      {
1049        free(psd->owner_sid);
1050        free(psd);
1051        *ppsd = NULL;
1052        return false;
1053      }
1054    }
1055
1056    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
1057    {
1058      if(ps->io)
1059      {
1060        free(psd->grp_sid);
1061        free(psd->owner_sid);
1062      }
1063      free(psd);
1064      *ppsd = NULL;
1065      return false;
1066    }
1067                       
1068    max_offset = MAX(max_offset, ps->data_offset);
1069
1070    if (!prs_set_offset(ps,tmp_offset))
1071    {
1072      if(ps->io)
1073      {
1074        free(psd->grp_sid);
1075        free(psd->owner_sid);
1076      }
1077      free(psd);
1078      *ppsd = NULL;
1079      return false;
1080    }
1081  }
1082
1083  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
1084  {
1085    tmp_offset = ps->data_offset;
1086    if(!prs_set_offset(ps, old_offset + psd->off_sacl)
1087       || !sec_io_acl("sacl", &psd->sacl, ps, depth))
1088    {
1089      if(ps->io)
1090      {
1091        free(psd->grp_sid);
1092        free(psd->owner_sid);
1093      }
1094      free(psd);
1095      *ppsd = NULL;
1096      return false;
1097    }
1098    max_offset = MAX(max_offset, ps->data_offset);
1099    if (!prs_set_offset(ps,tmp_offset))
1100    {
1101      if(ps->io)
1102      {
1103        free(psd->grp_sid);
1104        free(psd->owner_sid);
1105      }
1106      free(psd);
1107      *ppsd = NULL;
1108      return false;
1109    }
1110  }
1111
1112  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
1113  {
1114    tmp_offset = ps->data_offset;
1115    if(!prs_set_offset(ps, old_offset + psd->off_dacl)
1116       || !sec_io_acl("dacl", &psd->dacl, ps, depth))
1117    {
1118      if(ps->io)
1119      {
1120        free(psd->grp_sid);
1121        free(psd->owner_sid);
1122      }
1123      free(psd);
1124      *ppsd = NULL;
1125      return false;
1126    }
1127    max_offset = MAX(max_offset, ps->data_offset);
1128    if (!prs_set_offset(ps,tmp_offset))
1129    {
1130      if(ps->io)
1131      {
1132        free(psd->grp_sid);
1133        free(psd->owner_sid);
1134      }
1135      free(psd);
1136      *ppsd = NULL;
1137      return false;
1138    }
1139  }
1140
1141  if(!prs_set_offset(ps, max_offset))
1142  {
1143      if(ps->io)
1144      {
1145        free(psd->grp_sid);
1146        free(psd->owner_sid);
1147      }
1148      free(psd);
1149      *ppsd = NULL;
1150      return false;
1151  }
1152
1153  return true;
1154}
1155
1156/* End of stuff from rpc_parse/parse_sec.c */
1157
1158/* From lib/secace.c */
1159
1160/*******************************************************************
1161 Compares two SEC_ACE structures
1162********************************************************************/
1163bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
1164{
1165  /* Trivial cases */
1166  if (!s1 && !s2) 
1167    return true;
1168  if (!s1 || !s2) 
1169    return false;
1170
1171  /* Check top level stuff */
1172  if (s1->type != s2->type || s1->flags != s2->flags ||
1173      s1->info.mask != s2->info.mask) 
1174  { return false; }
1175
1176  /* Check SID */
1177  if (!sid_equal(&s1->trustee, &s2->trustee))
1178    return false;
1179
1180  return true;
1181}
1182
1183/* End of stuff from lib/secace.c */
1184
1185/* From lib/secacl.c */
1186
1187/*******************************************************************
1188 Compares two SEC_ACL structures
1189********************************************************************/
1190
1191bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
1192{
1193  unsigned int i, j;
1194
1195  /* Trivial cases */
1196  if (!s1 && !s2) 
1197    return true;
1198  if (!s1 || !s2) 
1199    return false;
1200
1201  /* Check top level stuff */
1202  if (s1->revision != s2->revision)
1203    return false;
1204
1205  if (s1->num_aces != s2->num_aces)
1206    return false;
1207
1208  /* The ACEs could be in any order so check each ACE in s1 against
1209     each ACE in s2. */
1210
1211  for (i = 0; i < s1->num_aces; i++) 
1212  {
1213    bool found = false;
1214
1215    for (j = 0; j < s2->num_aces; j++) 
1216    {
1217      if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) 
1218      {
1219        found = true;
1220        break;
1221      }
1222    }
1223
1224    if (!found)
1225      return false;
1226  }
1227
1228  return true;
1229}
1230
1231/* End of stuff from lib/secacl.c */
1232
1233/* From lib/secdesc.c */
1234
1235/*******************************************************************
1236 Compares two SEC_DESC structures
1237********************************************************************/
1238bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
1239{
1240  /* Trivial cases */
1241  if (!s1 && !s2)
1242    return true;
1243  if (!s1 || !s2)
1244    return false;
1245
1246  /* Check top level stuff */
1247  if (s1->revision != s2->revision)
1248    return false;
1249
1250  if (s1->type!= s2->type)
1251    return false;
1252
1253  /* Check owner and group */
1254  if (!sid_equal(s1->owner_sid, s2->owner_sid))
1255    return false;
1256
1257  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
1258    return false;
1259
1260  /* Check ACLs present in one but not the other */
1261  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
1262      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
1263  { return false; }
1264
1265  /* Sigh - we have to do it the hard way by iterating over all
1266     the ACEs in the ACLs */
1267  if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) 
1268    return false;
1269
1270  return true;
1271}
1272
1273/* End of stuff from lib/secdesc.c */
Note: See TracBrowser for help on using the repository browser.