LibreOffice Module svl (master) 1
passwordcontainer.cxx
Go to the documentation of this file.
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#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <string_view>
24
25#include "passwordcontainer.hxx"
26
32#include <o3tl/string_view.hxx>
33#include <com/sun/star/beans/PropertyValue.hpp>
34#include <com/sun/star/task/InteractionHandler.hpp>
35#include <com/sun/star/task/MasterPasswordRequest.hpp>
36#include <com/sun/star/task/NoMasterException.hpp>
37#include <com/sun/star/lang/XMultiServiceFactory.hpp>
38
39#include <osl/diagnose.h>
40#include <rtl/character.hxx>
41#include <rtl/cipher.h>
42#include <rtl/digest.h>
43#include <rtl/byteseq.hxx>
44#include <rtl/ustrbuf.hxx>
45
46using namespace osl;
47using namespace utl;
48using namespace com::sun::star;
49using namespace com::sun::star::uno;
50using namespace com::sun::star::registry;
51using namespace com::sun::star::lang;
52using namespace com::sun::star::task;
53using namespace com::sun::star::ucb;
54
55static OUString createIndex(const std::vector< OUString >& lines)
56{
57 OUStringBuffer aResult;
58
59 for( size_t i = 0; i < lines.size(); i++ )
60 {
61 if( i )
62 aResult.append("__");
63 OString line = OUStringToOString( lines[i], RTL_TEXTENCODING_UTF8 );
64 const char* pLine = line.getStr();
65
66 while( *pLine )
67 {
68 if (rtl::isAsciiAlphanumeric(static_cast<unsigned char>(*pLine)))
69 {
70 aResult.append(*pLine);
71 }
72 else
73 {
74 aResult.append("_" + OUString::number(*pLine, 16) );
75 }
76
77 pLine++;
78 }
79 }
80
81 return aResult.makeStringAndClear();
82}
83
84
85static std::vector< OUString > getInfoFromInd( std::u16string_view aInd )
86{
87 std::vector< OUString > aResult;
88 bool aStart = true;
89
90 OString line = OUStringToOString( aInd, RTL_TEXTENCODING_ASCII_US );
91 const char* pLine = line.getStr();
92 do
93 {
94 OUStringBuffer newItem;
95 if( !aStart )
96 pLine += 2;
97 else
98 aStart = false;
99
100 while( *pLine && ( pLine[0] != '_' || pLine[1] != '_' ))
101 if( *pLine != '_' )
102 {
103 newItem.append( *pLine );
104 pLine++;
105 }
106 else
107 {
108 OUString aNum;
109 for( int i = 1; i < 3; i++ )
110 {
111 if( !pLine[i]
112 || ( ( pLine[i] < '0' || pLine[i] > '9' )
113 && ( pLine[i] < 'a' || pLine[i] > 'f' )
114 && ( pLine[i] < 'A' || pLine[i] > 'F' ) ) )
115 {
116 OSL_FAIL( "Wrong index syntax!" );
117 return aResult;
118 }
119
120 aNum += OUStringChar( pLine[i] );
121 }
122
123 newItem.append( sal_Unicode( aNum.toUInt32( 16 ) ) );
124 pLine += 3;
125 }
126
127 aResult.push_back( newItem.makeStringAndClear() );
128 } while( pLine[0] == '_' && pLine[1] == '_' );
129
130 if( *pLine )
131 OSL_FAIL( "Wrong index syntax!" );
132
133 return aResult;
134}
135
136
137static bool shorterUrl( OUString& aURL )
138{
139 sal_Int32 aInd = aURL.lastIndexOf( '/' );
140 if( aInd > 0 && aURL.indexOf( "://" ) != aInd-2 )
141 {
142 aURL = aURL.copy( 0, aInd );
143 return true;
144 }
145
146 return false;
147}
148
149
150static OUString getAsciiLine( const ::rtl::ByteSequence& buf )
151{
152 OUString aResult;
153
154 ::rtl::ByteSequence outbuf( buf.getLength()*2+1 );
155
156 for( int ind = 0; ind < buf.getLength(); ind++ )
157 {
158 outbuf[ind*2] = ( static_cast<sal_uInt8>(buf[ind]) >> 4 ) + 'a';
159 outbuf[ind*2+1] = ( static_cast<sal_uInt8>(buf[ind]) & 0x0f ) + 'a';
160 }
161 outbuf[buf.getLength()*2] = '\0';
162
163 aResult = OUString::createFromAscii( reinterpret_cast<char*>(outbuf.getArray()) );
164
165 return aResult;
166}
167
168
169static ::rtl::ByteSequence getBufFromAsciiLine( std::u16string_view line )
170{
171 OSL_ENSURE( line.size() % 2 == 0, "Wrong syntax!" );
172 OString tmpLine = OUStringToOString( line, RTL_TEXTENCODING_ASCII_US );
173 ::rtl::ByteSequence aResult(line.size()/2);
174
175 for( int ind = 0; ind < tmpLine.getLength()/2; ind++ )
176 {
177 aResult[ind] = ( static_cast<sal_uInt8>( tmpLine[ind*2] - 'a' ) << 4 ) | static_cast<sal_uInt8>( tmpLine[ind*2+1] - 'a' );
178 }
179
180 return aResult;
181}
182
183
185{
186 PasswordMap aResult;
187
188 const Sequence< OUString > aNodeNames = ConfigItem::GetNodeNames( "Store" );
189 sal_Int32 aNodeCount = aNodeNames.getLength();
190 Sequence< OUString > aPropNames( aNodeCount * 2);
191
192 std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.getArray(),
193 [](const OUString& rName) -> OUString {
194 return "Store/Passwordstorage['" + rName + "']/Password"; });
195 std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.getArray() + aNodeCount,
196 [](const OUString& rName) -> OUString {
197 return "Store/Passwordstorage['" + rName + "']/InitializationVector"; });
198
199 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames );
200
201 if( aPropertyValues.getLength() != aNodeCount * 2)
202 {
203 OSL_FAIL( "Problems during reading" );
204 return aResult;
205 }
206
207 for( sal_Int32 aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd )
208 {
209 std::vector< OUString > aUrlUsr = getInfoFromInd( aNodeNames[aNodeInd] );
210
211 if( aUrlUsr.size() == 2 )
212 {
213 OUString aUrl = aUrlUsr[0];
214 OUString aName = aUrlUsr[1];
215
216 OUString aEPasswd;
217 OUString aIV;
218 aPropertyValues[aNodeInd] >>= aEPasswd;
219 aPropertyValues[aNodeInd + aNodeCount] >>= aIV;
220
221 PasswordMap::iterator aIter = aResult.find( aUrl );
222 if( aIter != aResult.end() )
223 aIter->second.emplace_back( aName, aEPasswd, aIV );
224 else
225 {
226 NamePasswordRecord aNewRecord( aName, aEPasswd, aIV );
227 std::vector< NamePasswordRecord > listToAdd( 1, aNewRecord );
228
229 aResult.insert( PairUrlRecord( aUrl, listToAdd ) );
230 }
231 }
232 else
233 OSL_FAIL( "Wrong index syntax!" );
234 }
235
236 return aResult;
237}
238
239
241{
242 ConfigItem::SetModified();
243 ConfigItem::PutProperties( { "UseStorage" }, { uno::Any(bUse) } );
244}
245
246
248{
249 Sequence<OUString> aNodeNames { "UseStorage" };
250
251 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
252
253 if( aPropertyValues.getLength() != aNodeNames.getLength() )
254 {
255 OSL_FAIL( "Problems during reading" );
256 return false;
257 }
258
259 bool aResult = false;
260 aPropertyValues[0] >>= aResult;
261
262 return aResult;
263}
264
265
267{
268 Sequence<OUString> aNodeNames { "StorageVersion" };
269
270 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
271
272 if( aPropertyValues.getLength() != aNodeNames.getLength() )
273 {
274 OSL_FAIL( "Problems during reading" );
275 return 0;
276 }
277
278 sal_Int32 nResult = 0;
279 aPropertyValues[0] >>= nResult;
280
281 return nResult;
282}
283
284bool StorageItem::getEncodedMasterPassword( OUString& aResult, OUString& aResultIV )
285{
286 if( hasEncoded )
287 {
288 aResult = mEncoded;
289 aResultIV = mEncodedIV;
290 return true;
291 }
292
293 Sequence< OUString > aNodeNames{ "HasMaster", "Master", "MasterInitializationVector" };
294
295 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
296
297 if( aPropertyValues.getLength() != aNodeNames.getLength() )
298 {
299 OSL_FAIL( "Problems during reading" );
300 return false;
301 }
302
306
307 aResult = mEncoded;
308 aResultIV = mEncodedIV;
309
310 return hasEncoded;
311}
312
313
314void StorageItem::setEncodedMasterPassword( const OUString& aEncoded, const OUString& aEncodedIV, bool bAcceptEmpty )
315{
316 bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty );
317
318 ConfigItem::SetModified();
319 ConfigItem::PutProperties( { "HasMaster", "Master", "MasterInitializationVector", "StorageVersion" },
320 { uno::Any(bHasMaster), uno::Any(aEncoded),
321 uno::Any(aEncodedIV), uno::Any(nCurrentStorageVersion) } );
322
323 hasEncoded = bHasMaster;
324 mEncoded = aEncoded;
325 mEncodedIV = aEncodedIV;
326}
327
328
329void StorageItem::remove( const OUString& aURL, const OUString& aName )
330{
331 Sequence< OUString > sendSeq { createIndex( { aURL, aName } ) };
332
333 ConfigItem::ClearNodeElements( "Store", sendSeq );
334}
335
336
338{
339 ConfigItem::ClearNodeSet( "Store" );
340}
341
342
343void StorageItem::update( const OUString& aURL, const NamePasswordRecord& aRecord )
344{
345 if ( !aRecord.HasPasswords( PERSISTENT_RECORD ) )
346 {
347 OSL_FAIL( "Unexpected storing of a record!" );
348 return;
349 }
350
352 "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/InitializationVector",
354 "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() } ) + "']/Password",
355 aRecord.GetPersistentPasswords()) };
356
357 ConfigItem::SetModified();
358 ConfigItem::SetSetProperties( "Store", sendSeq );
359}
360
361
363{
364 // this feature still should not be used
365 if( mainCont )
366 mainCont->Notify();
367}
368
369
371{
372 // Do nothing, we stored everything we want already
373}
374
375
377{
378 // m_pStorageFile->Notify() can be called
379 std::unique_lock aGuard( mMutex );
380
381 mComponent.set( rxContext->getServiceManager(), UNO_QUERY );
382 mComponent->addEventListener( this );
383
384 m_xStorageFile.emplace( this, "Office.Common/Passwords" );
385 if( m_xStorageFile->useStorage() )
386 m_aContainer = m_xStorageFile->getInfo();
387}
388
389
391{
392 std::unique_lock aGuard( mMutex );
393
394 m_xStorageFile.reset();
395
396 if( mComponent.is() )
397 {
398 mComponent->removeEventListener(this);
399 mComponent.clear();
400 }
401}
402
403void SAL_CALL PasswordContainer::disposing( const EventObject& )
404{
405 std::unique_lock aGuard( mMutex );
406
407 m_xStorageFile.reset();
408
409 if( mComponent.is() )
410 {
411 //mComponent->removeEventListener(this);
412 mComponent.clear();
413 }
414}
415
416std::vector< OUString > PasswordContainer::DecodePasswords( std::u16string_view aLine, std::u16string_view aIV, std::u16string_view aMasterPasswd, css::task::PasswordRequestMode mode )
417{
418 if( !aMasterPasswd.empty() )
419 {
420 rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
421 OSL_ENSURE( aDecoder, "Can't create decoder" );
422
423 if( aDecoder )
424 {
425 OSL_ENSURE( aMasterPasswd.size() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!" );
426
427 unsigned char code[RTL_DIGEST_LENGTH_MD5];
428 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
429 code[ ind ] = static_cast<char>(o3tl::toUInt32(aMasterPasswd.substr( ind*2, 2 ), 16));
430
431 unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0};
432 if (!aIV.empty())
433 {
434 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
435 {
436 auto tmp = aIV.substr( ind*2, 2 );
437 iv[ ind ] = static_cast<char>(rtl_ustr_toInt64_WithLength(tmp.data(), 16, tmp.size()));
438 }
439 }
440
441 rtlCipherError result = rtl_cipher_init (
442 aDecoder, rtl_Cipher_DirectionDecode,
443 code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 );
444
445 if( result == rtl_Cipher_E_None )
446 {
447 ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine );
448
449 ::rtl::ByteSequence resSeq( aSeq.getLength() );
450
451 rtl_cipher_decode ( aDecoder, aSeq.getArray(), aSeq.getLength(),
452 reinterpret_cast<sal_uInt8*>(resSeq.getArray()), resSeq.getLength() );
453
454 OUString aPasswd( reinterpret_cast<char*>(resSeq.getArray()), resSeq.getLength(), RTL_TEXTENCODING_UTF8 );
455
456 rtl_cipher_destroy (aDecoder);
457
458 return getInfoFromInd( aPasswd );
459 }
460
461 rtl_cipher_destroy (aDecoder);
462 }
463 }
464 else
465 {
466 OSL_FAIL( "No master password provided!" );
467 // throw special exception
468 }
469
470 // problems with decoding
471 OSL_FAIL( "Problem with decoding" );
472 throw css::task::NoMasterException(
473 "Can't decode!", css::uno::Reference<css::uno::XInterface>(), mode);
474}
475
476OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, std::u16string_view aIV, std::u16string_view aMasterPasswd)
477{
478 if( !aMasterPasswd.empty() )
479 {
480 OString aSeq = OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 );
481
482 rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
483 OSL_ENSURE( aEncoder, "Can't create encoder" );
484
485 if( aEncoder )
486 {
487 OSL_ENSURE( aMasterPasswd.size() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!" );
488
489 unsigned char code[RTL_DIGEST_LENGTH_MD5];
490 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
491 code[ ind ] = static_cast<char>(o3tl::toUInt32(aMasterPasswd.substr( ind*2, 2 ), 16));
492
493 unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0};
494 if (!aIV.empty())
495 {
496 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
497 {
498 auto tmp = aIV.substr( ind*2, 2 );
499 iv[ ind ] = static_cast<char>(rtl_ustr_toInt64_WithLength(tmp.data(), 16, tmp.size()));
500 }
501 }
502
503 rtlCipherError result = rtl_cipher_init (
504 aEncoder, rtl_Cipher_DirectionEncode,
505 code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 );
506
507 if( result == rtl_Cipher_E_None )
508 {
509 ::rtl::ByteSequence resSeq(aSeq.getLength()+1);
510
511 result = rtl_cipher_encode ( aEncoder, aSeq.getStr(), aSeq.getLength()+1,
512 reinterpret_cast<sal_uInt8*>(resSeq.getArray()), resSeq.getLength() );
513
514/*
515 //test
516 rtlCipherError result = rtl_cipher_init (
517 aEncoder, rtl_Cipher_DirectionDecode,
518 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
519
520
521 if( result == rtl_Cipher_E_None )
522 {
523 OUString testOU = getAsciiLine( resSeq );
524 ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU );
525
526 ::rtl::ByteSequence resSeq1( aSeq1.getLength() );
527
528 if( resSeq.getLength() == aSeq1.getLength() )
529 {
530 for( int ind = 0; ind < aSeq1.getLength(); ind++ )
531 if( resSeq[ind] != aSeq1[ind] )
532 testOU = "";
533 }
534
535 result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(),
536 (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() );
537
538 OUString aPasswd( ( char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 );
539 }
540*/
541
542 rtl_cipher_destroy (aEncoder);
543
544 if( result == rtl_Cipher_E_None )
545 return getAsciiLine( resSeq );
546
547 }
548
549 rtl_cipher_destroy (aEncoder);
550 }
551 }
552 else
553 {
554 OSL_FAIL( "No master password provided!" );
555 // throw special exception
556 }
557
558 // problems with encoding
559 OSL_FAIL( "Problem with encoding" );
560 throw RuntimeException("Can't encode!" );
561}
562
563void PasswordContainer::UpdateVector( const OUString& aURL, std::vector< NamePasswordRecord >& toUpdate, NamePasswordRecord const & aRecord, bool writeFile )
564{
565 for (auto & aNPIter : toUpdate)
566 if( aNPIter.GetUserName() == aRecord.GetUserName() )
567 {
568 if( aRecord.HasPasswords( MEMORY_RECORD ) )
569 aNPIter.SetMemoryPasswords( aRecord.GetMemoryPasswords() );
570
571 if( aRecord.HasPasswords( PERSISTENT_RECORD ) )
572 {
573 aNPIter.SetPersistentPasswords( aRecord.GetPersistentPasswords(), aRecord.GetPersistentIV() );
574
575 if( writeFile )
576 {
577 // the password must be already encoded
578 m_xStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile
579 }
580 }
581
582 return;
583 }
584
585
586 if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile )
587 {
588 // the password must be already encoded
589 m_xStorageFile->update( aURL, aRecord ); // add new aName to the existing url
590 }
591
592 toUpdate.insert( toUpdate.begin(), aRecord );
593}
594
595
596UserRecord PasswordContainer::CopyToUserRecord( const NamePasswordRecord& aRecord, bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler )
597{
598 ::std::vector< OUString > aPasswords;
599 if( aRecord.HasPasswords( MEMORY_RECORD ) )
600 aPasswords = aRecord.GetMemoryPasswords();
601
602 if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) )
603 {
604 try
605 {
606 ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersistentPasswords(), aRecord.GetPersistentIV(),
607 GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER );
608 aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() );
609 }
610 catch( NoMasterException& )
611 {
612 // if master password could not be detected the entry will be just ignored
613 io_bTryToDecode = false;
614 }
615 }
616
617 return UserRecord( aRecord.GetUserName(), comphelper::containerToSequence( aPasswords ) );
618}
619
620
621Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const std::vector< NamePasswordRecord >& original, const Reference< XInteractionHandler >& aHandler )
622{
623 Sequence< UserRecord > aResult( original.size() );
624 auto aResultRange = asNonConstRange(aResult);
625 sal_uInt32 nInd = 0;
626 bool bTryToDecode = true;
627
628 for (auto const& aNPIter : original)
629 {
630 aResultRange[nInd] = CopyToUserRecord( aNPIter, bTryToDecode, aHandler );
631 ++nInd;
632 }
633
634 return aResult;
635}
636
637
638void SAL_CALL PasswordContainer::add( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, const Reference< XInteractionHandler >& aHandler )
639{
640 std::unique_lock aGuard( mMutex );
641
642 PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler );
643}
644
645
646void SAL_CALL PasswordContainer::addPersistent( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, const Reference< XInteractionHandler >& aHandler )
647{
648 std::unique_lock aGuard( mMutex );
649
650 PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler );
651}
652
654{
655 rtlRandomPool randomPool = mRandomPool.get();
656 unsigned char iv[RTL_DIGEST_LENGTH_MD5];
657 rtl_random_getBytes(randomPool, iv, RTL_DIGEST_LENGTH_MD5);
658 OUStringBuffer aBuffer;
659 for (sal_uInt8 i : iv)
660 {
661 aBuffer.append(OUString::number(i >> 4, 16) + OUString::number(i & 15, 16));
662 }
663 return aBuffer.makeStringAndClear();
664}
665
666void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler )
667{
668 NamePasswordRecord aRecord( UserName );
669 ::std::vector< OUString > aStorePass = comphelper::sequenceToContainer< std::vector<OUString> >( Passwords );
670
671 if( Mode == PERSISTENT_RECORD )
672 {
673 OUString sIV = createIV();
674 OUString sEncodedPasswords = EncodePasswords(aStorePass, sIV, GetMasterPassword(aHandler));
675 aRecord.SetPersistentPasswords(sEncodedPasswords, sIV);
676 }
677 else if( Mode == MEMORY_RECORD )
678 aRecord.SetMemoryPasswords( std::move(aStorePass) );
679 else
680 {
681 OSL_FAIL( "Unexpected persistence status!" );
682 return;
683 }
684
685 if( !m_aContainer.empty() )
686 {
687 PasswordMap::iterator aIter = m_aContainer.find( Url );
688
689 if( aIter != m_aContainer.end() )
690 {
691 UpdateVector( aIter->first, aIter->second, aRecord, true );
692 return;
693 }
694 }
695
696 std::vector< NamePasswordRecord > listToAdd( 1, aRecord );
697 m_aContainer.insert( PairUrlRecord( Url, listToAdd ) );
698
699 if( Mode == PERSISTENT_RECORD && m_xStorageFile && m_xStorageFile->useStorage() )
700 m_xStorageFile->update( Url, aRecord );
701
702}
703
704
705UrlRecord SAL_CALL PasswordContainer::find( const OUString& aURL, const Reference< XInteractionHandler >& aHandler )
706{
707 return find( aURL, u"", false, aHandler );
708}
709
710
711UrlRecord SAL_CALL PasswordContainer::findForName( const OUString& aURL, const OUString& aName, const Reference< XInteractionHandler >& aHandler )
712{
713 return find( aURL, aName, true, aHandler );
714}
715
716
717Sequence< UserRecord > PasswordContainer::FindUsr( const std::vector< NamePasswordRecord >& userlist, std::u16string_view aName, const Reference< XInteractionHandler >& aHandler )
718{
719 for (auto const& aNPIter : userlist)
720 {
721 if( aNPIter.GetUserName() == aName )
722 {
723 bool bTryToDecode = true;
724 Sequence< UserRecord > aResult { CopyToUserRecord( aNPIter, bTryToDecode, aHandler ) };
725
726 return aResult;
727 }
728 }
729
730 return Sequence< UserRecord >();
731}
732
733
735 const PasswordMap::iterator & rIter,
736 bool bName,
737 std::u16string_view aName,
738 const Reference< XInteractionHandler >& aHandler,
739 UrlRecord & rRec )
740{
741 if ( bName )
742 {
744 = FindUsr( rIter->second, aName, aHandler );
745 if( aUsrRec.hasElements() )
746 {
747 rRec = UrlRecord( rIter->first, aUsrRec );
748 return true;
749 }
750 }
751 else
752 {
753 rRec = UrlRecord(
754 rIter->first,
755 CopyToUserRecordSequence( rIter->second, aHandler ) );
756 return true;
757 }
758 return false;
759}
760
761
763 const OUString& aURL,
764 std::u16string_view aName,
765 bool bName, // only needed to support empty user names
766 const Reference< XInteractionHandler >& aHandler )
767{
768 std::unique_lock aGuard( mMutex );
769
770 if( !m_aContainer.empty() && !aURL.isEmpty() )
771 {
772 OUString aUrl( aURL );
773
774 // each iteration remove last '/...' section from the aUrl
775 // while it's possible, up to the most left '://'
776 do
777 {
778 // first look for <url>/somename and then look for <url>/somename/...
779 PasswordMap::iterator aIter = m_aContainer.find( aUrl );
780 if( aIter != m_aContainer.end() )
781 {
782 UrlRecord aRec;
783 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
784 return aRec;
785 }
786 else
787 {
788 OUString tmpUrl( aUrl );
789 if ( !tmpUrl.endsWith("/") )
790 tmpUrl += "/";
791
792 aIter = m_aContainer.lower_bound( tmpUrl );
793 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) )
794 {
795 UrlRecord aRec;
796 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
797 return aRec;
798 }
799 }
800 }
801 while( shorterUrl( aUrl ) && !aUrl.isEmpty() );
802 }
803
804 return UrlRecord();
805}
806
808{
809 OUStringBuffer aResult;
810 for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ )
811 aResult.append("aa");
812
813 return aResult.makeStringAndClear();
814}
815
816OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler )
817{
818 // empty string means that the call was cancelled or just failed
819 OUString aResult;
820
821 if ( xHandler.is() )
822 {
824
825 xHandler->handle( xRequest );
826
827 ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection();
828
829 if ( xSelection.is() )
830 {
831 Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY );
832 if ( !xAbort.is() )
833 {
834 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
835 = xRequest->getAuthenticationSupplier();
836
837 aResult = xSupp->getPassword();
838 }
839 }
840 }
841
842 return aResult;
843}
844
845// Mangle the key to match an old bug
846static OUString ReencodeAsOldHash(std::u16string_view rPass)
847{
848 OUStringBuffer aBuffer;
849 for (int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ++ind)
850 {
851 auto tmp = rPass.substr(ind * 2, 2);
852 unsigned char i = static_cast<char>(rtl_ustr_toInt64_WithLength(tmp.data(), 16, tmp.size()));
853 aBuffer.append(OUStringChar(static_cast< sal_Unicode >('a' + (i >> 4)))
854 + OUStringChar(static_cast< sal_Unicode >('a' + (i & 15))));
855 }
856 return aBuffer.makeStringAndClear();
857}
858
860{
861 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
862 if( !m_xStorageFile || !m_xStorageFile->useStorage() )
863 throw NoMasterException("Password storing is not active!", Reference< XInterface >(), aRMode );
864
865 if( m_aMasterPassword.isEmpty() && aHandler.is() )
866 {
867 OUString aEncodedMP, aEncodedMPIV;
868 bool bDefaultPassword = false;
869
870 if( !m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) )
871 aRMode = PasswordRequestMode_PASSWORD_CREATE;
872 else if ( aEncodedMP.isEmpty() )
873 {
875 bDefaultPassword = true;
876 }
877
878 if ( !bDefaultPassword )
879 {
880 bool bAskAgain = false;
881 do {
882 bAskAgain = false;
883
884 OUString aPass = RequestPasswordFromUser( aRMode, aHandler );
885 if ( !aPass.isEmpty() )
886 {
887 if( aRMode == PasswordRequestMode_PASSWORD_CREATE )
888 {
889 m_aMasterPassword = aPass;
890 std::vector< OUString > aMaster( 1, m_aMasterPassword );
891
892 OUString sIV = createIV();
893 m_xStorageFile->setEncodedMasterPassword(EncodePasswords(aMaster, sIV, m_aMasterPassword), sIV);
894 }
895 else
896 {
897 if (m_xStorageFile->getStorageVersion() == 0)
898 aPass = ReencodeAsOldHash(aPass);
899
900 std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aEncodedMPIV, aPass, aRMode ) );
901 if( aRM.empty() || aPass != aRM[0] )
902 {
903 bAskAgain = true;
904 aRMode = PasswordRequestMode_PASSWORD_REENTER;
905 }
906 else
907 m_aMasterPassword = aPass;
908 }
909 }
910
911 } while( bAskAgain );
912 }
913 }
914
915 if ( m_aMasterPassword.isEmpty() )
916 throw NoMasterException("No master password!", Reference< XInterface >(), aRMode );
917
918 return m_aMasterPassword;
919}
920
921
922void SAL_CALL PasswordContainer::remove( const OUString& aURL, const OUString& aName )
923{
924 std::unique_lock aGuard( mMutex );
925
926 OUString aUrl( aURL );
927 if( m_aContainer.empty() )
928 return;
929
930 PasswordMap::iterator aIter = m_aContainer.find( aUrl );
931
932 if( aIter == m_aContainer.end() )
933 {
934 if( aUrl.endsWith("/") )
935 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
936 else
937 aUrl += "/";
938
939 aIter = m_aContainer.find( aUrl );
940 }
941
942 if( aIter == m_aContainer.end() )
943 return;
944
945 auto aNPIter = std::find_if(aIter->second.begin(), aIter->second.end(),
946 [&aName](const NamePasswordRecord& rNPRecord) { return rNPRecord.GetUserName() == aName; });
947
948 if (aNPIter != aIter->second.end())
949 {
950 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_xStorageFile )
951 m_xStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
952
953 // the iterator will not be used any more so it can be removed directly
954 aIter->second.erase( aNPIter );
955
956 if( aIter->second.empty() )
957 m_aContainer.erase( aIter );
958 }
959}
960
961
962void SAL_CALL PasswordContainer::removePersistent( const OUString& aURL, const OUString& aName )
963{
964 std::unique_lock aGuard( mMutex );
965
966 OUString aUrl( aURL );
967 if( m_aContainer.empty() )
968 return;
969
970 PasswordMap::iterator aIter = m_aContainer.find( aUrl );
971
972 if( aIter == m_aContainer.end() )
973 {
974 if( aUrl.endsWith("/") )
975 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
976 else
977 aUrl += "/";
978
979 aIter = m_aContainer.find( aUrl );
980 }
981
982 if( aIter == m_aContainer.end() )
983 return;
984
985 auto aNPIter = std::find_if(aIter->second.begin(), aIter->second.end(),
986 [&aName](const NamePasswordRecord& rNPRecord) { return rNPRecord.GetUserName() == aName; });
987
988 if (aNPIter == aIter->second.end())
989 return;
990
991 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
992 {
993 // TODO/LATER: should the password be converted to MemoryPassword?
994 aNPIter->RemovePasswords( PERSISTENT_RECORD );
995
996 if ( m_xStorageFile )
997 m_xStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
998 }
999
1000 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1001 aIter->second.erase( aNPIter );
1002
1003 if( aIter->second.empty() )
1004 m_aContainer.erase( aIter );
1005}
1006
1008{
1009 std::unique_lock aGuard(mMutex);
1010 removeAllPersistent(aGuard);
1011}
1012
1013void PasswordContainer::removeAllPersistent(std::unique_lock<std::mutex>& /*rGuard*/)
1014{
1015 if( m_xStorageFile )
1016 m_xStorageFile->clear();
1017
1018 for( PasswordMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); )
1019 {
1020 for( std::vector< NamePasswordRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1021 {
1022 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1023 {
1024 // TODO/LATER: should the password be converted to MemoryPassword?
1025 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1026
1027 if ( m_xStorageFile )
1028 m_xStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1029 }
1030
1031 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1032 {
1033 aNPIter = aIter->second.erase(aNPIter);
1034 }
1035 else
1036 ++aNPIter;
1037 }
1038
1039 if( aIter->second.empty() )
1040 {
1041 aIter = m_aContainer.erase(aIter);
1042 }
1043 else
1044 ++aIter;
1045 }
1046}
1047
1049{
1050 Sequence< UrlRecord > aResult;
1051
1052 std::unique_lock aGuard( mMutex );
1053 for( const auto& rEntry : m_aContainer )
1054 {
1056 for (auto const& aNP : rEntry.second)
1057 if( aNP.HasPasswords( PERSISTENT_RECORD ) )
1058 {
1059 sal_Int32 oldLen = aUsers.getLength();
1060 aUsers.realloc( oldLen + 1 );
1061 aUsers.getArray()[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersistentPasswords(), aNP.GetPersistentIV(),
1062 GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) );
1063 }
1064
1065 if( aUsers.hasElements() )
1066 {
1067 sal_Int32 oldLen = aResult.getLength();
1068 aResult.realloc( oldLen + 1 );
1069 aResult.getArray()[ oldLen ] = UrlRecord( rEntry.first, aUsers );
1070 }
1071 }
1072
1073 return aResult;
1074}
1075
1076sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1077{
1078 bool bResult = false;
1079 OUString aEncodedMP, aEncodedMPIV;
1080 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1081 std::unique_lock aGuard( mMutex );
1082
1083 // the method should fail if there is no master password
1084 if( m_xStorageFile && m_xStorageFile->useStorage() && m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) )
1085 {
1086 if ( aEncodedMP.isEmpty() )
1087 {
1088 // this is a default master password
1089 // no UI is necessary
1090 bResult = true;
1091 }
1092 else
1093 {
1094 if ( !xTmpHandler.is() )
1095 {
1096 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1097 uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
1098 xTmpHandler.set( InteractionHandler::createWithParent(xContext, nullptr), uno::UNO_QUERY_THROW );
1099 }
1100
1101 if ( !m_aMasterPassword.isEmpty() )
1102 {
1103 // there is a password, it should be just rechecked
1104 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
1105 OUString aPass;
1106
1107 do {
1108 aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1109
1110 if (!aPass.isEmpty() && m_xStorageFile->getStorageVersion() == 0)
1111 {
1112 aPass = ReencodeAsOldHash(aPass);
1113 }
1114
1115 bResult = ( !aPass.isEmpty() && aPass == m_aMasterPassword );
1116 aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
1117 } while( !bResult && !aPass.isEmpty() );
1118 }
1119 else
1120 {
1121 try
1122 {
1123 // ask for the password, if user provide no correct password an exception will be thrown
1124 bResult = !GetMasterPassword( xTmpHandler ).isEmpty();
1125 }
1126 catch( uno::Exception& )
1127 {}
1128 }
1129 }
1130 }
1131
1132 return bResult;
1133}
1134
1135sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1136{
1137 bool bResult = false;
1138 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1139 std::unique_lock aGuard( mMutex );
1140
1141 if ( m_xStorageFile && m_xStorageFile->useStorage() )
1142 {
1143 if ( !xTmpHandler.is() )
1144 {
1145 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1146 uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
1147 xTmpHandler.set( InteractionHandler::createWithParent(xContext, nullptr), uno::UNO_QUERY_THROW );
1148 }
1149
1150 bool bCanChangePassword = true;
1151 // if there is already a stored master password it should be entered by the user before the change happen
1152 OUString aEncodedMP, aEncodedMPIV;
1153 if( !m_aMasterPassword.isEmpty() || m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) )
1154 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1155
1156 if ( bCanChangePassword )
1157 {
1158 // ask for the new password, but do not set it
1159 OUString aPass = RequestPasswordFromUser( PasswordRequestMode_PASSWORD_CREATE, xTmpHandler );
1160
1161 if ( !aPass.isEmpty() )
1162 {
1163 // get all the persistent entries if it is possible
1164 const Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1165
1166 // remove the master password and the entries persistence
1168
1169 // store the new master password
1170 m_aMasterPassword = aPass;
1171 std::vector< OUString > aMaster( 1, m_aMasterPassword );
1172 OUString aIV = createIV();
1173 m_xStorageFile->setEncodedMasterPassword(EncodePasswords(aMaster, aIV, m_aMasterPassword), aIV);
1174
1175 // store all the entries with the new password
1176 for ( const auto& rURL : aPersistent )
1177 for ( const auto& rUser : rURL.UserList )
1178 addPersistent( rURL.Url, rUser.UserName, rUser.Passwords,
1179 uno::Reference< task::XInteractionHandler >() );
1180
1181 bResult = true;
1182 }
1183 }
1184 }
1185
1186 return bResult;
1187}
1188
1190{
1191 std::unique_lock aGuard(mMutex);
1192 removeMasterPassword(aGuard);
1193}
1194
1195void PasswordContainer::removeMasterPassword(std::unique_lock<std::mutex>& rGuard)
1196{
1197 // remove all the stored passwords and the master password
1198 removeAllPersistent(rGuard);
1199
1200 if ( m_xStorageFile )
1201 {
1202 m_aMasterPassword.clear();
1203 m_xStorageFile->setEncodedMasterPassword( OUString(), OUString() ); // let the master password be removed from configuration
1204 }
1205}
1206
1208{
1209 std::unique_lock aGuard( mMutex );
1210
1211 if ( !m_xStorageFile )
1212 throw uno::RuntimeException();
1213
1214 OUString aEncodedMP, aEncodedMPIV;
1215 return ( m_xStorageFile->useStorage() && m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) );
1216}
1217
1219{
1220 std::unique_lock aGuard( mMutex );
1221
1222 if ( !m_xStorageFile )
1223 throw uno::RuntimeException();
1224
1225 if ( !bAllow )
1226 removeMasterPassword(aGuard);
1227
1228 if (m_xStorageFile->useStorage() == static_cast<bool>(bAllow))
1229 return bAllow;
1230
1231 m_xStorageFile->setUseStorage( bAllow );
1232 return !bAllow;
1233}
1234
1236{
1237 std::unique_lock aGuard( mMutex );
1238
1239 if ( !m_xStorageFile )
1240 throw uno::RuntimeException();
1241
1242 return m_xStorageFile->useStorage();
1243}
1244
1245sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1246{
1247 bool bResult = false;
1248 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1249 std::unique_lock aGuard( mMutex );
1250
1251 if ( m_xStorageFile && m_xStorageFile->useStorage() )
1252 {
1253 if ( !xTmpHandler.is() )
1254 {
1255 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1256 uno::Reference< uno::XComponentContext > xContext( comphelper::getComponentContext(xFactory) );
1257 xTmpHandler.set( InteractionHandler::createWithParent(xContext, nullptr), uno::UNO_QUERY_THROW );
1258 }
1259
1260 bool bCanChangePassword = true;
1261 // if there is already a stored nondefault master password it should be entered by the user before the change happen
1262 OUString aEncodedMP, aEncodedMPIV;
1263 if( m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) && !aEncodedMP.isEmpty() )
1264 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1265
1266 if ( bCanChangePassword )
1267 {
1268 // generate the default password
1269 OUString aPass = GetDefaultMasterPassword();
1270 if ( !aPass.isEmpty() )
1271 {
1272 // get all the persistent entries if it is possible
1273 const Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1274
1275 // remove the master password and the entries persistence
1277
1278 // store the empty string to flag the default master password
1279 m_aMasterPassword = aPass;
1280 m_xStorageFile->setEncodedMasterPassword( OUString(), OUString(), true );
1281
1282 // store all the entries with the new password
1283 for ( const auto& rURL : aPersistent )
1284 for ( const auto& rUser : rURL.UserList )
1285 addPersistent( rURL.Url, rUser.UserName, rUser.Passwords,
1286 uno::Reference< task::XInteractionHandler >() );
1287
1288 bResult = true;
1289 }
1290 }
1291 }
1292
1293 return bResult;
1294
1295}
1296
1298{
1299 std::unique_lock aGuard( mMutex );
1300
1301 if ( !m_xStorageFile )
1302 throw uno::RuntimeException();
1303
1304 OUString aEncodedMP, aEncodedMPIV;
1305 return ( m_xStorageFile->useStorage() && m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) && aEncodedMP.isEmpty() );
1306}
1307
1308
1309void SAL_CALL PasswordContainer::addUrl( const OUString& Url, sal_Bool MakePersistent )
1310{
1311 mUrlContainer.add( Url, MakePersistent );
1312}
1313
1314OUString SAL_CALL PasswordContainer::findUrl( const OUString& Url )
1315{
1316 return mUrlContainer.find( Url );
1317}
1318
1319void SAL_CALL PasswordContainer::removeUrl( const OUString& Url )
1320{
1322}
1323
1324uno::Sequence< OUString > SAL_CALL PasswordContainer::getUrls( sal_Bool OnlyPersistent )
1325{
1326 return mUrlContainer.list( OnlyPersistent );
1327}
1328
1329
1331{
1332 std::unique_lock aGuard( mMutex );
1333
1334 // remove the cached persistent values in the memory
1335 for( auto& rEntry : m_aContainer )
1336 {
1337 for( std::vector< NamePasswordRecord >::iterator aNPIter = rEntry.second.begin(); aNPIter != rEntry.second.end(); )
1338 {
1339 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1340 {
1341 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1342
1343 if ( m_xStorageFile )
1344 m_xStorageFile->remove( rEntry.first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1345 }
1346
1347 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1348 {
1349 aNPIter = rEntry.second.erase(aNPIter);
1350 }
1351 else
1352 ++aNPIter;
1353 }
1354 }
1355
1356 PasswordMap addon;
1357 if( m_xStorageFile )
1358 addon = m_xStorageFile->getInfo();
1359
1360 for( const auto& rEntry : addon )
1361 {
1362 PasswordMap::iterator aSearchIter = m_aContainer.find( rEntry.first );
1363 if( aSearchIter != m_aContainer.end() )
1364 for (auto const& aNP : rEntry.second)
1365 UpdateVector( aSearchIter->first, aSearchIter->second, aNP, false );
1366 else
1367 m_aContainer.insert( PairUrlRecord( rEntry.first, rEntry.second ) );
1368 }
1369}
1370
1372{
1373 return "stardiv.svl.PasswordContainer";
1374}
1375
1376sal_Bool SAL_CALL PasswordContainer::supportsService( const OUString& ServiceName )
1377{
1378 return cppu::supportsService( this, ServiceName );
1379}
1380
1382{
1383 return { "com.sun.star.task.PasswordContainer" };
1384}
1385
1386extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1388 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
1389{
1390 return cppu::acquire(new PasswordContainer(context));
1391}
1392
1393
1395{
1396 MasterPasswordRequest aRequest;
1397
1398 aRequest.Classification = InteractionClassification_ERROR;
1399 aRequest.Mode = Mode;
1400
1401 setRequest( Any( aRequest ) );
1402
1403 // Fill continuations...
1404 Sequence< RememberAuthentication > aRememberModes{ RememberAuthentication_NO };
1405
1407 = new ::ucbhelper::InteractionSupplyAuthentication(
1408 this,
1409 false, // bCanSetRealm
1410 false, // bCanSetUserName
1411 true, // bCanSetPassword
1412 false, // bCanSetAccount
1413 aRememberModes, // rRememberPasswordModes
1414 RememberAuthentication_NO, // eDefaultRememberPasswordMode
1415 aRememberModes, // rRememberAccountModes
1416 RememberAuthentication_NO, // eDefaultRememberAccountMode
1417 false // bCanUseSystemCredentials
1418 );
1419
1420 Sequence<
1422 new ::ucbhelper::InteractionAbort( this ),
1423 new ::ucbhelper::InteractionRetry( this ),
1425 };
1426
1427 setContinuations( aContinuations );
1428}
1429
1430
1431
1432/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertyValueVector_t aPropertyValues
void * rtlRandomPool
MasterPasswordRequest_Impl(css::task::PasswordRequestMode Mode)
::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > m_xAuthSupplier
::std::vector< OUString > GetMemoryPasswords() const
bool HasPasswords(sal_Int8 nStatus) const
OUString GetPersistentPasswords() const
void SetMemoryPasswords(::std::vector< OUString > &&aMemList)
void SetPersistentPasswords(const OUString &aPersList, const OUString &aPersIV)
OUString GetPersistentIV() const
const OUString & GetUserName() const
SysCredentialsConfig mUrlContainer
css::uno::Sequence< css::task::UserRecord > CopyToUserRecordSequence(const ::std::vector< NamePasswordRecord > &original, const css::uno::Reference< css::task::XInteractionHandler > &Handler)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void PrivateAdd(const OUString &aUrl, const OUString &aUserName, const css::uno::Sequence< OUString > &aPasswords, char aMode, const css::uno::Reference< css::task::XInteractionHandler > &Handler)
static OUString GetDefaultMasterPassword()
static OUString RequestPasswordFromUser(css::task::PasswordRequestMode aRMode, const css::uno::Reference< css::task::XInteractionHandler > &xHandler)
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
void UpdateVector(const OUString &url, ::std::vector< NamePasswordRecord > &toUpdate, NamePasswordRecord const &rec, bool writeFile)
std::optional< StorageItem > m_xStorageFile
bool createUrlRecord(const PasswordMap::iterator &rIter, bool bName, std::u16string_view aName, const css::uno::Reference< css::task::XInteractionHandler > &aHandler, css::task::UrlRecord &rRec)
virtual void SAL_CALL removeUrl(const OUString &Url) override
virtual void SAL_CALL removeMasterPassword() override
virtual sal_Bool SAL_CALL useDefaultMasterPassword(const css::uno::Reference< css::task::XInteractionHandler > &xHandler) override
virtual css::uno::Sequence< OUString > SAL_CALL getUrls(sal_Bool OnlyPersistent) override
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::lang::XComponent > mComponent
static ::std::vector< OUString > DecodePasswords(std::u16string_view aLine, std::u16string_view aIV, std::u16string_view aMasterPassword, css::task::PasswordRequestMode mode)
virtual sal_Bool SAL_CALL isDefaultMasterPasswordUsed() override
virtual OUString SAL_CALL findUrl(const OUString &Url) override
virtual void SAL_CALL removePersistent(const OUString &aUrl, const OUString &aUserName) override
virtual void SAL_CALL remove(const OUString &aUrl, const OUString &aUserName) override
PasswordContainer(const css::uno::Reference< css::uno::XComponentContext > &)
virtual sal_Bool SAL_CALL changeMasterPassword(const css::uno::Reference< css::task::XInteractionHandler > &xHandler) override
css::task::UserRecord CopyToUserRecord(const NamePasswordRecord &aRecord, bool &io_bTryToDecode, const css::uno::Reference< css::task::XInteractionHandler > &aHandler)
virtual void SAL_CALL removeAllPersistent() override
virtual void SAL_CALL addPersistent(const OUString &aUrl, const OUString &aUserName, const css::uno::Sequence< OUString > &aPasswords, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual ~PasswordContainer() override
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL addUrl(const OUString &Url, sal_Bool MakePersistent) override
css::task::UrlRecord find(const OUString &aURL, std::u16string_view aName, bool bName, const css::uno::Reference< css::task::XInteractionHandler > &aHandler)
virtual sal_Bool SAL_CALL isPersistentStoringAllowed() override
OUString const & GetMasterPassword(const css::uno::Reference< css::task::XInteractionHandler > &Handler)
static OUString EncodePasswords(const std::vector< OUString > &lines, std::u16string_view aIV, std::u16string_view aMasterPassword)
virtual void SAL_CALL add(const OUString &aUrl, const OUString &aUserName, const css::uno::Sequence< OUString > &aPasswords, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual sal_Bool SAL_CALL allowPersistentStoring(sal_Bool bAllow) override
virtual sal_Bool SAL_CALL hasMasterPassword() override
css::uno::Sequence< css::task::UserRecord > FindUsr(const ::std::vector< NamePasswordRecord > &userlist, std::u16string_view name, const css::uno::Reference< css::task::XInteractionHandler > &Handler)
virtual sal_Bool SAL_CALL authorizateWithMasterPassword(const css::uno::Reference< css::task::XInteractionHandler > &xHandler) override
virtual css::uno::Sequence< css::task::UrlRecord > SAL_CALL getAllPersistent(const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
virtual css::task::UrlRecord SAL_CALL findForName(const OUString &aUrl, const OUString &aUserName, const css::uno::Reference< css::task::XInteractionHandler > &Handler) override
void setEncodedMasterPassword(const OUString &aResult, const OUString &aResultIV, bool bAcceptEmpty=false)
void remove(const OUString &url, const OUString &rec)
bool getEncodedMasterPassword(OUString &aResult, OUString &aResultIV)
void update(const OUString &url, const NamePasswordRecord &rec)
virtual void Notify(const css::uno::Sequence< OUString > &aPropertyNames) override
virtual void ImplCommit() override
PasswordContainer * mainCont
PasswordMap getInfo()
void setUseStorage(bool bUse)
sal_Int32 getStorageVersion()
OUString find(OUString const &rURL)
Definition: syscreds.cxx:189
css::uno::Sequence< OUString > list(bool bOnlyPersistent)
Definition: syscreds.cxx:236
void remove(OUString const &rURL)
Definition: syscreds.cxx:225
void add(OUString const &rURL, bool bPersistent)
Definition: syscreds.cxx:203
void setRequest(const css::uno::Any &rRequest)
void setContinuations(const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > &rContinuations)
URL aURL
Reference< XSingleServiceFactory > xFactory
OUString aName
Sequence< sal_Int8 > aSeq
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
line
sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix=10)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Mode
sal_Unicode code
static OUString ReencodeAsOldHash(std::u16string_view rPass)
static std::vector< OUString > getInfoFromInd(std::u16string_view aInd)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * svl_PasswordContainer_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
static bool shorterUrl(OUString &aURL)
::rtl::ByteSequence getBufFromAsciiLine(std::u16string_view line)
static OUString createIndex(const std::vector< OUString > &lines)
static OUString getAsciiLine(const ::rtl::ByteSequence &buf)
#define MEMORY_RECORD
constexpr sal_Int32 nCurrentStorageVersion
::std::pair< const OUString, ::std::vector< NamePasswordRecord > > PairUrlRecord
#define PERSISTENT_RECORD
::std::map< OUString, ::std::vector< NamePasswordRecord > > PasswordMap
const PropertyStruct aPropNames[]
ConversionMode mode
unsigned char sal_uInt8
unsigned char sal_Bool
sal_uInt16 sal_Unicode
Any result
std::unique_ptr< char[]> aBuffer