bc-java
bc-java copied to clipboard
"worked around javax.mail change for attachment only messages." breaks code
Hi,
the commit https://github.com/bcgit/bc-java/commit/d050ec4c1c40544ae8d453fc769edb114f969c4b (bcmail 1.74) breaks our code:
content.setDataHandler(new DataHandler(message.getDataHandler().getDataSource()));
When I try to sign the following attachment-only Message:
MimeMessage messageToSign = new SimpleMimeMessage();
messageToSign.setContent(new byte[]{ 1 }, "application/octet-stream");
messageToSign.setFileName("file.gz");
messageToSign.saveChanges();
The signing fails silently without explicit error. The created signed MumeMultipart from the SMIMESignedGenerator
is broken.
Setting the Datahandler and Conten-Headers manually "fixes" the problem:
//...
MimeMultipart signedMultiPart = sMIMESignedGenerator.generate(messageToSign);
BodyPart bodyPart = signedMultiPart.getBodyPart(0);
bodyPart.setDataHandler(messageToSign.getDataHandler());
bodyPart.addHeader("Content-Transfer-Encoding", "base64");
bodyPart.addHeader("Content-Type", "application/octet-stream; name=file.gz");
The difference seems to be, that the messageToSign has no DataSource, but calling new DataHandler(message.getDataHandler().getDataSource())
assumes there is one?
// DataHandler-Source
public void writeTo(OutputStream os) throws IOException {
// for the DataSource case
if (dataSource != null) {
// bcmail 1.74 way - throws Exception
InputStream is = null;
byte data[] = new byte[8*1024];
int bytes_read;
is = dataSource.getInputStream();
try {
while ((bytes_read = is.read(data)) > 0) {
os.write(data, 0, bytes_read);
}
} finally {
is.close();
is = null;
}
} else { // for the Object case
// bcmail 1.73 way - works
DataContentHandler dch = getDataContentHandler();
dch.writeTo(object, objectMimeType, os);
}
}
EDIT Using a MimeBodyPart instead seems to fix the problem. Is my previous code wrong? Or should both ways work?
MimeBodyPart mimeBodyPartToSign = new MimeBodyPart();
mimeBodyPartToSign.setContent(new byte[]{ 1 }, "application/octet-stream");
mimeBodyPartToSign.setFileName("file.gz");
I know this is going to sound dreadful, but you probably should be using a MimeBody part. What version of JavaMail are you using? The issue showed up for us because we updated the version of JavaMail we use locally - everything still worked except this one case, the assumption was that they'd fixed something which caused it to break. I'll admit attachment only messages are a bit of an edge condition, but even when we got everything working again it seemed surprising.
Yes I did switch to MimeBodyPart, as it works for both 1.74 and older versions. I am currently stuck on java mail 1.6.7.
However, I find it kind of critical, that signature creation fails without any exception. And since I use sign then encrypt, it completely shadowed the error, which only occurred after decrypting when the signature verification failed with an ArrayIndexOutOfBoundsException!
So I think there should be a check if the DataHandler has a valid DataSource, or if the created MultiPart is valid. But for the bare minimum this should be documented.
I'll see what I can do about adding a check, I should be able to get something that "works" now that I have another version of JavaMail to compare with.