1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#!/usr/bin/python
import sys
if sys.platform != 'darwin':
raise ImportError('Mac OS X only module')
from ctypes import CDLL, CFUNCTYPE, c_void_p, c_uint32, \
c_int32, c_char_p, byref, POINTER, memmove, create_string_buffer
# Types
SecKeychainRef = c_void_p
SecKeychainItemRef = c_void_p
OSStatus = c_int32
# Constants
errSecSuccess = 0
errSecUnimplemented = -4
errSecParam = -50
errSecAllocate = -108
errSecNotAvailable = -25291
errSecReadOnly = -25292
errSecAuthFailed = -25293
errSecNoSuchKeychain = -25294
errSecInvalidKeychain = -25295
errSecDuplicateKeychain = -25296
errSecDuplicateCallback = -25297
errSecInvalidCallback = -25298
errSecDuplicateItem = -25299
errSecItemNotFound = -25300
errSecBufferTooSmall = -25301
errSecDataTooLarge = -25302
errSecNoSuchAttr = -25303
errSecInvalidItemRef = -25304
errSecInvalidSearchRef = -25305
errSecNoSuchClass = -25306
errSecNoDefaultKeychain = -25307
errSecInteractionNotAllowed = -25308
errSecReadOnlyAttr = -25309
errSecWrongSecVersion = -25310
errSecKeySizeNotAllowed = -25311
errSecNoStorageModule = -25312
errSecNoCertificateModule = -25313
errSecNoPolicyModule = -25314
errSecInteractionRequired = -25315
errSecDataNotAvailable = -25316
errSecDataNotModifiable = -25317
errSecCreateChainFailed = -25318
errSecInvalidPrefsDomain = -25319
errSecACLNotSimple = -25240
errSecPolicyNotFound = -25241
errSecInvalidTrustSetting = -25242
errSecNoAccessForItem = -25243
errSecInvalidOwnerEdit = -25244
errSecTrustNotAvailable = -25245
errSecUnsupportedFormat = -25256
errSecUnknownFormat = -25257
errSecKeyIsSensitive = -25258
errSecMultiplePrivKeys = -25259
errSecPassphraseRequired = -25260
errSecInvalidPasswordRef = -25261
errSecInvalidTrustSettings = -25262
errSecNoTrustSettings = -25263
errSecPkcs12VerifyFailure = -25264
errSecDecode = -26275
# Functions
_dll = CDLL('/System/Library/Frameworks/Security.framework/Versions/A/Security')
_core = CDLL('/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices')
SecKeychainOpen = CFUNCTYPE(OSStatus, c_char_p, POINTER(SecKeychainRef))(('SecKeychainOpen', _dll))
SecKeychainFindGenericPassword = CFUNCTYPE(OSStatus, SecKeychainRef, c_uint32,
c_char_p, c_uint32, c_char_p,
POINTER(c_uint32), POINTER(c_void_p),
POINTER(SecKeychainItemRef))(('SecKeychainFindGenericPassword', _dll))
SecKeychainAddGenericPassword = CFUNCTYPE(OSStatus, SecKeychainRef, c_uint32, c_char_p,
c_uint32, c_char_p, c_uint32,
c_char_p, POINTER(SecKeychainItemRef))(('SecKeychainAddGenericPassword', _dll))
SecKeychainItemModifyAttributesAndData = CFUNCTYPE(OSStatus, SecKeychainItemRef, c_void_p, c_uint32, c_void_p)(('SecKeychainItemModifyAttributesAndData', _dll))
SecKeychainItemFreeContent = CFUNCTYPE(OSStatus, c_void_p, c_void_p)(('SecKeychainItemFreeContent', _dll))
def password_set(realmstring, username, password):
if username is None:
username = ''
keychain = SecKeychainRef()
if SecKeychainOpen('login.keychain', byref(keychain)):
raise OSError("Can't access the login keychain")
try:
item = SecKeychainItemRef()
status = SecKeychainFindGenericPassword(keychain, len(realmstring), realmstring, len(username), username, None, None, byref(item))
if status:
if status == errSecItemNotFound:
status = SecKeychainAddGenericPassword(keychain, len(realmstring), realmstring, len(username), username, len(password), password, None)
else:
status = SecKeychainItemModifyAttributesAndData(item, None, len(password), password)
_core.CFRelease(item)
if status:
raise OSError("Can't store password in keychain")
finally:
_core.CFRelease(keychain)
def password_get(realmstring, username):
if username is None:
username = ''
keychain = SecKeychainRef()
if SecKeychainOpen('login.keychain', byref(keychain)):
raise OSError("Can't access the login keychain")
try:
length = c_uint32()
data = c_void_p()
status = SecKeychainFindGenericPassword(keychain, len(realmstring), realmstring,
len(username), username,
byref(length), byref(data), None)
if status == 0:
password = create_string_buffer(length.value)
memmove(password, data.value, length.value)
password = password.raw
SecKeychainItemFreeContent(None, data)
elif status == errSecItemNotFound:
password = None
else:
raise OSError("Can't fetch password from system")
return password
finally:
_core.CFRelease(keychain)
|