Search code examples
pythonpyobjc

calling secitemcopymatching in python


Tying to read items from Keychain using python (Novice at Mac python)

This is where I have got hacking together several things found in googlepedia

from ctypes import CDll, byref, Structure, POINTER
from Foundation import NSDictionary
class OpaqueObject:
   pass
OpaquePtr = POINTER(OpaqueObject)
Security = CDLL('/System/Library......../Security')
query = NSDictionary.dictionaryWithDictionary({<still working on this part>})
items = OpauePtr()
Security.SecItemCopyMatching(query, byref(items))

the {still working on this part}, currently reads {"foo":"bar"} which is of course an invalid query, but it should at least run

anyway it fails on the call of SecItemCopyMatching saying it doent know how to convert param1. I know the the function is defined to take CFDictionary but I expected the toll-free bridging to accept NSDictionary

Anyway I suspect this is all v bad code that is mixing 2 mac python mechanisms ctypes and PyObjc.


Solution

  • Toll-free bridging isn't applicable to Python ctypes. Consider using a CFDictionary instead:

    CoreFoundation = CDLL('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation')
    
    CoreFoundation.CFDictionaryCreateMutable.restype = OpaquePtr
    CoreFoundation.CFStringCreateWithBytes.restype = OpaquePtr
    def CFDictionaryAddStringKeyValue(d, k, v):
        ck = CoreFoundation.CFStringCreateWithBytes(None, k, len(k), 0, 0)
        cv = CoreFoundation.CFStringCreateWithBytes(None, v, len(v), 0, 0)
        CoreFoundation.CFDictionaryAddValue(d, ck, cv)
        CoreFoundation.CFRelease(ck)
        CoreFoundation.CFRelease(cv)
    
    query = CoreFoundation.CFDictionaryCreateMutable(None, 0, None, None)
    CFDictionaryAddStringKeyValue(query, "foo", "bar")
    

    Then you can just pass query into SecItemCopyMatching.