• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • util
qosxkeychain.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 *
3 * Copyright (C) 2014 René Bertin <rjvbertin@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include <cassert>
22#include <sys/param.h>
23
24#include <QtGui/QApplication>
25#include <QtCore/QtCore>
26#include <QtCore/QPointer>
27#include <QtGui/QWidget>
28
29#include "kwallet.h"
30#include <kdebug.h>
31using namespace KWallet;
32#include "qosxkeychain.h"
33
34#include <CoreServices/CoreServices.h>
35
37#define INTERNET_TOO 0
38
39// #undef kWarning
40// #undef kDebug
41// #define kWarning qWarning
42// #define kDebug qDebug
43
44// returns the textual representation of a FourCharCode (e.g. 'JPEG')
45static QString OSTStr( FourCharCode etype )
46{ union OSTStr {
47 struct {
48 char startquote;
49 uint32_t four;
50 char endquote;
51 } __attribute__ ((packed)) value;
52 char representation[7];
53 } __attribute__ ((packed)) ltype;
54 ltype.value.four = EndianU32_BtoN(etype);
55 ltype.representation[0] = ltype.representation[5] = '\'';
56 ltype.representation[6] = '\0';
57 return QString::fromAscii(ltype.representation);
58}
59
60static SecKeychainRef defaultChain()
61{ QString errMsg;
62 SecKeychainRef keychain;
63 if( isError( SecKeychainCopyDefault(&keychain), &errMsg ) ){
64 kWarning() << "Could not retrieve reference to default keychain:" << qPrintable(errMsg);
65 keychain = NULL;
66 }
67 return keychain;
68}
69
74static QString keyChainName( SecKeychainRef keychain, QString *path=NULL )
75{ QFileInfo keyFile;
76 QString p = OSXKeychain::Path(keychain);
77 int ext = p.lastIndexOf(".keychain");
78 keyFile = QFileInfo( ((ext > 0)? p.left(ext) : p) );
79 if( path ){
80 *path = QString(p);
81 }
82 return keyFile.fileName();
83}
84
91static OSStatus openKeychain( const QString &n, SecKeychainRef *keychain )
92{ OSStatus err;
93 CFArrayRef list = NULL;
94
95 *keychain = NULL;
96 err = SecKeychainCopySearchList( &list );
97 if( !err && list ){
98 CFIndex len = CFArrayGetCount(list), i;
99 for( i = 0 ; i < len && !*keychain ; ++i ){
100 SecKeychainRef kr = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
101 QString path, name = keyChainName( kr, &path );
102 if( name == n ){
103 // a hit, try to open it!
104 err = SecKeychainOpen( path.toUtf8(), keychain );
105 if( err ){
106 kWarning() << "openKeychain(" << n << ") error" << err << "opening matching" << path;
107 }
108 else{
109 kDebug() << "openKeychain(" << n << ") opened matching" << path;
110 }
111 }
112 }
113 CFRelease(list);
114 }
115 if( !*keychain ){
116 err = SecKeychainOpen( n.toUtf8(), keychain );
117 }
118 // we actually need to query the keychain's status to know if we succeeded
119 // in opening an existing keychain!
120 if( !err ){
121 SecKeychainStatus status;
122 err = SecKeychainGetStatus( *keychain, &status );
123 }
124 return err;
125}
126
127static OSStatus basicWriteItem( const QByteArray *serviceName, const QByteArray &accountName, const QByteArray &value,
128 const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL )
129{ OSStatus err;
130 QString errMsg;
131 if( serviceName ){
132 err = SecKeychainAddGenericPassword( keychain, serviceName->size(), serviceName->constData(),
133 accountName.size(), accountName.constData(),
134 value.size(), value.constData(), itemRef );
135 }
136 else{
137 err = SecKeychainAddGenericPassword( keychain, 0, NULL,
138 accountName.size(), accountName.constData(),
139 value.size(), value.constData(), itemRef );
140 }
141 if( err != errSecDuplicateItem && isError( err, &errMsg ) ){
142 kWarning() << "Could not store password in keychain: " << qPrintable(errMsg);
143 }
144 return err;
145}
146
147OSXKeychain::OSXKeychain()
148 : name("default")
149{ QString errMsg;
150 keyChainRef = defaultChain();
151 if( keyChainRef ){
152 keyChainPath = OSXKeychain::Path(keyChainRef);
153 kDebug() << "Retrieved reference to default keychain" << (void*) keyChainRef << "in " << keyChainPath;
154 name = keyChainName(keyChainRef);
155 isDefaultKeychain = true;
156 }
157 else{
158 keyChainPath = QString::fromUtf8("<undefined>");
159 }
160 serviceList.clear();
161 serviceList.append("");
162}
163
164OSXKeychain::OSXKeychain(const QString &n)
165 : name(n)
166{ QString errMsg;
167 OSStatus err = openKeychain( n, &keyChainRef );
168
169 if( err == errSecNoSuchKeychain ){
170 kWarning() << "Keychain '" << n << "' does not exist: attempting to create it";
171 err = SecKeychainCreate( n.toUtf8(), 0, NULL, true, NULL, &keyChainRef );
172 isKDEChain = true;
173 }
174
175 if( isError( err, &errMsg ) ){
176 // the protocol cannot handle failure to open a keychain, so we have to return the default.
177 keyChainRef = defaultChain();
178 kWarning() << "Error opening keychain '" << n << "' (falling back to default keychain): " << qPrintable(errMsg);
179 name = keyChainName(keyChainRef);
180 isDefaultKeychain = true;
181 }
182 else{
183 isDefaultKeychain = false;
184 }
185
186 if( keyChainRef ){
187 keyChainPath = OSXKeychain::Path(keyChainRef);
188 kDebug() << "Retrieved reference to keychain" << name << (void*) keyChainRef << "in " << keyChainPath;
189 }
190 else{
191 keyChainPath = QString::fromUtf8("<undefined>");
192 }
193 serviceList.clear();
194 serviceList.append("");
195}
196
197void OSXKeychain::close()
198{
199 if( keyChainRef ){
200 CFRelease(keyChainRef);
201 keyChainRef = NULL;
202 }
203}
204
205OSXKeychain::~OSXKeychain()
206{
207 close();
208}
209
210OSStatus OSXKeychain::renameItem(const QString &currentKey, const QString &newKey)
211{ OSStatus err;
212 SecKeychainItemRef itemRef = NULL;
213 err = ReadItem( currentKey, NULL, keyChainRef, &itemRef, this );
214 if( !err && itemRef ){
215 const QByteArray accountName( newKey.toUtf8() );
216 // store the new key in the account and label attributes
217 SecKeychainAttribute attr[] = { { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() },
218 { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() } };
219 SecKeychainAttributeList attrList = { 2, &attr[0] };
220 QString errMsg;
221 if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
222 kWarning() << "OSXKeychain::renameItem(" << currentKey << ") couldn't change name & label to" << accountName
223 << ":" << err << "=" << qPrintable(errMsg);
224 }
225 CFRelease(itemRef);
226 }
227 return err;
228}
229
230#pragma mark ========= static member functions =========
231
232OSStatus OSXKeychain::KeychainList(QStringList &theList)
233{ CFArrayRef list = NULL;
234 OSStatus err = SecKeychainCopySearchList( &list );
235 theList.clear();
236 if( !err && list ){
237 CFIndex len = CFArrayGetCount(list), i;
238 for( i = 0 ; i < len ; ++i ){
239 SecKeychainRef keychain = (SecKeychainRef) CFArrayGetValueAtIndex( list, i );
240 QString name = keyChainName(keychain);
241 if( name.size() > 0 ){
242 theList.append(name);
243 }
244 }
245 CFRelease(list);
246 }
247 return err;
248}
249
250QString OSXKeychain::Path(const SecKeychainRef keychain)
251{ char pathName[MAXPATHLEN];
252 UInt32 plen = MAXPATHLEN;
253 if( SecKeychainGetPath( (keychain)? keychain : OSXKeychain().reference(), &plen, pathName ) == errSecSuccess ){
254 return QString::fromUtf8(pathName);
255 }
256 else{
257 return QString();
258 }
259}
260
261bool OSXKeychain::IsOpen(const SecKeychainRef keychain)
262{ bool isOpen = false;
263 SecKeychainStatus status;
264 QString errMsg;
265 if( isError( SecKeychainGetStatus( keychain, &status ), &errMsg ) ){
266 if( keychain ){
267 kDebug() << "Could not get the status of keychain" << OSXKeychain::Path(keychain) << ":" << qPrintable(errMsg);
268 }
269 else{
270 kWarning() << "Could not get the default keychain's status:" << qPrintable(errMsg);
271 }
272 }
273 else{
274 if( (status & kSecUnlockStateStatus) && (status & kSecReadPermStatus) ){
275 isOpen = true;
276 }
277 else{
278 kDebug() << "Keychain" << OSXKeychain::Path(keychain) << " has status" << status;
279 }
280 }
281 return isOpen;
282}
283
284bool OSXKeychain::IsOpen(const QString &walletName)
285{ SecKeychainRef keychain = NULL;
286 OSStatus err = openKeychain( walletName.toUtf8(), &keychain );
287 bool ret = false;
288 if( !err && keychain ){
289 ret = IsOpen(keychain);
290 CFRelease(keychain);
291 }
292 return ret;
293}
294
295OSStatus OSXKeychain::UnLock(const SecKeychainRef keychain)
296{ QString errMsg;
297 OSStatus err;
298 err = SecKeychainUnlock( keychain, 0, NULL, false );
299 if( isError( err, &errMsg ) ){
300 if( keychain ){
301 kDebug() << "Could not unlock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
302 }
303 else{
304 kDebug() << "Could not unlock the default keychain:" << qPrintable(errMsg);
305 }
306 }
307 return err;
308}
309
310OSStatus OSXKeychain::Lock(const SecKeychainRef keychain)
311{ QString errMsg;
312 OSStatus err;
313 if( keychain ){
314 err = SecKeychainLock(keychain);
315 if( isError( err, &errMsg ) ){
316 kDebug() << "Could not lock the keychain at '" << OSXKeychain::Path(keychain) << "': " << qPrintable(errMsg);
317 }
318 }
319 else{
320 err = SecKeychainLockAll();
321 if( isError( err, &errMsg ) ){
322 kDebug() << "Could not lock all keychains:" << qPrintable(errMsg);
323 }
324 }
325 return err;
326}
327
328OSStatus OSXKeychain::Lock(const QString &walletName)
329{ SecKeychainRef keychain = NULL;
330 OSStatus err = openKeychain( walletName, &keychain );
331 if( !err && keychain ){
332 err = Lock(keychain);
333 CFRelease(keychain);
334 }
335 return err;
336}
337
343bool OSXKeychain::HasItem(const QString &key,
344 const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef)
345{ const QByteArray accountName( key.toUtf8() );
346 OSStatus err;
347 SecKeychainSearchRef searchRef;
348 SecKeychainAttribute attrs = { kSecAccountItemAttr, accountName.size(), (void*) accountName.constData() };
349 SecKeychainAttributeList attrList = { 1, &attrs };
350 err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass,
351 (const SecKeychainAttributeList*) &attrList, &searchRef );
352 const CFReleaser<SecKeychainSearchRef> releaseSR(searchRef);
353 bool found;
354 SecKeychainItemRef item;
355 QString errMsg;
356 if( err ){
357 found = false;
358 errMsg = errorString(err);
359 kDebug() << "OSXKeychain::HasItem(" << key << "," << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed";
360 }
361 else{
362 if( !(err = SecKeychainSearchCopyNext( searchRef, &item )) ){
363 found = true;
364 if( itemRef ){
365 *itemRef = item;
366 }
367 else if( item ){
368 CFRelease(item);
369 }
370 errMsg = QString();
371 }
372 else{
373 found = false;
374 errMsg = errorString(err);
375 }
376 if( errReturn ){
377 *errReturn = err;
378 }
379 }
380 kDebug() << ((found)? "Found" : "Did not find") << "item '" << key << "' in keychain " << (void*) keychain << ", error=" << err << " " << qPrintable(errMsg);
381 return found;
382}
383
384OSStatus OSXKeychain::ReadItem(const QString &key, QByteArray *value,
385 const SecKeychainRef keychain, SecKeychainItemRef *itemRef, OSXKeychain *osxKeyChain)
386{ const QByteArray accountName( key.toUtf8() );
387 UInt32 passwordSize = 0;
388 void* passwordData = 0;
389 QString errMsg;
390 SecKeychainItemRef theItem;
391 OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
392 accountName.size(), accountName.constData(),
393 &passwordSize, &passwordData, &theItem );
394 if( isError( err, &errMsg ) ){
395 kDebug() << "Error" << err << "retrieving password for '" << accountName << "' :" << qPrintable(errMsg);
396#if INTERNET_TOO
397 if( SecKeychainFindInternetPassword( keychain, 0, NULL,
398 0, NULL,
399 accountName.size(), accountName.constData(),
400 0, NULL, 0,
401 kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
402 &passwordSize, &passwordData, &theItem ) ){
403 // just to be sure:
404 theItem = NULL;
405 }
406 else{
407 err = 0;
408 errMsg = QString();
409 }
410#else
411 theItem = NULL;
412#endif
413 }
414 if( !err && theItem ){
415 if( value ){
416 *value = QByteArray( reinterpret_cast<const char*>( passwordData ), passwordSize );
417 }
418 SecKeychainItemFreeContent( NULL, passwordData );
419 if( osxKeyChain && osxKeyChain->isKDEChain ){
420 SecKeychainAttribute attr = { kSecServiceItemAttr, 0, NULL };
421 SecKeychainAttributeList attrList = { 1, &attr };
422 UInt32 len = 0;
423 // try to fetch the item's ServiceItem attribute
424 if( !SecKeychainItemCopyContent( theItem, NULL, &attrList, &len, NULL ) ){
425 if( attr.length > 0 ){
426 osxKeyChain->lastReadService.clear();
427 osxKeyChain->lastReadService = QString::fromUtf8( (char*)attr.data, attr.length );
428 }
429 SecKeychainItemFreeContent( &attrList, NULL );
430 }
431 }
432 if( itemRef ){
433 *itemRef = theItem;
434 }
435 else if( theItem ){
436 CFRelease(theItem);
437 }
438 }
439 kDebug() << "OSXKeychain::ReadItem '" << key << "' from keychain " << OSXKeychain::Path(keychain) << ", error=" << err;
440 return err;
441}
442
443OSStatus OSXKeychain::ItemType(const QString &key, EntryType *entryType,
444 const SecKeychainRef keychain)
445{ const QByteArray accountName( key.toUtf8() );
446 QString errMsg;
447 EntryType etype = (EntryType) 0;
448 SecKeychainItemRef itemRef;
449#if INTERNET_TOO
450 bool isInternetPW = false;
451#endif
452 OSStatus err = SecKeychainFindGenericPassword( keychain, 0, NULL,
453 accountName.size(), accountName.constData(),
454 NULL, NULL, &itemRef );
455 if( isError( err, &errMsg ) ){
456 kDebug() << "Error" << err << "retrieving type for '" << accountName << "' :" << qPrintable(errMsg);
457#if INTERNET_TOO
458 if( SecKeychainFindInternetPassword( keychain, 0, NULL,
459 0, NULL,
460 accountName.size(), accountName.constData(),
461 0, NULL, 0,
462 kSecProtocolTypeAny, kSecAuthenticationTypeDefault,
463 0, NULL, &itemRef ) ){
464 // just to be sure:
465 itemRef = NULL;
466 }
467 else{
468 isInternetPW = true;
469 err = 0;
470 errMsg = QString();
471 }
472#else
473 itemRef = NULL;
474#endif
475 }
476 if( itemRef ){
477 UInt32 tags[] = { kSecTypeItemAttr };
478 UInt32 formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_STRING };
479 SecKeychainAttributeInfo attrGet = { 1, tags, formats };
480 SecKeychainAttributeList *attrList = NULL;
481 err = SecKeychainItemCopyAttributesAndData( itemRef, &attrGet, NULL, &attrList, NULL, NULL );
482 if( !err ){
483 if( attrList->attr[0].length == sizeof(EntryType) ){
484 memcpy( &etype, attrList->attr[0].data, sizeof(EntryType) );
485 }
486 else if( attrList->attr[0].length ){
487 kDebug() << "Error: key" << key << "item type retrieved is of size" << attrList->attr[0].length << "!=" << sizeof(EntryType);
488 }
489#if INTERNET_TOO
490 else if( isInternetPW ){
491 // this is just a wild guess ...
492 etype = Password;
493 }
494#endif
495 if( entryType ){
496 *entryType = etype;
497 }
498 }
499 SecKeychainItemFreeAttributesAndData( attrList, NULL );
500 CFRelease(itemRef);
501 }
502 kDebug() << "OSXKeychain::ItemType '" << key << "' from keychain " << OSXKeychain::Path(keychain) << "=" << OSTStr(etype) << ", error=" << err;
503 return err;
504}
505
506OSStatus OSXKeychain::RemoveItem(const QString &key, const SecKeychainRef keychain)
507{ const QByteArray accountName( key.toUtf8() );
508 SecKeychainItemRef itemRef;
509 QString errMsg;
510 OSStatus result = SecKeychainFindGenericPassword( keychain, 0, NULL,
511 accountName.size(), accountName.constData(), NULL, NULL, &itemRef );
512 if( isError( result, &errMsg ) ){
513 kDebug() << "Could not find entry" << key << ":" << qPrintable(errMsg);
514 }
515 else{
516 const CFReleaser<SecKeychainItemRef> itemReleaser(itemRef);
517 result = SecKeychainItemDelete(itemRef);
518 if( isError( result, &errMsg ) ){
519 kWarning() << "Could not delete entry" << key << ":" << qPrintable(errMsg);
520 }
521 }
522 return result;
523}
524
525OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
526 const SecKeychainRef keychain, SecKeychainItemRef *itemRef, EntryType *entryType, OSXKeychain *osxKeyChain )
527{ const QByteArray accountName( key.toUtf8() );
528 OSStatus err;
529 QString errMsg;
530 SecKeychainItemRef theItem = NULL;
531 bool saveLabel;
532 if( osxKeyChain && osxKeyChain->currentService.size() ){
533 const QByteArray serviceName( osxKeyChain->currentService.toUtf8() );
534 // save the "GenericPassword" item using the service name, which appears to be the only way to write
535 // to the "Where" field shown in the Keychain Utility.
536 err = basicWriteItem( &serviceName, accountName, value, keychain, &theItem );
537 // the service (folder!) string will also appear on the "Name" field, which however can be changed
538 // independently, via the Label attribute.
539 saveLabel = true;
540 }
541 else{
542 err = basicWriteItem( NULL, accountName, value, keychain, &theItem );
543 saveLabel = false;
544 }
545 if( err == errSecDuplicateItem ){
546 // RJVB: the previous implementation was wrong. errSecDuplicateItem means the write failed because of an existing item.
547 // So we have to find that item, and modify it.
548 if( !(err = ReadItem( key, NULL, keychain, &theItem )) ){
549 err = SecKeychainItemModifyAttributesAndData( theItem, NULL, value.size(), value.constData() );
550 if( isError( err, &errMsg ) ){
551 kDebug() << "Key '" << key
552 << "'already exists in keychain but error modifying the existing item: " << qPrintable(errMsg);
553 }
554 }
555 if( !err ){
556 kDebug() << "Key '" << key << "'already existed in keychain: modified the existing item";
557 }
558 }
559 if( !err && saveLabel ){
560 // store the desired text in the label attribute
561 SecKeychainAttribute attr = { kSecLabelItemAttr, accountName.size(), (void*) accountName.constData() };
562 SecKeychainAttributeList attrList = { 1, &attr };
563 QString errMsg;
564 if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
565 kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set the desired name/label" << accountName
566 << ":" << err << "=" << qPrintable(errMsg);
567 }
568 }
569 if( !err ){
570 EntryType defType = Stream;
571 if( !entryType ){
572 entryType = &defType;
573 }
574 SecKeychainAttribute attr = { kSecTypeItemAttr, sizeof(EntryType), (void*) entryType };
575 SecKeychainAttributeList attrList = { 1, &attr };
576 QString errMsg;
577 if( isError( (err = SecKeychainItemModifyAttributesAndData( theItem, &attrList, 0, NULL )), &errMsg ) ){
578 kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't set type to" << OSTStr(*entryType)
579 << ":" << qPrintable(errMsg);
580 }
581 }
582 if( itemRef ){
583 *itemRef = theItem;
584 }
585 else if( theItem ){
586 CFRelease(theItem);
587 }
588 kDebug() << "OSXKeychain::WriteItem '" << key << "' to keychain " << (void*) keychain << ", error=" << err;
589 return err;
590}
591
592OSStatus OSXKeychain::WriteItem( const QString &key, const QByteArray &value,
593 const QString &comment, const SecKeychainRef keychain, EntryType *entryType, OSXKeychain *osxKeyChain )
594{ SecKeychainItemRef itemRef = NULL;
595 OSStatus err = WriteItem( key, value, keychain, &itemRef, entryType, osxKeyChain );
596 if( !err && itemRef ){
597 const QByteArray commentString(comment.toUtf8());
598 if( commentString.size() ){
599 SecKeychainAttribute attr = { kSecCommentItemAttr, commentString.size(), (void*) commentString.constData() };
600 SecKeychainAttributeList attrList = { 1, &attr };
601 QString errMsg;
602 if( isError( (err = SecKeychainItemModifyAttributesAndData( itemRef, &attrList, 0, NULL )), &errMsg ) ){
603 kWarning() << "OSXKeychain::WriteItem(" << key << ") couldn't add comment" << comment
604 << ":" << qPrintable(errMsg);
605 }
606 }
607 CFRelease(itemRef);
608 }
609 return err;
610}
611
612// returns the kSecAccountItemAttr's of all items in the keychain
613OSStatus OSXKeychain::ItemList( SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain )
614{ OSStatus err;
615 SecKeychainSearchRef searchRef[2];
616 bool generateFolderList = ( osxKeyChain && osxKeyChain->isKDEChain && osxKeyChain->generateFolderList );
617
618 keyList.clear();
619 if( generateFolderList ){
620 osxKeyChain->serviceList.clear();
621 if( osxKeyChain->currentService.size() > 0 ){
622 osxKeyChain->serviceList.append(osxKeyChain->currentService);
623 }
624 }
625
626 err = SecKeychainSearchCreateFromAttributes( keychain, kSecGenericPasswordItemClass, NULL, &searchRef[0] );
627#if INTERNET_TOO
628 if( SecKeychainSearchCreateFromAttributes( keychain, kSecInternetPasswordItemClass, NULL, &searchRef[1] ) ){
629 searchRef[1] = NULL;
630 }
631#else
632 searchRef[1] = NULL;
633#endif
634 SecKeychainItemRef item;
635 QString errMsg;
636 if( isError(err, &errMsg) ){
637 kDebug() << "OSXKeychain::ItemList(" << (void*) keychain << "): SecKeychainSearchCreateFromAttributes failed" << qPrintable(errMsg);
638 }
639 else{
640 for( size_t i = 0 ; i < sizeof(searchRef)/sizeof(SecKeychainSearchRef) && !err ; ++i ){
641 if( searchRef[i] ){
642 while( !(err = SecKeychainSearchCopyNext( searchRef[i], &item )) ){
643 if( item ){
644 // whether the item will be listed in the keyList we return: by default it is
645 // (better an item shows up multiple times than not at all).
646 bool listItem = true;
647 SecKeychainAttribute attr = { kSecAccountItemAttr, 0, NULL };
648 SecKeychainAttributeList attrList = { 1, &attr };
649 UInt32 len = 0;
650 if( osxKeyChain && osxKeyChain->isKDEChain ){
651 // try to fetch the item's ServiceItem attribute
652 attr.tag = kSecServiceItemAttr;
653 if( !SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL ) ){
654 QString lbl = QString::fromUtf8( (char*)attr.data, attr.length );
655 // we got a service item attribute, which is where we store the kwallet folder info.
656 // If we disallow empty attributes, keychain items without service item attribute will
657 // appear in each folder that has a non-empty name. In other words, we allow a folder without name.
658 if( generateFolderList ){
659 // add the "folder" to the list if not already listed
660 if( !osxKeyChain->serviceList.contains(lbl) ){
661 osxKeyChain->serviceList.append(lbl);
662 }
663 }
664 else{
665 // only list the item if it's in the current "folder"
666 listItem = (lbl == osxKeyChain->currentService);
667 }
668 SecKeychainItemFreeContent( &attrList, NULL );
669 }
670 }
671 else{
672 // errors retrieving the service item attribute are ignored
673 }
674 if( listItem ){
675 attr.tag = kSecAccountItemAttr;
676 if( !(err = SecKeychainItemCopyContent( item, NULL, &attrList, &len, NULL )) ){
677 if( attr.length > 0 ){
678 keyList.append(QString::fromUtf8( (char*)attr.data, attr.length ));
679 }
680 SecKeychainItemFreeContent( &attrList, NULL );
681 }
682 else{
683 errMsg = errorString(err);
684 kDebug() << "SecKeychainItemCopyContent returned" << err << "=" << qPrintable(errMsg);
685 }
686 }
687 CFRelease(item);
688 }
689 }
690 if( err ){
691 errMsg = errorString(err);
692 }
693 CFRelease(searchRef[i]);
694 }
695 }
696 }
697 return err;
698}
699
700OSStatus OSXKeychain::Destroy( SecKeychainRef *keychain )
701{ OSStatus err = SecKeychainDelete(*keychain);
702 QString errMsg;
703 if( isError( err, &errMsg ) ){
704 kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error " << qPrintable(errMsg);
705 }
706 else{
707 kWarning() << "OSXKeychain::Destroy " << (void*) *keychain << ", error=" << err;
708 }
709 if( keychain ){
710 CFRelease(*keychain);
711 *keychain = NULL;
712 }
713 return err;
714}
715
716OSStatus OSXKeychain::Destroy( const QString &walletName )
717{ SecKeychainRef keychain;
718 OSStatus err = openKeychain( walletName, &keychain );
719 if( !err && keychain ){
720 err = Destroy(&keychain);
721 }
722 return err;
723}
OSXKeychain
Definition: qosxkeychain.h:91
OSXKeychain::currentService
QString currentService
Definition: qosxkeychain.h:100
OSXKeychain::IsOpen
static bool IsOpen(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:261
OSXKeychain::UnLock
static OSStatus UnLock(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:295
OSXKeychain::ItemList
static OSStatus ItemList(const SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain=NULL)
Definition: qosxkeychain.cpp:613
OSXKeychain::ItemType
static OSStatus ItemType(const QString &key, EntryType *entryType, const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:443
OSXKeychain::OSXKeychain
OSXKeychain()
Definition: qosxkeychain.cpp:147
OSXKeychain::RemoveItem
static OSStatus RemoveItem(const QString &key, const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:506
OSXKeychain::isKDEChain
bool isKDEChain
Definition: qosxkeychain.h:102
OSXKeychain::Path
static QString Path(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:250
OSXKeychain::name
QString name
Definition: qosxkeychain.h:99
OSXKeychain::lastReadService
QString lastReadService
Definition: qosxkeychain.h:100
OSXKeychain::Lock
static OSStatus Lock(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:310
OSXKeychain::EntryType
EntryType
Definition: qosxkeychain.h:98
OSXKeychain::Password
@ Password
Definition: qosxkeychain.h:98
OSXKeychain::Stream
@ Stream
Definition: qosxkeychain.h:98
OSXKeychain::HasItem
static bool HasItem(const QString &key, const SecKeychainRef keychain, OSStatus *errReturn, SecKeychainItemRef *itemRef)
use the keychain search functions to find the first matching item, if any, returning True if found.
Definition: qosxkeychain.cpp:343
OSXKeychain::close
void close()
Definition: qosxkeychain.cpp:197
OSXKeychain::Destroy
static OSStatus Destroy(SecKeychainRef *keychain)
Definition: qosxkeychain.cpp:700
OSXKeychain::renameItem
OSStatus renameItem(const QString &currentKey, const QString &newKey)
Definition: qosxkeychain.cpp:210
OSXKeychain::serviceList
QStringList serviceList
Definition: qosxkeychain.h:101
OSXKeychain::isOpen
bool isOpen()
Definition: qosxkeychain.h:120
OSXKeychain::WriteItem
static OSStatus WriteItem(const QString &key, const QByteArray &value, const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, EntryType *entryType=NULL, OSXKeychain *osxKeyChain=NULL)
Definition: qosxkeychain.cpp:525
OSXKeychain::~OSXKeychain
virtual ~OSXKeychain()
Definition: qosxkeychain.cpp:205
OSXKeychain::KeychainList
static OSStatus KeychainList(QStringList &theList)
Definition: qosxkeychain.cpp:232
OSXKeychain::ReadItem
static OSStatus ReadItem(const QString &key, QByteArray *value, const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, OSXKeychain *osxKeyChain=NULL)
Definition: qosxkeychain.cpp:384
OSXKeychain::reference
SecKeychainRef reference()
Definition: qosxkeychain.h:108
kDebug
#define kDebug
kWarning
#define kWarning
kdebug.h
currentKey
static const char * currentKey
Definition: kviewstatesaver.cpp:35
kwallet.h
KWallet
Definition: kwallet.cpp:56
OSTStr
static QString OSTStr(FourCharCode etype)
Definition: qosxkeychain.cpp:45
openKeychain
static OSStatus openKeychain(const QString &n, SecKeychainRef *keychain)
Definition: qosxkeychain.cpp:91
defaultChain
static SecKeychainRef defaultChain()
Definition: qosxkeychain.cpp:60
keyChainName
static QString keyChainName(SecKeychainRef keychain, QString *path=NULL)
Definition: qosxkeychain.cpp:74
basicWriteItem
static OSStatus basicWriteItem(const QByteArray *serviceName, const QByteArray &accountName, const QByteArray &value, const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL)
Definition: qosxkeychain.cpp:127
qosxkeychain.h
isError
static bool isError(OSStatus s, QString *errMsg)
Definition: qosxkeychain.h:82
errorString
static QString errorString(OSStatus s)
Definition: qosxkeychain.h:76
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal