Changeset 157 for trunk/lib


Ignore:
Timestamp:
11/22/09 19:47:22 (15 years ago)
Author:
tim
Message:

reorganized data parsing in regfi

simplified some length validation

added big data support to reglookup-recover

fixed reglookup-recover's handling of data values in the offset

Location:
trunk/lib
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/regfi.c

    r155 r157  
    471471
    472472
    473 /*******************************************************************
     473/******************************************************************************
    474474 * Given an offset and an hbin, is the offset within that hbin?
    475475 * The offset is a virtual file offset.
    476  *******************************************************************/
     476 ******************************************************************************/
    477477static bool regfi_offset_in_hbin(const REGFI_HBIN* hbin, uint32 voffset)
    478478{
     
    489489
    490490
    491 /*******************************************************************
    492  * Provide a virtual offset and receive the correpsonding HBIN
     491/******************************************************************************
     492 * Provide a physical offset and receive the correpsonding HBIN
    493493 * block for it.  NULL if one doesn't exist.
    494  *******************************************************************/
    495 const REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset)
    496 {
    497   return (const REGFI_HBIN*)range_list_find_data(file->hbins,
    498                                                  voffset+REGFI_REGF_SIZE);
    499 }
    500 
     494 ******************************************************************************/
     495const REGFI_HBIN* regfi_lookup_hbin(REGFI_FILE* file, uint32 offset)
     496{
     497  return (const REGFI_HBIN*)range_list_find_data(file->hbins, offset);
     498}
     499
     500
     501/******************************************************************************
     502 * Calculate the largest possible cell size given a physical offset.
     503 * Largest size is based on the HBIN the offset is currently a member of.
     504 * Returns negative values on error.
     505 * (Since cells can only be ~2^31 in size, this works out.)
     506 ******************************************************************************/
     507int32 regfi_calc_maxsize(REGFI_FILE* file, uint32 offset)
     508{
     509  const REGFI_HBIN* hbin = regfi_lookup_hbin(file, offset);
     510  if(hbin == NULL)
     511    return -1;
     512
     513  return (hbin->block_size + hbin->file_off) - offset;
     514}
    501515
    502516
     
    542556  REGFI_SUBKEY_LIST* ret_val;
    543557  REGFI_SUBKEY_LIST** sublists;
    544   const REGFI_HBIN* sublist_hbin;
    545   uint32 i, num_sublists, off, max_length;
     558  uint32 i, num_sublists, off;
     559  int32 sublist_maxsize;
    546560
    547561  if(depth_left == 0)
     
    565579    {
    566580      off = ret_val->elements[i].offset + REGFI_REGF_SIZE;
    567       sublist_hbin = regfi_lookup_hbin(file, ret_val->elements[i].offset);
    568       if(sublist_hbin == NULL)
     581
     582      sublist_maxsize = regfi_calc_maxsize(file, off);
     583      if(sublist_maxsize < 0)
    569584        sublists[i] = NULL;
    570585      else
    571       {
    572         max_length = sublist_hbin->block_size + sublist_hbin->file_off - off;
    573         sublists[i] = regfi_load_subkeylist_aux(file, off, max_length, strict,
    574                                                 depth_left-1);
    575       }
     586        sublists[i] = regfi_load_subkeylist_aux(file, off, sublist_maxsize,
     587                                                strict, depth_left-1);
    576588    }
    577589    talloc_free(ret_val);
     
    792804    ret_val->cell_size = max_size & 0xFFFFFFF8;
    793805  if((ret_val->cell_size < REGFI_SK_MIN_LENGTH)
    794      || (strict && ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8)))
     806     || (strict && (ret_val->cell_size & 0x00000007) != 0))
    795807  {
    796808    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size found while"
     
    808820  ret_val->desc_size = IVAL(sk_header, 0x10);
    809821
    810   if(ret_val->prev_sk_off != (ret_val->prev_sk_off & 0xFFFFFFF8)
    811      || ret_val->next_sk_off != (ret_val->next_sk_off & 0xFFFFFFF8))
     822  if((ret_val->prev_sk_off & 0x00000007) != 0
     823     || (ret_val->next_sk_off & 0x00000007) != 0)
    812824  {
    813825    regfi_add_message(file, REGFI_MSG_WARN, "SK record's next/previous offsets"
     
    873885  }
    874886
    875   if(cell_length != (cell_length & 0xFFFFFFF8))
     887  if((cell_length & 0x00000007) != 0)
    876888  {
    877889    regfi_add_message(file, REGFI_MSG_WARN, "Cell length not a multiple of 8"
     
    925937       *      with partial files. */
    926938      if((ret_val->elements[i] + REGFI_REGF_SIZE > file->file_length)
    927          || ((ret_val->elements[i] & 0xFFFFFFF8) != ret_val->elements[i]))
     939         || ((ret_val->elements[i] & 0x00000007) != 0))
    928940      {
    929941        regfi_add_message(file, REGFI_MSG_WARN, "Invalid value pointer"
     
    946958{
    947959  REGFI_VK_REC* ret_val = NULL;
    948   const REGFI_HBIN* hbin;
    949   uint32 data_offset, data_maxsize;
    950960  REGFI_BUFFER data;
    951 
    952   hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
    953   if(!hbin)
    954     return NULL;
    955  
    956   ret_val = regfi_parse_vk(file, offset,
    957                            hbin->block_size + hbin->file_off - offset, strict);
    958 
     961  int32 max_size;
     962
     963  max_size = regfi_calc_maxsize(file, offset);
     964  if(max_size < 0)
     965    return NULL;
     966 
     967  ret_val = regfi_parse_vk(file, offset, max_size, strict);
    959968  if(ret_val == NULL)
    960969    return NULL;
     
    964973  else
    965974  {
    966     if(ret_val->data_in_offset)
    967     {
    968       data = regfi_load_data(file, ret_val->type, ret_val->data_off,
    969                               ret_val->data_size, 4,
    970                               ret_val->data_in_offset, strict);
    971       ret_val->data = data.buf;
    972       ret_val->data_size = data.len;
    973     }
    974     else
    975     {
    976       hbin = regfi_lookup_hbin(file, ret_val->data_off);
    977       if(hbin)
    978       {
    979         data_offset = ret_val->data_off+REGFI_REGF_SIZE;
    980         data_maxsize = hbin->block_size + hbin->file_off - data_offset;
    981         data = regfi_load_data(file, ret_val->type, data_offset,
    982                                 ret_val->data_size, data_maxsize,
    983                                 ret_val->data_in_offset, strict);
    984         ret_val->data = data.buf;
    985         ret_val->data_size = data.len;
    986 
    987       }
    988       else
    989       {
    990         regfi_add_message(file, REGFI_MSG_WARN, "Could not find HBIN for data"
    991                           " while parsing VK record at offset 0x%.8X.",
    992                           ret_val->offset);
    993         ret_val->data = NULL;
    994       }
    995     }
     975    data = regfi_load_data(file, ret_val->data_off, ret_val->data_size,
     976                           ret_val->data_in_offset, strict);
     977    ret_val->data = data.buf;
     978    ret_val->data_size = data.len;
    996979
    997980    if(ret_val->data == NULL)
     
    10411024REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset, bool strict)
    10421025{
    1043   const REGFI_HBIN* hbin;
    1044   const REGFI_HBIN* sub_hbin;
    10451026  REGFI_NK_REC* nk;
    1046   uint32 max_length, off;
    1047 
    1048   hbin = regfi_lookup_hbin(file, offset-REGFI_REGF_SIZE);
    1049   if (hbin == NULL)
     1027  uint32 off;
     1028  int32 max_size;
     1029
     1030  max_size = regfi_calc_maxsize(file, offset);
     1031  if (max_size < 0)
    10501032    return NULL;
    10511033
    10521034  /* get the initial nk record */
    1053   max_length = hbin->block_size + hbin->file_off - offset;
    1054   if((nk = regfi_parse_nk(file, offset, max_length, true)) == NULL)
     1035  if((nk = regfi_parse_nk(file, offset, max_size, true)) == NULL)
    10551036  {
    10561037    regfi_add_message(file, REGFI_MSG_ERROR, "Could not load NK record at"
     
    10621043  if(nk->num_values && (nk->values_off!=REGFI_OFFSET_NONE))
    10631044  {
    1064     sub_hbin = hbin;
    1065     if(!regfi_offset_in_hbin(hbin, nk->values_off))
    1066       sub_hbin = regfi_lookup_hbin(file, nk->values_off);
    1067    
    1068     if(sub_hbin == NULL)
     1045    off = nk->values_off + REGFI_REGF_SIZE;
     1046    max_size = regfi_calc_maxsize(file, off);
     1047    if(max_size < 0)
    10691048    {
    10701049      if(strict)
     
    10791058    else
    10801059    {
    1081       off = nk->values_off + REGFI_REGF_SIZE;
    1082       max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    1083       nk->values = regfi_load_valuelist(file, off, nk->num_values, max_length,
    1084                                         true);
     1060      nk->values = regfi_load_valuelist(file, off, nk->num_values,
     1061                                        max_size, true);
    10851062      if(nk->values == NULL)
    10861063      {
     
    11001077  if(nk->num_subkeys && (nk->subkeys_off != REGFI_OFFSET_NONE))
    11011078  {
    1102     sub_hbin = hbin;
    1103     if(!regfi_offset_in_hbin(hbin, nk->subkeys_off))
    1104       sub_hbin = regfi_lookup_hbin(file, nk->subkeys_off);
    1105 
    1106     if(sub_hbin == NULL)
     1079    off = nk->subkeys_off + REGFI_REGF_SIZE;
     1080    max_size = regfi_calc_maxsize(file, off);
     1081    if(max_size < 0)
    11071082    {
    11081083      if(strict)
     
    11161091    else
    11171092    {
    1118       off = nk->subkeys_off + REGFI_REGF_SIZE;
    1119       max_length = sub_hbin->block_size + sub_hbin->file_off - off;
    11201093      nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys,
    1121                                           max_length, true);
     1094                                          max_size, true);
    11221095
    11231096      if(nk->subkeys == NULL)
     
    11401113{
    11411114  REGFI_SK_REC* ret_val = NULL;
    1142   const REGFI_HBIN* hbin;
    1143   uint32 max_length;
     1115  int32 max_size;
    11441116  void* failure_ptr = NULL;
    11451117 
     
    11531125  if(ret_val == NULL)
    11541126  {
    1155     hbin = regfi_lookup_hbin(file, offset - REGFI_REGF_SIZE);
    1156     if(hbin == NULL)
     1127    max_size = regfi_calc_maxsize(file, offset);
     1128    if(max_size < 0)
    11571129      return NULL;
    11581130
    1159     max_length = hbin->block_size + hbin->file_off - offset;
    1160     ret_val = regfi_parse_sk(file, offset, max_length, strict);
     1131    ret_val = regfi_parse_sk(file, offset, max_size, strict);
    11611132    if(ret_val == NULL)
    11621133    { /* Cache the parse failure and bail out. */
     
    18681839{
    18691840  uint8 nk_header[REGFI_NK_MIN_LENGTH];
    1870   const REGFI_HBIN *hbin;
    18711841  REGFI_NK_REC* ret_val;
    18721842  uint32 length,cell_length;
    1873   uint32 class_offset, class_maxsize;
     1843  uint32 class_offset;
     1844  int32 class_maxsize;
    18741845  bool unalloc = false;
    18751846
     
    19061877    ret_val->cell_size = max_size & 0xFFFFFFF8;
    19071878  if((ret_val->cell_size < REGFI_NK_MIN_LENGTH)
    1908      || (strict && ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8)))
     1879     || (strict && (ret_val->cell_size & 0x00000007) != 0))
    19091880  {
    19101881    regfi_add_message(file, REGFI_MSG_WARN, "A length check failed while"
     
    20041975  if(ret_val->classname_off != REGFI_OFFSET_NONE)
    20051976  {
    2006     hbin = regfi_lookup_hbin(file, ret_val->classname_off);
    2007     if(hbin)
    2008     {
    2009       class_offset = ret_val->classname_off+REGFI_REGF_SIZE;
    2010       class_maxsize = hbin->block_size + hbin->file_off - class_offset;
     1977    class_offset = ret_val->classname_off + REGFI_REGF_SIZE;
     1978    class_maxsize = regfi_calc_maxsize(file, class_offset);
     1979    if(class_maxsize > 0)
     1980    {
    20111981      ret_val->classname
    20121982        = regfi_parse_classname(file, class_offset, &ret_val->classname_length,
     
    20442014
    20452015  if(*name_length > 0 && offset != REGFI_OFFSET_NONE
    2046      && offset == (offset & 0xFFFFFFF8))
     2016     && (offset & 0x00000007) == 0)
    20472017  {
    20482018    if(!regfi_parse_cell(file->fd, offset, NULL, 0, &cell_length, &unalloc))
     
    20532023    }
    20542024
    2055     if((cell_length & 0xFFFFFFF8) != cell_length)
     2025    if((cell_length & 0x0000007) != 0)
    20562026    {
    20572027      regfi_add_message(file, REGFI_MSG_ERROR, "Cell length not a multiple of 8"
     
    21292099    ret_val->cell_size = max_size & 0xFFFFFFF8;
    21302100  if((ret_val->cell_size < REGFI_VK_MIN_LENGTH)
    2131      || ret_val->cell_size != (ret_val->cell_size & 0xFFFFFFF8))
     2101     || (ret_val->cell_size & 0x00000007) != 0)
    21322102  {
    21332103    regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size encountered"
     
    21542124  raw_data_size = IVAL(vk_header, 0x4);
    21552125  ret_val->data_size = raw_data_size & ~REGFI_VK_DATA_IN_OFFSET;
     2126  /* The data is typically stored in the offset if the size <= 4,
     2127   * in which case this flag is set.
     2128   */
    21562129  ret_val->data_in_offset = (bool)(raw_data_size & REGFI_VK_DATA_IN_OFFSET);
    21572130  ret_val->data_off = IVAL(vk_header, 0x8);
     
    22152188
    22162189/******************************************************************************
    2217 *******************************************************************************/
    2218 REGFI_BUFFER regfi_load_data(REGFI_FILE* file,
    2219                              uint32 data_type, uint32 offset,
    2220                              uint32 length, uint32 max_size,
    2221                              bool data_in_offset, bool strict)
     2190 *
     2191 ******************************************************************************/
     2192REGFI_BUFFER regfi_load_data(REGFI_FILE* file, uint32 voffset,
     2193                             uint32 length, bool data_in_offset,
     2194                             bool strict)
    22222195{
    22232196  REGFI_BUFFER ret_val;
    2224   uint32 read_length, cell_length;
    2225   uint8 i;
     2197  uint32 cell_length, offset;
     2198  int32 max_size;
    22262199  bool unalloc;
    22272200 
    2228   /* The data is typically stored in the offset if the size <= 4 */
    22292201  if(data_in_offset)
    2230   {
    2231     if(length > 4)
    2232     {
    2233       regfi_add_message(file, REGFI_MSG_ERROR, "Data in offset but length > 4"
    2234                         " while parsing data record at offset 0x%.8X.",
    2235                         offset);
     2202    return regfi_parse_little_data(file, voffset, length, strict);
     2203  else
     2204  {
     2205    offset = voffset + REGFI_REGF_SIZE;
     2206    max_size = regfi_calc_maxsize(file, offset);
     2207    if(max_size < 0)
     2208    {
     2209      regfi_add_message(file, REGFI_MSG_WARN, "Could not find HBIN for data"
     2210                        " at offset 0x%.8X.", offset);
    22362211      goto fail;
    22372212    }
    2238 
    2239     if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
    2240       goto fail;
    2241     ret_val.len = length;
    2242 
    2243     for(i = 0; i < length; i++)
    2244       ret_val.buf[i] = (uint8)((offset >> i*8) & 0xFF);
    2245   }
    2246   else
    2247   {
     2213   
    22482214    if(!regfi_parse_cell(file->fd, offset, NULL, 0,
    22492215                         &cell_length, &unalloc))
     
    22542220    }
    22552221
    2256     if((cell_length & 0xFFFFFFF8) != cell_length)
     2222    if((cell_length & 0x00000007) != 0)
    22572223    {
    22582224      regfi_add_message(file, REGFI_MSG_WARN, "Cell length not multiple of 8"
     
    22672233                        " while parsing data record at offset 0x%.8X.",
    22682234                        offset);
    2269       if(strict)
    2270         goto fail;
    2271       else
    2272         cell_length = max_size;
     2235      goto fail;
    22732236    }
    22742237
     
    22822245      {
    22832246        /* Attempt to parse a big data record */
    2284         return regfi_load_big_data(file, offset, length, cell_length, strict);
     2247        return regfi_load_big_data(file, offset, length, cell_length,
     2248                                   NULL, strict);
    22852249      }
    22862250      else
     
    22972261    }
    22982262
    2299     if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
    2300       goto fail;
    2301     ret_val.len = length;
    2302 
    2303     read_length = length;
    2304     if((regfi_read(file->fd, ret_val.buf, &read_length) != 0)
    2305        || read_length != length)
    2306     {
    2307       regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
    2308                         " parsing data record at offset 0x%.8X.", offset);
    2309       talloc_free(ret_val.buf);
    2310       goto fail;
    2311     }
     2263    ret_val = regfi_parse_data(file, offset, length, strict);
    23122264  }
    23132265
     
    23222274
    23232275/******************************************************************************
     2276 * Parses the common case data records stored in a single cell.
     2277 ******************************************************************************/
     2278REGFI_BUFFER regfi_parse_data(REGFI_FILE* file, uint32 offset,
     2279                              uint32 length, bool strict)
     2280{
     2281  REGFI_BUFFER ret_val;
     2282  uint32 read_length;
     2283
     2284  ret_val.buf = NULL;
     2285  ret_val.len = 0;
     2286 
     2287  if(lseek(file->fd, offset+4, SEEK_SET) == -1)
     2288  {
     2289    regfi_add_message(file, REGFI_MSG_WARN, "Could not seek while "
     2290                      "reading data at offset 0x%.8X.", offset);
     2291    return ret_val;
     2292  }
     2293
     2294  if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2295    return ret_val;
     2296  ret_val.len = length;
     2297 
     2298  read_length = length;
     2299  if((regfi_read(file->fd, ret_val.buf, &read_length) != 0)
     2300     || read_length != length)
     2301  {
     2302    regfi_add_message(file, REGFI_MSG_ERROR, "Could not read data block while"
     2303                      " parsing data record at offset 0x%.8X.", offset);
     2304    talloc_free(ret_val.buf);
     2305    ret_val.buf = NULL;
     2306    ret_val.buf = 0;
     2307  }
     2308
     2309  return ret_val;
     2310}
     2311
     2312
     2313
     2314/******************************************************************************
     2315 *
     2316 ******************************************************************************/
     2317REGFI_BUFFER regfi_parse_little_data(REGFI_FILE* file, uint32 voffset,
     2318                                     uint32 length, bool strict)
     2319{
     2320  REGFI_BUFFER ret_val;
     2321  uint8 i;
     2322
     2323  ret_val.buf = NULL;
     2324  ret_val.len = 0;
     2325
     2326  if(length > 4)
     2327  {
     2328    regfi_add_message(file, REGFI_MSG_ERROR, "Data in offset but length > 4"
     2329                      " while parsing data record. (voffset=0x%.8X, length=%d)",
     2330                      voffset, length);
     2331    return ret_val;
     2332  }
     2333
     2334  if((ret_val.buf = talloc_array(NULL, uint8_t, length)) == NULL)
     2335    return ret_val;
     2336  ret_val.len = length;
     2337 
     2338  for(i = 0; i < length; i++)
     2339    ret_val.buf[i] = (uint8)((voffset >> i*8) & 0xFF);
     2340
     2341  return ret_val;
     2342}
     2343
     2344/******************************************************************************
     2345*******************************************************************************/
     2346REGFI_BUFFER regfi_parse_big_data_header(REGFI_FILE* file, uint32 offset,
     2347                                         uint32 max_size, bool strict)
     2348{
     2349  REGFI_BUFFER ret_val;
     2350  uint32 cell_length;
     2351  bool unalloc;
     2352
     2353  /* XXX: do something with unalloc? */
     2354  ret_val.buf = (uint8*)talloc_array(NULL, uint8, REGFI_BIG_DATA_MIN_LENGTH);
     2355  if(ret_val.buf == NULL)
     2356    goto fail;
     2357
     2358  if(REGFI_BIG_DATA_MIN_LENGTH > max_size)
     2359  {
     2360    regfi_add_message(file, REGFI_MSG_WARN, "Big data header exceeded max_size "
     2361                      "while parsing big data header at offset 0x%.8X.",offset);
     2362    goto fail;
     2363  }
     2364
     2365  if(!regfi_parse_cell(file->fd, offset, ret_val.buf, REGFI_BIG_DATA_MIN_LENGTH,
     2366                       &cell_length, &unalloc))
     2367  {
     2368    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2369                      " parsing big data header at offset 0x%.8X.", offset);
     2370    goto fail;
     2371  }
     2372
     2373  if((ret_val.buf[0] != 'd') || (ret_val.buf[1] != 'b'))
     2374  {
     2375    regfi_add_message(file, REGFI_MSG_WARN, "Unknown magic number"
     2376                      " (0x%.2X, 0x%.2X) encountered while parsing"
     2377                      " big data header at offset 0x%.8X.",
     2378                      ret_val.buf[0], ret_val.buf[1], offset);
     2379    goto fail;
     2380  }
     2381
     2382  ret_val.len = REGFI_BIG_DATA_MIN_LENGTH;
     2383  return ret_val;
     2384
     2385 fail:
     2386  if(ret_val.buf != NULL)
     2387  {
     2388    talloc_free(ret_val.buf);
     2389    ret_val.buf = NULL;
     2390  }
     2391  ret_val.len = 0;
     2392  return ret_val;
     2393}
     2394
     2395
     2396
     2397/******************************************************************************
     2398 *
     2399 ******************************************************************************/
     2400uint32* regfi_parse_big_data_indirect(REGFI_FILE* file, uint32 offset,
     2401                                      uint16 num_chunks, bool strict)
     2402{
     2403  uint32* ret_val;
     2404  uint32 indirect_length;
     2405  int32 max_size;
     2406  uint16 i;
     2407  bool unalloc;
     2408
     2409  /* XXX: do something with unalloc? */
     2410
     2411  max_size = regfi_calc_maxsize(file, offset);
     2412  if((max_size < 0) || (num_chunks*sizeof(uint32) + 4 > max_size))
     2413    return NULL;
     2414
     2415  ret_val = (uint32*)talloc_array(NULL, uint32, num_chunks);
     2416  if(ret_val == NULL)
     2417    goto fail;
     2418
     2419  if(!regfi_parse_cell(file->fd, offset, (uint8*)ret_val,
     2420                       num_chunks*sizeof(uint32),
     2421                       &indirect_length, &unalloc))
     2422  {
     2423    regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2424                      " parsing big data indirect record at offset 0x%.8X.",
     2425                      offset);
     2426    goto fail;
     2427  }
     2428
     2429  /* Convert pointers to proper endianess, verify they are aligned. */
     2430  for(i=0; i<num_chunks; i++)
     2431  {
     2432    ret_val[i] = IVAL(ret_val, i*sizeof(uint32));
     2433    if((ret_val[i] & 0x00000007) != 0)
     2434      goto fail;
     2435  }
     2436 
     2437  return ret_val;
     2438
     2439 fail:
     2440  if(ret_val != NULL)
     2441    talloc_free(ret_val);
     2442  return NULL;
     2443}
     2444
     2445
     2446/******************************************************************************
     2447 * Arguments:
     2448 *  file       --
     2449 *  offsets    -- list of virtual offsets.
     2450 *  num_chunks --
     2451 *  strict     --
     2452 *
     2453 * Returns:
     2454 *  A range_list with physical offsets and complete lengths
     2455 *  (including cell headers) of associated cells. 
     2456 *  No data in range_list elements.
     2457 ******************************************************************************/
     2458range_list* regfi_parse_big_data_cells(REGFI_FILE* file, uint32* offsets,
     2459                                       uint16 num_chunks, bool strict)
     2460{
     2461  uint32 cell_length, chunk_offset, data_left;
     2462  range_list* ret_val;
     2463  uint16 i;
     2464  bool unalloc;
     2465 
     2466  /* XXX: do something with unalloc? */
     2467  ret_val = range_list_new();
     2468  if(ret_val == NULL)
     2469    goto fail;
     2470 
     2471  for(i=0; (i<num_chunks) && (data_left>0); i++)
     2472  {
     2473    chunk_offset = offsets[i]+REGFI_REGF_SIZE;
     2474    if(!regfi_parse_cell(file->fd, chunk_offset, NULL, 0,
     2475                         &cell_length, &unalloc))
     2476    {
     2477      regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
     2478                        " parsing big data chunk at offset 0x%.8X.",
     2479                        chunk_offset);
     2480      goto fail;
     2481    }
     2482
     2483    if(!range_list_add(ret_val, chunk_offset, cell_length, NULL))
     2484      goto fail;
     2485  }
     2486
     2487  return ret_val;
     2488
     2489 fail:
     2490  if(ret_val != NULL)
     2491    range_list_free(ret_val);
     2492  return NULL;
     2493}
     2494
     2495
     2496/******************************************************************************
    23242497*******************************************************************************/
    23252498REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file,
    23262499                                 uint32 offset, uint32 data_length,
    2327                                  uint32 cell_length, bool strict)
     2500                                 uint32 cell_length, range_list* used_ranges,
     2501                                 bool strict)
    23282502{
    23292503  REGFI_BUFFER ret_val;
    23302504  uint16 num_chunks, i;
    2331   uint32 indirect_offset, indirect_length, chunk_length, chunk_offset;
    2332   uint32 read_length, data_left;
    2333   bool unalloc;
    2334   uint32* indirect_ptrs;
    2335   uint8* big_data_cell = (uint8*)malloc(cell_length*sizeof(uint8));
    2336   if(big_data_cell == NULL)
     2505  uint32 read_length, data_left, tmp_len, indirect_offset;
     2506  uint32* indirect_ptrs = NULL;
     2507  REGFI_BUFFER bd_header;
     2508  range_list* bd_cells = NULL;
     2509  const range_list_element* cell_info;
     2510
     2511  ret_val.buf = NULL;
     2512
     2513  /* XXX: Add better error/warning messages */
     2514
     2515  bd_header = regfi_parse_big_data_header(file, offset, cell_length, strict);
     2516  if(bd_header.buf == NULL)
    23372517    goto fail;
    23382518
    2339   if(!regfi_parse_cell(file->fd, offset, big_data_cell, cell_length-4,
    2340                        &cell_length, &unalloc))
    2341   {
    2342     regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2343                       " parsing big data record at offset 0x%.8X.", offset);
    2344     free(big_data_cell);
    2345     goto fail;
    2346   }
    2347  
    2348   if((big_data_cell[0] != 'd') || (big_data_cell[1] != 'b'))
    2349   {
    2350     regfi_add_message(file, REGFI_MSG_WARN, "Unknown magic number"
    2351                       " (0x%.2X, 0x%.2X) encountered while parsing"
    2352                       " big data record at offset 0x%.8X.",
    2353                       big_data_cell[0], big_data_cell[1], offset);
    2354     free(big_data_cell);
    2355     goto fail;
    2356   }
    2357   num_chunks = SVAL(big_data_cell, 0x2);
    2358   /* XXX: Should check sanity of pointers here and in the indirect
    2359    *      block.  At least ensure they are a multiple of 8.
    2360    */
    2361   indirect_offset = IVAL(big_data_cell, 0x4) + REGFI_REGF_SIZE;
    2362   free(big_data_cell);
    2363 
    2364   indirect_ptrs = (uint32*)malloc(num_chunks*sizeof(uint32));
     2519  /* Keep track of used space for use by reglookup-recover */
     2520  if(used_ranges != NULL)
     2521    if(!range_list_add(used_ranges, offset, cell_length, NULL))
     2522      goto fail;
     2523
     2524  num_chunks = SVAL(bd_header.buf, 0x2);
     2525  indirect_offset = IVAL(bd_header.buf, 0x4) + REGFI_REGF_SIZE;
     2526  talloc_free(bd_header.buf);
     2527
     2528  indirect_ptrs = regfi_parse_big_data_indirect(file, indirect_offset,
     2529                                                num_chunks, strict);
    23652530  if(indirect_ptrs == NULL)
    23662531    goto fail;
    23672532
    2368   if(!regfi_parse_cell(file->fd, indirect_offset, (uint8*)indirect_ptrs,
    2369                        num_chunks*sizeof(uint32),
    2370                        &indirect_length, &unalloc))
    2371   {
    2372     regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2373                       " parsing big data indirect record at offset 0x%.8X.",
    2374                       offset);
    2375     free(indirect_ptrs);
     2533  if(used_ranges != NULL)
     2534    if(!range_list_add(used_ranges, indirect_offset, num_chunks*4+4, NULL))
     2535      goto fail;
     2536 
     2537  if((ret_val.buf = talloc_array(NULL, uint8_t, data_length)) == NULL)
    23762538    goto fail;
    2377   }
    2378  
    2379   if((ret_val.buf = talloc_array(NULL, uint8_t, data_length)) == NULL)
    2380   {
    2381     free(indirect_ptrs);
     2539  data_left = data_length;
     2540
     2541  bd_cells = regfi_parse_big_data_cells(file, indirect_ptrs, num_chunks, strict);
     2542  if(bd_cells == NULL)
    23822543    goto fail;
    2383   }
    2384   data_left = data_length;
    2385 
     2544
     2545  talloc_free(indirect_ptrs);
     2546  indirect_ptrs = NULL;
     2547 
    23862548  for(i=0; (i<num_chunks) && (data_left>0); i++)
    23872549  {
    2388     /* Fix endianness of pointer and convert to physical offset */
    2389     chunk_offset = IVAL(indirect_ptrs, i*4) + REGFI_REGF_SIZE;
    2390     if(!regfi_parse_cell(file->fd, chunk_offset, NULL, 0,
    2391                          &chunk_length, &unalloc))
    2392     {
    2393       regfi_add_message(file, REGFI_MSG_WARN, "Could not parse cell while"
    2394                         " parsing big data chunk at offset 0x%.8X.",
    2395                         chunk_offset);
    2396       if(strict)
    2397         goto chunk_fail;
    2398       else
    2399         break;
    2400     }
    2401 
    2402     /* XXX: This should be "chunk_length-4" to account for the 4 byte cell
     2550    cell_info = range_list_get(bd_cells, i);
     2551    if(cell_info == NULL)
     2552      goto fail;
     2553
     2554    /* XXX: This should be "cell_info->length-4" to account for the 4 byte cell
    24032555     *      length.  However, it has been observed that some (all?) chunks
    24042556     *      have an additional 4 bytes of 0 at the end of their cells that
    24052557     *      isn't part of the data, so we're trimming that off too.
     2558     *      Perhaps it's just an 8 byte alignment requirement...
    24062559     */
    2407     if(chunk_length-8 >= data_left)
     2560    if(cell_info->length - 8 >= data_left)
     2561    {
     2562      if(i+1 != num_chunks)
     2563      {
     2564        regfi_add_message(file, REGFI_MSG_WARN, "Left over chunks detected "
     2565                          "while constructing big data at offset 0x%.8X "
     2566                          "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2567      }
    24082568      read_length = data_left;
     2569    }
    24092570    else
    2410       read_length = chunk_length-8;
    2411 
     2571      read_length = cell_info->length - 8;
     2572
     2573
     2574    if(read_length > regfi_calc_maxsize(file, cell_info->offset))
     2575    {
     2576      regfi_add_message(file, REGFI_MSG_WARN, "A chunk exceeded the maxsize "
     2577                        "while constructing big data at offset 0x%.8X "
     2578                        "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2579      goto fail;
     2580    }
     2581
     2582    if(lseek(file->fd, cell_info->offset+sizeof(uint32), SEEK_SET) == -1)
     2583    {
     2584      regfi_add_message(file, REGFI_MSG_WARN, "Could not seek to chunk while "
     2585                        "constructing big data at offset 0x%.8X "
     2586                        "(chunk offset 0x%.8X).", offset, cell_info->offset);
     2587      goto fail;
     2588    }
     2589
     2590    tmp_len = read_length;
    24122591    if(regfi_read(file->fd, ret_val.buf+(data_length-data_left),
    2413                   &read_length) != 0)
     2592                  &read_length) != 0 || (read_length != tmp_len))
    24142593    {
    24152594      regfi_add_message(file, REGFI_MSG_WARN, "Could not read data chunk while"
    2416                         " constructing big data at offset 0x%.8X.",
    2417                         chunk_offset);
    2418       if(strict)
    2419         goto chunk_fail;
    2420       else
    2421         break;
    2422     }
     2595                        " constructing big data at offset 0x%.8X"
     2596                        " (chunk offset 0x%.8X).", offset, cell_info->offset);
     2597      goto fail;
     2598    }
     2599
     2600    if(used_ranges != NULL)
     2601      if(!range_list_add(used_ranges, cell_info->offset,cell_info->length,NULL))
     2602        goto fail;
    24232603
    24242604    data_left -= read_length;
    24252605  }
    2426   free(indirect_ptrs);
     2606  range_list_free(bd_cells);
     2607
    24272608  ret_val.len = data_length-data_left;
    2428 
    2429   return ret_val;
    2430 
    2431  chunk_fail:
    2432   free(indirect_ptrs);
    2433   talloc_free(ret_val.buf);
     2609  return ret_val;
     2610
    24342611 fail:
     2612  if(ret_val.buf != NULL)
     2613    talloc_free(ret_val.buf);
     2614  if(indirect_ptrs != NULL)
     2615    talloc_free(indirect_ptrs);
     2616  if(bd_cells != NULL)
     2617    range_list_free(bd_cells);
    24352618  ret_val.buf = NULL;
    24362619  ret_val.len = 0;
     
    24662649        break;
    24672650     
    2468       if((cell_len == 0) || ((cell_len & 0xFFFFFFF8) != cell_len))
     2651      if((cell_len == 0) || ((cell_len & 0x00000007) != 0))
    24692652      {
    24702653        regfi_add_message(file, REGFI_MSG_ERROR, "Bad cell length encountered"
  • trunk/lib/smb_deps.c

    r147 r157  
    2626#include "smb_deps.h"
    2727
    28 
    29 /* These act as replacements for numerous Samba memory allocation
    30  *   functions.
    31  */
    32 void* zalloc(size_t size)
    33 {
    34   void* ret_val = NULL;
    35   if((size > 0) && (ret_val = (void*)malloc(size)) != NULL)
    36     memset(ret_val, 0, size);
    37 
    38   return ret_val;
    39 }
    40 
    41 void* zcalloc(size_t size, unsigned int count)
    42 {
    43   return zalloc(size*count);
    44 }
    4528
    4629/* From lib/time.c */
Note: See TracChangeset for help on using the changeset viewer.