source: trunk/lib/smb_deps.c @ 53

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

Moved security descriptor parsing functions into regfio.c

Improved malloc() mode of failure.

Eliminated some warnings in regfio.c

  • 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 53 2005-09-04 21:04:58Z 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, 
430                uint8* data8s, int len)
431{
432        int i;
433        char *q = prs_mem_get(ps, len);
434        if (q == NULL)
435                return false;
436
437        if (ps->io) {
438                for (i = 0; i < len; i++)
439                        data8s[i] = CVAL(q,i);
440        } else {
441                for (i = 0; i < len; i++)
442                        SCVAL(q, i, data8s[i]);
443        }
444
445        ps->data_offset += len;
446
447        return true;
448}
449
450
451/*******************************************************************
452 Set the current offset (external interface).
453 ********************************************************************/
454bool prs_set_offset(prs_struct *ps, uint32 offset)
455{
456        if(offset <= ps->data_offset) {
457                ps->data_offset = offset;
458                return true;
459        }
460
461        if(!prs_grow(ps, offset - ps->data_offset))
462                return false;
463
464        ps->data_offset = offset;
465        return true;
466}
467
468/* End of stuff from parse_prs.c */
469
470/* From rpc_parse/parse_misc.c */
471
472/*******************************************************************
473 Reads or writes a struct uuid
474********************************************************************/
475bool smb_io_uuid(const char *desc, struct uuid *uuid, 
476                 prs_struct *ps, int depth)
477{
478        if (uuid == NULL)
479                return false;
480        depth++;
481
482        if(!prs_uint32 ("data   ", ps, depth, &uuid->time_low))
483                return false;
484        if(!prs_uint16 ("data   ", ps, depth, &uuid->time_mid))
485                return false;
486        if(!prs_uint16 ("data   ", ps, depth, &uuid->time_hi_and_version))
487                return false;
488
489        if(!prs_uint8s (false, "data   ", ps, depth, uuid->clock_seq, sizeof(uuid->clock_seq)))
490                return false;
491        if(!prs_uint8s (false, "data   ", ps, depth, uuid->node, sizeof(uuid->node)))
492                return false;
493
494        return true;
495}
496
497
498/*******************************************************************
499 Reads or writes an NTTIME structure.
500********************************************************************/
501bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth)
502{
503        if (nttime == NULL)
504                return false;
505        depth++;
506
507        if(!prs_align(ps))
508                return false;
509       
510        if(!prs_uint32("low ", ps, depth, &nttime->low)) /* low part */
511                return false;
512        if(!prs_uint32("high", ps, depth, &nttime->high)) /* high part */
513                return false;
514
515        return true;
516}
517
518
519/*******************************************************************
520 Reads or writes a DOM_SID structure.
521********************************************************************/
522bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
523{
524        int i;
525
526        if (sid == NULL)
527                return false;
528        depth++;
529
530        if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
531                return false;
532
533        if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
534                return false;
535
536        for (i = 0; i < 6; i++)
537        {
538                fstring tmp;
539                snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
540                if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
541                        return false;
542        }
543
544        /* oops! XXXX should really issue a warning here... */
545        if (sid->num_auths > MAXSUBAUTHS)
546                sid->num_auths = MAXSUBAUTHS;
547
548        if(!prs_uint32s(false, "sub_auths ", ps, depth, sid->sub_auths, sid->num_auths))
549                return false;
550
551        return true;
552}
553
554/* End of stuff from rpc_parse/parse_misc.c */
555
556/* From lib/util_sid.c */
557
558/*****************************************************************
559 Calculates size of a sid.
560*****************************************************************/ 
561size_t sid_size(const DOM_SID *sid)
562{
563        if (sid == NULL)
564                return 0;
565
566        return sid->num_auths * sizeof(uint32) + 8;
567}
568
569
570/*****************************************************************
571 Compare the auth portion of two sids.
572*****************************************************************/ 
573int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
574{
575        int i;
576
577        if (sid1 == sid2)
578                return 0;
579        if (!sid1)
580                return -1;
581        if (!sid2)
582                return 1;
583
584        if (sid1->sid_rev_num != sid2->sid_rev_num)
585                return sid1->sid_rev_num - sid2->sid_rev_num;
586
587        for (i = 0; i < 6; i++)
588                if (sid1->id_auth[i] != sid2->id_auth[i])
589                        return sid1->id_auth[i] - sid2->id_auth[i];
590
591        return 0;
592}
593
594
595/*****************************************************************
596 Compare two sids.
597*****************************************************************/ 
598int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
599{
600        int i;
601
602        if (sid1 == sid2)
603                return 0;
604        if (!sid1)
605                return -1;
606        if (!sid2)
607                return 1;
608
609        /* Compare most likely different rids, first: i.e start at end */
610        if (sid1->num_auths != sid2->num_auths)
611                return sid1->num_auths - sid2->num_auths;
612
613        for (i = sid1->num_auths-1; i >= 0; --i)
614                if (sid1->sub_auths[i] != sid2->sub_auths[i])
615                        return sid1->sub_auths[i] - sid2->sub_auths[i];
616
617        return sid_compare_auth(sid1, sid2);
618}
619
620
621/*****************************************************************
622 Compare two sids.
623*****************************************************************/ 
624bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
625{
626        return sid_compare(sid1, sid2) == 0;
627}
628
629/* End of stuff from lib/util_sid.c */
630
631/* From lib/secace.c */
632
633/*******************************************************************
634 Check if ACE has OBJECT type.
635********************************************************************/
636
637bool sec_ace_object(uint8 type)
638{
639        if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
640            type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
641            type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
642            type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
643                return true;
644        }
645        return false;
646}
647
648/* End of stuff from lib/secace.c */
649
650/* From rpc_parse/parse_sec.c */
651
652/*******************************************************************
653 Reads or writes a SEC_ACCESS structure.
654********************************************************************/
655bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
656{
657        if (t == NULL)
658                return false;
659
660        depth++;
661       
662        if(!prs_uint32("mask", ps, depth, &t->mask))
663                return false;
664
665        return true;
666}
667
668
669/*******************************************************************
670 Reads or writes a SEC_ACE structure.
671********************************************************************/
672bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
673{
674        uint32 old_offset;
675        uint32 offset_ace_size;
676
677        if (psa == NULL)
678                return false;
679
680        depth++;
681       
682        old_offset = ps->data_offset;
683
684        if(!prs_uint8("type ", ps, depth, &psa->type))
685                return false;
686
687        if(!prs_uint8("flags", ps, depth, &psa->flags))
688                return false;
689
690        if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
691                return false;
692
693        if(!sec_io_access("info ", &psa->info, ps, depth))
694                return false;
695
696        /* check whether object access is present */
697        if (!sec_ace_object(psa->type)) {
698                if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
699                        return false;
700        } else {
701                if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
702                        return false;
703
704                if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
705                        if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
706                                return false;
707
708                if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
709                        if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
710                                return false;
711
712                if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
713                        return false;
714        }
715
716        /* Theorectically an ACE can have a size greater than the
717           sum of its components. When marshalling, pad with extra null bytes up to the
718           correct size. */
719
720        if (!ps->io && (psa->size > ps->data_offset - old_offset)) {
721                uint32 extra_len = psa->size - (ps->data_offset - old_offset);
722                uint32 i;
723                uint8 c = 0;
724
725                for (i = 0; i < extra_len; i++) {
726                        if (!prs_uint8("ace extra space", ps, depth, &c))
727                                return false;
728                }
729        }
730
731        if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
732                return false;
733
734        return true;
735}
736
737
738/*******************************************************************
739 Reads or writes a SEC_ACL structure. 
740
741 First of the xx_io_xx functions that allocates its data structures
742 for you as it reads them.
743********************************************************************/
744bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
745{
746        unsigned int i;
747        uint32 old_offset;
748        uint32 offset_acl_size;
749        SEC_ACL *psa;
750
751        /*
752         * Note that the size is always a multiple of 4 bytes due to the
753         * nature of the data structure.  Therefore the prs_align() calls
754         * have been removed as they through us off when doing two-layer
755         * marshalling such as in the printing code (RPC_BUFFER).  --jerry
756         */
757
758        if (ppsa == NULL)
759                return false;
760
761        psa = *ppsa;
762
763        if(ps->io && psa == NULL) {
764                /*
765                 * This is a read and we must allocate the stuct to read into.
766                 */
767          if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
768                        return false;
769                *ppsa = psa;
770        }
771
772        depth++;
773       
774        old_offset = ps->data_offset;
775
776        if(!prs_uint16("revision", ps, depth, &psa->revision))
777                return false;
778
779        if(!prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size))
780                return false;
781
782        if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
783                return false;
784
785        if (ps->io) {
786                /*
787                 * Even if the num_aces is zero, allocate memory as there's a difference
788                 * between a non-present DACL (allow all access) and a DACL with no ACE's
789                 * (allow no access).
790                 */
791          if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
792                        return false;
793        }
794
795        for (i = 0; i < psa->num_aces; i++) {
796                fstring tmp;
797                snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
798                if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
799                        return false;
800        }
801
802        /* Theorectically an ACL can have a size greater than the
803           sum of its components. When marshalling, pad with extra null bytes up to the
804           correct size. */
805
806        if (!ps->io && (psa->size > ps->data_offset - old_offset)) {
807                uint32 extra_len = psa->size - (ps->data_offset - old_offset);
808                uint8 c = 0;
809
810                for (i = 0; i < extra_len; i++) {
811                        if (!prs_uint8("acl extra space", ps, depth, &c))
812                                return false;
813                }
814        }
815
816        if(!prs_uint16_post("size     ", ps, depth, &psa->size, offset_acl_size, old_offset))
817                return false;
818
819        return true;
820}
821
822
823/*******************************************************************
824 Reads or writes a SEC_DESC structure.
825 If reading and the *ppsd = NULL, allocates the structure.
826********************************************************************/
827bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
828{
829        uint32 old_offset;
830        uint32 max_offset = 0; /* after we're done, move offset to end */
831        uint32 tmp_offset = 0;
832
833        SEC_DESC *psd;
834
835        if (ppsd == NULL)
836                return false;
837
838        psd = *ppsd;
839
840        if (psd == NULL) {
841                if(ps->io) {
842                  if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
843                                return false;
844                        *ppsd = psd;
845                } else {
846                        /* Marshalling - just ignore. */
847                        return true;
848                }
849        }
850
851        depth++;
852
853        /* start of security descriptor stored for back-calc offset purposes */
854        old_offset = ps->data_offset;
855
856        if(!prs_uint16("revision ", ps, depth, &psd->revision))
857                return false;
858
859        if(!prs_uint16("type     ", ps, depth, &psd->type))
860                return false;
861
862        if (!ps->io) {
863                uint32 offset = SEC_DESC_HEADER_SIZE;
864
865                /*
866                 * Work out the offsets here, as we write it out.
867                 */
868
869                if (psd->sacl != NULL) {
870                        psd->off_sacl = offset;
871                        offset += psd->sacl->size;
872                } else {
873                        psd->off_sacl = 0;
874                }
875
876                if (psd->dacl != NULL) {
877                        psd->off_dacl = offset;
878                        offset += psd->dacl->size;
879                } else {
880                        psd->off_dacl = 0;
881                }
882
883                if (psd->owner_sid != NULL) {
884                        psd->off_owner_sid = offset;
885                        offset += sid_size(psd->owner_sid);
886                } else {
887                        psd->off_owner_sid = 0;
888                }
889
890                if (psd->grp_sid != NULL) {
891                        psd->off_grp_sid = offset;
892                        offset += sid_size(psd->grp_sid);
893                } else {
894                        psd->off_grp_sid = 0;
895                }
896        }
897
898        if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
899                return false;
900
901        if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
902                return false;
903
904        if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
905                return false;
906
907        if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
908                return false;
909
910        max_offset = MAX(max_offset, ps->data_offset);
911
912        if (psd->off_owner_sid != 0) {
913
914                tmp_offset = ps->data_offset;
915                if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
916                        return false;
917
918                if (ps->io) {
919                        /* reading */
920                  if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
921                                return false;
922                }
923
924                if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
925                        return false;
926
927                max_offset = MAX(max_offset, ps->data_offset);
928
929                if (!prs_set_offset(ps,tmp_offset))
930                        return false;
931        }
932
933        if (psd->off_grp_sid != 0) {
934
935                tmp_offset = ps->data_offset;
936                if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
937                        return false;
938
939                if (ps->io) {
940                        /* reading */
941                        if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
942                                return false;
943                }
944
945                if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
946                        return false;
947                       
948                max_offset = MAX(max_offset, ps->data_offset);
949
950                if (!prs_set_offset(ps,tmp_offset))
951                        return false;
952        }
953
954        if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
955                tmp_offset = ps->data_offset;
956                if(!prs_set_offset(ps, old_offset + psd->off_sacl))
957                        return false;
958                if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
959                        return false;
960                max_offset = MAX(max_offset, ps->data_offset);
961                if (!prs_set_offset(ps,tmp_offset))
962                        return false;
963        }
964
965        if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
966                tmp_offset = ps->data_offset;
967                if(!prs_set_offset(ps, old_offset + psd->off_dacl))
968                        return false;
969                if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
970                        return false;
971                max_offset = MAX(max_offset, ps->data_offset);
972                if (!prs_set_offset(ps,tmp_offset))
973                        return false;
974        }
975
976        if(!prs_set_offset(ps, max_offset))
977                return false;
978
979        return true;
980}
981
982/* End of stuff from rpc_parse/parse_sec.c */
983
984/* From lib/secace.c */
985
986/*******************************************************************
987 Compares two SEC_ACE structures
988********************************************************************/
989bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
990{
991        /* Trivial case */
992
993        if (!s1 && !s2) return true;
994
995        /* Check top level stuff */
996
997        if (s1->type != s2->type || s1->flags != s2->flags ||
998            s1->info.mask != s2->info.mask) {
999                return false;
1000        }
1001
1002        /* Check SID */
1003
1004        if (!sid_equal(&s1->trustee, &s2->trustee)) {
1005                return false;
1006        }
1007
1008        return true;
1009}
1010
1011/* End of stuff from lib/secace.c */
1012
1013/* From lib/secacl.c */
1014
1015/*******************************************************************
1016 Compares two SEC_ACL structures
1017********************************************************************/
1018
1019bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
1020{
1021        unsigned int i, j;
1022
1023        /* Trivial cases */
1024
1025        if (!s1 && !s2) return true;
1026        if (!s1 || !s2) return false;
1027
1028        /* Check top level stuff */
1029
1030        if (s1->revision != s2->revision) {
1031                return false;
1032        }
1033
1034        if (s1->num_aces != s2->num_aces) {
1035                return false;
1036        }
1037
1038        /* The ACEs could be in any order so check each ACE in s1 against
1039           each ACE in s2. */
1040
1041        for (i = 0; i < s1->num_aces; i++) {
1042                bool found = false;
1043
1044                for (j = 0; j < s2->num_aces; j++) {
1045                        if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
1046                                found = true;
1047                                break;
1048                        }
1049                }
1050
1051                if (!found) return false;
1052        }
1053
1054        return true;
1055}
1056
1057/* End of stuff from lib/secacl.c */
1058
1059/* From lib/secdesc.c */
1060
1061/*******************************************************************
1062 Compares two SEC_DESC structures
1063********************************************************************/
1064bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
1065{
1066        /* Trivial case */
1067
1068        if (!s1 && !s2) {
1069                goto done;
1070        }
1071
1072        /* Check top level stuff */
1073
1074        if (s1->revision != s2->revision) {
1075                return false;
1076        }
1077
1078        if (s1->type!= s2->type) {
1079                return false;
1080        }
1081
1082        /* Check owner and group */
1083
1084        if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
1085                return false;
1086        }
1087
1088        if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
1089                return false;
1090        }
1091
1092        /* Check ACLs present in one but not the other */
1093
1094        if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
1095            (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) 
1096        {
1097                return false;
1098        }
1099
1100        /* Sigh - we have to do it the hard way by iterating over all
1101           the ACEs in the ACLs */
1102
1103        if (!sec_acl_equal(s1->dacl, s2->dacl) ||
1104            !sec_acl_equal(s1->sacl, s2->sacl)) 
1105        {
1106                return false;
1107        }
1108
1109 done:
1110        return true;
1111}
1112
1113/* End of stuff from lib/secdesc.c */
Note: See TracBrowser for help on using the repository browser.