123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /******************************************************************************
- * Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.com> *
- * *
- * This program is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
- * or FITNESS FOR A PARTICULAR PURPOSE. For licensing and distribution *
- * details, check the accompanying file 'COPYING'. *
- *****************************************************************************/
- #include "keychain_p.h"
- #import <Foundation/Foundation.h>
- #import <Security/Security.h>
- using namespace QKeychain;
- struct ErrorDescription
- {
- QKeychain::Error code;
- QString message;
- ErrorDescription(QKeychain::Error code, const QString &message)
- : code(code), message(message) {}
- static ErrorDescription fromStatus(OSStatus status)
- {
- switch(status) {
- case errSecSuccess:
- return ErrorDescription(QKeychain::NoError, Job::tr("No error"));
- case errSecItemNotFound:
- return ErrorDescription(QKeychain::EntryNotFound, Job::tr("The specified item could not be found in the keychain"));
- case errSecUserCanceled:
- return ErrorDescription(QKeychain::AccessDeniedByUser, Job::tr("User canceled the operation"));
- case errSecInteractionNotAllowed:
- return ErrorDescription(QKeychain::AccessDenied, Job::tr("User interaction is not allowed"));
- case errSecNotAvailable:
- return ErrorDescription(QKeychain::AccessDenied, Job::tr("No keychain is available. You may need to restart your computer"));
- case errSecAuthFailed:
- return ErrorDescription(QKeychain::AccessDenied, Job::tr("The user name or passphrase you entered is not correct"));
- case errSecVerifyFailed:
- return ErrorDescription(QKeychain::AccessDenied, Job::tr("A cryptographic verification failure has occurred"));
- case errSecUnimplemented:
- return ErrorDescription(QKeychain::NotImplemented, Job::tr("Function or operation not implemented"));
- case errSecIO:
- return ErrorDescription(QKeychain::OtherError, Job::tr("I/O error"));
- case errSecOpWr:
- return ErrorDescription(QKeychain::OtherError, Job::tr("Already open with with write permission"));
- case errSecParam:
- return ErrorDescription(QKeychain::OtherError, Job::tr("Invalid parameters passed to a function"));
- case errSecAllocate:
- return ErrorDescription(QKeychain::OtherError, Job::tr("Failed to allocate memory"));
- case errSecBadReq:
- return ErrorDescription(QKeychain::OtherError, Job::tr("Bad parameter or invalid state for operation"));
- case errSecInternalComponent:
- return ErrorDescription(QKeychain::OtherError, Job::tr("An internal component failed"));
- case errSecDuplicateItem:
- return ErrorDescription(QKeychain::OtherError, Job::tr("The specified item already exists in the keychain"));
- case errSecDecode:
- return ErrorDescription(QKeychain::OtherError, Job::tr("Unable to decode the provided data"));
- }
- return ErrorDescription(QKeychain::OtherError, Job::tr("Unknown error"));
- }
- };
- void ReadPasswordJobPrivate::scheduledStart()
- {
- NSDictionary *const query = @{
- (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
- (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
- (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
- (__bridge id) kSecReturnData: @YES,
- };
- CFTypeRef dataRef = nil;
- const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef);
- data.clear();
- mode = Binary;
- if (status == errSecSuccess) {
- if (dataRef)
- data = QByteArray::fromCFData((CFDataRef) dataRef);
- q->emitFinished();
- } else {
- const ErrorDescription error = ErrorDescription::fromStatus(status);
- q->emitFinishedWithError(error.code, Job::tr("Could not retrieve private key from keystore: %1").arg(error.message));
- }
- if (dataRef)
- [dataRef release];
- }
- void WritePasswordJobPrivate::scheduledStart()
- {
- NSDictionary *const query = @{
- (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
- (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
- (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
- };
- OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, nil);
- if (status == errSecSuccess) {
- NSDictionary *const update = @{
- (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(),
- };
- status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) update);
- } else {
- NSDictionary *const insert = @{
- (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
- (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
- (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
- (__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(),
- };
- status = SecItemAdd((__bridge CFDictionaryRef) insert, nil);
- }
- if (status == errSecSuccess) {
- q->emitFinished();
- } else {
- const ErrorDescription error = ErrorDescription::fromStatus(status);
- q->emitFinishedWithError(error.code, tr("Could not store data in settings: %1").arg(error.message));
- }
- }
- void DeletePasswordJobPrivate::scheduledStart()
- {
- const NSDictionary *const query = @{
- (__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
- (__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
- (__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
- };
- const OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query);
- if (status == errSecSuccess) {
- q->emitFinished();
- } else {
- const ErrorDescription error = ErrorDescription::fromStatus(status);
- q->emitFinishedWithError(error.code, Job::tr("Could not remove private key from keystore: %1").arg(error.message));
- }
- }
|