Mac OS Login Items with Arguments? - macos

In Mac OS, I've created a few AppleScripts to add and remove start up applications (Login Items, under the Accounts system pane).
#!/bin/bash
/usr/bin/osascript -e "tell application \"System Events\" to make new login item with properties { path: \"$1\", hidden:false } at end"
Usage would be like this:
./addloginitem.sh /Applications/TextEdit.app
I'm curious if it's possible to have startup items that use arguments? I have a program that I would like to pass a "startup" argument to if it is running directly after a login.

It is possible however not by using "Login Items". You can use launchd to run commands when you login. It's a little complicated to use compared to login items but they're much more flexible and can do as you request. Just google for launchd instructions, setup the required plist file, and you'd have a powerful method for launching things at login.

Related

Send file URL and args to (running) macOS app via command line

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.

AppleScript - Change prefs when home

Alright guys, so I have a script set up to turn off the "require password on wake" function when I am at home. It pings my phone to see if I am connected to the network, and if not turns on lock to wake. So:
try
do shell script "ping -c2 X.X.X.X"
set theResult to the result
if theResult contains " 2 packets received," then
tell application "System Events"
tell security preferences
get properties
set properties to {require password to wake:false, require password to unlock:false}
end tell
end tell
end if
on error
tell application "System Events"
tell security preferences
get properties
set properties to {require password to wake:true, require password to unlock:true}
end tell
end tell
end try
end
This works just fine, however it asks to authenticate. I don't really want to use the enter text & return route, nor the clipboard route, because I don't want the password in the script... so is there a way to avoid the authentication?
If your goal is to enable/disable "password on wake" rather than to run that particular script without authentication, use either
tell application "System Events"
set require password to wake of security preferences to true
end tell
or
do shell script "defaults write com.apple.screensaver -int 1"
and the same with "to false" and "-int 0" to turn the setting off. None of these require authentication, as they're simply changing a user-level preference (stored in
~/Library/Preferences/com.apple.screensaver.plist
on my system, though this is an implementation detail you shouldn't rely on).
What triggers the authentication dialog in your script is the other property, "require password to unlock", equivalent to the "Require an administrator password to access locked preferences" option in the "Advanced..." part of Security Preferences. Under the hood, this option is equivalent to changing a number of settings in the Authorization Services database,
/private/etc/authorization
controlling whether various system-wide preferences may be left unlocked for unauthenticated changes.
System Events does appear to have a (less serious) bug, however: on my systems, setting "require password to unlock" has no effect, whether I authenticate as an admin or not.
There are two parts to this answer:
there is no way to pass the password, either via the script or via GUI Scripting, to the SecurityAgent application, which is in charge of the prompt (that is by design), nor can you suppress it altogether; this being said,
you can ignore the prompt and dismiss the window without inputting a password – your property settings will be applied even in that case (tested on OS X 10.7.4).
Reported as a Security issue to Apple as rdar://11484075
UPDATE: Apple Product Security does not consider this a security issue, but the bug itself is still tracked (I’ll have to guess, as it is closed as duplicate of another radar, which is not available on Openradar, but I’d expect the spurious dialog appearing to be the issue Apple has its eyes on).

Can an applescript "tell" call execute without visibly launching the application?

I have a Mail rule set up to launch the following applescript:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
-- do stuff, including...
CheckAddressBook(theName, theAddress)
end tell
end perform mail action with messages
end using terms from
on CheckAddressBook(theName, theAddress)
tell application "Address Book"
-- do stuff
end tell
end CheckAddressBook
Whenever this mail rule executes, it launches address book. Its not activated, but it suddenly shows up on my desktop. My question is, can tell blocks be instructed to launch the application silently, and quit when complete?
AppleScript can't control an application without it running. That's just the way it works. There are other methods you might use to access the Address Book database without launching the application, but if you're using AppleScript to get data from your Address Book database the application has to launch. My recommendation would be to simply add a quit command as suggested by Fábio.
To read the Address Book Database without launching "Address Book.app" I´d suggest to have a look at the command line tool "contacts" available for free here. You would then run it from Applescript like do shell script "/usr/bin/contacts Peter" and handle the values returned.

run kiosk .app at startup in mac

i want to startup an application (.app) at startup in a GUEST ACCOUNT in mac(snow leopard). THe app disables all shortcuts and dock as well(using kiosk). The user must enter a token number to login . I have made the app but i cant force every other service to stop . If i put it in boot sequence through system->services, the app does not come at front. instead it is launched but is in the doc and i have to left click it to launch it in front. :(
(i want to do this programmatically by editing the boot sequence of mac OS )
Problem is I used kiosk and it only works when my application is in front.
So i need to perform this that i cant figure out.
1) run my app only(after login and NO OTHER SERVICE) and rest of the mac should boot once my app has exited.
Thanks in advance
for any help that u can provide
I already tried to tell you in your previous question that you are probably going the wrong way. If you put something into a user´s login items, it can easily be deactivated by holding "shift" while logging in (which you probably do not want); also, completely hacking your Mac OS Startup routine (if it can be done) is a bit too much in my eyes.
You should seriously consider
using a login/policy banner (realised for example here) which would pop up over the loginwindow (so a user has to agree)
using a loginwindow hook combined with a logout hook to change the user password (e.g. based on a hidden password-list and using dscl -passwd or pwpolicy) once the user logs out. This way you should be able to generate passwords based on a list and validate them (token system)
Yours, Asmus
P.S.: on your previous question you commented on mipadi´s answer that you have found a great link, thought it´s missing. Could you maybe add this, as this might be interesting for other people in the future.

Is there a quick and easy way to dump the contents of a MacOS X keychain?

I'm looking for a way to dump (export) the contents of an OS X keychain into a file that I can easily process elsewhere, such as tab-delimited plaintext or something of the sort.
The Keychain Access app does not offer any such functionality, and getting a key's data involves opening each in turn, and having to type in the keychain's password to see the password stored with the key, every time.
After a bit of digging, I found somebody's solution by using AppleScript and the Keychain Scripting app to access keychains (can't link to individual post; scroll down about two thirds to the end of the page):
http://discussions.apple.com/thread.jspa?threadID=1398759
Using Keychain scripting, you can access all data fields of all the keys – including the plaintext password! – and it's fairly easy to dump this data into a text file etc. I've tested it and it works well.
However, this solution still involves having to confirm access to each key by clicking OK on a dialog. This is much better than having to type in the keychain's password every time, but it's still irritating. Furthermore, you have to confirm access twice for each key; once for Script Editor (or the script itself if it's running as an app) and once for Keychain Scripting. So, if you're processing a keychain with 100 keys, you have to manually click OK on 200 dialogs.
I'm now looking for a solution to get around this. I realize that as it's the purpose of keychains to safeguard the sensitive data and prevent precisely the kind of thing I'm trying to do, any such solution would probably involve some kind of hack.
I'd be very interested in your ideas!
Allright, I'm stupid. There's a command-line tool called security that does just this (and lots of other actions on keychains).
An example usage:
security dump-keychain -d login.keychain
This will dump all the data in the login.keychain (the default keychain for a user) as plaintext, including the passwords. You still have to confirm access , but only once for each key, and it's much faster than (and doesn't throw weird errors when trying to access certain fields) using AppleScript. And it's no hack.
Without the -d option, it will dump all the fields except for the password.
The dumped data for a key looks like this (for an internet key; program keys and certificates have other fields, but the format is the same):
keychain: "/Users/<username>/Library/Keychains/login.keychain"
class: "inet"
attributes:
0x00000007 <blob>="tech.slashdot.org (<username for this web login>)"
0x00000008 <blob>=<NULL>
"acct"<blob>="<username for this web login>"
"atyp"<blob>="form"
"cdat"<timedate>=0x32303038303432333038323730355A00 "20080423082705Z\000"
"crtr"<uint32>=<NULL>
"cusi"<sint32>=<NULL>
"desc"<blob>="Kennwort des Web-Formulars"
"icmt"<blob>="default"
"invi"<sint32>=<NULL>
"mdat"<timedate>=0x32303038303432333038323730355A00 "20080423082705Z\000"
"nega"<sint32>=<NULL>
"path"<blob>=<NULL>
"port"<uint32>=0x00000000
"prot"<blob>=<NULL>
"ptcl"<uint32>="http"
"scrp"<sint32>=<NULL>
"sdmn"<blob>=<NULL>
"srvr"<blob>="tech.slashdot.org"
"type"<uint32>=<NULL>
data:
"<the plaintext password for this key>"
Please read this: https://gist.github.com/rmondello/b933231b1fcc83a7db0b
Ignore:-----
I found a sollution to the "Always Allow" dialog in each key!
Just run the previous command with sudo.
sudo security dump-keychain -d login.keychain
This way you'll only need to enter your password two times. One on the Terminal to sudo and another to unlock the keychain! ;)
Have a nice day!
Update, there is now a tool that does this nicely:
Keychaindump is a proof-of-concept tool for reading OS X keychain passwords as root. It hunts for unlocked keychain master keys located in the memory space of the securityd process, and uses them to decrypt keychain files.
Source: https://github.com/juuso/keychaindump
Actually I was just looking for the same:
Modified applescript from github somebody posted. To be run in ScriptEditor and must be allowed in Preferences & Security.
set keychainPassword to "yourpasswordgoeshere"
tell application "System Events"
repeat while exists (processes where name is "SecurityAgent")
tell process "SecurityAgent"
delay 0.1
try
set value of text field 1 of window 1 to keychainPassword
click button "Allow" of window 1
end try
end tell
end repeat
end tell
You must click each window separetly in order to activate them. For that I used tool "murgaa auto clicker" I had known from runescape many years ago (http://www.murgaa.com/auto-clicker-mac/ seems still active). You just set shortcut for autoclicking (eg. Command+R) and set timer to 10ms and it works like charm.
Keysafe
Keysafe reads and decrypts Apple Keychain files. Use Keysafe to securely access your passwords and credentials without a Mac.
I wrote a tool called Keysafe to extract the contents of Keychain files. The tool is available on Mac, Windows, and Linux.
Keysafe is not free; a licence is required to fully decrypt a Keychain. Without a licence the contents are still extracted but the decrypted values are partially redacted and secure notes are not post-processed into RTFD files.
If you have a Keychain that does not "just work" with Keysafe, please get in touch. The Keychain format is expansive and finding edge cases is always interesting.
I found solution for not clicking "Allow" multiple times
sudo su
security dump-keychain -d /Users/YourUsername/Library/Keychains/login.keychain

Resources