poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r804381 - in /poi/trunk/src: java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/record/crypto/ testcases/org/apache/poi/hssf/record/
Date Fri, 14 Aug 2009 21:35:45 GMT
Author: josh
Date: Fri Aug 14 21:35:44 2009
New Revision: 804381

URL: http://svn.apache.org/viewvc?rev=804381&view=rev
Log:
Follow-on for bugzilla 47652 - used more specific exception when password is incorrect

Added:
    poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java
Modified:
    poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java
    poi/trunk/src/java/org/apache/poi/hssf/record/crypto/Biff8EncryptionKey.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java?rev=804381&r1=804380&r2=804381&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java Fri Aug 14
21:35:44 2009
@@ -23,6 +23,7 @@
 import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
 import org.apache.poi.hssf.eventusermodel.HSSFListener;
 import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.EncryptedDocumentException;
 
 /**
  * A stream based way to get at complete records, with
@@ -41,7 +42,7 @@
 	 * Needed for protected files because each byte is encrypted with respect to its absolute
 	 * position from the start of the stream.
 	 */
-	public static final class StreamEncryptionInfo {
+	private static final class StreamEncryptionInfo {
 		private final int _initialRecordsSize;
 		private final FilePassRecord _filePassRec;
 		private final Record _lastRecord;
@@ -97,7 +98,9 @@
 				key = Biff8EncryptionKey.create(userPassword, fpr.getDocId());
 			}
 			if (!key.validate(fpr.getSaltData(), fpr.getSaltHash())) {
-				throw new RecordFormatException("Password/docId do not correspond to saltData/saltHash");
+				throw new EncryptedDocumentException(
+						(userPassword == null ? "Default" : "Supplied")
+						+ " password is invalid for docId/saltData/saltHash");
 			}
 			return new RecordInputStream(original, key, _initialRecordsSize);
 		}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/crypto/Biff8EncryptionKey.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/crypto/Biff8EncryptionKey.java?rev=804381&r1=804380&r2=804381&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/crypto/Biff8EncryptionKey.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/crypto/Biff8EncryptionKey.java Fri Aug 14
21:35:44 2009
@@ -90,9 +90,21 @@
 		md5.update(saltDataPrime);
 		byte[] finalSaltResult = md5.digest();
 
+		if (false) { // set true to see a valid saltHash value
+			byte[] saltHashThatWouldWork = xor(saltHash, xor(saltHashPrime, finalSaltResult));
+			System.out.println(HexDump.toHex(saltHashThatWouldWork));
+		}
+
 		return Arrays.equals(saltHashPrime, finalSaltResult);
 	}
 
+	private static byte[] xor(byte[] a, byte[] b) {
+		byte[] c = new byte[a.length];
+		for (int i = 0; i < c.length; i++) {
+			c[i] = (byte) (a[i] ^ b[i]);
+		}
+		return c;
+	}
 	private static void check16Bytes(byte[] data, String argName) {
 		if (data.length != 16) {
 			throw new IllegalArgumentException("Expected 16 byte " + argName + ", but got " + HexDump.toHex(data));

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java?rev=804381&r1=804380&r2=804381&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java Fri Aug 14 21:35:44
2009
@@ -47,9 +47,11 @@
 		result.addTestSuite(TestBOFRecord.class);
 		result.addTestSuite(TestBoolErrRecord.class);
 		result.addTestSuite(TestBoundSheetRecord.class);
+		result.addTestSuite(TestCellRange.class);
 		result.addTestSuite(TestCFHeaderRecord.class);
 		result.addTestSuite(TestCFRuleRecord.class);
 		result.addTestSuite(TestCommonObjectDataSubRecord.class);
+		result.addTestSuite(TestConstantValueParser.class);
 		result.addTestSuite(TestDrawingGroupRecord.class);
 		result.addTestSuite(TestEmbeddedObjectRefSubRecord.class);
 		result.addTestSuite(TestEndSubRecord.class);
@@ -67,8 +69,9 @@
 		result.addTestSuite(TestObjRecord.class);
 		result.addTestSuite(TestPaletteRecord.class);
 		result.addTestSuite(TestPaneRecord.class);
-		result.addTestSuite(TestRecordInputStream.class);
 		result.addTestSuite(TestRecordFactory.class);
+		result.addTestSuite(TestRecordFactoryInputStream.class);
+		result.addTestSuite(TestRecordInputStream.class);
 		result.addTestSuite(TestSCLRecord.class);
 		result.addTestSuite(TestSSTDeserializer.class);
 		result.addTestSuite(TestSSTRecord.class);
@@ -84,8 +87,6 @@
 		result.addTestSuite(TestUnicodeNameRecord.class);
 		result.addTestSuite(TestUnicodeString.class);
 		result.addTestSuite(TestWriteAccessRecord.class);
-		result.addTestSuite(TestCellRange.class);
-		result.addTestSuite(TestConstantValueParser.class);
 		return result;
 	}
 }

