1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #ifndef INCLUDED_COMPHELPER_DOCPASSWORDHELPER_HXX 21 #define INCLUDED_COMPHELPER_DOCPASSWORDHELPER_HXX 22 23 #include <comphelper/comphelperdllapi.h> 24 #include <string_view> 25 #include <vector> 26 #include <comphelper/docpasswordrequest.hxx> 27 #include <comphelper/hash.hxx> 28 29 namespace com::sun::star::task { class XInteractionHandler; } 30 namespace com::sun::star::beans { struct PropertyValue; } 31 namespace com::sun::star::beans { struct NamedValue; } 32 33 namespace comphelper { 34 35 enum class DocPasswordVerifierResult 36 { 37 OK, 38 WrongPassword, 39 Abort 40 }; 41 42 43 /** Base class for a password verifier used by the DocPasswordHelper class 44 below. 45 46 Users have to implement the virtual functions and pass an instance of the 47 verifier to one of the password request functions. 48 */ 49 class COMPHELPER_DLLPUBLIC IDocPasswordVerifier 50 { 51 public: 52 virtual ~IDocPasswordVerifier(); 53 54 /** Will be called every time a password needs to be verified. 55 56 @param rPassword 57 The password to be verified 58 59 @param o_rEncryptionData 60 Output parameter, that is filled with the EncryptionData generated 61 from the password. The data is filled only if the validation was 62 successful. 63 64 @return The result of the verification. 65 - DocPasswordVerifierResult_OK, if and only if the passed password 66 is valid and can be used to process the related document. 67 - DocPasswordVerifierResult_WRONG_PASSWORD, if the password is 68 wrong. The user may be asked again for a new password. 69 - DocPasswordVerifierResult_ABORT, if an unrecoverable error 70 occurred while password verification. The password request loop 71 will be aborted. 72 */ 73 virtual DocPasswordVerifierResult verifyPassword( const OUString& rPassword, css::uno::Sequence< css::beans::NamedValue >& o_rEncryptionData ) = 0; 74 75 /** Will be called every time an encryption data needs to be verified. 76 77 @param rEncryptionData 78 The data will be validated 79 80 @return The result of the verification. 81 - DocPasswordVerifierResult_OK, if and only if the passed encryption data 82 is valid and can be used to process the related document. 83 - DocPasswordVerifierResult_WRONG_PASSWORD, if the encryption data is 84 wrong. 85 - DocPasswordVerifierResult_ABORT, if an unrecoverable error 86 occurred while data verification. The password request loop 87 will be aborted. 88 */ 89 virtual DocPasswordVerifierResult verifyEncryptionData( const css::uno::Sequence< css::beans::NamedValue >& o_rEncryptionData ) = 0; 90 91 }; 92 93 94 /** Helper that asks for a document password and checks its validity. 95 */ 96 class COMPHELPER_DLLPUBLIC DocPasswordHelper 97 { 98 public: 99 100 101 /** This helper function generates the information related 102 to "Password to modify" provided by user. The result 103 sequence contains the hash and the algorithm-related 104 info. 105 106 @param aString 107 The string for which the info should be generated 108 109 @return 110 The sequence containing the hash and the algorithm-related info 111 */ 112 113 static css::uno::Sequence< css::beans::PropertyValue > 114 GenerateNewModifyPasswordInfo( std::u16string_view aPassword ); 115 116 /** This helper function converts a grab-bagged password, e.g. the 117 trackChanges password which has no complete inner equivalent to 118 the inner format. The result sequence contains the hash and the 119 algorithm-related info to use e.g. in IsModifyPasswordCorrect(). 120 121 @param aInfo 122 The sequence containing the hash and the algorithm-related info 123 according to the OOXML origin, used by grab-bagging. 124 125 @return 126 The sequence containing the hash and the algorithm-related info 127 in the inner format. 128 */ 129 130 static css::uno::Sequence< css::beans::PropertyValue > ConvertPasswordInfo( 131 const css::uno::Sequence< css::beans::PropertyValue >& aInfo ); 132 133 static css::uno::Sequence<css::beans::PropertyValue> 134 GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassword); 135 136 /** This helper function allows to check whether 137 the "Password to modify" provided by user is the correct one. 138 139 @param aString 140 The string containing the provided password 141 142 @param aInfo 143 The sequence containing the hash and the algorithm-info 144 145 @return 146 <TRUE/> if the password is correct one 147 <FALSE/> otherwise 148 */ 149 150 static bool IsModifyPasswordCorrect( 151 std::u16string_view aPassword, 152 const css::uno::Sequence< css::beans::PropertyValue >& aInfo ); 153 154 155 /** This helper function generates the hash code based on the algorithm 156 specified by MS for "Password to modify" feature of Word. 157 158 @param aString 159 The string for which the hash should be calculated 160 161 @return 162 The hash represented by sal_uInt32 163 */ 164 165 static sal_uInt32 GetWordHashAsUINT32( std::u16string_view aString ); 166 167 168 /** This helper function generates the hash code based on the algorithm 169 specified by MS for "Password to modify" and passwords related to 170 table protection of Excel. 171 172 @param aString 173 The string for which the hash should be calculated 174 175 @param nEnc 176 The encoding that should be used to generate the 8-bit string 177 before the hash is generated 178 179 @return 180 The hash represented by sal_uInt16 181 */ 182 183 static sal_uInt16 GetXLHashAsUINT16( 184 std::u16string_view aString, 185 rtl_TextEncoding nEnc = RTL_TEXTENCODING_UTF8 ); 186 187 188 /** This helper function generates the hash code based on the algorithm 189 specified by MS for "Password to modify" and passwords related to 190 table protection. 191 192 @param aString 193 The string for which the hash should be calculated 194 195 @return 196 The hash represented by sequence of bytes in BigEndian form 197 */ 198 199 static css::uno::Sequence< sal_Int8 > GetXLHashAsSequence( 200 std::u16string_view aString ); 201 202 203 /** Convenience function to calculate a salted hash with iterations as 204 specified in https://msdn.microsoft.com/en-us/library/dd920692 for the 205 OOXML sheetProtection and fileSharing elements, or 206 https://msdn.microsoft.com/en-us/library/dd924776 and 207 https://msdn.microsoft.com/en-us/library/dd925430 for Standard and 208 Agile Encryption. 209 210 @param rPassword 211 UTF-16 encoded string without leading BOM character 212 213 @param rSaltValue 214 Base64 encoded salt that will be decoded and prepended to password 215 data. 216 217 @param nSpinCount 218 If >0 the number of repeated iterations. 219 220 @param eIterCount 221 If Hash::IterCount::APPEND, append iteration count as per 222 https://msdn.microsoft.com/en-us/library/dd920692 223 If Hash::IterCount::PREPEND, prepend iteration count as per 224 https://msdn.microsoft.com/en-us/library/dd924776 and 225 https://msdn.microsoft.com/en-us/library/dd925430 226 If Hash::IterCount::NONE, do not add the iteration count to hash 227 iterations. 228 229 @param rAlgorithmName 230 One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in 231 https://msdn.microsoft.com/en-us/library/dd920692 232 or "SHA512", "SHA256", ... as listed for HashAlgorithm in 233 https://msdn.microsoft.com/en-us/library/dd925810 234 that have a valid match in comphelper::HashType. If not, an 235 empty sequence is returned. Not all algorithm names are 236 supported. 237 238 @return the raw hash value as sal_Int8 sequence. 239 */ 240 static css::uno::Sequence<sal_Int8> GetOoxHashAsSequence( 241 std::u16string_view rPassword, 242 std::u16string_view rSaltValue, 243 sal_uInt32 nSpinCount, 244 comphelper::Hash::IterCount eIterCount, 245 std::u16string_view rAlgorithmName); 246 247 248 /** Convenience function to calculate a salted hash with iterations as 249 specified in https://msdn.microsoft.com/en-us/library/dd920692 for the 250 OOXML sheetProtection and fileSharing elements, or 251 https://msdn.microsoft.com/en-us/library/dd924776 and 252 https://msdn.microsoft.com/en-us/library/dd925430 for Standard and 253 Agile Encryption. 254 255 @param rPassword 256 UTF-16 encoded string without leading BOM character 257 258 @param rSaltValue 259 Base64 encoded salt that will be decoded and prepended to password 260 data. 261 262 @param nSpinCount 263 If >0 the number of repeated iterations. 264 265 @param eIterCount 266 If Hash::IterCount::APPEND, append iteration count as per 267 https://msdn.microsoft.com/en-us/library/dd920692 268 If Hash::IterCount::PREPEND, prepend iteration count as per 269 https://msdn.microsoft.com/en-us/library/dd924776 and 270 https://msdn.microsoft.com/en-us/library/dd925430 271 If Hash::IterCount::NONE, do not add the iteration count to hash 272 iterations. 273 274 @param rAlgorithmName 275 One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in 276 https://msdn.microsoft.com/en-us/library/dd920692 277 or "SHA512", "SHA256", ... as listed for HashAlgorithm in 278 https://msdn.microsoft.com/en-us/library/dd925810 279 that have a valid match in comphelper::HashType. If not, an 280 empty sequence is returned. Not all algorithm names are 281 supported. 282 283 @return the base64 encoded string of the hash value, that can be 284 compared against a stored base64 encoded hash value. 285 */ 286 static OUString GetOoxHashAsBase64( 287 std::u16string_view rPassword, 288 std::u16string_view rSaltValue, 289 sal_uInt32 nSpinCount, 290 comphelper::Hash::IterCount eIterCount, 291 std::u16string_view rAlgorithmName); 292 293 294 /** Convenience function to calculate a salted hash with iterations as 295 specified in https://msdn.microsoft.com/en-us/library/dd920692 for the 296 OOXML sheetProtection and fileSharing elements, or 297 https://msdn.microsoft.com/en-us/library/dd924776 and 298 https://msdn.microsoft.com/en-us/library/dd925430 for Standard and 299 Agile Encryption. 300 301 @param rPassword 302 UTF-16 encoded string without leading BOM character 303 304 @param rSaltValue 305 A raw salt that will be prepended to password data. 306 307 @param nSpinCount 308 If >0 the number of repeated iterations. 309 310 @param eIterCount 311 If Hash::IterCount::APPEND, append iteration count as per 312 https://msdn.microsoft.com/en-us/library/dd920692 313 If Hash::IterCount::PREPEND, prepend iteration count as per 314 https://msdn.microsoft.com/en-us/library/dd924776 and 315 https://msdn.microsoft.com/en-us/library/dd925430 316 If Hash::IterCount::NONE, do not add the iteration count to hash 317 iterations. 318 319 @param rAlgorithmName 320 One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in 321 https://msdn.microsoft.com/en-us/library/dd920692 322 or "SHA512", "SHA256", ... as listed for HashAlgorithm in 323 https://msdn.microsoft.com/en-us/library/dd925810 324 that have a valid match in comphelper::HashType. If not, an 325 empty sequence is returned. Not all algorithm names are 326 supported. 327 328 @return the raw the hash value. 329 */ 330 static std::vector<unsigned char> GetOoxHashAsVector( 331 std::u16string_view rPassword, 332 const std::vector<unsigned char>& rSaltValue, 333 sal_uInt32 nSpinCount, 334 comphelper::Hash::IterCount eIterCount, 335 std::u16string_view rAlgorithmName); 336 337 338 /** This helper function generates a random sequence of bytes of 339 requested length. 340 */ 341 342 static css::uno::Sequence< sal_Int8 > GenerateRandomByteSequence( 343 sal_Int32 nLength ); 344 345 346 /** This helper function generates a byte sequence representing the 347 key digest value used by MSCodec_Std97 codec. 348 */ 349 350 static css::uno::Sequence< sal_Int8 > GenerateStd97Key( 351 std::u16string_view aPassword, 352 const css::uno::Sequence< sal_Int8 >& aDocId ); 353 354 355 /** This helper function generates a byte sequence representing the 356 key digest value used by MSCodec_Std97 codec. 357 */ 358 359 static css::uno::Sequence< sal_Int8 > GenerateStd97Key( 360 const sal_uInt16 pPassData[16], 361 const css::uno::Sequence< sal_Int8 >& aDocId ); 362 363 /** This helper function generates a byte sequence representing the 364 key digest value used by MSCodec_Std97 codec. 365 */ 366 367 static css::uno::Sequence< sal_Int8 > GenerateStd97Key( 368 const sal_uInt16 pPassData[16], 369 const sal_uInt8 pDocId[16] ); 370 371 372 /** This helper function tries to request and verify a password to load a 373 protected document. 374 375 First, the list of default passwords will be tried if provided. This is 376 needed by import filters for external file formats that have to check a 377 predefined password in some cases without asking the user for a 378 password. Every password is checked using the passed password verifier. 379 380 If not successful, the passed password of a medium is tried, that has 381 been set e.g. by an API call to load a document. If existing, the 382 password is checked using the passed password verifier. 383 384 If still not successful, the passed interaction handler is used to 385 request a password from the user. This will be repeated until the 386 passed password verifier validates the entered password, or if the user 387 chooses to cancel password input. 388 389 @param rVerifier 390 The password verifier used to check every processed password. 391 392 @param rMediaPassword 393 If not empty, will be passed to the password validator before 394 requesting a password from the user. This password usually should 395 be queried from a media descriptor. 396 397 @param rxInteractHandler 398 The interaction handler that will be used to request a password 399 from the user, e.g. by showing a password input dialog. 400 401 @param rDocumentUrl 402 The URL of the related document that will be shown in the password 403 input dialog. 404 405 @param eRequestType 406 The password request type that will be passed to the 407 DocPasswordRequest object created internally. See 408 docpasswordrequest.hxx for more details. 409 410 @param pDefaultPasswords 411 If not null, contains default passwords that will be tried before a 412 password will be requested from the media descriptor or the user. 413 414 @param pbIsDefaultPassword 415 (output parameter) If not null, the type of the found password will 416 be returned. True means the password has been found in the passed 417 list of default passwords. False means the password has been taken 418 from the rMediaPassword parameter or has been entered by the user. 419 420 @return 421 If not empty, contains the password that has been validated by the 422 passed password verifier. If empty, no valid password has been 423 found, or the user has chosen to cancel password input. 424 */ 425 static css::uno::Sequence< css::beans::NamedValue > requestAndVerifyDocPassword( 426 IDocPasswordVerifier& rVerifier, 427 const css::uno::Sequence< css::beans::NamedValue >& rMediaEncData, 428 const OUString& rMediaPassword, 429 const css::uno::Reference< css::task::XInteractionHandler >& rxInteractHandler, 430 const OUString& rDocumentUrl, 431 DocPasswordRequestType eRequestType, 432 const ::std::vector< OUString >* pDefaultPasswords = nullptr, 433 bool* pbIsDefaultPassword = nullptr ); 434 435 static css::uno::Sequence< css::beans::NamedValue > decryptGpgSession( 436 const css::uno::Sequence< css::uno::Sequence< css::beans::NamedValue > >& rGpgProperties); 437 438 private: 439 ~DocPasswordHelper(); 440 }; 441 442 443 } // namespace comphelper 444 445 #endif 446 447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 448
