123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- //
- // SKKeychain.m
- // Skim
- //
- // Created by Christiaan on 29/01/2018.
- /*
- This software is Copyright (c) 2018
- Christiaan Hofman. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- - Neither the name of Christiaan Hofman nor the names of any
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #import "SKKeychain.h"
- #import <Security/Security.h>
- @implementation SKKeychain
- + (SKPasswordStatus)getPassword:(NSString **)password item:(id *)itemPtr forService:(NSString *)service account:(NSString *)account {
- void *passwordData = NULL;
- UInt32 passwordLength = 0;
- const char *serviceData = [service UTF8String];
- const char *accountData = [account UTF8String];
- OSStatus err = SecKeychainFindGenericPassword(NULL, strlen(serviceData), serviceData, strlen(accountData), accountData, password ? &passwordLength : NULL, password ? &passwordData : NULL, NULL);
-
- if (err == noErr) {
- if (password) {
- *password = [[NSString alloc] initWithBytes:passwordData length:passwordLength encoding:NSUTF8StringEncoding];
- SecKeychainItemFreeContent(NULL, passwordData);
- }
- // if (itemPtr)
- // [*itemPtr autorelease];
- return SKPasswordStatusFound;
- } else if (err == errSecItemNotFound) {
- return SKPasswordStatusNotFound;
- } else {
- if (err != errSecUserCanceled)
- NSLog(@"Error %d occurred finding password: %@", (int)err, SecCopyErrorMessageString(err, NULL));
- return SKPasswordStatusError;
- }
- }
- static inline SecKeychainAttribute makeKeychainAttribute(SecKeychainAttrType tag, NSString *string) {
- const char *data = [string UTF8String];
- SecKeychainAttribute attr;
- attr.tag = tag;
- attr.length = strlen(data);
- attr.data = (void *)data;
- return attr;
- }
- + (void)setPassword:(NSString *)password item:(id)item forService:(NSString *)service account:(NSString *)account label:(NSString *)label comment:(NSString *)comment {
- const void *passwordData = [password UTF8String];
- UInt32 passwordLength = password ? strlen(passwordData) : 0;
- NSUInteger attrCount = 2;
- SecKeychainAttributeList attributes;
- SecKeychainAttribute attrs[4];
- OSStatus err;
-
- attrs[0] = makeKeychainAttribute(kSecServiceItemAttr, service);
- attrs[1] = makeKeychainAttribute(kSecAccountItemAttr, account);
- if (label)
- attrs[attrCount++] = makeKeychainAttribute(kSecLabelItemAttr, label);
- if (comment)
- attrs[attrCount++] = makeKeychainAttribute(kSecCommentItemAttr, comment);
-
- attributes.count = attrCount;
- attributes.attr = attrs;
-
- if (item) {
- // password was on keychain, so modify the keychain
- err = SecKeychainItemModifyAttributesAndData((SecKeychainItemRef)CFBridgingRetain(item), &attributes, passwordLength, passwordData);
- if (err != noErr && err != errSecUserCanceled)
- NSLog(@"Error %d occurred modifying password: %@", (int)err, SecCopyErrorMessageString(err, NULL));
- } else if (password) {
- // password not on keychain, so add it
- err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, NULL, NULL, NULL);
- if (err != noErr && err != errSecUserCanceled)
- NSLog(@"Error %d occurred adding password: %@", (int)err, SecCopyErrorMessageString(err, NULL));
- }
- }
- @end
|