File: osx_keychain.py

package info (click to toggle)
python-keyring 0.7.1-1%2Bdeb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 428 kB
  • sloc: python: 1,563; makefile: 29
file content (136 lines) | stat: -rw-r--r-- 5,293 bytes parent folder | download
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)