Closed griggsrl closed 1 year ago
Thank you for reporting this issue. What is the size of the MSI file before and after signing?
Oddly, all 3 MSIs that have the issue are 96KB before signing and 116KB after signing. We do have a couple of other MSI files that start at 96KB as well which don't have the issue.
Would it be possible to send one of these MSI to ebourg@apache.org please? I'll give it a look.
I'll see if I can get approval to send one to you or see if I can get a sample project made to demonstrate the issue.
I just sent over a copy of one of the MSIs for you to take a look at. Let me know if you need anything else.
Thank you for the file. I'm able to reproduce the error but I don't understand why it happens. It looks like a bug in Apache POI, adding an empty entry to the MSI file triggers the error but that depends on the entry name length (names between 4 and 19 characters corrupt the file).
We also have a file that gets corrupted (according to Windows) after a signature entry is added using Apache POI. I can not share the file as it belongs to one of our customers.
But I can confirm that using a file name of 3 characters is fine (except of-course the signature is not there then). @ebourg How did you find out about the 4-19 characters range?
Previously when troubleshooting a bug in POI we discovered that the msidump tool (from msitools) segfaulted and could use that information to figure out where the problem was. Unfortunately, in this case, at least after a first look, this does not happen in this case. So we need to find some other way to figure out where the problem is.
@netmackan I've simply opened the MSI file with POI and then added a Foo
entry with a empty 4K byte array. With the name Foo
the MSI was still valid, but with an entry named FooBar
it became invalid (with the same 4K content). A longer entry name of 20 characters was fine (the signature entry is named \u0005DigitalSignature
, so 17 characters and in the invalid range).
I noticed now that the lengths of the existing entry names (in my file) are between 3-19 characters long. It could be a coincidence but also considering that there is a sorting algorithm (DirectoryProperty.preWrite()) that is based on the lengths of the entry names, I am getting suspicious there could be an issue with the sorting implementation if the file has entries with specific file name lengths and names...
Thank you for the hint, I tried disabling the sorting but the modified MSI file was still invalid. Even with the sorting disabled, the entries of the modified file were in a different order (as iterated by POI) than the unmodified file. It seems that the entries have an index that doesn't match the iteration order of POI, and this index remained the same in the modified file.
I also compared with signtool, the signature entries (MsiDigitalSignatureEx and DigitalSignature) are "inserted" after the SummaryInformation entry (but the actual index start after the highest index of the original file), and the overall order isn't modified.
This order variation is likely to be the cause of the issue but it remains a mystery to me.
Any updates on this issue? Looks like we have the same.
If I check the signature afterwards with CMSSignedData data : Signable.of(targetFile).getSignatures()
It looks fine. If I re-write the file but just comment fsWrite.getRoot().createOrUpdateDocument(DIGITAL_SIGNATURE_ENTRY_NAME, new ByteArrayInputStream(signatureBytes));
, the order of the Properties is different but the .msi is still valid/throws no error.
With this line I got the error above.
I haven't investigated further yet. The next step I think is to write a minimal test case and report the issue to Apache POI.
After a few hours ingesting the CFB file format and writing a homemade parser I've eventually figured out the issue: Apache POI doesn't update the number of directory sectors in the MSI header.
The test file sent by @griggsrl has 32 entries which fill exactly one directory sector. The addition of a new entry (such as the signature entry created by Jsign) generates a second directory sector, but the number of directory sectors in the header remains 1. It looks like msiexec.exe
, the program processing the MSI files, reads only the number of directory sectors specified in the header, instead of reading the full stream as specified by the FAT. Depending on the name of the entry added, the binary tree of the entry nodes is reshaped, a part of the tree is grafted to the new entry located on the second directory sector and becomes unavailable. If this affects a critical entry such as the SummaryInformation
entry, the installation fails. Increasing the number of directory sectors by one in the header (offset 0x28) fixes the issue.
The issue has been forwarded: https://bz.apache.org/bugzilla/show_bug.cgi?id=66590
Good morning , It looks like I have just run into this issue. I see that the apache poi merge request has not progressed . Is there any ETA on it ?. Is there a workaround I can use in the meantime ? Thanks John
Reopening, @johm6340 pointed out by email that MSI files using the format version 3 with 512 byte sectors must have the number of directory sectors set to zero.
@johm6340 I've pushed a fix, could you give it a try with the msm files?
Fix confirmed
Hi, My team has encountered an issue while using the programmatic API to sign some MSI files. We sign many files every day including other MSIs and have no issues with the vast majority. We're not sure why these couple of MSIs are the exception. The signing doesn't fail or throw any errors at all but immediately after the MSI is signed it becomes corrupt and attempting to run the MSI displays the following error:![image](https://user-images.githubusercontent.com/3331954/114104476-8c361800-9890-11eb-9ea6-aef444a2129d.png)
The code we're using to sign is as follows:
It's pretty straightforward so I'm not sure what's going on or additional spots to look.