- Timestamp:
- 08/19/08 19:31:33 (16 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/regfi.h
r125 r126 406 406 uint32* cell_length, bool* unalloc); 407 407 408 char* regfi_parse_classname(REGF_FILE* file, uint32 offset, 409 uint16* name_length, bool strict); 410 408 411 #endif /* _REGFI_H */ -
trunk/lib/regfi.c
r125 r126 1510 1510 1511 1511 1512 1512 /******************************************************************* 1513 *******************************************************************/ 1513 1514 REGF_NK_REC* regfi_parse_nk(REGF_FILE* file, uint32 offset, 1514 1515 uint32 max_size, bool strict) … … 1635 1636 ret_val->keyname[ret_val->name_length] = '\0'; 1636 1637 1637 1638 /***/ 1639 1640 if(ret_val->classname_length > 0 1641 && ret_val->classname_off != REGF_OFFSET_NONE 1642 && ret_val->classname_off == (ret_val->classname_off & 0xFFFFFFF8)) 1643 { 1644 ret_val->classname = (char*)zalloc(ret_val->classname_length+1); 1645 if(ret_val->classname != NULL) 1646 { 1647 if(!regfi_parse_cell(file->fd, ret_val->classname_off+REGF_BLOCKSIZE, 1648 (uint8*)ret_val->classname, ret_val->classname_length, 1649 &cell_length, &unalloc) 1650 || (cell_length < ret_val->classname_length) 1651 || (strict && unalloc)) 1638 if(ret_val->classname_off != REGF_OFFSET_NONE) 1639 { 1640 ret_val->classname 1641 = regfi_parse_classname(file, ret_val->classname_off+REGF_BLOCKSIZE, 1642 &ret_val->classname_length, strict); 1643 /* 1644 if(strict && ret_val->classname == NULL) 1645 return NULL; 1646 */ 1647 } 1648 1649 return ret_val; 1650 } 1651 1652 1653 /*******************************************************************/ 1654 /* XXX: Not currently validating against hbin length. */ 1655 /*******************************************************************/ 1656 char* regfi_parse_classname(REGF_FILE* file, uint32 offset, 1657 uint16* name_length, bool strict) 1658 { 1659 char* ret_val = NULL; 1660 uint32 length; 1661 uint32 cell_length; 1662 bool unalloc = false; 1663 1664 if(*name_length > 0 && offset != REGF_OFFSET_NONE 1665 && offset == (offset & 0xFFFFFFF8)) 1666 { 1667 if(!regfi_parse_cell(file->fd, offset, NULL, 0, &cell_length, &unalloc)) 1668 return NULL; 1669 1670 if(cell_length < *name_length) 1671 { 1672 if(strict) 1673 return NULL; 1674 *name_length = cell_length & 0xFFFFFFF8; 1675 } 1676 1677 ret_val = (char*)zalloc(*name_length); 1678 if(ret_val != NULL) 1679 { 1680 length = *name_length; 1681 if((regfi_read(file->fd, (uint8*)ret_val, &length) != 0) 1682 || length != *name_length) 1652 1683 { 1653 /* Being careful not to reject the whole key here even when 1654 * strict and things are obviously wrong, since it appears 1655 * they're commonly obviously wrong. 1656 */ 1657 free(ret_val->classname); 1658 ret_val->classname = NULL; 1659 return ret_val; 1684 free(ret_val); 1685 return NULL; 1660 1686 } 1661 1687 1662 ret_val->classname[ret_val->classname_length] = '\0';1663 1688 /*printf("==> cell_length=%d, classname_length=%d, max_bytes_subkeyclassname=%d\n", cell_length, ret_val->classname_length, ret_val->max_bytes_subkeyclassname);*/ 1664 1689 } 1665 1690 } 1666 /***/1667 1668 1691 1669 1692 return ret_val; 1670 1693 } 1671 1672 1694 1673 1695 -
trunk/src/common.c
r121 r126 123 123 * it's length, uni_max. Writes ASCII to the buffer ascii, whose size 124 124 * is ascii_max. Writes at most (ascii_max-1) bytes to ascii, and null 125 * terminates the string. Returns the length of the string stored in125 * terminates the string. Returns the length of the data written to 126 126 * ascii. On error, returns a negative errno code. 127 127 */ 128 128 static int uni_to_ascii(unsigned char* uni, char* ascii, 129 u nsigned int uni_max, unsigned intascii_max)129 uint32 uni_max, uint32 ascii_max) 130 130 { 131 131 char* inbuf = (char*)uni; … … 136 136 137 137 /* Set up conversion descriptor. */ 138 conv_desc = iconv_open("US-ASCII ", "UTF-16LE");138 conv_desc = iconv_open("US-ASCII//TRANSLIT", "UTF-16LE"); 139 139 140 140 ret = iconv(conv_desc, &inbuf, &in_len, &outbuf, &out_len); … … 147 147 148 148 iconv_close(conv_desc); 149 return strlen(ascii); 149 return ascii_max-out_len-1; 150 } 151 152 153 static char* quote_unicode(unsigned char* uni, uint32 length, 154 const char* special, char** error_msg) 155 { 156 char* ret_val; 157 char* ascii; 158 char* tmp_err; 159 int ret_err; 160 *error_msg = NULL; 161 162 ascii = malloc(length+1); 163 if(ascii == NULL) 164 { 165 *error_msg = (char*)malloc(27); 166 if(*error_msg == NULL) 167 return NULL; 168 strcpy(*error_msg, "Memory allocation failure."); 169 return NULL; 170 } 171 172 ret_err = uni_to_ascii(uni, ascii, length, length+1); 173 if(ret_err < 0) 174 { 175 free(ascii); 176 tmp_err = strerror(-ret_err); 177 *error_msg = (char*)malloc(54+strlen(tmp_err)); 178 if(*error_msg == NULL) 179 { 180 free(ascii); 181 return NULL; 182 } 183 184 sprintf(*error_msg, 185 "Unicode conversion failed with '%s'. Quoting as binary.", tmp_err); 186 ret_val = quote_buffer(uni, length, special); 187 } 188 else 189 { 190 ret_val = quote_string(ascii, special); 191 free(ascii); 192 } 193 194 return ret_val; 150 195 } 151 196 … … 166 211 char* asciip; 167 212 char* ascii; 168 unsigned char* cur_str; 169 char* cur_ascii; 213 char* ascii_tmp; 170 214 char* cur_quoted; 171 char* tmp_err ;172 const char* str_type;215 char* tmp_err = NULL; 216 const char* delim; 173 217 uint32 i; 174 218 uint32 cur_str_len; 175 uint32 ascii_max , cur_str_max;176 uint32 str_rem, cur_str_rem,alen;219 uint32 ascii_max; 220 uint32 str_rem, alen; 177 221 int ret_err; 178 unsigned short num_nulls;179 222 180 223 if(datap == NULL) … … 194 237 /* REG_LINK is a symbolic link, stored as a unicode string. */ 195 238 case REG_LINK: 196 ascii_max = sizeof(char)*(len+1);197 ascii = malloc(ascii_max);198 if(ascii == NULL)199 return NULL;200 201 239 /* Sometimes values have binary stored in them. If the unicode 202 240 * conversion fails, just quote it raw. 203 241 */ 204 ret_err = uni_to_ascii(datap, ascii, len, ascii_max); 205 if(ret_err < 0) 206 { 207 tmp_err = strerror(-ret_err); 208 str_type = regfi_type_val2str(type); 209 *error_msg = (char*)malloc(65+strlen(str_type)+strlen(tmp_err)+1); 210 if(*error_msg == NULL) 211 { 212 free(ascii); 213 return NULL; 214 } 215 sprintf(*error_msg, "Unicode conversion failed on %s field; " 216 "printing as binary. Error: %s", str_type, tmp_err); 217 218 cur_quoted = quote_buffer(datap, len, common_special_chars); 219 } 220 else 221 cur_quoted = quote_string(ascii, common_special_chars); 222 free(ascii); 242 cur_quoted = quote_unicode(datap, len, common_special_chars, &tmp_err); 223 243 if(cur_quoted == NULL) 224 244 { 225 *error_msg = (char*)malloc(27+1); 226 if(*error_msg != NULL) 227 strcpy(*error_msg, "Buffer could not be quoted."); 228 } 245 if(tmp_err == NULL && (*error_msg = (char*)malloc(49)) != NULL) 246 strcpy(*error_msg, "Buffer could not be quoted due to unknown error."); 247 else if((*error_msg = (char*)malloc(42+strlen(tmp_err))) != NULL) 248 { 249 sprintf(*error_msg, "Buffer could not be quoted due to error: %s", 250 tmp_err); 251 free(tmp_err); 252 } 253 } 254 else if (tmp_err != NULL) 255 *error_msg = tmp_err; 229 256 return cur_quoted; 230 257 break; … … 264 291 break; 265 292 266 267 /* XXX: this MULTI_SZ parser is pretty inefficient. Should be268 * redone with fewer malloc calls and better string concatenation.269 * Also, gives lame output when "\0\0" is the string.270 */271 293 case REG_MULTI_SZ: 272 294 ascii_max = sizeof(char)*(len*4+1); 273 cur_str_max = sizeof(char)*(len+1); 274 cur_str = malloc(cur_str_max); 275 cur_ascii = malloc(cur_str_max); 276 ascii = malloc(ascii_max); 277 if(ascii == NULL || cur_str == NULL || cur_ascii == NULL) 278 return NULL; 279 280 /* Reads until it reaches 4 consecutive NULLs, 281 * which is two nulls in unicode, or until it reaches len, or until we 282 * run out of buffer. The latter should never happen, but we shouldn't 283 * trust our file to have the right lengths/delimiters. 295 ascii_tmp = malloc(ascii_max); 296 if(ascii_tmp == NULL) 297 return NULL; 298 299 /* Attempt to convert entire string from UTF-16LE to ASCII, 300 * then parse and quote fields individually. 301 * If this fails, simply quote entire buffer as binary. 284 302 */ 285 asciip = ascii; 286 num_nulls = 0; 287 str_rem = ascii_max; 288 cur_str_rem = cur_str_max; 289 cur_str_len = 0; 290 291 for(i=0; (i < len) && str_rem > 0; i++) 292 { 293 *(cur_str+cur_str_len) = *(datap+i); 294 if(*(cur_str+cur_str_len) == 0) 295 num_nulls++; 296 else 297 num_nulls = 0; 298 cur_str_len++; 299 300 if(num_nulls == 2) 301 { 302 ret_err = uni_to_ascii(cur_str, cur_ascii, cur_str_len-1, cur_str_max); 303 if(ret_err < 0) 303 ret_err = uni_to_ascii(datap, ascii_tmp, len, ascii_max); 304 if(ret_err < 0) 305 { 306 tmp_err = strerror(-ret_err); 307 *error_msg = (char*)malloc(54+strlen(tmp_err)); 308 if(*error_msg == NULL) 309 return NULL; 310 sprintf(*error_msg, "MULTI_SZ unicode conversion" 311 " failed with '%s'. Quoting as binary.", tmp_err); 312 ascii = quote_buffer(datap, len, subfield_special_chars); 313 } 314 else 315 { 316 ascii = malloc(ascii_max); 317 if(ascii == NULL) 318 { 319 free(ascii_tmp); 320 return NULL; 321 } 322 asciip = ascii; 323 asciip[0] = '\0'; 324 str_rem = ascii_max; 325 delim = ""; 326 for(i=0; i<ret_err; i+=cur_str_len+1) 327 { 328 cur_str_len = strlen(ascii_tmp+i); 329 if(ascii_tmp[i] != '\0') 304 330 { 305 /* XXX: should every sub-field error be enumerated? */306 if( *error_msg == NULL)331 cur_quoted = quote_string(ascii_tmp+i, subfield_special_chars); 332 if(cur_quoted != NULL) 307 333 { 308 tmp_err = strerror(-ret_err); 309 *error_msg = (char*)malloc(90+strlen(tmp_err)+1); 310 if(*error_msg == NULL) 311 { 312 free(cur_str); 313 free(cur_ascii); 314 free(ascii); 315 return NULL; 316 } 317 sprintf(*error_msg, "Unicode conversion failed on at least one " 318 "MULTI_SZ sub-field; printing as binary. Error: %s", 319 tmp_err); 334 alen = snprintf(asciip, str_rem, "%s%s", delim, cur_quoted); 335 asciip += alen; 336 str_rem -= alen; 337 free(cur_quoted); 320 338 } 321 cur_quoted = quote_buffer(cur_str, cur_str_len-1,322 subfield_special_chars);323 339 } 324 else 325 cur_quoted = quote_string(cur_ascii, subfield_special_chars); 326 327 alen = snprintf(asciip, str_rem, "%s", cur_quoted); 328 asciip += alen; 329 str_rem -= alen; 330 free(cur_quoted); 331 332 if(*(datap+i+1) == 0 && *(datap+i+2) == 0) 333 break; 334 else 335 { 336 if(str_rem > 0) 337 { 338 asciip[0] = '|'; 339 asciip[1] = '\0'; 340 asciip++; 341 str_rem--; 342 } 343 memset(cur_str, 0, cur_str_max); 344 cur_str_len = 0; 345 num_nulls = 0; 346 /* To eliminate leading nulls in subsequent strings. */ 347 i++; 348 } 349 } 350 } 351 *asciip = 0; 352 free(cur_str); 353 free(cur_ascii); 340 delim = "|"; 341 } 342 } 343 344 free(ascii_tmp); 354 345 return ascii; 355 346 break; … … 357 348 /* XXX: Dont know what to do with these yet, just print as binary... */ 358 349 default: 359 /* XXX: It would be really nice if this message somehow included the 360 * name of the current value we're having trouble with, since 361 * stderr/stdout don't always sync nicely. 362 */ 363 fprintf(stderr, "WARNING: Unrecognized registry data type (0x%.8X); quoting as binary.\n", type); 350 *error_msg = (char*)malloc(65); 351 if(*error_msg == NULL) 352 return NULL; 353 sprintf(*error_msg, 354 "Unrecognized registry data type (0x%.8X); quoting as binary.", 355 type); 364 356 365 357 case REG_NONE: -
trunk/src/reglookup.c
r125 r126 97 97 "Returned error: %s\n", prefix, quoted_name, conv_error); 98 98 } 99 /* XXX: should these always be printed? */100 99 else if(conv_error != NULL && print_verbose) 101 100 fprintf(stderr, "VERBOSE: While quoting value for '%s/%s', " … … 296 295 char* dacl = NULL; 297 296 char* quoted_classname; 297 char* error_msg = NULL; 298 298 char mtime[20]; 299 299 time_t tmp_time[1]; … … 322 322 323 323 if(k->classname != NULL) 324 quoted_classname = quote_string(k->classname, key_special_chars); 324 { 325 quoted_classname = quote_unicode((uint8*)k->classname, k->classname_length, 326 key_special_chars, &error_msg); 327 if(quoted_classname == NULL) 328 { 329 if(error_msg == NULL) 330 fprintf(stderr, "ERROR: Could not quote classname" 331 " for key '%s' due to unknown error.\n", full_path); 332 else 333 { 334 fprintf(stderr, "ERROR: Could not quote classname" 335 " for key '%s' due to error: %s\n", full_path, error_msg); 336 free(error_msg); 337 } 338 } 339 else if (error_msg != NULL) 340 { 341 if(print_verbose) 342 fprintf(stderr, "WARNING: While converting classname" 343 " for key '%s': %s.\n", full_path, error_msg); 344 free(error_msg); 345 } 346 } 325 347 else 326 348 quoted_classname = empty_str;
Note: See TracChangeset
for help on using the changeset viewer.