source: trunk/lib/smb_deps.c @ 60

Last change on this file since 60 was 59, checked in by tim, 19 years ago

Updated version

Code format cleanup, some comments added.

  • Property svn:keywords set to Id
File size: 27.7 KB
RevLine 
[30]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 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 59 2005-10-03 01:26:12Z 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;
[31]35  if((ret_val = (void*)malloc(size)) != NULL)
[30]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{
[59]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));
[30]89}
90
[42]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{
[59]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  */
[42]139
[59]140  return(ret);
[42]141}
142
[30]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{
[59]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;
[30]183
[59]184    memset(new_data, '\0', (size_t)new_size );
185  } 
186  else 
187  {
188    /*
189     * If the current buffer size is bigger than the space needed, just
190     * double it, else add extra_space.
191     */
192    new_size = MAX(ps->buffer_size*2, ps->buffer_size + extra_space);           
193   
194    if ((new_data = (char*)realloc(ps->data_p, new_size)) == NULL)
195      return false;
196   
197    memset(&new_data[ps->buffer_size], '\0', 
198           (size_t)(new_size - ps->buffer_size));
199  }
200  ps->buffer_size = new_size;
201  ps->data_p = new_data;
202 
203  return true;
[30]204}
205
206
207/*******************************************************************
208 Align a the data_len to a multiple of align bytes - filling with
209 zeros.
210 ********************************************************************/
211bool prs_align(prs_struct *ps)
212{
[59]213  uint32 mod = ps->data_offset & (ps->align-1);
214 
215  if (ps->align != 0 && mod != 0) 
216  {
217    uint32 extra_space = (ps->align - mod);
218    if(!prs_grow(ps, extra_space))
219      return false;
220    memset(&ps->data_p[ps->data_offset], '\0', (size_t)extra_space);
221    ps->data_offset += extra_space;
222  }
223 
224  return true;
[30]225}
226
227
228/**
229 * Initialise an expandable parse structure.
230 *
231 * @param size Initial buffer size.  If >0, a new buffer will be
232 * created with malloc().
233 *
234 * @return false if allocation fails, otherwise true.
235 **/
236
237bool prs_init(prs_struct *ps, uint32 size, void *ctx, bool io)
238{
[31]239  memset(ps, 0, sizeof(prs_struct));
240  ps->io = io;
241  ps->bigendian_data = RPC_LITTLE_ENDIAN;
242  ps->align = RPC_PARSE_ALIGN;
243  ps->is_dynamic = false;
244  ps->data_offset = 0;
245  ps->buffer_size = 0;
246  ps->data_p = NULL;
247  ps->mem_ctx = ctx;
248 
[59]249  if (size != 0) 
250  {
[31]251    ps->buffer_size = size;
[59]252    if((ps->data_p = (char *)zalloc((size_t)size)) == NULL)
[31]253      return false;
[59]254
[31]255    memset(ps->data_p, '\0', (size_t)size);
256    ps->is_dynamic = true; /* We own this memory. */
257  }
258 
259  return true;
[30]260}
261
262
263char *prs_mem_get(prs_struct *ps, uint32 extra_size)
264{
[59]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  return &ps->data_p[ps->data_offset];
[30]282}
283
284
285/*******************************************************************
286 Stream a uint32.
287 ********************************************************************/
288bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32)
289{
[59]290  char *q = prs_mem_get(ps, sizeof(uint32));
291  if (q == NULL)
292    return false;
293 
294  if (ps->io) 
295  {
296    if (ps->bigendian_data)
297      *data32 = RIVAL(q,0);
298    else
299      *data32 = IVAL(q,0);
300  } 
301  else 
302  {
303    if (ps->bigendian_data)
304      RSIVAL(q,0,*data32);
305    else
306      SIVAL(q,0,*data32);
307  }
308  ps->data_offset += sizeof(uint32);
309 
310  return true;
[30]311}
312
313
314/******************************************************************
315 Stream an array of uint32s. Length is number of uint32s.
316 ********************************************************************/
317bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, 
318                 int depth, uint32 *data32s, int len)
319{
[59]320  int i;
321  char *q = prs_mem_get(ps, len * sizeof(uint32));
322  if (q == NULL)
323    return false;
324 
325  if (ps->io) 
326  {
327    if (ps->bigendian_data) 
328    {
329      for (i = 0; i < len; i++)
330        data32s[i] = RIVAL(q, 4*i);
331    } 
332    else 
333    {
334      for (i = 0; i < len; i++)
335        data32s[i] = IVAL(q, 4*i);
336    }
337  } 
338  else 
339  {
340    if (ps->bigendian_data) 
341    {
342      for (i = 0; i < len; i++)
343        RSIVAL(q, 4*i, data32s[i]);
344    } 
345    else 
346    {
347      for (i = 0; i < len; i++)
348        SIVAL(q, 4*i, data32s[i]);
349    }
350  }
351  ps->data_offset += (len * sizeof(uint32));
352 
353  return true;
[30]354}
355
356
357/*******************************************************************
358 Stream a uint16.
359 ********************************************************************/
360bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16)
361{
[59]362  char *q = prs_mem_get(ps, sizeof(uint16));
363  if (q == NULL)
364    return false;
365 
366  if (ps->io) 
367  {
368    if (ps->bigendian_data)
369      *data16 = RSVAL(q,0);
370    else
371      *data16 = SVAL(q,0);
372  } 
373  else 
374  {
375    if (ps->bigendian_data)
376      RSSVAL(q,0,*data16);
377    else
378      SSVAL(q,0,*data16);
379  }
380  ps->data_offset += sizeof(uint16);
381 
382  return true;
[30]383}
384
385
386/*******************************************************************
387 prs_uint16 wrapper. Call this and it sets up a pointer to where the
388 uint16 should be stored, or gets the size if reading.
389 ********************************************************************/
390bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, 
391                    uint16 *data16, uint32 *offset)
392{
[59]393  *offset = ps->data_offset;
394  if (ps->io) 
395  {
396    /* reading. */
397    return prs_uint16(name, ps, depth, data16);
398  } 
399  else 
400  {
401    char *q = prs_mem_get(ps, sizeof(uint16));
402    if(q ==NULL)
403      return false;
404    ps->data_offset += sizeof(uint16);
405  }
406  return true;
[30]407}
408
409
410/*******************************************************************
411 prs_uint16 wrapper.  call this and it retrospectively stores the size.
412 does nothing on reading, as that is already handled by ...._pre()
413 ********************************************************************/
414bool prs_uint16_post(const char *name, prs_struct *ps, int depth, 
415                     uint16 *data16, uint32 ptr_uint16, uint32 start_offset)
416{
[59]417  if (!ps->io) 
418  {
419    /*
420     * Writing - temporarily move the offset pointer.
421     */
422    uint16 data_size = ps->data_offset - start_offset;
423    uint32 old_offset = ps->data_offset;
424   
425    ps->data_offset = ptr_uint16;
426    if(!prs_uint16(name, ps, depth, &data_size)) 
427    {
428      ps->data_offset = old_offset;
429      return false;
430    }
431    ps->data_offset = old_offset;
432  } 
433  else 
434    ps->data_offset = start_offset + (uint32)(*data16);
[30]435
[59]436  return true;
[30]437}
438
439
440/*******************************************************************
441 Stream a uint8.
442 ********************************************************************/
443bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
444{
[59]445  char *q = prs_mem_get(ps, 1);
446  if (q == NULL)
447    return false;
448 
449  if (ps->io)
450    *data8 = CVAL(q,0);
451  else
452    SCVAL(q,0,*data8);
453 
454  ps->data_offset += 1;
455 
456  return true;
[30]457}
458
459
460/******************************************************************
461 Stream an array of uint8s. Length is number of uint8s.
462 ********************************************************************/
[53]463bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, 
464                uint8* data8s, int len)
[30]465{
[59]466  int i;
467  char *q = prs_mem_get(ps, len);
468  if (q == NULL)
469    return false;
470 
471  if (ps->io) 
472  {
473    for (i = 0; i < len; i++)
474      data8s[i] = CVAL(q,i);
475  } 
476  else 
477  {
478    for (i = 0; i < len; i++)
479      SCVAL(q, i, data8s[i]);
480  }
481 
482  ps->data_offset += len;
483 
484  return true;
[30]485}
486
487
488/*******************************************************************
489 Set the current offset (external interface).
490 ********************************************************************/
491bool prs_set_offset(prs_struct *ps, uint32 offset)
492{
[59]493  if(offset <= ps->data_offset) 
494  {
495    ps->data_offset = offset;
496    return true;
497  }
498 
499  if(!prs_grow(ps, offset - ps->data_offset))
500    return false;
501 
502  ps->data_offset = offset;
503  return true;
[30]504}
505
506/* End of stuff from parse_prs.c */
507
508/* From rpc_parse/parse_misc.c */
509
510/*******************************************************************
511 Reads or writes a struct uuid
512********************************************************************/
513bool smb_io_uuid(const char *desc, struct uuid *uuid, 
514                 prs_struct *ps, int depth)
515{
[59]516  if (uuid == NULL)
517    return false;
518  depth++;
519 
520  if(!prs_uint32 ("data   ", ps, depth, &uuid->time_low))
521    return false;
522  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_mid))
523    return false;
524  if(!prs_uint16 ("data   ", ps, depth, &uuid->time_hi_and_version))
525    return false;
526 
527  if(!prs_uint8s (false, "data   ", ps, depth, 
528                  uuid->clock_seq, sizeof(uuid->clock_seq)))
529    return false;
[30]530
[59]531  if(!prs_uint8s (false, "data   ", ps, depth, uuid->node, sizeof(uuid->node)))
532    return false;
533 
534  return true;
[30]535}
536
537
538/*******************************************************************
539 Reads or writes an NTTIME structure.
540********************************************************************/
541bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
542{
[59]543  if (nttime == NULL)
544    return false;
545  depth++;
[30]546
[59]547  if(!prs_align(ps))
548    return false;
[30]549       
[59]550  if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
551    return false;
552  if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
553    return false;
[30]554
[59]555  return true;
[30]556}
557
558
559/*******************************************************************
560 Reads or writes a DOM_SID structure.
561********************************************************************/
562bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
563{
[59]564  int i;
[30]565
[59]566  if (sid == NULL)
567    return false;
568  depth++;
[30]569
[59]570  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
571    return false;
[30]572
[59]573  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
574    return false;
[30]575
[59]576  for (i = 0; i < 6; i++)
577  {
578    fstring tmp;
579    snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
580    if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
581      return false;
582  }
[30]583
[59]584  /* oops! XXXX should really issue a warning here... */
585  if (sid->num_auths > MAXSUBAUTHS)
586    sid->num_auths = MAXSUBAUTHS;
[30]587
[59]588  if(!prs_uint32s(false, "sub_auths ", ps, depth, 
589                  sid->sub_auths, sid->num_auths))
590  { return false; }
[30]591
[59]592  return true;
[30]593}
594
595/* End of stuff from rpc_parse/parse_misc.c */
596
597/* From lib/util_sid.c */
598
599/*****************************************************************
600 Calculates size of a sid.
601*****************************************************************/ 
602size_t sid_size(const DOM_SID *sid)
603{
[59]604  if (sid == NULL)
605    return 0;
[30]606
[59]607  return sid->num_auths * sizeof(uint32) + 8;
[30]608}
609
610
611/*****************************************************************
612 Compare the auth portion of two sids.
613*****************************************************************/ 
[31]614int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
[30]615{
[59]616  int i;
[30]617
[59]618  if (sid1 == sid2)
619    return 0;
620  if (!sid1)
621    return -1;
622  if (!sid2)
623    return 1;
[30]624
[59]625  if (sid1->sid_rev_num != sid2->sid_rev_num)
626    return sid1->sid_rev_num - sid2->sid_rev_num;
[30]627
[59]628  for (i = 0; i < 6; i++)
629    if (sid1->id_auth[i] != sid2->id_auth[i])
630      return sid1->id_auth[i] - sid2->id_auth[i];
[30]631
[59]632  return 0;
[30]633}
634
635
636/*****************************************************************
637 Compare two sids.
638*****************************************************************/ 
639int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
640{
[59]641  int i;
[30]642
[59]643  if (sid1 == sid2)
644    return 0;
645  if (!sid1)
646    return -1;
647  if (!sid2)
648    return 1;
[30]649
[59]650  /* Compare most likely different rids, first: i.e start at end */
651  if (sid1->num_auths != sid2->num_auths)
652    return sid1->num_auths - sid2->num_auths;
[30]653
[59]654  for (i = sid1->num_auths-1; i >= 0; --i)
655    if (sid1->sub_auths[i] != sid2->sub_auths[i])
656      return sid1->sub_auths[i] - sid2->sub_auths[i];
[30]657
[59]658  return sid_compare_auth(sid1, sid2);
[30]659}
660
661
662/*****************************************************************
663 Compare two sids.
664*****************************************************************/ 
665bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
666{
[59]667  return sid_compare(sid1, sid2) == 0;
[30]668}
669
670/* End of stuff from lib/util_sid.c */
671
672/* From lib/secace.c */
673
674/*******************************************************************
675 Check if ACE has OBJECT type.
676********************************************************************/
677
678bool sec_ace_object(uint8 type)
679{
[59]680  if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
681      type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
682      type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
683      type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
684    return true;
685  }
686  return false;
[30]687}
688
689/* End of stuff from lib/secace.c */
690
691/* From rpc_parse/parse_sec.c */
692
693/*******************************************************************
694 Reads or writes a SEC_ACCESS structure.
695********************************************************************/
696bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
697{
[59]698  if (t == NULL)
699    return false;
[30]700
[59]701  depth++;
[30]702       
[59]703  if(!prs_uint32("mask", ps, depth, &t->mask))
704    return false;
[30]705
[59]706  return true;
[30]707}
708
709
710/*******************************************************************
711 Reads or writes a SEC_ACE structure.
712********************************************************************/
713bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
714{
[59]715  uint32 old_offset;
716  uint32 offset_ace_size;
[30]717
[59]718  if (psa == NULL)
719    return false;
[30]720
[59]721  depth++;
[30]722       
[59]723  old_offset = ps->data_offset;
[30]724
[59]725  if(!prs_uint8("type ", ps, depth, &psa->type))
726    return false;
[30]727
[59]728  if(!prs_uint8("flags", ps, depth, &psa->flags))
729    return false;
[30]730
[59]731  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
732    return false;
[30]733
[59]734  if(!sec_io_access("info ", &psa->info, ps, depth))
735    return false;
[30]736
[59]737  /* check whether object access is present */
738  if (!sec_ace_object(psa->type)) 
739  {
740    if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
741      return false;
742  } 
743  else 
744  {
745    if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
746      return false;
[30]747
[59]748    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
749      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
750        return false;
[30]751
[59]752    if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
753      if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
754        return false;
[30]755
[59]756    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
757      return false;
758  }
[30]759
[59]760  /* Theorectically an ACE can have a size greater than the
761   * sum of its components. When marshalling, pad with extra null bytes
762   * up to the
763   * correct size.
764   */
765  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
766  {
767    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
768    uint32 i;
769    uint8 c = 0;
[30]770
[59]771    for (i = 0; i < extra_len; i++) 
772    {
773      if (!prs_uint8("ace extra space", ps, depth, &c))
774        return false;
775    }
776  }
[30]777
[59]778  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
779                      offset_ace_size, old_offset))
780  { return false; }
[30]781
[59]782  return true;
[30]783}
784
785
786/*******************************************************************
787 Reads or writes a SEC_ACL structure. 
788
789 First of the xx_io_xx functions that allocates its data structures
790 for you as it reads them.
791********************************************************************/
792bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
793{
[59]794  unsigned int i;
795  uint32 old_offset;
796  uint32 offset_acl_size;
797  SEC_ACL *psa;
[30]798
[59]799  /*
800   * Note that the size is always a multiple of 4 bytes due to the
801   * nature of the data structure.  Therefore the prs_align() calls
802   * have been removed as they through us off when doing two-layer
803   * marshalling such as in the printing code (RPC_BUFFER).  --jerry
804   */
[30]805
[59]806  if (ppsa == NULL)
807    return false;
[30]808
[59]809  psa = *ppsa;
[30]810
[59]811  if(ps->io && psa == NULL) 
812  {
813    /*
814     * This is a read and we must allocate the stuct to read into.
815     */
816    if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
817      return false;
818    *ppsa = psa;
819  }
[30]820
[59]821  depth++;
[30]822       
[59]823  old_offset = ps->data_offset;
[30]824
[59]825  if(!prs_uint16("revision", ps, depth, &psa->revision))
826    return false;
[30]827
[59]828  if(!prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size))
829    return false;
[30]830
[59]831  if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
832    return false;
[30]833
[59]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      return false;
843  }
[30]844
[59]845  for (i = 0; i < psa->num_aces; i++) 
846  {
847    fstring tmp;
848    snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
849    if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
850      return false;
851  }
[30]852
[59]853  /* Theoretically an ACL can have a size greater than the
854   *  sum of its components. When marshalling, pad with extra null
855   *  bytes up to the
856   *  correct size.
857   */
858  if (!ps->io && (psa->size > ps->data_offset - old_offset)) 
859  {
860    uint32 extra_len = psa->size - (ps->data_offset - old_offset);
861    uint8 c = 0;
[30]862
[59]863    for (i = 0; i < extra_len; i++) 
864    {
865      if (!prs_uint8("acl extra space", ps, depth, &c))
866        return false;
867    }
868  }
[30]869
[59]870  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
871                      offset_acl_size, old_offset))
872  { return false; }
[30]873
[59]874  return true;
[30]875}
876
877
878/*******************************************************************
879 Reads or writes a SEC_DESC structure.
880 If reading and the *ppsd = NULL, allocates the structure.
881********************************************************************/
882bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
883{
[59]884  uint32 old_offset;
885  uint32 max_offset = 0; /* after we're done, move offset to end */
886  uint32 tmp_offset = 0;
[30]887
[59]888  SEC_DESC *psd;
[30]889
[59]890  if (ppsd == NULL)
891    return false;
[30]892
[59]893  psd = *ppsd;
[30]894
[59]895  if (psd == NULL) 
896  {
897    if(ps->io) 
898    {
899      if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
900        return false;
901      *ppsd = psd;
902    } 
903    else 
904    {
905      /* Marshalling - just ignore. */
906      return true;
907    }
908  }
[30]909
[59]910  depth++;
[30]911
[59]912  /* start of security descriptor stored for back-calc offset purposes */
913  old_offset = ps->data_offset;
[30]914
[59]915  if(!prs_uint16("revision ", ps, depth, &psd->revision))
916    return false;
[30]917
[59]918  if(!prs_uint16("type     ", ps, depth, &psd->type))
919    return false;
[30]920
[59]921  if (!ps->io) 
922  {
923    uint32 offset = SEC_DESC_HEADER_SIZE;
[30]924
[59]925    /*
926     * Work out the offsets here, as we write it out.
927     */
[30]928
[59]929    if (psd->sacl != NULL) 
930    {
931      psd->off_sacl = offset;
932      offset += psd->sacl->size;
933    } 
934    else
935      psd->off_sacl = 0;
[30]936
[59]937    if (psd->dacl != NULL) 
938    {
939      psd->off_dacl = offset;
940      offset += psd->dacl->size;
941    } 
942    else 
943      psd->off_dacl = 0;
[30]944
[59]945    if (psd->owner_sid != NULL) 
946    {
947      psd->off_owner_sid = offset;
948      offset += sid_size(psd->owner_sid);
949    } 
950    else
951      psd->off_owner_sid = 0;
[30]952
[59]953    if (psd->grp_sid != NULL) 
954    {
955      psd->off_grp_sid = offset;
956      offset += sid_size(psd->grp_sid);
957    } 
958    else
959      psd->off_grp_sid = 0;
960  }
[30]961
[59]962  if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
963    return false;
[30]964
[59]965  if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
966    return false;
[30]967
[59]968  if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
969    return false;
[30]970
[59]971  if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
972    return false;
[30]973
[59]974  max_offset = MAX(max_offset, ps->data_offset);
[30]975
[59]976  if (psd->off_owner_sid != 0) 
977  {
978    tmp_offset = ps->data_offset;
979    if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
980      return false;
[30]981
[59]982    if (ps->io) 
983    {
984      /* reading */
985      if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
986        return false;
987    }
[30]988
[59]989    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
990      return false;
[30]991
[59]992    max_offset = MAX(max_offset, ps->data_offset);
[30]993
[59]994    if (!prs_set_offset(ps,tmp_offset))
995      return false;
996  }
[30]997
[59]998  if (psd->off_grp_sid != 0) 
999  {
1000    tmp_offset = ps->data_offset;
1001    if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
1002      return false;
[30]1003
[59]1004    if (ps->io) 
1005    {
1006      /* reading */
1007      if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
1008        return false;
1009    }
[30]1010
[59]1011    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
1012      return false;
[30]1013                       
[59]1014    max_offset = MAX(max_offset, ps->data_offset);
[30]1015
[59]1016    if (!prs_set_offset(ps,tmp_offset))
1017      return false;
1018  }
[30]1019
[59]1020  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
1021  {
1022    tmp_offset = ps->data_offset;
1023    if(!prs_set_offset(ps, old_offset + psd->off_sacl))
1024      return false;
1025    if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
1026      return false;
1027    max_offset = MAX(max_offset, ps->data_offset);
1028    if (!prs_set_offset(ps,tmp_offset))
1029      return false;
1030  }
[30]1031
[59]1032  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
1033  {
1034    tmp_offset = ps->data_offset;
1035    if(!prs_set_offset(ps, old_offset + psd->off_dacl))
1036      return false;
1037    if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
1038      return false;
1039    max_offset = MAX(max_offset, ps->data_offset);
1040    if (!prs_set_offset(ps,tmp_offset))
1041      return false;
1042  }
[30]1043
[59]1044  if(!prs_set_offset(ps, max_offset))
1045    return false;
[30]1046
[59]1047  return true;
[30]1048}
1049
1050/* End of stuff from rpc_parse/parse_sec.c */
1051
1052/* From lib/secace.c */
1053
1054/*******************************************************************
1055 Compares two SEC_ACE structures
1056********************************************************************/
1057bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
1058{
[59]1059  /* Trivial case */
1060  if (!s1 && !s2) 
1061    return true;
[30]1062
[59]1063  /* Check top level stuff */
1064  if (s1->type != s2->type || s1->flags != s2->flags ||
1065      s1->info.mask != s2->info.mask) 
1066  { return false; }
[30]1067
[59]1068  /* Check SID */
1069  if (!sid_equal(&s1->trustee, &s2->trustee))
1070    return false;
[30]1071
[59]1072  return true;
[30]1073}
1074
1075/* End of stuff from lib/secace.c */
1076
1077/* From lib/secacl.c */
1078
1079/*******************************************************************
1080 Compares two SEC_ACL structures
1081********************************************************************/
1082
1083bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
1084{
[59]1085  unsigned int i, j;
[30]1086
[59]1087  /* Trivial cases */
1088  if (!s1 && !s2) 
1089    return true;
1090  if (!s1 || !s2) 
1091    return false;
[30]1092
[59]1093  /* Check top level stuff */
1094  if (s1->revision != s2->revision)
1095    return false;
[30]1096
[59]1097  if (s1->num_aces != s2->num_aces)
1098    return false;
[30]1099
[59]1100  /* The ACEs could be in any order so check each ACE in s1 against
1101     each ACE in s2. */
[30]1102
[59]1103  for (i = 0; i < s1->num_aces; i++) 
1104  {
1105    bool found = false;
[30]1106
[59]1107    for (j = 0; j < s2->num_aces; j++) 
1108    {
1109      if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) 
1110      {
1111        found = true;
1112        break;
1113      }
1114    }
[30]1115
[59]1116    if (!found)
1117      return false;
1118  }
[30]1119
[59]1120  return true;
[30]1121}
1122
1123/* End of stuff from lib/secacl.c */
1124
1125/* From lib/secdesc.c */
1126
1127/*******************************************************************
1128 Compares two SEC_DESC structures
1129********************************************************************/
1130bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
1131{
[59]1132  /* Trivial case */
[30]1133
[59]1134  if (!s1 && !s2)
1135    goto done;
[30]1136
[59]1137  /* Check top level stuff */
1138  if (s1->revision != s2->revision)
1139    return false;
[30]1140
[59]1141  if (s1->type!= s2->type)
1142    return false;
[30]1143
[59]1144  /* Check owner and group */
1145  if (!sid_equal(s1->owner_sid, s2->owner_sid))
1146    return false;
[30]1147
[59]1148  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
1149    return false;
[30]1150
[59]1151  /* Check ACLs present in one but not the other */
1152  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
1153      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
1154  { return false; }
[30]1155
[59]1156  /* Sigh - we have to do it the hard way by iterating over all
1157     the ACEs in the ACLs */
1158  if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl)) 
1159    return false;
[30]1160
1161 done:
[59]1162  return true;
[30]1163}
1164
1165/* End of stuff from lib/secdesc.c */
Note: See TracBrowser for help on using the repository browser.