source: releases/0.3.0/lib/smb_deps.c @ 87

Last change on this file since 87 was 65, checked in by tim, 18 years ago

fixed a bug in types

added paranoid checks in smb_deps to prevent NULL pointer dereferences and corner-case memory leaks.

  • Property svn:keywords set to Id
File size: 29.2 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 65 2006-07-23 17:00:20Z 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(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(bool charmode, 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(bool charmode, 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 (false, "data   ", ps, depth, 
529                  uuid->clock_seq, sizeof(uuid->clock_seq)))
530    return false;
531
532  if(!prs_uint8s (false, "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(false, "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.