Skip to content

Instantly share code, notes, and snippets.

@pudquick
Last active February 28, 2020 17:09
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pudquick/4cf32c2b403bf0be23b268d6dd3cf803 to your computer and use it in GitHub Desktop.
Save pudquick/4cf32c2b403bf0be23b268d6dd3cf803 to your computer and use it in GitHub Desktop.
Manipulating the Keychain in macOS via python and pyobjc
from Foundation import NSBundle
import objc, array
# from CoreFoundation import CFGetTypeID
Security = NSBundle.bundleWithPath_('/System/Library/Frameworks/Security.framework')
# First we need the CF TypeIDs to build some signatures
functions = [
('SecKeychainGetTypeID', 'I'),
]
objc.loadBundleFunctions(Security, globals(), functions)
# Build out our CF type signatures
objc.registerCFSignature('SecKeychainRef', '^{__SecKeychain=}', SecKeychainGetTypeID())
functions = [
('SecKeychainCopyDomainSearchList', 'IIo^^{__CFArray}'),
('SecKeychainSetDomainSearchList', 'II^{__CFArray}'),
('SecKeychainGetPath', 'I^{__SecKeychain=}N^IN^t', '', dict(
arguments={2: dict(type='N^t', c_array_of_variable_length=True,)})),
('SecKeychainOpen', 'I*o^^{__SecKeychain=}'),
('SecKeychainGetStatus', 'I^{__SecKeychain=}o^I'),
('SecKeychainLock', 'I^{__SecKeychain=}'),
('SecKeychainUnlock', 'I^{__SecKeychain=}I*I'),
]
# SecKeychainCopySettings
# SecKeychainSetSettings
objc.loadBundleFunctions(Security, globals(), functions)
kSecPreferencesDomainUser = 0
kSecPreferencesDomainSystem = 1
kSecPreferencesDomainCommon = 2
kSecPreferencesDomainDynamic = 3
MAX_PATH = 1024
# Pretty up some of the functions
_SecKeychainGetPath = SecKeychainGetPath
def SecKeychainGetPath(seckeychainref, path_len=None):
if path_len is None:
path_len = MAX_PATH
path_buf = array.array('c','\0'*MAX_PATH)
err, path_len, path_buf = _SecKeychainGetPath(seckeychainref, path_len, path_buf)
if err == 0:
return (err, path_buf[:path_len].tostring())
return (err, '')
# Example usages
err, keychains = SecKeychainCopyDomainSearchList(kSecPreferencesDomainUser, None)
err, path = SecKeychainGetPath(keychains[0])
err, status = SecKeychainGetStatus(keychains[0],None)
err, keychain = SecKeychainOpen('login.keychain', None)
err, path = SecKeychainGetPath(keychain)
@mosen
Copy link

mosen commented Feb 3, 2017

functions = [
    ('SecKeychainOpen', 'I*o^^{__SecKeychain=}'),
    ('SecKeychainUnlock', 'I^{__SecKeychain=}I*I'),
    ('SecKeychainCopySettings', 'I^{__SecKeychain=}o^{SecKeychainSettings}')
]

# ...

SecKeychainSettings = objc.createStructType("SecKeychainSettings", b"{SecKeychainSettings=IBBI}",
                                            ["version", "lockOnSleep", "useLockInterval", "lockInterval"])
objc.createStructAlias("SecKeychainSettings", "{SecKeychainSettings}", SecKeychainSettings)

status, kcsettings = SecKeychainCopySettings(self.ref, None)

print(kcsettings)

Output

<SecKeychainSettings version=0 lockOnSleep=False useLockInterval=False lockInterval=1839023225>

@sheagcraig
Copy link

Oh yeah!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment