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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • 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>
31 using 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')
45 static 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 
60 static 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 
74 static 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 
91 static 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 
127 static 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 
147 OSXKeychain::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 
164 OSXKeychain::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 
197 void OSXKeychain::close()
198 {
199  if( keyChainRef ){
200  CFRelease(keyChainRef);
201  keyChainRef = NULL;
202  }
203 }
204 
205 OSXKeychain::~OSXKeychain()
206 {
207  close();
208 }
209 
210 OSStatus 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 
232 OSStatus 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 
250 QString 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 
261 bool 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 
284 bool 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 
295 OSStatus 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 
310 OSStatus 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 
328 OSStatus 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 
343 bool 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 
384 OSStatus 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 
443 OSStatus 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 
506 OSStatus 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 
525 OSStatus 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 
592 OSStatus 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
613 OSStatus 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 
700 OSStatus 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 
716 OSStatus 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 }
QList::clear
void clear()
QString::fromAscii
QString fromAscii(const char *str, int size)
OSTStr
static QString OSTStr(FourCharCode etype)
Definition: qosxkeychain.cpp:45
OSXKeychain::RemoveItem
static OSStatus RemoveItem(const QString &key, const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:506
errorString
static QString errorString(OSStatus s)
Definition: qosxkeychain.h:76
isError
static bool isError(OSStatus s, QString *errMsg)
Definition: qosxkeychain.h:82
OSXKeychain::Destroy
static OSStatus Destroy(SecKeychainRef *keychain)
Definition: qosxkeychain.cpp:700
kdebug.h
basicWriteItem
static OSStatus basicWriteItem(const QByteArray *serviceName, const QByteArray &accountName, const QByteArray &value, const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL)
Definition: qosxkeychain.cpp:127
OSXKeychain::Stream
Definition: qosxkeychain.h:98
QByteArray
currentKey
static const char * currentKey
Definition: kviewstatesaver.cpp:35
QString::size
int size() const
OSXKeychain::Path
static QString Path(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:250
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
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
OSXKeychain::Password
Definition: qosxkeychain.h:98
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
OSXKeychain::EntryType
EntryType
Definition: qosxkeychain.h:98
openKeychain
static OSStatus openKeychain(const QString &n, SecKeychainRef *keychain)
Definition: qosxkeychain.cpp:91
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
OSXKeychain::isOpen
bool isOpen()
Definition: qosxkeychain.h:120
OSXKeychain::renameItem
OSStatus renameItem(const QString &currentKey, const QString &newKey)
Definition: qosxkeychain.cpp:210
OSXKeychain::lastReadService
QString lastReadService
Definition: qosxkeychain.h:100
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString::clear
void clear()
QList::append
void append(const T &value)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
OSXKeychain::UnLock
static OSStatus UnLock(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:295
OSXKeychain::Lock
static OSStatus Lock(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:310
OSXKeychain::IsOpen
static bool IsOpen(const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:261
QFileInfo::fileName
QString fileName() const
keyChainName
static QString keyChainName(SecKeychainRef keychain, QString *path=NULL)
Definition: qosxkeychain.cpp:74
OSXKeychain
Definition: qosxkeychain.h:90
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::ItemType
static OSStatus ItemType(const QString &key, EntryType *entryType, const SecKeychainRef keychain)
Definition: qosxkeychain.cpp:443
QByteArray::constData
const char * constData() const
OSXKeychain::close
void close()
Definition: qosxkeychain.cpp:197
OSXKeychain::isKDEChain
bool isKDEChain
Definition: qosxkeychain.h:102
QString
OSXKeychain::serviceList
QStringList serviceList
Definition: qosxkeychain.h:101
defaultChain
static SecKeychainRef defaultChain()
Definition: qosxkeychain.cpp:60
QStringList
OSXKeychain::KeychainList
static OSStatus KeychainList(QStringList &theList)
Definition: qosxkeychain.cpp:232
QFileInfo
OSXKeychain::reference
SecKeychainRef reference()
Definition: qosxkeychain.h:108
qosxkeychain.h
OSXKeychain::OSXKeychain
OSXKeychain()
Definition: qosxkeychain.cpp:147
kwallet.h
OSXKeychain::currentService
QString currentService
Definition: qosxkeychain.h:100
OSXKeychain::ItemList
static OSStatus ItemList(const SecKeychainRef keychain, QStringList &keyList, OSXKeychain *osxKeyChain=NULL)
Definition: qosxkeychain.cpp:613
OSXKeychain::ReadItem
static OSStatus ReadItem(const QString &key, QByteArray *value, const SecKeychainRef keychain, SecKeychainItemRef *itemRef=NULL, OSXKeychain *osxKeyChain=NULL)
Definition: qosxkeychain.cpp:384
QString::length
int length() const
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QString::left
QString left(int n) const
QByteArray::size
int size() const
OSXKeychain::name
QString name
Definition: qosxkeychain.h:99
OSXKeychain::~OSXKeychain
virtual ~OSXKeychain()
Definition: qosxkeychain.cpp:205
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:01 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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