comparison src/libpst.c @ 170:0e1e048716e4

fix bug where we failed to pickup the last extended attribute. patch from Emmanuel Andry to fix potential security bug in pst2dii with printf(err).
author Carl Byington <carl@five-ten-sg.com>
date Sun, 22 Mar 2009 14:34:26 -0700
parents c1a2fd06ffe6
children 6c1e75bc4cac
comparison
equal deleted inserted replaced
169:062aa7b7ec22 170:0e1e048716e4
516 uint16_t type; 516 uint16_t type;
517 uint16_t map; 517 uint16_t map;
518 } pst_x_attrib; 518 } pst_x_attrib;
519 519
520 520
521 /** Try to load the extended attributes from the pst file.
522 @return true(1) or false(0) to indicate whether the extended attributes have been loaded
523 */
521 int pst_load_extended_attributes(pst_file *pf) { 524 int pst_load_extended_attributes(pst_file *pf) {
522 // for PST files this will load up ID2 0x61 and check it's "list" attribute. 525 // for PST files this will load up d_id 0x61 and check it's "assoc_tree" attribute.
523 pst_desc_ll *p; 526 pst_desc_ll *p;
524 pst_mapi_object *na; 527 pst_mapi_object *list;
525 pst_id2_ll *id2_head = NULL; 528 pst_id2_ll *id2_head = NULL;
526 char *buffer=NULL, *headerbuffer=NULL; 529 char *buffer=NULL, *headerbuffer=NULL;
527 size_t bsize=0, hsize=0, bptr=0; 530 size_t bsize=0, hsize=0, bptr=0;
528 pst_x_attrib xattrib; 531 pst_x_attrib xattrib;
529 int32_t tint, err=0, x; 532 int32_t tint, err=0, x;
530 pst_x_attrib_ll *ptr, *p_head=NULL, *p_sh=NULL, *p_sh2=NULL; 533 pst_x_attrib_ll *ptr, *p_head=NULL;
531 534
532 DEBUG_ENT("pst_loadExtendedAttributes"); 535 DEBUG_ENT("pst_loadExtendedAttributes");
533 p = pst_getDptr(pf, (uint64_t)0x61); 536 p = pst_getDptr(pf, (uint64_t)0x61);
534 if (!p) { 537 if (!p) {
535 DEBUG_WARN(("Cannot find DescID 0x61 for loading the Extended Attributes\n")); 538 DEBUG_WARN(("Cannot find d_id 0x61 for loading the Extended Attributes\n"));
536 DEBUG_RET(); 539 DEBUG_RET();
537 return 0; 540 return 0;
538 } 541 }
539 542
540 if (!p->desc) { 543 if (!p->desc) {
541 DEBUG_WARN(("desc is NULL for item 0x61. Cannot load Extended Attributes\n")); 544 DEBUG_WARN(("descriptor is NULL for d_id 0x61. Cannot load Extended Attributes\n"));
542 DEBUG_RET(); 545 DEBUG_RET();
543 return 0; 546 return 0;
544 } 547 }
545 548
546 if (p->assoc_tree) { 549 if (p->assoc_tree) {
547 id2_head = pst_build_id2(pf, p->assoc_tree); 550 id2_head = pst_build_id2(pf, p->assoc_tree);
548 pst_printID2ptr(id2_head); 551 pst_printID2ptr(id2_head);
549 } else { 552 } else {
550 DEBUG_WARN(("Have not been able to fetch any id2 values for item 0x61. Brace yourself!\n")); 553 DEBUG_WARN(("Have not been able to fetch any id2 values for d_id 0x61. Brace yourself!\n"));
551 } 554 }
552 555
553 na = pst_parse_block(pf, p->desc->i_id, id2_head); 556 list = pst_parse_block(pf, p->desc->i_id, id2_head);
554 if (!na) { 557 if (!list) {
555 DEBUG_WARN(("Cannot process desc block for item 0x61. Not loading extended Attributes\n")); 558 DEBUG_WARN(("Cannot process desc block for item 0x61. Not loading extended Attributes\n"));
556 pst_free_id2(id2_head); 559 pst_free_id2(id2_head);
557 DEBUG_RET(); 560 DEBUG_RET();
558 return 0; 561 return 0;
559 } 562 }
560 563
561 for (x=0; x < na->count_elements; x++) { 564 DEBUG_EMAIL(("look thru d_id 0x61 list of mapi objects\n"));
562 if (na->elements[x]->mapi_id == (uint32_t)0x0003) { 565 for (x=0; x < list->count_elements; x++) {
563 buffer = na->elements[x]->data; 566 DEBUG_EMAIL(("#%d - mapi-id: %#x type: %#x length: %#x\n", x, list->elements[x]->mapi_id, list->elements[x]->type, list->elements[x]->size));
564 bsize = na->elements[x]->size; 567 if (list->elements[x]->data) {
565 } else if (na->elements[x]->mapi_id == (uint32_t)0x0004) { 568 DEBUG_HEXDUMPC(list->elements[x]->data, list->elements[x]->size, 0x10);
566 headerbuffer = na->elements[x]->data; 569 }
567 hsize = na->elements[x]->size; 570 if (list->elements[x]->mapi_id == (uint32_t)0x0003) {
571 buffer = list->elements[x]->data;
572 bsize = list->elements[x]->size;
573 } else if (list->elements[x]->mapi_id == (uint32_t)0x0004) {
574 headerbuffer = list->elements[x]->data;
575 hsize = list->elements[x]->size;
568 } else { 576 } else {
569 // leave them null 577 // leave them null
570 } 578 }
571 } 579 }
572 580
573 if (!buffer) { 581 if (!buffer) {
574 pst_free_list(na); 582 pst_free_list(list);
575 DEBUG_WARN(("No extended attributes buffer found. Not processing\n")); 583 DEBUG_WARN(("No extended attributes buffer found. Not processing\n"));
576 DEBUG_RET(); 584 DEBUG_RET();
577 return 0; 585 return 0;
578 } 586 }
579 587
580 xattrib.extended= PST_LE_GET_UINT32(buffer+bptr), bptr += 4; 588 while (bptr < bsize) {
581 xattrib.type = PST_LE_GET_UINT16(buffer+bptr), bptr += 2; 589 int err = 0;
582 xattrib.map = PST_LE_GET_UINT16(buffer+bptr), bptr += 2; 590 xattrib.extended= PST_LE_GET_UINT32(buffer+bptr), bptr += 4;
583 591 xattrib.type = PST_LE_GET_UINT16(buffer+bptr), bptr += 2;
584 while (xattrib.type != 0 && bptr < bsize) { 592 xattrib.map = PST_LE_GET_UINT16(buffer+bptr), bptr += 2;
585 ptr = (pst_x_attrib_ll*) xmalloc(sizeof(*ptr)); 593 ptr = (pst_x_attrib_ll*) xmalloc(sizeof(*ptr));
586 memset(ptr, 0, sizeof(*ptr)); 594 memset(ptr, 0, sizeof(*ptr));
587 ptr->type = xattrib.type; 595 ptr->type = xattrib.type;
588 ptr->map = xattrib.map+0x8000; 596 ptr->map = xattrib.map+0x8000;
589 ptr->next = NULL; 597 ptr->next = NULL;
590 DEBUG_INDEX(("xattrib: ext = %#x, type = %#hx, map = %#hx\n", 598 DEBUG_INDEX(("xattrib: ext = %#"PRIx32", type = %#"PRIx16", map = %#"PRIx16"\n",
591 xattrib.extended, xattrib.type, xattrib.map)); 599 xattrib.extended, xattrib.type, xattrib.map));
592 err=0;
593 if (xattrib.type & 0x0001) { // if the Bit 1 is set 600 if (xattrib.type & 0x0001) { // if the Bit 1 is set
594 // pointer to Unicode field in buffer 601 // pointer to Unicode field in buffer
595 if (xattrib.extended < hsize) { 602 if (xattrib.extended < hsize) {
596 char *wt; 603 char *wt;
597 // copy the size of the header. It is 32 bit int 604 // copy the size of the header. It is 32 bit int
600 wt = (char*) xmalloc((size_t)(tint+2)); // plus 2 for a uni-code zero 607 wt = (char*) xmalloc((size_t)(tint+2)); // plus 2 for a uni-code zero
601 memset(wt, 0, (size_t)(tint+2)); 608 memset(wt, 0, (size_t)(tint+2));
602 memcpy(wt, &(headerbuffer[xattrib.extended+sizeof(tint)]), (size_t)tint); 609 memcpy(wt, &(headerbuffer[xattrib.extended+sizeof(tint)]), (size_t)tint);
603 ptr->data = pst_wide_to_single(wt, (size_t)tint); 610 ptr->data = pst_wide_to_single(wt, (size_t)tint);
604 free(wt); 611 free(wt);
605 DEBUG_INDEX(("Read string (converted from UTF-16): %s\n", ptr->data)); 612 DEBUG_INDEX(("Mapped attribute %#"PRIx32" to %s\n", ptr->map, ptr->data));
606 } else { 613 } else {
607 DEBUG_INDEX(("Cannot read outside of buffer [%i !< %i]\n", xattrib.extended, hsize)); 614 DEBUG_INDEX(("Cannot read outside of buffer [%i !< %i]\n", xattrib.extended, hsize));
615 err = 1;
608 } 616 }
609 ptr->mytype = PST_MAP_HEADER; 617 ptr->mytype = PST_MAP_HEADER;
610 } else { 618 } else {
611 // contains the attribute code to map to. 619 // contains the attribute code to map to.
612 ptr->data = (uint32_t*)xmalloc(sizeof(uint32_t)); 620 ptr->data = (uint32_t*)xmalloc(sizeof(uint32_t));
613 memset(ptr->data, 0, sizeof(uint32_t)); 621 memset(ptr->data, 0, sizeof(uint32_t));
614 *((uint32_t*)ptr->data) = xattrib.extended; 622 *((uint32_t*)ptr->data) = xattrib.extended;
615 ptr->mytype = PST_MAP_ATTRIB; 623 ptr->mytype = PST_MAP_ATTRIB;
616 DEBUG_INDEX(("Mapped attribute %#x to %#x\n", ptr->map, *((int32_t*)ptr->data))); 624 DEBUG_INDEX(("Mapped attribute %#"PRIx32" to %#"PRIx32"\n", ptr->map, *((uint32_t*)ptr->data)));
617 } 625 }
618 626
619 if (err==0) { 627 if (!err) {
620 // add it to the list 628 // add it to the list
621 p_sh = p_head; 629 pst_x_attrib_ll *p_sh = p_head;
622 p_sh2 = NULL; 630 pst_x_attrib_ll *p_sh2 = NULL;
623 while (p_sh && ptr->map > p_sh->map) { 631 while (p_sh && ptr->map > p_sh->map) {
624 p_sh2 = p_sh; 632 p_sh2 = p_sh;
625 p_sh = p_sh->next; 633 p_sh = p_sh->next;
626 } 634 }
627 if (!p_sh2) { 635 if (!p_sh2) {
628 // needs to go before first item 636 // needs to go before first item
629 ptr->next = p_head; 637 ptr->next = p_head;
630 p_head = ptr; 638 p_head = ptr;
633 ptr->next = p_sh2->next; 641 ptr->next = p_sh2->next;
634 p_sh2->next = ptr; 642 p_sh2->next = ptr;
635 } 643 }
636 } else { 644 } else {
637 free(ptr); 645 free(ptr);
638 ptr = NULL; 646 }
639 }
640 memcpy(&xattrib, &(buffer[bptr]), sizeof(xattrib));
641 LE32_CPU(xattrib.extended);
642 LE16_CPU(xattrib.type);
643 LE16_CPU(xattrib.map);
644 bptr += sizeof(xattrib);
645 } 647 }
646 pst_free_id2(id2_head); 648 pst_free_id2(id2_head);
647 pst_free_list(na); 649 pst_free_list(list);
648 pf->x_head = p_head; 650 pf->x_head = p_head;
649 DEBUG_RET(); 651 DEBUG_RET();
650 return 1; 652 return 1;
651 } 653 }
652 654
1554 if (mapptr && (mapptr->map == table_rec.type)) { 1556 if (mapptr && (mapptr->map == table_rec.type)) {
1555 if (mapptr->mytype == PST_MAP_ATTRIB) { 1557 if (mapptr->mytype == PST_MAP_ATTRIB) {
1556 mo_ptr->elements[x]->mapi_id = *((uint32_t*)mapptr->data); 1558 mo_ptr->elements[x]->mapi_id = *((uint32_t*)mapptr->data);
1557 DEBUG_EMAIL(("Mapped attrib %#x to %#x\n", table_rec.type, mo_ptr->elements[x]->mapi_id)); 1559 DEBUG_EMAIL(("Mapped attrib %#x to %#x\n", table_rec.type, mo_ptr->elements[x]->mapi_id));
1558 } else if (mapptr->mytype == PST_MAP_HEADER) { 1560 } else if (mapptr->mytype == PST_MAP_HEADER) {
1559 DEBUG_EMAIL(("Internet Header mapping found %#x\n", table_rec.type)); 1561 DEBUG_EMAIL(("Internet Header mapping found %#"PRIx32" to %s\n", table_rec.type, mapptr->data));
1560 mo_ptr->elements[x]->mapi_id = (uint32_t)PST_ATTRIB_HEADER; 1562 mo_ptr->elements[x]->mapi_id = (uint32_t)PST_ATTRIB_HEADER;
1561 mo_ptr->elements[x]->extra = mapptr->data; 1563 mo_ptr->elements[x]->extra = mapptr->data;
1562 } 1564 }
1563 else { 1565 else {
1564 DEBUG_WARN(("Missing assertion failure\n")); 1566 DEBUG_WARN(("Missing assertion failure\n"));
1565 // nothing, should be assertion failure here 1567 // nothing, should be assertion failure here
1566 } 1568 }
1979 1981
1980 while (list) { 1982 while (list) {
1981 int32_t x; 1983 int32_t x;
1982 for (x=0; x<list->count_elements; x++) { 1984 for (x=0; x<list->count_elements; x++) {
1983 int32_t t; 1985 int32_t t;
1984 pst_item_extra_field *ef;
1985 // check here to see if the id is one that is mapped.
1986 DEBUG_EMAIL(("#%d - mapi-id: %#x type: %#x length: %#x\n", x, list->elements[x]->mapi_id, list->elements[x]->type, list->elements[x]->size)); 1986 DEBUG_EMAIL(("#%d - mapi-id: %#x type: %#x length: %#x\n", x, list->elements[x]->mapi_id, list->elements[x]->type, list->elements[x]->size));
1987 1987
1988 switch (list->elements[x]->mapi_id) { 1988 switch (list->elements[x]->mapi_id) {
1989 case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers 1989 case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers
1990 if ((list->elements[x]->extra) && 1990 if (list->elements[x]->extra) {
1991 ((list->elements[x]->type == 0x1f) || 1991 pst_item_extra_field *ef = (pst_item_extra_field*) xmalloc(sizeof(pst_item_extra_field));
1992 (list->elements[x]->type == 0x1e))) {
1993 ef = (pst_item_extra_field*) xmalloc(sizeof(pst_item_extra_field));
1994 memset(ef, 0, sizeof(pst_item_extra_field)); 1992 memset(ef, 0, sizeof(pst_item_extra_field));
1995 ef->field_name = (char*) xmalloc(strlen(list->elements[x]->extra)+1); 1993 ef->field_name = strdup(list->elements[x]->extra);
1996 strcpy(ef->field_name, list->elements[x]->extra);
1997 LIST_COPY_CSTR(ef->value); 1994 LIST_COPY_CSTR(ef->value);
1998 ef->next = item->extra_fields; 1995 if (ef->value) {
1999 item->extra_fields = ef; 1996 ef->next = item->extra_fields;
2000 DEBUG_EMAIL(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value)); 1997 item->extra_fields = ef;
2001 if (strcmp(ef->field_name, "content-type") == 0) { 1998 DEBUG_EMAIL(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value));
2002 char *p = strstr(ef->value, "charset=\""); 1999 if (strcmp(ef->field_name, "content-type") == 0) {
2003 if (p) { 2000 char *p = strstr(ef->value, "charset=\"");
2004 p += 9; // skip over charset=" 2001 if (p) {
2005 char *pp = strchr(p, '"'); 2002 p += 9; // skip over charset="
2006 if (pp) { 2003 char *pp = strchr(p, '"');
2007 *pp = '\0'; 2004 if (pp) {
2008 char *set = strdup(p); 2005 *pp = '\0';
2009 *pp = '"'; 2006 char *set = strdup(p);
2010 if (item->body_charset.str) free(item->body_charset.str); 2007 *pp = '"';
2011 item->body_charset.str = set; 2008 if (item->body_charset.str) free(item->body_charset.str);
2012 item->body_charset.is_utf8 = 1; 2009 item->body_charset.str = set;
2013 DEBUG_EMAIL(("body charset %s from content-type extra field\n", set)); 2010 item->body_charset.is_utf8 = 1;
2011 DEBUG_EMAIL(("body charset %s from content-type extra field\n", set));
2012 }
2014 } 2013 }
2015 } 2014 }
2016 } 2015 }
2017 } 2016 else {
2018 else { 2017 DEBUG_EMAIL(("What does this mean? Internet header %s value\n", list->elements[x]->extra));
2019 DEBUG_EMAIL(("What does this mean?\n")); 2018 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
2020 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); 2019 }
2021 } 2020 }
2022 break; 2021 break;
2023 case 0x0002: // PR_ALTERNATE_RECIPIENT_ALLOWED 2022 case 0x0002: // PR_ALTERNATE_RECIPIENT_ALLOWED
2024 if (list->elements[x]->type == 0x0b) { 2023 if (list->elements[x]->type == 0x0b) {
2025 // If set to true, the sender allows this email to be autoforwarded 2024 // If set to true, the sender allows this email to be autoforwarded