xref: /core/include/comphelper/docpasswordhelper.hxx (revision 234b42d44933f371f386340d6918111f15264c3a)
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