source: trunk/lib/smb_deps.c @ 76

Last change on this file since 76 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
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 *
[65]6 * Copyright (C) 2005-2006 Timothy D. Morgan
[30]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;
[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;
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;
[30]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{
[59]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;
[30]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{
[65]237  if(ps == NULL)
238    return false;
[31]239  memset(ps, 0, sizeof(prs_struct));
[65]240
[31]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 
[59]250  if (size != 0) 
251  {
[31]252    ps->buffer_size = size;
[59]253    if((ps->data_p = (char *)zalloc((size_t)size)) == NULL)
[31]254      return false;
[59]255
[31]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  }
[65]281
[59]282  return &ps->data_p[ps->data_offset];
[30]283}
284
285
286/*******************************************************************
287 Stream a uint32.
288 ********************************************************************/
289bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32)
290{
[59]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;
[30]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{
[59]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;
[30]355}
356
357
358/*******************************************************************
359 Stream a uint16.
360 ********************************************************************/
361bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16)
362{
[59]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;
[30]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{
[59]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;
[30]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{
[59]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);
[30]436
[59]437  return true;
[30]438}
439
440
441/*******************************************************************
442 Stream a uint8.
443 ********************************************************************/
444bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8)
445{
[59]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;
[30]458}
459
460
461/******************************************************************
462 Stream an array of uint8s. Length is number of uint8s.
463 ********************************************************************/
[53]464bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, 
465                uint8* data8s, int len)
[30]466{
[59]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;
[30]486}
487
488
489/*******************************************************************
490 Set the current offset (external interface).
491 ********************************************************************/
492bool prs_set_offset(prs_struct *ps, uint32 offset)
493{
[59]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;
[30]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{
[59]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;
[30]531
[59]532  if(!prs_uint8s (false, "data   ", ps, depth, uuid->node, sizeof(uuid->node)))
533    return false;
534 
535  return true;
[30]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{
[59]544  if (nttime == NULL)
545    return false;
546  depth++;
[30]547
[59]548  if(!prs_align(ps))
549    return false;
[30]550       
[59]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;
[30]555
[59]556  return true;
[30]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{
[59]565  int i;
[30]566
[59]567  if (sid == NULL)
568    return false;
569  depth++;
[30]570
[59]571  if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
572    return false;
[30]573
[59]574  if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
575    return false;
[30]576
[59]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  }
[30]584
[59]585  /* oops! XXXX should really issue a warning here... */
586  if (sid->num_auths > MAXSUBAUTHS)
587    sid->num_auths = MAXSUBAUTHS;
[30]588
[59]589  if(!prs_uint32s(false, "sub_auths ", ps, depth, 
590                  sid->sub_auths, sid->num_auths))
591  { return false; }
[30]592
[59]593  return true;
[30]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{
[59]605  if (sid == NULL)
606    return 0;
[30]607
[59]608  return sid->num_auths * sizeof(uint32) + 8;
[30]609}
610
611
612/*****************************************************************
613 Compare the auth portion of two sids.
614*****************************************************************/ 
[31]615int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
[30]616{
[59]617  int i;
[30]618
[59]619  if (sid1 == sid2)
620    return 0;
621  if (!sid1)
622    return -1;
623  if (!sid2)
624    return 1;
[30]625
[59]626  if (sid1->sid_rev_num != sid2->sid_rev_num)
627    return sid1->sid_rev_num - sid2->sid_rev_num;
[30]628
[59]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];
[30]632
[59]633  return 0;
[30]634}
635
636
637/*****************************************************************
638 Compare two sids.
639*****************************************************************/ 
640int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
641{
[59]642  int i;
[30]643
[59]644  if (sid1 == sid2)
645    return 0;
646  if (!sid1)
647    return -1;
648  if (!sid2)
649    return 1;
[30]650
[59]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;
[30]654
[59]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];
[30]658
[59]659  return sid_compare_auth(sid1, sid2);
[30]660}
661
662
663/*****************************************************************
664 Compare two sids.
665*****************************************************************/ 
666bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
667{
[59]668  return sid_compare(sid1, sid2) == 0;
[30]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{
[59]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;
[30]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{
[59]699  if (t == NULL)
700    return false;
[30]701
[59]702  depth++;
[30]703       
[59]704  if(!prs_uint32("mask", ps, depth, &t->mask))
705    return false;
[30]706
[59]707  return true;
[30]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{
[59]716  uint32 old_offset;
717  uint32 offset_ace_size;
[30]718
[59]719  if (psa == NULL)
720    return false;
[30]721
[59]722  depth++;
[30]723       
[59]724  old_offset = ps->data_offset;
[30]725
[59]726  if(!prs_uint8("type ", ps, depth, &psa->type))
727    return false;
[30]728
[59]729  if(!prs_uint8("flags", ps, depth, &psa->flags))
730    return false;
[30]731
[59]732  if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
733    return false;
[30]734
[59]735  if(!sec_io_access("info ", &psa->info, ps, depth))
736    return false;
[30]737
[59]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;
[30]748
[59]749    if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
750      if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
751        return false;
[30]752
[59]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;
[30]756
[59]757    if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
758      return false;
759  }
[30]760
[59]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;
[30]771
[59]772    for (i = 0; i < extra_len; i++) 
773    {
774      if (!prs_uint8("ace extra space", ps, depth, &c))
775        return false;
776    }
777  }
[30]778
[59]779  if(!prs_uint16_post("size ", ps, depth, &psa->size, 
780                      offset_ace_size, old_offset))
781  { return false; }
[30]782
[59]783  return true;
[30]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{
[59]795  unsigned int i;
796  uint32 old_offset;
797  uint32 offset_acl_size;
[65]798  SEC_ACL* psa;
[30]799
[59]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   */
[30]806
[65]807  if (ppsa == NULL || ps == NULL)
[59]808    return false;
[30]809
[59]810  psa = *ppsa;
[30]811
[59]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  }
[30]821
[65]822  depth++;     
[59]823  old_offset = ps->data_offset;
[30]824
[65]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;
[59]831    return false;
[65]832  }
[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)
[65]842    {
843      free(psa);
844      *ppsa = NULL;
[59]845      return false;
[65]846    }
[59]847  }
[30]848
[59]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))
[65]854    {
855      free(psa);
856      *ppsa = NULL;
[59]857      return false;
[65]858    }
[59]859  }
[30]860
[59]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;
[30]870
[59]871    for (i = 0; i < extra_len; i++) 
872    {
873      if (!prs_uint8("acl extra space", ps, depth, &c))
[65]874      {
875        free(psa);
876        *ppsa = NULL;
[59]877        return false;
[65]878      }
[59]879    }
880  }
[30]881
[59]882  if(!prs_uint16_post("size     ", ps, depth, &psa->size, 
883                      offset_acl_size, old_offset))
[65]884  { 
885    free(psa);
886    *ppsa = NULL;
887    return false; 
888  }
[30]889
[59]890  return true;
[30]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{
[59]900  uint32 old_offset;
901  uint32 max_offset = 0; /* after we're done, move offset to end */
902  uint32 tmp_offset = 0;
[30]903
[59]904  SEC_DESC *psd;
[30]905
[65]906  if (ppsd == NULL || ps == NULL)
[59]907    return false;
[30]908
[59]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  }
[30]924
[59]925  depth++;
[30]926
[59]927  /* start of security descriptor stored for back-calc offset purposes */
928  old_offset = ps->data_offset;
[30]929
[65]930  if(!prs_uint16("revision ", ps, depth, &psd->revision)
931     || !prs_uint16("type     ", ps, depth, &psd->type))
932  {
933    free(psd);
934    *ppsd = NULL;
[59]935    return false;
[65]936  }
[30]937
[65]938  if (!ps->io)
[59]939  {
940    uint32 offset = SEC_DESC_HEADER_SIZE;
[30]941
[59]942    /*
943     * Work out the offsets here, as we write it out.
944     */
[30]945
[59]946    if (psd->sacl != NULL) 
947    {
948      psd->off_sacl = offset;
949      offset += psd->sacl->size;
950    } 
951    else
952      psd->off_sacl = 0;
[30]953
[59]954    if (psd->dacl != NULL) 
955    {
956      psd->off_dacl = offset;
957      offset += psd->dacl->size;
958    } 
959    else 
960      psd->off_dacl = 0;
[30]961
[59]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;
[30]969
[59]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  }
[30]978
[65]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;   
[59]986    return false;
[65]987  }
[59]988  max_offset = MAX(max_offset, ps->data_offset);
[30]989
[59]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))
[65]994    {
995      free(psd);
996      *ppsd = NULL;
[59]997      return false;
[65]998    }
[30]999
[59]1000    if (ps->io) 
1001    {
1002      /* reading */
1003      if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
[65]1004      {
1005        free(psd);
1006        *ppsd = NULL;
[59]1007        return false;
[65]1008      }
[59]1009    }
[30]1010
[59]1011    if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
[65]1012    {
1013      if(ps->io)
1014        free(psd->owner_sid);
1015      free(psd);
1016      *ppsd = NULL;
[59]1017      return false;
[65]1018    }
[30]1019
[59]1020    max_offset = MAX(max_offset, ps->data_offset);
[30]1021
[59]1022    if (!prs_set_offset(ps,tmp_offset))
[65]1023    {
1024      if(ps->io)
1025        free(psd->owner_sid);
1026      free(psd);
1027      *ppsd = NULL;
[59]1028      return false;
[65]1029    }
[59]1030  }
[30]1031
[59]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))
[65]1036    {
1037      if(ps->io)
1038        free(psd->owner_sid);
1039      free(psd);
1040      *ppsd = NULL;
[59]1041      return false;
[65]1042    }
[30]1043
[59]1044    if (ps->io) 
1045    {
1046      /* reading */
1047      if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
[65]1048      {
1049        free(psd->owner_sid);
1050        free(psd);
1051        *ppsd = NULL;
[59]1052        return false;
[65]1053      }
[59]1054    }
[30]1055
[59]1056    if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
[65]1057    {
1058      if(ps->io)
1059      {
1060        free(psd->grp_sid);
1061        free(psd->owner_sid);
1062      }
1063      free(psd);
1064      *ppsd = NULL;
[59]1065      return false;
[65]1066    }
[30]1067                       
[59]1068    max_offset = MAX(max_offset, ps->data_offset);
[30]1069
[59]1070    if (!prs_set_offset(ps,tmp_offset))
[65]1071    {
1072      if(ps->io)
1073      {
1074        free(psd->grp_sid);
1075        free(psd->owner_sid);
1076      }
1077      free(psd);
1078      *ppsd = NULL;
[59]1079      return false;
[65]1080    }
[59]1081  }
[30]1082
[59]1083  if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) 
1084  {
1085    tmp_offset = ps->data_offset;
[65]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;
[59]1096      return false;
[65]1097    }
[59]1098    max_offset = MAX(max_offset, ps->data_offset);
1099    if (!prs_set_offset(ps,tmp_offset))
[65]1100    {
1101      if(ps->io)
1102      {
1103        free(psd->grp_sid);
1104        free(psd->owner_sid);
1105      }
1106      free(psd);
1107      *ppsd = NULL;
[59]1108      return false;
[65]1109    }
[59]1110  }
[30]1111
[59]1112  if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) 
1113  {
1114    tmp_offset = ps->data_offset;
[65]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;
[59]1125      return false;
[65]1126    }
[59]1127    max_offset = MAX(max_offset, ps->data_offset);
1128    if (!prs_set_offset(ps,tmp_offset))
[65]1129    {
1130      if(ps->io)
1131      {
1132        free(psd->grp_sid);
1133        free(psd->owner_sid);
1134      }
1135      free(psd);
1136      *ppsd = NULL;
[59]1137      return false;
[65]1138    }
[59]1139  }
[30]1140
[59]1141  if(!prs_set_offset(ps, max_offset))
[65]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  }
[30]1152
[59]1153  return true;
[30]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{
[65]1165  /* Trivial cases */
[59]1166  if (!s1 && !s2) 
1167    return true;
[65]1168  if (!s1 || !s2) 
1169    return false;
[30]1170
[59]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; }
[30]1175
[59]1176  /* Check SID */
1177  if (!sid_equal(&s1->trustee, &s2->trustee))
1178    return false;
[30]1179
[59]1180  return true;
[30]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{
[59]1193  unsigned int i, j;
[30]1194
[59]1195  /* Trivial cases */
1196  if (!s1 && !s2) 
1197    return true;
1198  if (!s1 || !s2) 
1199    return false;
[30]1200
[59]1201  /* Check top level stuff */
1202  if (s1->revision != s2->revision)
1203    return false;
[30]1204
[59]1205  if (s1->num_aces != s2->num_aces)
1206    return false;
[30]1207
[59]1208  /* The ACEs could be in any order so check each ACE in s1 against
1209     each ACE in s2. */
[30]1210
[59]1211  for (i = 0; i < s1->num_aces; i++) 
1212  {
1213    bool found = false;
[30]1214
[59]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    }
[30]1223
[59]1224    if (!found)
1225      return false;
1226  }
[30]1227
[59]1228  return true;
[30]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{
[65]1240  /* Trivial cases */
[59]1241  if (!s1 && !s2)
[65]1242    return true;
1243  if (!s1 || !s2)
1244    return false;
[30]1245
[59]1246  /* Check top level stuff */
1247  if (s1->revision != s2->revision)
1248    return false;
[30]1249
[59]1250  if (s1->type!= s2->type)
1251    return false;
[30]1252
[59]1253  /* Check owner and group */
1254  if (!sid_equal(s1->owner_sid, s2->owner_sid))
1255    return false;
[30]1256
[59]1257  if (!sid_equal(s1->grp_sid, s2->grp_sid)) 
1258    return false;
[30]1259
[59]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; }
[30]1264
[59]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;
[30]1269
[59]1270  return true;
[30]1271}
1272
1273/* End of stuff from lib/secdesc.c */
Note: See TracBrowser for help on using the repository browser.