source: releases/0.4.0/lib/smb_deps.c@ 293

Last change on this file since 293 was 84, checked in by tim, 18 years ago

rearranged structure contents to reduce fragmentation on 64 bit systems.

make regfi interface return const structures to help enforce separation

removed a little cruft from some parsing functions

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