1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_COMPHELPER_DOCPASSWORDHELPER_HXX
21 #define INCLUDED_COMPHELPER_DOCPASSWORDHELPER_HXX
23 #include <comphelper/comphelperdllapi.h>
24 #include <string_view>
26 #include <comphelper/docpasswordrequest.hxx>
27 #include <comphelper/hash.hxx>
29 namespace com::sun::star::task
{ class XInteractionHandler
; }
30 namespace com::sun::star::beans
{ struct PropertyValue
; }
31 namespace com::sun::star::beans
{ struct NamedValue
; }
33 namespace comphelper
{
35 enum class DocPasswordVerifierResult
43 /** Base class for a password verifier used by the DocPasswordHelper class
46 Users have to implement the virtual functions and pass an instance of the
47 verifier to one of the password request functions.
49 class COMPHELPER_DLLPUBLIC IDocPasswordVerifier
52 virtual ~IDocPasswordVerifier();
54 /** Will be called every time a password needs to be verified.
57 The password to be verified
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
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
73 virtual DocPasswordVerifierResult
verifyPassword( const OUString
& rPassword
, css::uno::Sequence
< css::beans::NamedValue
>& o_rEncryptionData
) = 0;
75 /** Will be called every time an encryption data needs to be verified.
77 @param rEncryptionData
78 The data will be validated
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
85 - DocPasswordVerifierResult_ABORT, if an unrecoverable error
86 occurred while data verification. The password request loop
89 virtual DocPasswordVerifierResult
verifyEncryptionData( const css::uno::Sequence
< css::beans::NamedValue
>& o_rEncryptionData
) = 0;
94 /** Helper that asks for a document password and checks its validity.
96 class COMPHELPER_DLLPUBLIC DocPasswordHelper
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
107 The string for which the info should be generated
110 The sequence containing the hash and the algorithm-related info
113 static css::uno::Sequence
< css::beans::PropertyValue
>
114 GenerateNewModifyPasswordInfo( std::u16string_view aPassword
);
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().
122 The sequence containing the hash and the algorithm-related info
123 according to the OOXML origin, used by grab-bagging.
126 The sequence containing the hash and the algorithm-related info
130 static css::uno::Sequence
< css::beans::PropertyValue
> ConvertPasswordInfo(
131 const css::uno::Sequence
< css::beans::PropertyValue
>& aInfo
);
133 static css::uno::Sequence
<css::beans::PropertyValue
>
134 GenerateNewModifyPasswordInfoOOXML(std::u16string_view aPassword
);
136 /** This helper function allows to check whether
137 the "Password to modify" provided by user is the correct one.
140 The string containing the provided password
143 The sequence containing the hash and the algorithm-info
146 <TRUE/> if the password is correct one
150 static bool IsModifyPasswordCorrect(
151 std::u16string_view aPassword
,
152 const css::uno::Sequence
< css::beans::PropertyValue
>& aInfo
);
155 /** This helper function generates the hash code based on the algorithm
156 specified by MS for "Password to modify" feature of Word.
159 The string for which the hash should be calculated
162 The hash represented by sal_uInt32
165 static sal_uInt32
GetWordHashAsUINT32( std::u16string_view aString
);
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.
173 The string for which the hash should be calculated
176 The encoding that should be used to generate the 8-bit string
177 before the hash is generated
180 The hash represented by sal_uInt16
183 static sal_uInt16
GetXLHashAsUINT16(
184 std::u16string_view aString
,
185 rtl_TextEncoding nEnc
= RTL_TEXTENCODING_UTF8
);
188 /** This helper function generates the hash code based on the algorithm
189 specified by MS for "Password to modify" and passwords related to
193 The string for which the hash should be calculated
196 The hash represented by sequence of bytes in BigEndian form
199 static css::uno::Sequence
< sal_Int8
> GetXLHashAsSequence(
200 std::u16string_view aString
);
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
211 UTF-16 encoded string without leading BOM character
214 Base64 encoded salt that will be decoded and prepended to password
218 If >0 the number of repeated iterations.
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
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
238 @return the raw hash value as sal_Int8 sequence.
240 static css::uno::Sequence
<sal_Int8
> GetOoxHashAsSequence(
241 const OUString
& rPassword
,
242 std::u16string_view rSaltValue
,
243 sal_uInt32 nSpinCount
,
244 comphelper::Hash::IterCount eIterCount
,
245 std::u16string_view rAlgorithmName
);
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
256 UTF-16 encoded string without leading BOM character
259 Base64 encoded salt that will be decoded and prepended to password
263 If >0 the number of repeated iterations.
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
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
283 @return the base64 encoded string of the hash value, that can be
284 compared against a stored base64 encoded hash value.
286 static OUString
GetOoxHashAsBase64(
287 const OUString
& rPassword
,
288 std::u16string_view rSaltValue
,
289 sal_uInt32 nSpinCount
,
290 comphelper::Hash::IterCount eIterCount
,
291 std::u16string_view rAlgorithmName
);
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
302 UTF-16 encoded string without leading BOM character
305 A raw salt that will be prepended to password data.
308 If >0 the number of repeated iterations.
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
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
328 @return the raw the hash value.
330 static std::vector
<unsigned char> GetOoxHashAsVector(
331 const OUString
& rPassword
,
332 const std::vector
<unsigned char>& rSaltValue
,
333 sal_uInt32 nSpinCount
,
334 comphelper::Hash::IterCount eIterCount
,
335 std::u16string_view rAlgorithmName
);
338 /** This helper function generates a random sequence of bytes of
342 static css::uno::Sequence
< sal_Int8
> GenerateRandomByteSequence(
346 /** This helper function generates a byte sequence representing the
347 key digest value used by MSCodec_Std97 codec.
350 static css::uno::Sequence
< sal_Int8
> GenerateStd97Key(
351 std::u16string_view aPassword
,
352 const css::uno::Sequence
< sal_Int8
>& aDocId
);
355 /** This helper function generates a byte sequence representing the
356 key digest value used by MSCodec_Std97 codec.
359 static css::uno::Sequence
< sal_Int8
> GenerateStd97Key(
360 const sal_uInt16 pPassData
[16],
361 const css::uno::Sequence
< sal_Int8
>& aDocId
);
363 /** This helper function generates a byte sequence representing the
364 key digest value used by MSCodec_Std97 codec.
367 static css::uno::Sequence
< sal_Int8
> GenerateStd97Key(
368 const sal_uInt16 pPassData
[16],
369 const sal_uInt8 pDocId
[16] );
372 /** This helper function tries to request and verify a password to load a
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.
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.
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.
390 The password verifier used to check every processed password.
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 querried from a media descriptor.
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.
402 The URL of the related document that will be shown in the password
406 The password request type that will be passed to the
407 DocPasswordRequest object created internally. See
408 docpasswordrequest.hxx for more details.
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.
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.
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.
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 );
435 static css::uno::Sequence
< css::beans::NamedValue
> decryptGpgSession(
436 const css::uno::Sequence
< css::uno::Sequence
< css::beans::NamedValue
> >& rGpgProperties
);
439 ~DocPasswordHelper();
443 } // namespace comphelper
447 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */