- Timestamp:
- 11/22/09 19:47:22 (15 years ago)
- Location:
- trunk/lib
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/regfi.c
r155 r157 471 471 472 472 473 /******************************************************************* 473 /****************************************************************************** 474 474 * Given an offset and an hbin, is the offset within that hbin? 475 475 * The offset is a virtual file offset. 476 ******************************************************************* /476 ******************************************************************************/ 477 477 static bool regfi_offset_in_hbin(const REGFI_HBIN* hbin, uint32 voffset) 478 478 { … … 489 489 490 490 491 /******************************************************************* 492 * Provide a virtual offset and receive the correpsonding HBIN491 /****************************************************************************** 492 * Provide a physical offset and receive the correpsonding HBIN 493 493 * 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 ******************************************************************************/ 495 const 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 ******************************************************************************/ 507 int32 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 } 501 515 502 516 … … 542 556 REGFI_SUBKEY_LIST* ret_val; 543 557 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; 546 560 547 561 if(depth_left == 0) … … 565 579 { 566 580 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) 569 584 sublists[i] = NULL; 570 585 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); 576 588 } 577 589 talloc_free(ret_val); … … 792 804 ret_val->cell_size = max_size & 0xFFFFFFF8; 793 805 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)) 795 807 { 796 808 regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size found while" … … 808 820 ret_val->desc_size = IVAL(sk_header, 0x10); 809 821 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) 812 824 { 813 825 regfi_add_message(file, REGFI_MSG_WARN, "SK record's next/previous offsets" … … 873 885 } 874 886 875 if( cell_length != (cell_length & 0xFFFFFFF8))887 if((cell_length & 0x00000007) != 0) 876 888 { 877 889 regfi_add_message(file, REGFI_MSG_WARN, "Cell length not a multiple of 8" … … 925 937 * with partial files. */ 926 938 if((ret_val->elements[i] + REGFI_REGF_SIZE > file->file_length) 927 || ((ret_val->elements[i] & 0x FFFFFFF8) != ret_val->elements[i]))939 || ((ret_val->elements[i] & 0x00000007) != 0)) 928 940 { 929 941 regfi_add_message(file, REGFI_MSG_WARN, "Invalid value pointer" … … 946 958 { 947 959 REGFI_VK_REC* ret_val = NULL; 948 const REGFI_HBIN* hbin;949 uint32 data_offset, data_maxsize;950 960 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); 959 968 if(ret_val == NULL) 960 969 return NULL; … … 964 973 else 965 974 { 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; 996 979 997 980 if(ret_val->data == NULL) … … 1041 1024 REGFI_NK_REC* regfi_load_key(REGFI_FILE* file, uint32 offset, bool strict) 1042 1025 { 1043 const REGFI_HBIN* hbin;1044 const REGFI_HBIN* sub_hbin;1045 1026 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) 1050 1032 return NULL; 1051 1033 1052 1034 /* 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) 1055 1036 { 1056 1037 regfi_add_message(file, REGFI_MSG_ERROR, "Could not load NK record at" … … 1062 1043 if(nk->num_values && (nk->values_off!=REGFI_OFFSET_NONE)) 1063 1044 { 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) 1069 1048 { 1070 1049 if(strict) … … 1079 1058 else 1080 1059 { 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); 1085 1062 if(nk->values == NULL) 1086 1063 { … … 1100 1077 if(nk->num_subkeys && (nk->subkeys_off != REGFI_OFFSET_NONE)) 1101 1078 { 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) 1107 1082 { 1108 1083 if(strict) … … 1116 1091 else 1117 1092 { 1118 off = nk->subkeys_off + REGFI_REGF_SIZE;1119 max_length = sub_hbin->block_size + sub_hbin->file_off - off;1120 1093 nk->subkeys = regfi_load_subkeylist(file, off, nk->num_subkeys, 1121 max_ length, true);1094 max_size, true); 1122 1095 1123 1096 if(nk->subkeys == NULL) … … 1140 1113 { 1141 1114 REGFI_SK_REC* ret_val = NULL; 1142 const REGFI_HBIN* hbin; 1143 uint32 max_length; 1115 int32 max_size; 1144 1116 void* failure_ptr = NULL; 1145 1117 … … 1153 1125 if(ret_val == NULL) 1154 1126 { 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) 1157 1129 return NULL; 1158 1130 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); 1161 1132 if(ret_val == NULL) 1162 1133 { /* Cache the parse failure and bail out. */ … … 1868 1839 { 1869 1840 uint8 nk_header[REGFI_NK_MIN_LENGTH]; 1870 const REGFI_HBIN *hbin;1871 1841 REGFI_NK_REC* ret_val; 1872 1842 uint32 length,cell_length; 1873 uint32 class_offset, class_maxsize; 1843 uint32 class_offset; 1844 int32 class_maxsize; 1874 1845 bool unalloc = false; 1875 1846 … … 1906 1877 ret_val->cell_size = max_size & 0xFFFFFFF8; 1907 1878 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)) 1909 1880 { 1910 1881 regfi_add_message(file, REGFI_MSG_WARN, "A length check failed while" … … 2004 1975 if(ret_val->classname_off != REGFI_OFFSET_NONE) 2005 1976 { 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 { 2011 1981 ret_val->classname 2012 1982 = regfi_parse_classname(file, class_offset, &ret_val->classname_length, … … 2044 2014 2045 2015 if(*name_length > 0 && offset != REGFI_OFFSET_NONE 2046 && offset == (offset & 0xFFFFFFF8))2016 && (offset & 0x00000007) == 0) 2047 2017 { 2048 2018 if(!regfi_parse_cell(file->fd, offset, NULL, 0, &cell_length, &unalloc)) … … 2053 2023 } 2054 2024 2055 if((cell_length & 0x FFFFFFF8) != cell_length)2025 if((cell_length & 0x0000007) != 0) 2056 2026 { 2057 2027 regfi_add_message(file, REGFI_MSG_ERROR, "Cell length not a multiple of 8" … … 2129 2099 ret_val->cell_size = max_size & 0xFFFFFFF8; 2130 2100 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) 2132 2102 { 2133 2103 regfi_add_message(file, REGFI_MSG_WARN, "Invalid cell size encountered" … … 2154 2124 raw_data_size = IVAL(vk_header, 0x4); 2155 2125 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 */ 2156 2129 ret_val->data_in_offset = (bool)(raw_data_size & REGFI_VK_DATA_IN_OFFSET); 2157 2130 ret_val->data_off = IVAL(vk_header, 0x8); … … 2215 2188 2216 2189 /****************************************************************************** 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, boolstrict)2190 * 2191 ******************************************************************************/ 2192 REGFI_BUFFER regfi_load_data(REGFI_FILE* file, uint32 voffset, 2193 uint32 length, bool data_in_offset, 2194 bool strict) 2222 2195 { 2223 2196 REGFI_BUFFER ret_val; 2224 uint32 read_length, cell_length;2225 uint8 i;2197 uint32 cell_length, offset; 2198 int32 max_size; 2226 2199 bool unalloc; 2227 2200 2228 /* The data is typically stored in the offset if the size <= 4 */2229 2201 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); 2236 2211 goto fail; 2237 2212 } 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 2248 2214 if(!regfi_parse_cell(file->fd, offset, NULL, 0, 2249 2215 &cell_length, &unalloc)) … … 2254 2220 } 2255 2221 2256 if((cell_length & 0x FFFFFFF8) != cell_length)2222 if((cell_length & 0x00000007) != 0) 2257 2223 { 2258 2224 regfi_add_message(file, REGFI_MSG_WARN, "Cell length not multiple of 8" … … 2267 2233 " while parsing data record at offset 0x%.8X.", 2268 2234 offset); 2269 if(strict) 2270 goto fail; 2271 else 2272 cell_length = max_size; 2235 goto fail; 2273 2236 } 2274 2237 … … 2282 2245 { 2283 2246 /* 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); 2285 2249 } 2286 2250 else … … 2297 2261 } 2298 2262 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); 2312 2264 } 2313 2265 … … 2322 2274 2323 2275 /****************************************************************************** 2276 * Parses the common case data records stored in a single cell. 2277 ******************************************************************************/ 2278 REGFI_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 ******************************************************************************/ 2317 REGFI_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 *******************************************************************************/ 2346 REGFI_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 ******************************************************************************/ 2400 uint32* 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 ******************************************************************************/ 2458 range_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 /****************************************************************************** 2324 2497 *******************************************************************************/ 2325 2498 REGFI_BUFFER regfi_load_big_data(REGFI_FILE* file, 2326 2499 uint32 offset, uint32 data_length, 2327 uint32 cell_length, bool strict) 2500 uint32 cell_length, range_list* used_ranges, 2501 bool strict) 2328 2502 { 2329 2503 REGFI_BUFFER ret_val; 2330 2504 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) 2337 2517 goto fail; 2338 2518 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); 2365 2530 if(indirect_ptrs == NULL) 2366 2531 goto fail; 2367 2532 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) 2376 2538 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) 2382 2543 goto fail; 2383 } 2384 data_left = data_length; 2385 2544 2545 talloc_free(indirect_ptrs); 2546 indirect_ptrs = NULL; 2547 2386 2548 for(i=0; (i<num_chunks) && (data_left>0); i++) 2387 2549 { 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 2403 2555 * length. However, it has been observed that some (all?) chunks 2404 2556 * have an additional 4 bytes of 0 at the end of their cells that 2405 2557 * isn't part of the data, so we're trimming that off too. 2558 * Perhaps it's just an 8 byte alignment requirement... 2406 2559 */ 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 } 2408 2568 read_length = data_left; 2569 } 2409 2570 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; 2412 2591 if(regfi_read(file->fd, ret_val.buf+(data_length-data_left), 2413 &read_length) != 0 )2592 &read_length) != 0 || (read_length != tmp_len)) 2414 2593 { 2415 2594 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; 2423 2603 2424 2604 data_left -= read_length; 2425 2605 } 2426 free(indirect_ptrs); 2606 range_list_free(bd_cells); 2607 2427 2608 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 2434 2611 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); 2435 2618 ret_val.buf = NULL; 2436 2619 ret_val.len = 0; … … 2466 2649 break; 2467 2650 2468 if((cell_len == 0) || ((cell_len & 0x FFFFFFF8) != cell_len))2651 if((cell_len == 0) || ((cell_len & 0x00000007) != 0)) 2469 2652 { 2470 2653 regfi_add_message(file, REGFI_MSG_ERROR, "Bad cell length encountered" -
trunk/lib/smb_deps.c
r147 r157 26 26 #include "smb_deps.h" 27 27 28 29 /* These act as replacements for numerous Samba memory allocation30 * 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 }45 28 46 29 /* From lib/time.c */
Note: See TracChangeset
for help on using the changeset viewer.