Added: poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java?rev=804381&view=auto
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java (added)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java Fri
Aug 14 21:35:44 2009
@@ -0,0 +1,147 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.util.HexRead;
+
+/**
+ * Tests for {@link RecordFactoryInputStream}
+ *
+ * @author Josh Micich
+ */
+public final class TestRecordFactoryInputStream extends TestCase {
+
+	/**
+	 * Hex dump of a BOF record and most of a FILEPASS record.
+	 * A 16 byte saltHash should be added to complete the second record
+	 */
+	private static final String COMMON_HEX_DATA = ""
+		// BOF
+		+ "09 08 10 00"
+		+ "00 06  05 00  D3 10  CC 07  01 00 00 00  00 06 00 00"
+		// FILEPASS
+		+ "2F 00 36 00"
+		+ "01 00  01 00  01 00"
+		+ "BAADF00D BAADF00D BAADF00D BAADF00D" // docId
+		+ "DEADBEEF DEADBEEF DEADBEEF DEADBEEF" // saltData
+		;
+
+	/**
+	 * Hex dump of a sample WINDOW1 record
+	 */
+	private static final String SAMPLE_WINDOW1 = "3D 00 12 00"
+		+ "00 00 00 00 40 38 55 23 38 00 00 00 00 00 01 00 58 02";
+
+	/**
+	 * Makes sure that a default password mismatch condition is represented with {@link EncryptedDocumentException}
+	 */
+	public void testDefaultPassword() {
+		// This encodng depends on docId, password and stream position
+		final String SAMPLE_WINDOW1_ENCR1 = "3D 00 12 00"
+			+ "C4, 9B, 02, 50, 86, E0, DF, 34, FB, 57, 0E, 8C, CE, 25, 45, E3, 80, 01";
+
+		byte[] dataWrongDefault = HexRead.readFromString(""
+				+ COMMON_HEX_DATA
+				+ "00000000 00000000 00000000 00000001"
+				+ SAMPLE_WINDOW1_ENCR1
+		);
+
+		RecordFactoryInputStream rfis;
+		try {
+			rfis = createRFIS(dataWrongDefault);
+			throw new AssertionFailedError("Expected password mismatch error");
+		} catch (EncryptedDocumentException e) {
+			// expected during successful test
+			if (!e.getMessage().equals("Default password is invalid for docId/saltData/saltHash"))
{
+				throw e;
+			}
+		}
+
+		byte[] dataCorrectDefault = HexRead.readFromString(""
+				+ COMMON_HEX_DATA
+				+ "137BEF04 969A200B 306329DE 52254005" // correct saltHash for default password (and
docId/saltHash)
+				+ SAMPLE_WINDOW1_ENCR1
+		);
+
+		rfis = createRFIS(dataCorrectDefault);
+
+		confirmReadInitialRecords(rfis);
+	}
+
+	/**
+	 * Makes sure that an incorrect user supplied password condition is represented with {@link
EncryptedDocumentException}
+	 */
+	public void testSuppliedPassword() {
+		// This encodng depends on docId, password and stream position
+		final String SAMPLE_WINDOW1_ENCR2 = "3D 00 12 00"
+			+ "45, B9, 90, FE, B6, C6, EC, 73, EE, 3F, 52, 45, 97, DB, E3, C1, D6, FE";
+
+		byte[] dataWrongDefault = HexRead.readFromString(""
+				+ COMMON_HEX_DATA
+				+ "00000000 00000000 00000000 00000000"
+				+ SAMPLE_WINDOW1_ENCR2
+		);
+
+
+		Biff8EncryptionKey.setCurrentUserPassword("passw0rd");
+
+		RecordFactoryInputStream rfis;
+		try {
+			rfis = createRFIS(dataWrongDefault);
+			throw new AssertionFailedError("Expected password mismatch error");
+		} catch (EncryptedDocumentException e) {
+			// expected during successful test
+			if (!e.getMessage().equals("Supplied password is invalid for docId/saltData/saltHash"))
{
+				throw e;
+			}
+		}
+
+		byte[] dataCorrectDefault = HexRead.readFromString(""
+				+ COMMON_HEX_DATA
+				+ "C728659A C38E35E0 568A338F C3FC9D70" // correct saltHash for supplied password (and
docId/saltHash)
+				+ SAMPLE_WINDOW1_ENCR2
+		);
+
+		rfis = createRFIS(dataCorrectDefault);
+		Biff8EncryptionKey.setCurrentUserPassword(null);
+
+		confirmReadInitialRecords(rfis);
+	}
+
+	/**
+	 * makes sure the record stream starts with {@link BOFRecord} and then {@link WindowOneRecord}
+	 * The second record is gets decrypted so this method also checks its content.
+	 */
+	private void confirmReadInitialRecords(RecordFactoryInputStream rfis) {
+		assertEquals(BOFRecord.class, rfis.nextRecord().getClass());
+		WindowOneRecord rec1 = (WindowOneRecord) rfis.nextRecord();
+		assertTrue(Arrays.equals(HexRead.readFromString(SAMPLE_WINDOW1),rec1.serialize()));
+	}
+
+	private static RecordFactoryInputStream createRFIS(byte[] data) {
+		return new RecordFactoryInputStream(new ByteArrayInputStream(data), true);
+	}
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message