source: trunk/lib/smb_deps.c @ 132

Last change on this file since 132 was 132, checked in by tim, 15 years ago

separated ACL parsing code from smb_deps into new winsec library

  • Property svn:keywords set to Id
File size: 13.4 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,2009 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 3 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 132 2009-01-11 21:44:33Z 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}
Note: See TracBrowser for help on using the repository browser.