Example #1
0
		protected override DecryptResult Decrypt(IContentEncryptionUi ui, string sourceFile)
		{			
			object doc = null;

			string tempfile = Path.GetTempFileName();
            var decryptWrapper = new WordApplicationDecryptWrapper();

			try
			{
	            decryptWrapper.CreateHostApplication();
			    DecryptResult result = OpenDocument(ui, sourceFile, out doc, decryptWrapper);
			 
				if (result != DecryptResult.Ok)
				{
					return result;
				}
				  
				//	Modify document passwords, save to -another- temporary file (decryptedPath)
				//	Need to save twice, or for some reason the read/modify passwords get kept
				Logger.LogDebug(string.Format("WordEncryption.Decrypt: Saving attachment to \"{0}\"", sourceFile));
                decryptWrapper.SetOpenPassword(doc, string.Empty);
                decryptWrapper.SetWritePassword(doc, string.Empty);
			    try
			    {
                    decryptWrapper.Save(doc);
			    }
			    catch (InvalidOperationException ex)
			    {
			        // if the document is readonly, Save() throws up UI, so instead it throws an InvalidOperationException, which we ignore...
			        Logger.LogInfo(ex);
			    }

				// If you have Office 2003 & a .docx file the SaveDocumentAs cannot write over the original
				// source file as it is currently locked. As a workaround we save to a temporary file
				// then move the tempfile over the sourceFile
                decryptWrapper.SaveDocumentAs(doc, tempfile, false, string.Empty, string.Empty);
			}
			finally
			{
				if (doc != null)
				{
                    decryptWrapper.CloseDocument(doc, false);
				}
                decryptWrapper.Dispose();
			}

			if (File.Exists(sourceFile))
			{
				File.Delete(sourceFile);
			}
			File.Move(tempfile, sourceFile);	// creates an empty file where sourceFile was -> only do if no error!!
			
			return DecryptResult.Ok;
		}
Example #2
0
		private DecryptResult OpenDocument(IContentEncryptionUi ui, string sourceFile, out object doc, WordApplicationDecryptWrapper decryptWrapper)
		{
			bool bUseDummyModifyPassword = false;
			doc = null;
			DecryptResult result = DecryptResult.Skip;

			// TODO - Fix the handling of Modify passwords to correctly validate them.
			// Currently any Modify password is stripped from the document when it is saved.
			// This is due to the fact that we don't correctly verify the Modify password when opening
			// the document and as a result it might be possible for the user to enter an incorrect password.
			// When saving, the incorrect password would still be applied causing problems for the receiver.

			string extension = System.IO.Path.GetExtension(sourceFile);

			switch (extension.ToLower())
			{
				case ".doc":
				case ".docx":
				case ".docm":
				case ".dotx":
				case ".dotm":
					result = this.GetAndCheckPasswords(ui);
					break;
				case ".rtf":
					result = this.GetAndCheckModifyPassword(ui);
					break;
				default:
					result = this.GetAndCheckOpenPassword(ui);
					break;
			}
		  
			if (result == DecryptResult.Ok)
			{
                // Don't use the cache to decrypt because password errors leave word in a state where
				// subsequent calls return RPC_UNAVAIABLE.
			    try
				{
                    doc = decryptWrapper.Decrypt(sourceFile, false, string.IsNullOrEmpty(OpenPassword) ? DUMMY_PASSWORD : OpenPassword, string.IsNullOrEmpty(ModifyPassword) ? DUMMY_PASSWORD : ModifyPassword, AttachmentFileType);

					// If the user typed a Modify or Open password for a document that didn't need one
					// remove it here, otherwise it will be added to the saved document.

                    if (!decryptWrapper.ShouldHandleOpenPassword(doc))
                    {
                        OpenPassword = "";
                    }

                    if (!decryptWrapper.ShouldHandleWritePassword(doc))
					{
						ModifyPassword = "";
					}
					// Bug fix for VE: 97
					// In OfficeXP, casting Microsoft.Office.Interop.Word.DocumentClass to Microsoft.Office.Interop.Word.Document fails at 
					// runtime. Use _Document instead.
					Word12Interop._Document wordDoc = doc as Word12Interop._Document;
                    DisableReadingLayout(wordDoc);
					Logger.LogDebug("Document Protection Type: " + wordDoc.ProtectionType);

					if( wordDoc.ProtectionType != Microsoft.Office.Interop.Word.WdProtectionType.wdNoProtection )
					{
						m_typeProtect = wordDoc.ProtectionType;


						if (!CanUnprotectDocument(wordDoc))
						{
							result = this.GetDocumentProtectionPassword(ui);

							if (result == DecryptResult.Ok)
							{
								if (string.IsNullOrEmpty(DocumentProtectionPassword))
								{
									m_typeProtect = Microsoft.Office.Interop.Word.WdProtectionType.wdNoProtection;
								}
								else if (m_typeProtect != Microsoft.Office.Interop.Word.WdProtectionType.wdNoProtection)
								{									
									object password = DocumentProtectionPassword;
									wordDoc.Unprotect(ref password);

									Logger.LogDebug(string.Format("WordEncryption.OpenDocument: Successfully unprotected document \"{0}\"", sourceFile));								
								}
							}
						}
					}
				}
                catch(UnauthorizedAccessException)
                {
                    Logger.LogInfo("Incorrect password. Exit word, and retry");
					DocumentProtectionPassword = string.Empty;
                    decryptWrapper.ForceQuit();
                    throw;
                }
				catch (COMException ex)
				{                   
					Logger.LogError("Office Open Exception");
					Logger.LogError(ex);

                    // handle exceptions for incorrect encryption passwords and the document preotection password 
                    if( ex.ErrorCode == unchecked((int)0x800A03EC) || ex.ErrorCode == unchecked((int)0x800A156D) )
                    {								
						Logger.LogInfo("Incorrect password. Exit word, and retry");
						DocumentProtectionPassword = string.Empty;
                        decryptWrapper.ForceQuit();
						throw new UnauthorizedAccessException("Failed to open encrypted file - incorrect password");
					}

					throw;
				}
				finally
				{
					// Reset any dummy password which may have been used so that the
					// document doesn't incorrectly get saved with it.
					if (bUseDummyModifyPassword)
					{
						ModifyPassword = "";
					}
				}
			}

			return result;
		}