ronaldoussoren / pyobjc

The Python <-> Objective-C Bridge with bindings for macOS frameworks
https://pyobjc.readthedocs.io
560 stars 47 forks source link

Wrap Security* frameworks #135

Closed ronaldoussoren closed 6 years ago

ronaldoussoren commented 9 years ago

Original report by Anonymous.


For a particular project, I need to call [SFAuthorization authorizationWithFlags:rights:environment:], which resides in the SecurityInterface framework (although it may also require the Security and/or SecurityFoundation frameworks).

At the moment, this doesn't seem to be possible due to the type of the rights argument.

Some more background is provided on the mailinglist.

ronaldoussoren commented 7 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


Removing version: 3.0 (automated comment)

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


I've added bindings for SecurityFoundation and SecurityInterface, those will be included in PyObjC 4.1 (before the end of the year)

Those aren't very useful though because I did not yet add bindings to the Security framework. That framework is a lot more complex.

My current plan is to add bindings for that framework as well, but only the non-deprecated bits and possibly excluding the really low-level stuff (depending on how easy it is to bind the low-level APIs)

ronaldoussoren commented 6 years ago

Original comment by Oskari Timperi (Bitbucket: oswjk, GitHub: oswjk).


I've been banging my head against the table for a day now to get AuthorizationCreate to work. I'm trying to create an authorization that I would like to pass to SCPreferencesCreateWithAuthorization so that I could make permanent changes to network configuration. It would be nice to have the Security framework supported out of the box to make this work. Or is there something that I can do now to make this work?

My code is looking like this now: https://bitbucket.org/snippets/oswjk/ReBBza I tried to recreate that using Objective-C directly and I got that working as expected.

I have no idea if I have done something stupid. This is my first experience with pyobjc and I haven't got much experience from ObjC either :-)

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


I'm working on the Security framework bindings on branch "add-security-framework ".

The bindings are quite minimal at the moment, and don't provide AuthorizationCreate at this point (that will change).

I hope to finish work on these bindings before the end of the year, and with some luck next week.

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


The default branch now contains bindings to the Security frameworks, except for AuthorizationCreate and some other APIs dealing with AuthorizationRights :-(

I hope to add those later tonight. Adding these requires some C code, the authorization datastructures use constructs that cannot be represented with PyObjC metadata.

BTW. Your snippet is nice to have, Apple's documentation is fairly value w.r.t. how to use these APIs.

ronaldoussoren commented 6 years ago

Original comment by Oskari Timperi (Bitbucket: oswjk, GitHub: oswjk).


I'm not sure if the signatures in the snippet are okay. Good if there is some help in it though.

I can also provide you with the Obj-C version of that snippet tomorrow, if that's relevant at that point anymore.

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


In changeset a1cce1b75c39 the following code works:

#!python

import Security

rights = (
    Security.AuthorizationItem(name=b'system.services.systemconfiguration.network'),
)
flags = Security.kAuthorizationFlagDefaults | Security.kAuthorizationFlagInteractionAllowed | Security.kAuthorizationFlagExtendRights

status, authref = Security.AuthorizationCreate(rights, environment, flags, None)
print(status, authref)

Note that this code is lightly tested, and only using Python 3.6 (there's bound to be problems w.r.t. Python 2 support).

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


The bindings are basicly done, and will be included in PyObjC 4.1 later this year.

ronaldoussoren commented 6 years ago

Original comment by Oskari Timperi (Bitbucket: oswjk, GitHub: oswjk).


This is great! Thank you!

There's still a little issue with AuthorizationCopyRights:

#!python

from Security import (AuthorizationCreate, AuthorizationCopyRights,
    AuthorizationFree, AuthorizationItem, kAuthorizationEmptyEnvironment,
    kAuthorizationFlagDefaults, kAuthorizationFlagInteractionAllowed,
    kAuthorizationFlagExtendRights)
import objc

status, authref = AuthorizationCreate(None, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, None)
if status != 0:
    raise Exception('AuthorizationCreate: {}'.format(status))

rights = (
    AuthorizationItem(name=b'system.services.systemconfiguration.network'),
)

flags = (kAuthorizationFlagDefaults |
         kAuthorizationFlagInteractionAllowed |
         kAuthorizationFlagExtendRights)

status = AuthorizationCopyRights(authref, rights, None, flags, objc.NULL)

This fails with the following error message:

ValueError: depythonifying 'pointer', got 'bytes'

I was able to get it to work by changing the signature on line _Security.m:327 from

{_AuthorizationItem=^cL^vI}

to

{_AuthorizationItem=*L^vI}

After that change, the system pops up a dialog asking for credentials, which is exactly what should happen. :-)

Btw, the same issue happens also if passing the rights sequence directly to AuthorizationCreate.

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


That's odd. I cannot reproduce the issue.

Did you reinstall pyobjc-core as well? For technical reasons I had to add some code to pyobjc-core to properly support these APIs.

A future version will likely add a hook to pyobjc-core that allows me to move that code back to the right place.

ronaldoussoren commented 6 years ago

Original comment by Oskari Timperi (Bitbucket: oswjk, GitHub: oswjk).


Ah, I did not think about installing the other parts! The issue I was having was indeed fixed by reinstalling pyobjc-core.

Thank you again! :-)