source: trunk/lib/smb_deps.c @ 42

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

Changed to a CSV-like output format to accommodate extended fields

Added mtime output for keys

Added security descriptor columns (probably broken right now)

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