Mercurial > libpst
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 |