I'm having trouble with my own AppleScript applications and Accessibility in "Security & Privacy".
I've written an application called "open cubase" that I've granted accessibility rights. I used Apple's advice on how to prevent repeated re-authorization (http://support.apple.com/kb/HT5914). But now even when the application is listed and selected in the Accessibility list, it says that it doesn't have assistive access.
And when I'm using
sudo sqlite3 /Library/Application\ Support/com.apple.TCC/Tcc.db 'SELECT * FROM access WHERE client LIKE "%%"'
to check what's going on, I can see this:
kTCCServiceAccessibility|com.atonus.open-cubase|0|1|0|??
Why is there ?? at the end of that? Is there anyone who would know how to resolve this?
I'm using OSX 10.9.2.
Update, based on feedback from the OP:
The OP's issue is not the use of property statements that normally cause an AppleScript-based application to self-modify the application bundle's embedded Contents/Resources/Scripts/main.scpt script file when property values change at runtime.
However, Apple's workaround at http://support.apple.com/kb/HT5914
IS specifically meant to address not requiring re-authorization as a result of this self-modification issue for a given version of an application.
is NOT meant to allow updating the app (changing its source code or resources) without re-authorization.
For security reasons there is NO way to grant one-time authorization to an app based on its bundle ID and then keep it authorized no matter how it changes (e.g., through updates).
You have two options:
Either: Re-authorize the application every time you update it.
After updating your app, go to System Preferences > Security & Privacy > Privacy > Accessibility and toggle the checkmark next to the list item representing your application (if you application isn't there, drag it there).
Note: With Apple's workaround in place - which for security reasons is NOT a good idea unless you truly need to use property statements that persist their values - it may be sufficient to re-sign the application - haven't verified that.
Or: Use a workaround - not recommended for security reasons:
Make your app an unchanging wrapper that loads the true script code at runtime from a location OUTSIDE the app bundle - that way, the app stays the same and doesn't require re-authorization even if the script file loaded at runtime changes.
Example: Say your true script code - involving code requiring assistive access - is stored as ~/Desktop.test.scpt; your wrapper application, once authorized, can then invoke that script with run script file ((path to home folder as text) & "Desktop:test.scpt")
I don't have a specific explanation, but a recommendation:
Do not use properties (e.g., property FNAME : "Input.txt") in your AppleScript-based applications: AppleScript persists these automatically (preserves their values between runs), but the feature is implemented awkwardly (the persisted values are written to the *.scpt file itself - this is what causes the repeated authorization problem) and flimsily (if you modify your application and save (the *.scpt file at the heart of the) application again, previously persistent values are lost).
If you stay away from properties, the problem with repeated authorization simply goes away (unless you update your application). You can roll your own persistence, e.g., via AppleScript's support for .plist (property-list) files (see the System Events dictionary).
You also won't need the workaround described in the linked support article (http://support.apple.com/kb/HT5914), which is also a plus, given that the workaround is based on opening up a security hole.
As for your specific question:
The ?? is the - unhelpful - representation of the csreq columnn value from the TCC.db database and is not a problem per se; OSX manages that column behind the scenes; it contains a fingerprint of sorts identifying the application in its specific current form (similar to an MD5 hash, though I have no idea what is actually being used), so as to be able to detect tampering later.
However, I suspect you may be looking at the wrong database entry:
I'm puzzled by your bundle ID being com.atonus.open-cubase: if your app is an AppleScript-based *.app bundle, its bundle ID would have the fixed prefix com.apple.ScriptEditor.id., e.g., com.apple.ScriptEditor.id.open-cubase. Did you manually modify the bundle ID via the bundle's Info.plist file, or am I missing something?
When the OS determines tampering/a change in an authorized application:
It resets the allowed column value to 0, i.e., revokes authorization
It resets the csreq column value to NULL.
Thus, after you've seen the ... is not allowed assistive access dialog, the database entry should be reported as kTCCServiceAccessibility|com.atonus.open-cubase|0|0|1| - note the changed Boolean flags and the absence of the ?? at the end.
Related
I've been trying to create a way to tell my (running) macOS app to open some files and supply some additional arguments to the command.
For cold-start apps, using the
$ open MyApp.app fileA.txt --args --foo-arg
would launch the app and I would be able to inspect the --foo-arg via UserDefaults/CommandLine/ProcessInfo. However, if the app is already running, the --foo-arg is missing from UserDefaults/ProcessInfo/CommandLine.
I've been struggling to wrap my head around a solution here because I have a few requirements which make things a tad more difficult.
Requirements
File paths sent to app must be opened/saved with sandbox permissions
Arguments and file paths must be intercepted by app at the same time.
Potential Solutions
XPC
Some people have suggested I use XPC but after reading about it, I'm not sure how that solution might look?
Do I have to create a Launch Agent app-companion which is always running so that it can detect command line operations and pass it to my app?
How does this work with sandboxing because each process has their own permission entitlements?
Apple Script
Should I use Apple script to tell my app to open these files with arguments, thus getting around the sandboxing feature?
When opening files via AppleScript, can I save those files swell?
URL Scheme
I can register my app to have its own URL scheme but the way NSApplicationDelegate handles the incoming URLs comes in two batches. First, the URLs it can open, followed by the URL schemes or the file paths it can't open. ie:
open -a MyApp.app myapp:foo; open -a MyApp.app file.txt
I can probably make this work but it's a tad tacky and I really want to do this the right way.
A command-line tool which ingests its arguments and turns them in to Apple Events is the way to go. You can see how this works from the user's point of view by installing the BBEdit command-line tools and then running man bbedit or man bbdiff in a Terminal window.
From your command-line tool's point of view, the "interesting" parts are:
Figure out whether the application is running: +[NSRunningApplication runningApplicationsWithBundleIdentifier:] will help with that.
If the application is not running, then use -[NSWorkspaceURLForApplicationWithBundleIdentifier:] to first locate the application by bundle ID, then -[NSWorkspace launchApplicationAtURL:options:configuration:error:] to launch the application. This will return an NSRunningApplication instance, or NIL and an error. (Make sure to handle the error case.)
Using the NSRunningApplication instance obtained from either step 1 or step 2, you can now use either the NSAppleEventDescriptor APIs or the low-level AppleEvent C APIs to construct an event. (The higher-level API is probably easier to use.)
That would go something like this:
Construct a target descriptor using the processIdentifier from your running application:
targetDesc = [NSAppleEventDescriptor descriptorWithProcessIdentifier: myRunningApplication.processIdentifier;
Construct an "open documents" event, addressed to your target application:
event = [NSAppleEventDescriptor appleEventWithEventClass: kCoreEventClass eventID: kAEOpenDocuments targetDescriptor: targetDesc returnID: kAutoGenerateReturnID transactionID: kAnyTransactionID];
Note: I use kCoreEventClass/kAEOpenDocuments as an example - if you're trying to open one or more files with additional information, that's fine. If you're doing some other work, then you should invent a four-character code for an event class which is specific to your application, and a four-character event ID which is unique to the operation you're requesting.
Add the command arguments to the event. For each argument, this consists of creating an appropriate descriptor based on the argument's intrinsic type (boolean, int, string, file URL), and then adding it to the event using a keyword parameter.
(An Apple Event "keyword" is a four-character code. You can invent your own, with constraints (don't use all-lowercase, and you can use ones defined in AEDataModel.h or AERegistry.h where they fit with your needs).
For each descriptor you create, add it to the event using -[setParamDescriptor: forKeyword:]:
myURLParamDesc = [NSAppleEventDescriptor descriptorWithFileURL: myFileURL];
[event setParamDescriptor: myURLParamDesc forKey: kMyFileParamKeyword];
When you've added all of the parameters to the event, send it:
[event sendWithOptions: kAENoReply timeout: FLOAT_MAX error: &error];
On the application side, you'll need to use -[NSAppleEventManager setEventHandler: andSelector: forEventClass: andID:]. This will get called for your custom event class and ID that you invented above, at which point you can use the descriptor APIs to pull the event apart and run your operation.
Sandboxing takes care of itself: your application automatically gets a sandboxing extension for files that it's been passed via Apple Events.
Your command-line tool is not sandboxed -- it can't be, because it's run from Terminal and (potentially) other nonsandboxed apps.
However, the tool must be signed with the hardened runtime, and with com.apple.security.automation.apple-events = YES and a com.apple.security.temporary-exception.apple-events naming your application's bundle identifier, so that the tool can send Apple Events to your application.
(And the tool will need an Info.plist with an NSAppleEventsUsageDescription string.)
I've left a fair amount as an exercise for the reader; but hopefully this will get you started.
Trying to detect the first install event from branch.io link (succesfully implement link creating and sharing). I am using Unity branch sdk. The feature i try to create:
user_1 creates and share link to user_2.
When user_2 opens the link and install app i need to reward both of them (with inner in-game coins)
So i succesfully implement the 1. but I cant understand how to detect is user_2 installs the app or simply open it. All data that comes from branch.io UniversalObject callback doesn't contain information that i need.
Which the correct way to detect the install from code?
Alex from Branch here.
The callback parameter you need is +is_first_session. This is one of the parameters returned when the Branch session is initiated each time your app opens (you can find all all these parameters here). If this returns true, then that device has just installed the app (instead of opening it).
However, note that when these parameters are returned, it's impossible to immediately determine if the user is new (what you want), the device is new (not what you want, since the reward could be given twice if the user has installed on multiple devices), or neither (the user deleted the app and reinstalled on the same device). You would probably want to hold off on actually awarding the referral points until after the user has logged in with some sort of unique ID.
Branch also has a built-in feature for tracking referral points that might be useful. That lets you configure all the rules using the dashboard UI instead of needing to do it programmatically inside your app.
In Apple's document about App Sandbox, I found something about Temporary Exception, and the value of Global Mach Service Temporary Exception is an array, but I do know what items can this array contains.
Actually, I hope there is place where I can check what entitlement items should be added for a specific function in sandbox app. For example, for a certain function, maybe I should add some com.apple.security.temporary-exception.mach-lookup.global-name and com.apple.security.temporary-exception.files.absolute-path.read-write, but the problem is what they are.
For now, when the function is unable to work in sandbox, I can find error message in system log, but still do not know what entitlements are needed.
documentation of sandbox is pretty inconsistent. what it suggests is to just use whatever you want to do, run the app and check console to see which functions fail. https://developer.apple.com/library/mac/documentation/Security/Conceptual/AppSandboxDesignGuide/DesigningYourSandbox/DesigningYourSandbox.html#//apple_ref/doc/uid/TP40011183-CH4-SW1
EDIT: if you're using temporary exceptions you'll need to add them in iTunes connect and explain each one in detail.
I enabled sandbox and I want to create data by bookmarkDataWithOptions.
If the URL is created by NSPanel that work very well. But, If I obtain URL without using NSOpenPanel, the bookmarkDataWithOptions method always return nil. why?
thank about If I want to set a special folder default can read/write without using NSOpenPanel.
How can i do?
Thanks
The main feature of the Sandbox is security. If an application could read/write an arbitrary folder without user permission, the security would be broken.
The App Sandbox Design Guide states clearly:
• Simulation of user input in Open and Save dialogs:
if your app depends on programmatically manipulating Open or Save dialogs to simulate or alter user input, your app is unsuitable for sandboxing.
The only way to achieve something similar, is to add a read/write entitlement to one of the preset directories (Documents, Pictures, Music, etc…). For further documentation, take a look at this guide.
I'm trying to override the default login/lock screen in OS X to allow the user to login in other way than providing a password (think fingerprint scanner or how "Knock to unlock" works), and I'm looking for a way to do it for hours now - all I found that looks useful is the Authorization Plugin ADC reference and this example: https://developer.apple.com/library/mac/samplecode/NameAndPassword/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004022
This NameAndPassword xcode project is a little outdated, but I managed to build it simply by specifying the Base SDK (there was a hardcoded wrong path), then I put the resulting .bundle file into /Library/Security/SecurityAgentPlugins directory. Nothing changed after I locked my screen, but I know I need to add the authorization role to /etc/authorization file, which I know no longer exists in Mavericks (there is this auth.db file and the whole auth API), but I'm therefore stuck here - I don't know how to put NameAndPassword inside this database.
Please let me know how do I do it right, or if you know some other way to achieve my goal.
I found a way to edit the database - at first, I tried direct /var/private/db/auth.db sqlite modifications, but it didn't work, so after some time I managed to do this easier than I thought I will:
security authorizationdb read system.login.console > outfile.plist
After this, you need to modify the resulting outfile.plist as it's said in the NullAuthPlugin readme:
<key>mechanisms</key>
<array>
<string>NameAndPassword:invoke</string>
(the last line is the one you need to add to the file).
Then, to save it to the database:
security authorizationdb write system.login.console < outfile.plist
Then the changes should be visible on any login/lock screen of your system, but be careful!
You will not be able to authenticate with current version of NameAndPassword example!
Be sure to estabilish a working SSH connection to your Mac before you modify the database, so you will be able to revert the changes using other device (just repeat the db modification process but this time remove the line you added before).