Changeset 134


Ignore:
Timestamp:
01/16/09 13:36:04 (16 years ago)
Author:
tim
Message:

rewrote winsec library, stripping out Samba dependencies

eliminated remaining Samba prs functions

added support for 'li' subkey list records

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r132 r134  
    11/*
    2  * Branched from Samba project, Subversion repository version #6903:
     2 * Branched from Samba project Subversion repository, version #6903:
    33 *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/include/regfio.h?rev=6903&view=auto
    44 *
    5  * Unix SMB/CIFS implementation.
    6  * Windows NT registry I/O library
     5 * Windows NT (and later) registry parsing library
    76 *
    87 * Copyright (C) 2005-2009 Timothy D. Morgan
     
    1110 * This program is free software; you can redistribute it and/or modify
    1211 * it under the terms of the GNU General Public License as published by
    13  * the Free Software Foundation; version 2 of the License.
     12 * the Free Software Foundation; version 3 of the License.
    1413 *
    1514 * This program is distributed in the hope that it will be useful,
     
    191190  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
    192191
    193   SEC_DESC* sec_desc;
     192  WINSEC_DESC* sec_desc;
    194193  uint32 hbin_off;      /* offset from beginning of this hbin block */
    195194 
     
    316315int                   regfi_type_str2val(const char* str);
    317316
    318 char*                 regfi_get_sacl(SEC_DESC* sec_desc);
    319 char*                 regfi_get_dacl(SEC_DESC* sec_desc);
    320 char*                 regfi_get_owner(SEC_DESC* sec_desc);
    321 char*                 regfi_get_group(SEC_DESC* sec_desc);
     317char*                 regfi_get_sacl(WINSEC_DESC* sec_desc);
     318char*                 regfi_get_dacl(WINSEC_DESC* sec_desc);
     319char*                 regfi_get_owner(WINSEC_DESC* sec_desc);
     320char*                 regfi_get_group(WINSEC_DESC* sec_desc);
    322321
    323322REGF_FILE*            regfi_open(const char* filename);
  • trunk/include/smb_deps.h

    r132 r134  
    2929#include <stdlib.h>
    3030#include <stdbool.h>
     31#include <stdint.h>
    3132#include <stdio.h>
    3233#include <string.h>
     
    4647/* From includes.h */
    4748
    48 #define uint8 unsigned char
    49 #define int16 short
    50 #define uint16 unsigned short
    51 #define int32 int
    52 #define uint32 unsigned int
    53 
    54 #define SMB_STRUCT_STAT struct stat
    55 #define QSORT_CAST (int (*)(const void *, const void *))
     49#define uint8  uint8_t
     50#define int16  int8_t
     51#define uint16 uint16_t
     52#define int32  int32_t
     53#define uint32 uint32_t
    5654
    5755#define MIN(a,b) ((a)<(b)?(a):(b))
     
    5957
    6058extern int DEBUGLEVEL;
    61 
    62 #define DLIST_ADD(list, p) \
    63 { \
    64         if (!(list)) { \
    65                 (list) = (p); \
    66                 (p)->next = (p)->prev = NULL; \
    67         } else { \
    68                 (list)->prev = (p); \
    69                 (p)->next = (list); \
    70                 (p)->prev = NULL; \
    71                 (list) = (p); \
    72         }\
    73 }
    7459
    7560/* End of stuff from includes.h */
     
    8469
    8570/* End of stuff from smb.h */
    86 
    87 /* From smb_macros.h */
    88 
    89 #define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
    90 #define SMB_MALLOC_P(type) (type *)malloc_(sizeof(type))
    91 #define TALLOC_ARRAY(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
    92 #define TALLOC_ZERO_ARRAY(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
    93 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
    94 
    95 /* End of stuff from smb_macros.h */
    96 
    97 /* From ntdomain.h */
    98 
    99 struct uuid {
    100        uint32 time_low;
    101        uint16 time_mid;
    102        uint16 time_hi_and_version;
    103        uint8  clock_seq[2];
    104        uint8  node[6];
    105 };
    106 
    107 typedef struct _prs_struct {
    108         bool io; /* parsing in or out of data stream */
    109         /*
    110          * If the (incoming) data is big-endian. On output we are
    111           * always little-endian.
    112            */
    113            bool bigendian_data;
    114            uint8 align; /* data alignment */
    115            bool is_dynamic; /* Do we own this memory or not ? */
    116            uint32 data_offset; /* Current working offset into data. */
    117            uint32 buffer_size; /* Current allocated size of the buffer. */
    118            uint32 grow_size; /* size requested via prs_grow() calls */
    119            char *data_p; /* The buffer itself. */
    120            void *mem_ctx; /* When unmarshalling, use this.... */
    121 } prs_struct;
    122 
    123 #define MARSHALL 0
    124 #define UNMARSHALL 1
    125 
    126 #define RPC_LITTLE_ENDIAN  0
    127 #define RPC_PARSE_ALIGN    4
    128 
    129 /* End of stuff from ntdomain.h */
    130 
    13171
    13272/* From lib/time.c */
     
    14383/* End of stuff from lib/time.c */
    14484
    145 /* From rpc_dce.h */
    146 
    147 #define MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */
    148 
    149 /* End of stuff from rpc_dce.h */
    150 
    151 /* From parse_prs.h */
    152 
    153 bool prs_grow(prs_struct *ps, uint32 extra_space);
    154 bool prs_align(prs_struct *ps);
    155 bool prs_init(prs_struct *ps, uint32 size, void *ctx, bool io);
    156 char *prs_mem_get(prs_struct *ps, uint32 extra_size);
    157 bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32);
    158 bool prs_uint32s(const char *name, prs_struct *ps,
    159                  int depth, uint32 *data32s, int len);
    160 bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16);
    161 bool prs_uint16_pre(const char *name, prs_struct *ps, int depth,
    162                     uint16 *data16, uint32 *offset);
    163 bool prs_uint16_post(const char *name, prs_struct *ps, int depth,
    164                      uint16 *data16, uint32 ptr_uint16, uint32 start_offset);
    165 bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8);
    166 bool prs_uint8s(const char *name, prs_struct *ps, int depth,
    167                 uint8* data8s, int len);
    168 bool prs_set_offset(prs_struct *ps, uint32 offset);
    169 
    170 /* End of stuff from parse_prs.h */
    171 
    172 
    173 /* From pstring.h */
    174 
    175 #define FSTRING_LEN 256
    176 typedef char fstring[FSTRING_LEN];
    177 
    178 /* End of stuff from pstring.h */
    179 
    180 /* From rpc_parse/parse_misc.c */
    181 
    182 bool smb_io_uuid(const char *desc, struct uuid *uuid,
    183                  prs_struct *ps, int depth);
    184 bool smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth);
    185 
    186 /* End of stuff from rpc_parse/parse_misc.c */
    187 
    18885#endif /* _SMB_DEPS_H */
  • trunk/include/winsec.h

    r133 r134  
    33 * Security Descriptors. See:
    44 *   http://websvn.samba.org/cgi-bin/viewcvs.cgi/trunk/source/
     5 *
     6 * Revisions have been made based on information provided by Microsoft
     7 * at:
     8 *    http://msdn.microsoft.com/en-us/library/cc230366(PROT.10).aspx
    59 *
    610 * Copyright (C) 2005,2009 Timothy D. Morgan
     
    2327 */
    2428
     29#ifndef _WINSEC_H
     30#define _WINSEC_H
     31
    2532#include <stdlib.h>
    2633#include <stdbool.h>
     34#include <stdint.h>
    2735#include <stdio.h>
    2836#include <string.h>
     
    3644
    3745
    38 #define MAXSUBAUTHS 15
     46/* This is the maximum number of subauths in a SID, as defined here:
     47 *   http://msdn.microsoft.com/en-us/library/cc230371(PROT.10).aspx
     48 */
     49#define WINSEC_MAX_SUBAUTHS 15
    3950
    40 #define SEC_DESC_HEADER_SIZE     (2 * sizeof(uint16) + 4 * sizeof(uint32))
    41                                  /*thanks for Jim McDonough <jmcd@us.ibm.com>*/
    42 #define SEC_DESC_DACL_PRESENT    0x0004
    43 #define SEC_DESC_SACL_PRESENT    0x0010
     51#define WINSEC_DESC_HEADER_SIZE     (5 * sizeof(uint32_t))
     52#define WINSEC_ACL_HEADER_SIZE      (2 * sizeof(uint32_t))
     53#define WINSEC_ACE_MIN_SIZE         16
    4454
    45 #define SEC_ACE_OBJECT_PRESENT              0x00000001
    46 #define SEC_ACE_OBJECT_INHERITED_PRESENT    0x00000002
    47 #define SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT  0x5
    48 #define SEC_ACE_TYPE_ACCESS_DENIED_OBJECT   0x6
    49 #define SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT    0x7
    50 #define SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT    0x8
     55/* TODO: Fill in definitions of other flags */
     56/* This means offsets contained in the descriptor are relative to the
     57 * descriptor's offset.  This had better be true in the registry.
     58 */
     59#define WINSEC_DESC_SELF_RELATIVE   0x8000
     60#define WINSEC_DESC_SACL_PRESENT    0x0010
     61#define WINSEC_DESC_DACL_PRESENT    0x0004
     62
     63#define WINSEC_ACE_OBJECT_PRESENT              0x00000001
     64#define WINSEC_ACE_OBJECT_INHERITED_PRESENT    0x00000002
     65#define WINSEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT  0x5
     66#define WINSEC_ACE_TYPE_ACCESS_DENIED_OBJECT   0x6
     67#define WINSEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT    0x7
     68#define WINSEC_ACE_TYPE_SYSTEM_ALARM_OBJECT    0x8
    5169
    5270
    53 typedef struct sid_info
     71typedef struct _winsec_uuid
    5472{
    55   uint8  sid_rev_num;             /**< SID revision number */
    56   uint8  num_auths;               /**< Number of sub-authorities */
    57   uint8  id_auth[6];              /**< Identifier Authority */
     73       uint32 time_low;
     74       uint16 time_mid;
     75       uint16 time_hi_and_version;
     76       uint8  clock_seq[2];
     77       uint8  node[6];
     78} WINSEC_UUID;
     79
     80
     81typedef struct _winsec_sid
     82{
     83  uint8_t  sid_rev_num;             /* SID revision number */
     84  uint8_t  num_auths;               /* Number of sub-authorities */
     85  uint8_t  id_auth[6];              /* Identifier Authority */
    5886  /*
    5987   *  Pointer to sub-authorities.
    6088   *
    61    * @note The values in these uint32's are in *native* byteorder, not
     89   * @note The values in these uint32_t's are in *native* byteorder, not
    6290   * neccessarily little-endian...... JRA.
    6391   */
    64   uint32 sub_auths[MAXSUBAUTHS];
    65 } DOM_SID;
     92  /* XXX: Make this dynamically allocated? */
     93  uint32_t sub_auths[WINSEC_MAX_SUBAUTHS];
     94} WINSEC_DOM_SID;
    6695
    6796
    68 typedef struct security_info_info
     97typedef struct _winsec_ace
    6998{
    70         uint32 mask;
    71 
    72 } SEC_ACCESS;
    73 
    74 typedef struct security_ace_info
    75 {
    76         uint8 type;  /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */
    77         uint8 flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */
    78         uint16 size;
    79 
    80         SEC_ACCESS info;
     99        uint8_t type;  /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */
     100        uint8_t flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */
     101        uint16_t size;
     102        uint32_t access_mask;
    81103
    82104        /* this stuff may be present when type is XXXX_TYPE_XXXX_OBJECT */
    83         uint32  obj_flags; /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */
    84         struct uuid obj_guid;  /* object GUID */
    85         struct uuid inh_guid;  /* inherited object GUID */             
     105        uint32_t  obj_flags;  /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */
     106        WINSEC_UUID* obj_guid;  /* object GUID */
     107        WINSEC_UUID* inh_guid;  /* inherited object GUID */             
    86108        /* eof object stuff */
    87109
    88         DOM_SID trustee;
     110        WINSEC_DOM_SID* trustee;
    89111
    90 } SEC_ACE;
     112} WINSEC_ACE;
    91113
    92 typedef struct security_acl_info
     114typedef struct _winsec_acl
    93115{
    94         uint16 revision; /* 0x0003 */
    95         uint16 size; /* size in bytes of the entire ACL structure */
    96         uint32 num_aces; /* number of Access Control Entries */
     116        uint16_t revision; /* 0x0003 */
     117        uint16_t size;    /* size in bytes of the entire ACL structure */
     118        uint32_t num_aces; /* number of Access Control Entries */
    97119
    98         SEC_ACE *ace;
     120        WINSEC_ACE** aces;
    99121
    100 } SEC_ACL;
     122} WINSEC_ACL;
    101123
    102 typedef struct security_descriptor_info
     124typedef struct _winsec_desc
    103125{
    104         uint16 revision; /* 0x0001 */
    105         uint16 type;     /* SEC_DESC_xxxx flags */
     126        uint8_t revision; /* 0x01 */
     127        uint8_t sbz1;     /* "If the Control field has the RM flag set,
     128                           *  then this field contains the resource
     129                           *  manager (RM) control value. ... Otherwise,
     130                           *  this field is reserved and MUST be set to
     131                           *  zero." -- Microsoft.  See reference above.
     132                           */
     133        uint16_t control; /* WINSEC_DESC_* flags */
    106134
    107         uint32 off_owner_sid; /* offset to owner sid */
    108         uint32 off_grp_sid  ; /* offset to group sid */
    109         uint32 off_sacl     ; /* offset to system list of permissions */
    110         uint32 off_dacl     ; /* offset to list of permissions */
     135        uint32_t off_owner_sid; /* offset to owner sid */
     136        uint32_t off_grp_sid  ; /* offset to group sid */
     137        uint32_t off_sacl     ; /* offset to system list of permissions */
     138        uint32_t off_dacl     ; /* offset to list of permissions */
    111139
    112         SEC_ACL *dacl; /* user ACL */
    113         SEC_ACL *sacl; /* system ACL */
    114         DOM_SID *owner_sid;
    115         DOM_SID *grp_sid;
     140        WINSEC_DOM_SID* owner_sid;
     141        WINSEC_DOM_SID* grp_sid;
     142        WINSEC_ACL* sacl;       /* system ACL */
     143        WINSEC_ACL* dacl;       /* user ACL */
    116144
    117 } SEC_DESC;
     145} WINSEC_DESC;
    118146
    119147
     148/* XXX: Need API functions to deallocate these structures */
     149WINSEC_DESC* winsec_parse_desc(const uint8_t* buf, uint32_t buf_len);
     150WINSEC_ACL* winsec_parse_acl(const uint8_t* buf, uint32_t buf_len);
     151WINSEC_ACE* winsec_parse_ace(const uint8_t* buf, uint32_t buf_len);
     152WINSEC_DOM_SID* winsec_parse_dom_sid(const uint8_t* buf, uint32_t buf_len);
     153WINSEC_UUID* winsec_parse_uuid(const uint8_t* buf, uint32_t buf_len);
    120154
    121 bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth);
    122 bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth);
    123 bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth);
    124 bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth);
    125 bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth);
     155size_t winsec_sid_size(const WINSEC_DOM_SID* sid);
     156int winsec_sid_compare_auth(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
     157int winsec_sid_compare(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
     158bool winsec_sid_equal(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2);
     159bool winsec_desc_equal(WINSEC_DESC* s1, WINSEC_DESC* s2);
     160bool winsec_acl_equal(WINSEC_ACL* s1, WINSEC_ACL* s2);
     161bool winsec_ace_equal(WINSEC_ACE* s1, WINSEC_ACE* s2);
     162bool winsec_ace_object(uint8_t type);
    126163
    127 size_t sid_size(const DOM_SID *sid);
    128 int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2);
    129 int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2);
    130 bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2);
    131 bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2);
    132 bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2);
    133 bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2);
    134 bool sec_ace_object(uint8 type);
     164#endif /* _WINSEC_H */
  • trunk/lib/regfi.c

    r133 r134  
    33 *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/registry/regfio.c?rev=7470&view=auto
    44 *
    5  * Unix SMB/CIFS implementation.
    6  * Windows NT registry parsing library
     5 * Windows NT (and later) registry parsing library
    76 *
    87 * Copyright (C) 2005-2009 Timothy D. Morgan
     
    226225
    227226
    228 char* regfi_sid2str(DOM_SID* sid)
    229 {
    230   uint32 i, size = MAXSUBAUTHS*11 + 24;
     227char* regfi_sid2str(WINSEC_DOM_SID* sid)
     228{
     229  uint32 i, size = WINSEC_MAX_SUBAUTHS*11 + 24;
    231230  uint32 left = size;
    232231  uint8 comps = sid->num_auths;
     
    236235    return NULL;
    237236
    238   if(comps > MAXSUBAUTHS)
    239     comps = MAXSUBAUTHS;
     237  if(comps > WINSEC_MAX_SUBAUTHS)
     238    comps = WINSEC_MAX_SUBAUTHS;
    240239
    241240  left -= sprintf(ret_val, "S-%u-%u", sid->sid_rev_num, sid->id_auth[5]);
     
    248247
    249248
    250 char* regfi_get_acl(SEC_ACL* acl)
     249char* regfi_get_acl(WINSEC_ACL* acl)
    251250{
    252251  uint32 i, extra, size = 0;
     
    263262  for (i = 0; i < acl->num_aces && !failed; i++)
    264263  {
    265     sid_str = regfi_sid2str(&acl->ace[i].trustee);
    266     type_str = regfi_ace_type2str(acl->ace[i].type);
    267     perms_str = regfi_ace_perms2str(acl->ace[i].info.mask);
    268     flags_str = regfi_ace_flags2str(acl->ace[i].flags);
     264    sid_str = regfi_sid2str(acl->aces[i]->trustee);
     265    type_str = regfi_ace_type2str(acl->aces[i]->type);
     266    perms_str = regfi_ace_perms2str(acl->aces[i]->access_mask);
     267    flags_str = regfi_ace_flags2str(acl->aces[i]->flags);
    269268   
    270269    if(flags_str != NULL && perms_str != NULL
     
    307306
    308307
    309 char* regfi_get_sacl(SEC_DESC *sec_desc)
     308char* regfi_get_sacl(WINSEC_DESC *sec_desc)
    310309{
    311310  if (sec_desc->sacl)
     
    316315
    317316
    318 char* regfi_get_dacl(SEC_DESC *sec_desc)
     317char* regfi_get_dacl(WINSEC_DESC *sec_desc)
    319318{
    320319  if (sec_desc->dacl)
     
    325324
    326325
    327 char* regfi_get_owner(SEC_DESC *sec_desc)
     326char* regfi_get_owner(WINSEC_DESC *sec_desc)
    328327{
    329328  return regfi_sid2str(sec_desc->owner_sid);
     
    331330
    332331
    333 char* regfi_get_group(SEC_DESC *sec_desc)
     332char* regfi_get_group(WINSEC_DESC *sec_desc)
    334333{
    335334  return regfi_sid2str(sec_desc->grp_sid);
     
    447446{
    448447  uint32 i,j,k;
    449   REGF_SUBKEY_LIST* ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
    450   if(ret_val == NULL || lists == NULL)
     448  REGF_SUBKEY_LIST* ret_val;
     449
     450  if(lists == NULL)
     451    return NULL;
     452  ret_val = (REGF_SUBKEY_LIST*)zalloc(sizeof(REGF_SUBKEY_LIST));
     453
     454  if(ret_val == NULL)
    451455    return NULL;
    452456 
     
    457461    if(lists[i] == NULL)
    458462    {
    459       ret_val->num_keys = 0;
    460       break;
     463      free(ret_val);
     464      free(lists);
     465      return NULL;
    461466    }
    462467    ret_val->num_keys += lists[i]->num_keys;
     
    469474                                     * ret_val->num_keys);
    470475    k=0;
     476
    471477    if(ret_val->elements != NULL)
    472478    {
     
    498504  REGF_SUBKEY_LIST** sublists;
    499505  REGF_HBIN* sublist_hbin;
    500   uint32 i, cell_length, length, num_sublists, off, max_length;
     506  uint32 i, cell_length, length, num_sublists, off, max_length, elem_size;
    501507  uint8* hashes;
    502508  uint8 buf[REGFI_SUBKEY_LIST_MIN_LEN];
     
    541547      sublists[i] = regfi_load_subkeylist(file, off, 0, max_length, strict);
    542548    }
    543    
     549    free(hashes);
     550
    544551    return regfi_merge_subkeylists(num_sublists, sublists, strict);
     552  }
     553
     554  if(buf[0] == 'l' && buf[1] == 'i')
     555    elem_size = sizeof(uint32);
     556  else if((buf[0] == 'l') && (buf[1] == 'f' || buf[1] == 'h'))
     557    elem_size = sizeof(REGF_SUBKEY_LIST_ELEM);
     558  else
     559  {
     560    /* fprintf(stderr, "DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
     561    return NULL;
    545562  }
    546563
     
    551568  ret_val->offset = offset;
    552569  ret_val->cell_size = cell_length;
    553 
    554   if((buf[0] != 'l' || buf[1] != 'f') && (buf[0] != 'l' || buf[1] != 'h'))
    555   {
    556     /*printf("DEBUG: lf->header=%c%c\n", buf[0], buf[1]);*/
    557     free(ret_val);
    558     return NULL;
    559   }
    560 
    561570  ret_val->magic[0] = buf[0];
    562571  ret_val->magic[1] = buf[1];
     
    579588
    580589  if(cell_length - REGFI_SUBKEY_LIST_MIN_LEN - sizeof(uint32)
    581      < ret_val->num_keys*sizeof(REGF_SUBKEY_LIST_ELEM))
    582     return NULL;
    583 
    584   length = sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys;
    585   ret_val->elements = (REGF_SUBKEY_LIST_ELEM*)zalloc(length);
     590     < ret_val->num_keys*elem_size)
     591  {
     592    free(ret_val);
     593    return NULL;
     594  }
     595
     596  length = elem_size*ret_val->num_keys;
     597  ret_val->elements
     598    = (REGF_SUBKEY_LIST_ELEM*)zalloc(ret_val->num_keys
     599                                     * sizeof(REGF_SUBKEY_LIST_ELEM));
    586600  if(ret_val->elements == NULL)
    587601  {
     
    599613
    600614  if(regfi_read(file->fd, hashes, &length) != 0
    601      || length != sizeof(REGF_SUBKEY_LIST_ELEM)*ret_val->num_keys)
     615     || length != elem_size*ret_val->num_keys)
    602616  {
    603617    free(ret_val->elements);
     
    606620  }
    607621
    608   for (i=0; i < ret_val->num_keys; i++)
    609   {
    610     ret_val->elements[i].nk_off = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM));
    611     ret_val->elements[i].hash = IVAL(hashes, i*sizeof(REGF_SUBKEY_LIST_ELEM)+4);
     622  if(buf[0] == 'l' && buf[1] == 'i')
     623  {
     624    for (i=0; i < ret_val->num_keys; i++)
     625    {
     626      ret_val->elements[i].nk_off = IVAL(hashes, i*elem_size);
     627      ret_val->elements[i].hash = 0;
     628    }
     629  }
     630  else
     631  {
     632    for (i=0; i < ret_val->num_keys; i++)
     633    {
     634      ret_val->elements[i].nk_off = IVAL(hashes, i*elem_size);
     635      ret_val->elements[i].hash = IVAL(hashes, i*elem_size+4);
     636    }
    612637  }
    613638  free(hashes);
     
    623648{
    624649  REGF_SK_REC* ret_val;
     650  uint8* sec_desc_buf;
    625651  uint32 cell_length, length;
    626   prs_struct ps;
     652  /*prs_struct ps;*/
    627653  uint8 sk_header[REGFI_SK_MIN_LENGTH];
    628654  bool unalloc = false;
    629 
    630655
    631656  if(!regfi_parse_cell(file->fd, offset, sk_header, REGFI_SK_MIN_LENGTH,
     
    674699   * code depends on the ps structure.
    675700   */
     701  /*
    676702  if(!prs_init(&ps, ret_val->desc_size, NULL, UNMARSHALL))
    677703  {
     
    687713    return NULL;
    688714  }
    689 
    690   /* XXX: call should look more like: */
    691   /*if (!(ret_val->sec_desc = winsec_parse_desc(sec_desc_buf, ret_val->desc_size)))*/
    692   if (!sec_io_desc("sec_desc", &ret_val->sec_desc, &ps, 0))
    693   {
    694     free(ret_val);
    695     return NULL;
    696   }
    697 
    698   free(ps.data_p);
     715  */
     716
     717  sec_desc_buf = (uint8*)zalloc(ret_val->desc_size);
     718  if(ret_val == NULL)
     719  {
     720    free(ret_val);
     721    return NULL;
     722  }
     723
     724  length = ret_val->desc_size;
     725  if(regfi_read(file->fd, sec_desc_buf, &length) != 0
     726     || length != ret_val->desc_size)
     727  {
     728    free(ret_val);
     729    return NULL;
     730  }
     731
     732  if(!(ret_val->sec_desc = winsec_parse_desc(sec_desc_buf, ret_val->desc_size)))
     733  {
     734    free(sec_desc_buf);
     735    free(ret_val);
     736    return NULL;
     737  }
     738  free(sec_desc_buf);
     739
     740  /*  free(ps.data_p);*/
    699741
    700742  return ret_val;
     
    893935      off = nk->subkeys_off + REGF_BLOCKSIZE;
    894936      max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    895       nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys, 
     937      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys,
    896938                                          max_length, true);
     939
    897940      if(nk->subkeys == NULL)
    898941      {
  • trunk/lib/smb_deps.c

    r132 r134  
    142142
    143143/* 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  ********************************************************************/
    151 bool 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  ********************************************************************/
    209 bool 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 
    235 bool 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 
    263 char *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  ********************************************************************/
    289 bool 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  ********************************************************************/
    318 bool 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  ********************************************************************/
    361 bool 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  ********************************************************************/
    391 bool 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  ********************************************************************/
    415 bool 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  ********************************************************************/
    444 bool 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  ********************************************************************/
    464 bool 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  ********************************************************************/
    492 bool 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 ********************************************************************/
    514 bool 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 ********************************************************************/
    542 bool 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 }
  • trunk/lib/winsec.c

    r133 r134  
    2828
    2929
    30 /*******************************************************************
    31  * Parses a SEC_DESC structure.
    32  *******************************************************************/
    33 bool sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
    34 {
    35   uint32 old_offset;
    36   uint32 max_offset = 0; /* after we're done, move offset to end */
    37   uint32 tmp_offset = 0;
    38 
    39   SEC_DESC *psd;
    40 
    41   if (ppsd == NULL || ps == NULL)
    42     return false;
    43 
    44   psd = *ppsd;
    45   if (psd == NULL)
    46   {
    47     if((psd = (SEC_DESC*)zalloc(sizeof(SEC_DESC))) == NULL)
    48       return false;
    49     *ppsd = psd;
    50   }
    51 
    52   depth++;
    53 
    54   /* start of security descriptor stored for back-calc offset purposes */
    55   old_offset = ps->data_offset;
    56 
    57   if(!prs_uint16("revision ", ps, depth, &psd->revision)
    58      || !prs_uint16("type     ", ps, depth, &psd->type))
    59   {
    60     free(psd);
    61     *ppsd = NULL;
    62     return false;
    63   }
    64 
    65   if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid)
    66      || !prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid)
    67      || !prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl)
    68      || !prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
    69   {
    70     free(psd);
    71     *ppsd = NULL;   
    72     return false;
    73   }
    74   max_offset = MAX(max_offset, ps->data_offset);
    75 
    76   if (psd->off_owner_sid != 0)
    77   {
    78     tmp_offset = ps->data_offset;
    79     if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
    80     {
    81       free(psd);
    82       *ppsd = NULL;
    83       return false;
    84     }
    85 
    86     /* reading */
    87     if((psd->owner_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
    88     {
    89       free(psd);
    90       *ppsd = NULL;
    91       return false;
    92     }
    93 
    94     if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
    95     {
    96       free(psd->owner_sid);
    97       free(psd);
    98       *ppsd = NULL;
    99       return false;
    100     }
    101 
    102     max_offset = MAX(max_offset, ps->data_offset);
    103 
    104     if (!prs_set_offset(ps,tmp_offset))
    105     {
    106       free(psd->owner_sid);
    107       free(psd);
    108       *ppsd = NULL;
    109       return false;
    110     }
    111   }
    112 
    113   if (psd->off_grp_sid != 0)
    114   {
    115     tmp_offset = ps->data_offset;
    116     if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
    117     {
    118       free(psd->owner_sid);
    119       free(psd);
    120       *ppsd = NULL;
    121       return false;
    122     }
    123 
    124     /* reading */
    125     if((psd->grp_sid = (DOM_SID*)zalloc(sizeof(DOM_SID))) == NULL)
    126     {
    127       free(psd->owner_sid);
    128       free(psd);
    129       *ppsd = NULL;
    130       return false;
    131     }
    132 
    133     if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
    134     {
    135       free(psd->grp_sid);
    136       free(psd->owner_sid);
    137       free(psd);
    138       *ppsd = NULL;
    139       return false;
    140     }
    141                        
    142     max_offset = MAX(max_offset, ps->data_offset);
    143 
    144     if (!prs_set_offset(ps,tmp_offset))
    145     {
    146       free(psd->grp_sid);
    147       free(psd->owner_sid);
    148       free(psd);
    149       *ppsd = NULL;
    150       return false;
    151     }
    152   }
    153 
    154   if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl)
    155   {
    156     tmp_offset = ps->data_offset;
    157     if(!prs_set_offset(ps, old_offset + psd->off_sacl)
    158        || !sec_io_acl("sacl", &psd->sacl, ps, depth))
    159     {
    160       free(psd->grp_sid);
    161       free(psd->owner_sid);
    162       free(psd);
    163       *ppsd = NULL;
    164       return false;
    165     }
    166     max_offset = MAX(max_offset, ps->data_offset);
    167     if (!prs_set_offset(ps,tmp_offset))
    168     {
    169       free(psd->grp_sid);
    170       free(psd->owner_sid);
    171       free(psd);
    172       *ppsd = NULL;
    173       return false;
    174     }
    175   }
    176 
    177   if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0)
    178   {
    179     tmp_offset = ps->data_offset;
    180     if(!prs_set_offset(ps, old_offset + psd->off_dacl)
    181        || !sec_io_acl("dacl", &psd->dacl, ps, depth))
    182     {
    183       free(psd->grp_sid);
    184       free(psd->owner_sid);
    185       free(psd);
    186       *ppsd = NULL;
    187       return false;
    188     }
    189     max_offset = MAX(max_offset, ps->data_offset);
    190     if (!prs_set_offset(ps,tmp_offset))
    191     {
    192       free(psd->grp_sid);
    193       free(psd->owner_sid);
    194       free(psd);
    195       *ppsd = NULL;
    196       return false;
    197     }
    198   }
    199 
    200   if(!prs_set_offset(ps, max_offset))
    201   {
    202     free(psd->grp_sid);
    203     free(psd->owner_sid);
    204     free(psd);
    205     *ppsd = NULL;
    206     return false;
    207   }
    208 
    209   return true;
    210 }
    211 
    212 
    213 /*******************************************************************
    214  Reads or writes a DOM_SID structure.
    215 ********************************************************************/
    216 bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth)
    217 {
    218   int i;
    219 
    220   if (sid == NULL)
    221     return false;
    222   depth++;
    223 
    224   if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num))
    225     return false;
    226 
    227   if(!prs_uint8 ("num_auths  ", ps, depth, &sid->num_auths))
    228     return false;
    229 
    230   for (i = 0; i < 6; i++)
    231   {
    232     fstring tmp;
    233     snprintf(tmp, sizeof(tmp) - 1, "id_auth[%d] ", i);
    234     if(!prs_uint8 (tmp, ps, depth, &sid->id_auth[i]))
    235       return false;
    236   }
    237 
    238   /* oops! XXXX should really issue a warning here... */
    239   if (sid->num_auths > MAXSUBAUTHS)
    240     sid->num_auths = MAXSUBAUTHS;
    241 
    242   if(!prs_uint32s("sub_auths ", ps, depth,
    243                   sid->sub_auths, sid->num_auths))
    244   { return false; }
    245 
    246   return true;
    247 }
    248 
    249 
    250 
    251 /*******************************************************************
    252  Reads or writes a SEC_ACCESS structure.
    253 ********************************************************************/
    254 bool sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
    255 {
    256   if (t == NULL)
    257     return false;
    258 
    259   depth++;
    260        
    261   if(!prs_uint32("mask", ps, depth, &t->mask))
    262     return false;
    263 
    264   return true;
    265 }
    266 
    267 
    268 /*******************************************************************
    269  Reads or writes a SEC_ACE structure.
    270 ********************************************************************/
    271 bool sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
    272 {
    273   uint32 old_offset;
    274   uint32 offset_ace_size;
    275 
    276   if (psa == NULL)
    277     return false;
    278 
    279   depth++;
    280        
    281   old_offset = ps->data_offset;
    282 
    283   if(!prs_uint8("type ", ps, depth, &psa->type))
    284     return false;
    285 
    286   if(!prs_uint8("flags", ps, depth, &psa->flags))
    287     return false;
    288 
    289   if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
    290     return false;
    291 
    292   if(!sec_io_access("info ", &psa->info, ps, depth))
    293     return false;
    294 
    295   /* check whether object access is present */
    296   if (!sec_ace_object(psa->type))
    297   {
    298     if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
    299       return false;
    300   }
    301   else
    302   {
    303     if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
    304       return false;
    305 
    306     if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
    307       if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
    308         return false;
    309 
    310     if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
    311       if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
    312         return false;
    313 
    314     if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
    315       return false;
    316   }
    317 
    318   if(!prs_uint16_post("size ", ps, depth, &psa->size,
    319                       offset_ace_size, old_offset))
    320   { return false; }
    321 
    322   return true;
    323 }
    324 
    325 
    326 /*******************************************************************
    327  Reads or writes a SEC_ACL structure. 
    328 
    329  First of the xx_io_xx functions that allocates its data structures
    330  for you as it reads them.
    331 ********************************************************************/
    332 bool sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
    333 {
    334   unsigned int i;
    335   uint32 old_offset;
    336   uint32 offset_acl_size;
    337   SEC_ACL* psa;
     30/******************************************************************************
     31 * Parses a WINSEC_DESC structure and substructures.
     32 ******************************************************************************/
     33WINSEC_DESC* winsec_parse_desc(const uint8_t* buf, uint32_t buf_len)
     34{
     35  WINSEC_DESC* ret_val;
     36
     37  if (buf == NULL || buf_len <  WINSEC_DESC_HEADER_SIZE)
     38    return NULL;
     39
     40  if((ret_val = (WINSEC_DESC*)zalloc(sizeof(WINSEC_DESC))) == NULL)
     41    return NULL;
     42
     43  ret_val->revision = buf[0];
     44  ret_val->sbz1 = buf[1];
     45  ret_val->control = SVAL(buf, 0x2);
     46
     47  if(!(ret_val->control & WINSEC_DESC_SELF_RELATIVE))
     48    fprintf(stderr, "DEBUG: NOT self-relative!\n");
     49
     50  ret_val->off_owner_sid = IVAL(buf, 0x4);
     51  ret_val->off_grp_sid = IVAL(buf, 0x8);
     52  ret_val->off_sacl = IVAL(buf, 0xC);
     53  ret_val->off_dacl = IVAL(buf, 0x10);
     54
     55  /* A basic sanity check to ensure our offsets are within our buffer.
     56   * Additional length checking is done in secondary parsing functions.
     57   */
     58  if((ret_val->off_owner_sid >= buf_len)
     59     || (ret_val->off_grp_sid >= buf_len)
     60     || (ret_val->off_sacl >= buf_len)
     61     || (ret_val->off_dacl >= buf_len))
     62  {
     63    free(ret_val);
     64    return NULL;
     65  }
     66
     67  if(ret_val->off_owner_sid != 0)
     68  {
     69    ret_val->owner_sid = winsec_parse_dom_sid(buf + ret_val->off_owner_sid,
     70                                              buf_len - ret_val->off_owner_sid);
     71    if(ret_val->owner_sid == NULL)
     72    {
     73      free(ret_val);
     74      return NULL;
     75    }
     76  }
     77
     78  if (ret_val->off_grp_sid != 0)
     79  {
     80    ret_val->grp_sid = winsec_parse_dom_sid(buf + ret_val->off_grp_sid,
     81                                            buf_len - ret_val->off_grp_sid);
     82    if(ret_val->grp_sid == NULL)
     83    {
     84      if(ret_val->owner_sid != NULL)
     85        free(ret_val->owner_sid);
     86      free(ret_val);
     87      return NULL;
     88    }
     89  }
     90
     91  if ((ret_val->control & WINSEC_DESC_SACL_PRESENT) && ret_val->off_sacl)
     92  {
     93    ret_val->sacl = winsec_parse_acl(buf + ret_val->off_sacl,
     94                                     buf_len - ret_val->off_sacl);
     95    if(ret_val->sacl == NULL)
     96    {
     97      if(ret_val->owner_sid != NULL)
     98        free(ret_val->owner_sid);
     99      if(ret_val->grp_sid != NULL)
     100        free(ret_val->grp_sid);
     101      free(ret_val);
     102      return NULL;
     103    }
     104  }
     105
     106  if ((ret_val->control & WINSEC_DESC_DACL_PRESENT) && ret_val->off_dacl != 0)
     107  {
     108    ret_val->dacl = winsec_parse_acl(buf + ret_val->off_dacl,
     109                                     buf_len - ret_val->off_dacl);
     110    if(ret_val->dacl == NULL)
     111    {
     112      if(ret_val->owner_sid != NULL)
     113        free(ret_val->owner_sid);
     114      if(ret_val->grp_sid != NULL)
     115        free(ret_val->grp_sid);
     116      if(ret_val->sacl != NULL)
     117        free(ret_val->sacl);
     118      free(ret_val);
     119      return NULL;
     120    }
     121  }
     122
     123  return ret_val;
     124}
     125
     126
     127/******************************************************************************
     128 * Parses a WINSEC_ACL structure and all substructures.
     129 ******************************************************************************/
     130WINSEC_ACL* winsec_parse_acl(const uint8_t* buf, uint32_t buf_len)
     131{
     132  uint32_t i, offset;
     133  WINSEC_ACL* ret_val;
    338134
    339135  /*
    340136   * Note that the size is always a multiple of 4 bytes due to the
    341    * nature of the data structure.  Therefore the prs_align() calls
    342    * have been removed as they through us off when doing two-layer
    343    * marshalling such as in the printing code (RPC_BUFFER).  --jerry
     137   * nature of the data structure.
    344138   */
    345 
    346   if (ppsa == NULL || ps == NULL)
    347     return false;
    348 
    349   psa = *ppsa;
    350 
    351   if(psa == NULL)
    352   {
    353     /*
    354      * This is a read and we must allocate the stuct to read into.
    355      */
    356     if((psa = (SEC_ACL*)zalloc(sizeof(SEC_ACL))) == NULL)
    357       return false;
    358     *ppsa = psa;
    359   }
    360 
    361   depth++;     
    362   old_offset = ps->data_offset;
    363 
    364   if(!prs_uint16("revision", ps, depth, &psa->revision)
    365      || !prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size)
    366      || !prs_uint32("num_aces ", ps, depth, &psa->num_aces))
    367   {
    368     free(psa);
    369     *ppsa = NULL;
    370     return false;
    371   }
    372 
    373   /*
    374    * Even if the num_aces is zero, allocate memory as there's a difference
     139  if (buf == NULL || buf_len < 8)
     140    return NULL;
     141
     142  if((ret_val = (WINSEC_ACL*)zalloc(sizeof(WINSEC_ACL))) == NULL)
     143    return NULL;
     144 
     145  ret_val->revision = SVAL(buf, 0x0);
     146  ret_val->size     = SVAL(buf, 0x2);
     147  ret_val->num_aces = IVAL(buf, 0x4);
     148
     149  /* The num_aces can be at most around 4k because anything greater
     150   * wouldn't fit in the 16 bit size even if every ace was as small as
     151   * possible.
     152   */
     153  if((ret_val->size > buf_len) || (ret_val->num_aces > 4095))
     154  {
     155    free(ret_val);
     156    return NULL;
     157  }
     158
     159  /* Even if the num_aces is zero, allocate memory as there's a difference
    375160   * between a non-present DACL (allow all access) and a DACL with no ACE's
    376161   * (allow no access).
    377162   */
    378   if((psa->ace = (SEC_ACE*)zcalloc(sizeof(SEC_ACE), psa->num_aces+1)) == NULL)
    379   {
    380     free(psa);
    381     *ppsa = NULL;
    382     return false;
    383   }
    384 
    385   for (i = 0; i < psa->num_aces; i++)
    386   {
    387     fstring tmp;
    388     snprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
    389     if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
    390     {
    391       free(psa);
    392       *ppsa = NULL;
    393       return false;
    394     }
    395   }
    396 
    397   if(!prs_uint16_post("size     ", ps, depth, &psa->size,
    398                       offset_acl_size, old_offset))
    399   {
    400     free(psa);
    401     *ppsa = NULL;
    402     return false;
    403   }
    404 
    405   return true;
    406 }
    407 
    408 
    409 /*****************************************************************
    410  Calculates size of a sid.
    411 *****************************************************************/ 
    412 size_t sid_size(const DOM_SID *sid)
     163  if((ret_val->aces = (WINSEC_ACE**)zcalloc(sizeof(WINSEC_ACE*),
     164                                           ret_val->num_aces+1)) == NULL)
     165  {
     166    free(ret_val);
     167    return NULL;
     168  }
     169
     170  offset = 8;
     171  for(i=0; i < ret_val->num_aces; i++)
     172  {
     173    ret_val->aces[i] = winsec_parse_ace(buf+offset, buf_len-offset);
     174    if(ret_val->aces[i] == NULL)
     175    {
     176      free(ret_val->aces);
     177      free(ret_val);
     178      return NULL;
     179    }
     180
     181    offset += ret_val->aces[i]->size;
     182    if(offset > buf_len)
     183    {
     184      free(ret_val->aces);
     185      free(ret_val);
     186      return NULL;
     187    }
     188  }
     189
     190  return ret_val;
     191}
     192
     193
     194/******************************************************************************
     195 * Parses a WINSEC_ACE structure and all substructures.
     196 ******************************************************************************/
     197WINSEC_ACE* winsec_parse_ace(const uint8_t* buf, uint32_t buf_len)
     198{
     199  uint32_t offset;
     200  WINSEC_ACE* ret_val;
     201
     202  if(buf == NULL || buf_len < WINSEC_ACE_MIN_SIZE)
     203    return NULL;
     204
     205  if((ret_val = (WINSEC_ACE*)zalloc(sizeof(WINSEC_ACE))) == NULL)
     206    return NULL;
     207
     208  ret_val->type = buf[0];
     209  ret_val->flags = buf[1];
     210  ret_val->size = SVAL(buf, 0x2);
     211  ret_val->access_mask = IVAL(buf, 0x4);
     212
     213  offset = 0x8;
     214
     215  /* check whether object access is present */
     216  if (winsec_ace_object(ret_val->type))
     217  {
     218    ret_val->obj_flags = IVAL(buf, offset);
     219    offset += 4;
     220
     221    if(ret_val->obj_flags & WINSEC_ACE_OBJECT_PRESENT)
     222    {
     223      ret_val->obj_guid = winsec_parse_uuid(buf+offset, buf_len-offset);
     224      if(ret_val->obj_guid == NULL)
     225      {
     226        free(ret_val);
     227        return NULL;
     228      }
     229      offset += sizeof(WINSEC_UUID);
     230    }
     231
     232    if(ret_val->obj_flags & WINSEC_ACE_OBJECT_INHERITED_PRESENT)
     233    {
     234      ret_val->inh_guid = winsec_parse_uuid(buf+offset, buf_len-offset);
     235      if(ret_val->inh_guid == NULL)
     236      {
     237        if(ret_val->obj_guid != NULL)
     238          free(ret_val->obj_guid);
     239        free(ret_val);
     240        return NULL;
     241      }
     242      offset += sizeof(WINSEC_UUID);
     243    }
     244  }
     245
     246  ret_val->trustee = winsec_parse_dom_sid(buf+offset, buf_len-offset);
     247  if(ret_val->trustee == NULL)
     248  {
     249    if(ret_val->obj_guid != NULL)
     250      free(ret_val->obj_guid);
     251    if(ret_val->inh_guid != NULL)
     252      free(ret_val->inh_guid);
     253    free(ret_val);
     254        return NULL;
     255  }
     256 
     257  return ret_val;
     258}
     259
     260
     261/******************************************************************************
     262 * Parses a WINSEC_DOM_SID structure.
     263 ******************************************************************************/
     264WINSEC_DOM_SID* winsec_parse_dom_sid(const uint8_t* buf, uint32_t buf_len)
     265{
     266  uint32_t i;
     267  WINSEC_DOM_SID* ret_val;
     268
     269  if(buf == NULL || buf_len < 8)
     270    return NULL;
     271
     272  if((ret_val = (WINSEC_DOM_SID*)zalloc(sizeof(WINSEC_DOM_SID))) == NULL)
     273    return NULL;
     274
     275  ret_val->sid_rev_num = buf[0];
     276  ret_val->num_auths = buf[1];
     277  memcpy(ret_val->id_auth, buf+2, 6);
     278
     279  /* XXX: should really issue a warning here... */
     280  if (ret_val->num_auths > WINSEC_MAX_SUBAUTHS)
     281    ret_val->num_auths = WINSEC_MAX_SUBAUTHS;
     282
     283  if(buf_len < ret_val->num_auths*sizeof(uint32_t)+8)
     284  {
     285    free(ret_val);
     286    return NULL;
     287  }
     288 
     289  for(i=0; i < ret_val->num_auths; i++)
     290    ret_val->sub_auths[i] = IVAL(buf, 8+i*sizeof(uint32_t));
     291
     292  return ret_val;
     293}
     294
     295
     296/******************************************************************************
     297 * Parses a WINSEC_UUID struct.
     298 ******************************************************************************/
     299WINSEC_UUID* winsec_parse_uuid(const uint8_t* buf, uint32_t buf_len)
     300{
     301  WINSEC_UUID* ret_val;
     302
     303  if(buf == NULL || buf_len < sizeof(WINSEC_UUID))
     304    return false;
     305
     306  if((ret_val = (WINSEC_UUID*)zalloc(sizeof(WINSEC_UUID))) == NULL)
     307    return NULL;
     308 
     309  ret_val->time_low = IVAL(buf, 0x0);
     310  ret_val->time_mid = SVAL(buf, 0x4);
     311  ret_val->time_hi_and_version = SVAL(buf, 0x6);
     312 
     313  memcpy(ret_val->clock_seq, buf+0x8, 2);
     314  memcpy(ret_val->node, buf+0xB, 6);
     315
     316  return ret_val;
     317}
     318
     319
     320/******************************************************************************
     321 * Calculates the size of a SID.
     322 ******************************************************************************/
     323/*size_t sid_size(const WINSEC_DOM_SID *sid)*/
     324size_t winsec_sid_size(const WINSEC_DOM_SID* sid)
    413325{
    414326  if (sid == NULL)
    415327    return 0;
    416328
    417   return sid->num_auths * sizeof(uint32) + 8;
    418 }
    419 
    420 
    421 /*****************************************************************
    422  Compare the auth portion of two sids.
    423 *****************************************************************/ 
    424 int sid_compare_auth(const DOM_SID *sid1, const DOM_SID *sid2)
     329  return sid->num_auths * sizeof(uint32_t) + 8;
     330}
     331
     332
     333/******************************************************************************
     334 * Compare the auth portion of two SIDs.
     335 ******************************************************************************/
     336/*int sid_compare_auth(const WINSEC_DOM_SID *sid1, const WINSEC_DOM_SID *sid2)*/
     337int winsec_sid_compare_auth(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
    425338{
    426339  int i;
     
    444357
    445358
    446 /*****************************************************************
    447  Compare two sids.
    448 *****************************************************************/ 
    449 int sid_compare(const DOM_SID *sid1, const DOM_SID *sid2)
     359/******************************************************************************
     360 * Compare two SIDs.
     361 ******************************************************************************/
     362/*int sid_compare(const WINSEC_DOM_SID *sid1, const WINSEC_DOM_SID *sid2)*/
     363int winsec_sid_compare(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
    450364{
    451365  int i;
     
    466380      return sid1->sub_auths[i] - sid2->sub_auths[i];
    467381
    468   return sid_compare_auth(sid1, sid2);
    469 }
    470 
    471 
    472 /*****************************************************************
    473  Compare two sids.
    474 *****************************************************************/ 
    475 bool sid_equal(const DOM_SID *sid1, const DOM_SID *sid2)
    476 {
    477   return sid_compare(sid1, sid2) == 0;
    478 }
    479 
    480 
    481 
    482 /*******************************************************************
    483  Check if ACE has OBJECT type.
    484 ********************************************************************/
    485 bool sec_ace_object(uint8 type)
    486 {
    487   if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
    488       type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
    489       type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
    490       type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
     382  return winsec_sid_compare_auth(sid1, sid2);
     383}
     384
     385
     386/******************************************************************************
     387 * Compare two SIDs.
     388 ******************************************************************************/
     389bool winsec_sid_equal(const WINSEC_DOM_SID* sid1, const WINSEC_DOM_SID* sid2)
     390{
     391  return winsec_sid_compare(sid1, sid2) == 0;
     392}
     393
     394
     395/******************************************************************************
     396 * Compares two WINSEC_DESC structures.
     397 ******************************************************************************/
     398bool winsec_desc_equal(WINSEC_DESC* s1, WINSEC_DESC* s2)
     399{
     400  /* Trivial cases */
     401  if (!s1 && !s2)
    491402    return true;
    492   }
    493   return false;
    494 }
    495 
    496 
    497 /*******************************************************************
    498  Compares two SEC_ACE structures
    499 ********************************************************************/
    500 bool sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
    501 {
     403  if (!s1 || !s2)
     404    return false;
     405
     406  /* Check top level stuff */
     407  if (s1->revision != s2->revision)
     408    return false;
     409
     410  if (s1->control != s2->control)
     411    return false;
     412
     413  /* Check owner and group */
     414  if (!winsec_sid_equal(s1->owner_sid, s2->owner_sid))
     415    return false;
     416
     417  if (!winsec_sid_equal(s1->grp_sid, s2->grp_sid))
     418    return false;
     419
     420  /* Check ACLs present in one but not the other */
     421  if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
     422      (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl))
     423  { return false; }
     424
     425  /* Sigh - we have to do it the hard way by iterating over all
     426     the ACEs in the ACLs */
     427  if(!winsec_acl_equal(s1->dacl, s2->dacl) || !winsec_acl_equal(s1->sacl, s2->sacl))
     428    return false;
     429
     430  return true;
     431}
     432
     433
     434
     435/******************************************************************************
     436 * Compares two WINSEC_ACL structures.
     437 ******************************************************************************/
     438bool winsec_acl_equal(WINSEC_ACL* s1, WINSEC_ACL* s2)
     439{
     440  unsigned int i, j;
     441
    502442  /* Trivial cases */
    503443  if (!s1 && !s2)
     
    507447
    508448  /* Check top level stuff */
    509   if (s1->type != s2->type || s1->flags != s2->flags ||
    510       s1->info.mask != s2->info.mask)
    511   { return false; }
    512 
    513   /* Check SID */
    514   if (!sid_equal(&s1->trustee, &s2->trustee))
    515     return false;
     449  if (s1->revision != s2->revision)
     450    return false;
     451
     452  if (s1->num_aces != s2->num_aces)
     453    return false;
     454
     455  /* The ACEs could be in any order so check each ACE in s1 against
     456     each ACE in s2. */
     457
     458  for (i = 0; i < s1->num_aces; i++)
     459  {
     460    bool found = false;
     461
     462    for (j = 0; j < s2->num_aces; j++)
     463    {
     464      if (winsec_ace_equal(s1->aces[i], s2->aces[j]))
     465      {
     466        found = true;
     467        break;
     468      }
     469    }
     470
     471    if (!found)
     472      return false;
     473  }
    516474
    517475  return true;
     
    519477
    520478
    521 /*******************************************************************
    522  Compares two SEC_ACL structures
    523 ********************************************************************/
    524 bool sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
    525 {
    526   unsigned int i, j;
    527 
     479/******************************************************************************
     480 * Compares two WINSEC_ACE structures.
     481 ******************************************************************************/
     482bool winsec_ace_equal(WINSEC_ACE* s1, WINSEC_ACE* s2)
     483{
    528484  /* Trivial cases */
    529485  if (!s1 && !s2)
     
    533489
    534490  /* Check top level stuff */
    535   if (s1->revision != s2->revision)
    536     return false;
    537 
    538   if (s1->num_aces != s2->num_aces)
    539     return false;
    540 
    541   /* The ACEs could be in any order so check each ACE in s1 against
    542      each ACE in s2. */
    543 
    544   for (i = 0; i < s1->num_aces; i++)
    545   {
    546     bool found = false;
    547 
    548     for (j = 0; j < s2->num_aces; j++)
    549     {
    550       if (sec_ace_equal(&s1->ace[i], &s2->ace[j]))
    551       {
    552         found = true;
    553         break;
    554       }
    555     }
    556 
    557     if (!found)
    558       return false;
    559   }
     491  if (s1->type != s2->type || s1->flags != s2->flags ||
     492      s1->access_mask != s2->access_mask)
     493  { return false; }
     494
     495  /* Check SID */
     496  if (!winsec_sid_equal(s1->trustee, s2->trustee))
     497    return false;
    560498
    561499  return true;
     
    563501
    564502
    565 /*******************************************************************
    566  Compares two SEC_DESC structures
    567 ********************************************************************/
    568 bool sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
    569 {
    570   /* Trivial cases */
    571   if (!s1 && !s2)
    572     return true;
    573   if (!s1 || !s2)
    574     return false;
    575 
    576   /* Check top level stuff */
    577   if (s1->revision != s2->revision)
    578     return false;
    579 
    580   if (s1->type!= s2->type)
    581     return false;
    582 
    583   /* Check owner and group */
    584   if (!sid_equal(s1->owner_sid, s2->owner_sid))
    585     return false;
    586 
    587   if (!sid_equal(s1->grp_sid, s2->grp_sid))
    588     return false;
    589 
    590   /* Check ACLs present in one but not the other */
    591   if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
    592       (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl))
    593   { return false; }
    594 
    595   /* Sigh - we have to do it the hard way by iterating over all
    596      the ACEs in the ACLs */
    597   if(!sec_acl_equal(s1->dacl, s2->dacl) || !sec_acl_equal(s1->sacl, s2->sacl))
    598     return false;
    599 
    600   return true;
    601 }
     503/******************************************************************************
     504 * Check if ACE has OBJECT type.
     505 ******************************************************************************/
     506bool winsec_ace_object(uint8_t type)
     507{
     508  if (type == WINSEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
     509      type == WINSEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
     510      type == WINSEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
     511      type == WINSEC_ACE_TYPE_SYSTEM_ALARM_OBJECT)
     512  { return true; }
     513
     514  return false;
     515}
  • trunk/src/common.c

    r126 r134  
    2929const char* common_special_chars = ",\"\\";
    3030
    31 #define REGLOOKUP_VERSION "0.9.0"
     31#define REGLOOKUP_VERSION "0.10.0"
    3232
    3333
Note: See TracChangeset for help on using the changeset viewer.