Induce Mac graphical login from SSH

17

9

How do I induce the Mac graphical login from SSH? Is there a way to make the loginwindow process start a user session by running a command when remotely logged in via SSH as an admin on Mac OS X?

When the machine is at the login window (no user is currently logged in), I want it to open up a user's session as if I had clicked on the username and entered a password.

Solutions that don't involve scripting the GUI are highly preferred, but this Apple KB page may be of interest for those who go that route.

Sophie Alpert

Posted 2009-09-10T23:17:10.860

Reputation: 1 057

Answers

5

Not knowing the password makes things complicated, but maybe the solution is: is it possible to temporarily blank out a user's password? (And afterwards reset it to whatever it was before.)

As a start:

First, get the login window to display. Just log out the current user, use fast user switching, or use SSH:

cd "/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/"
sudo ./CGSession -suspend

Or, to switch to a specific user right away, which will probably show the login window (this suddenly no longer works on my 10.5 Leopard):

sudo ./CGSession -switchToUserID 501

What's shown now depends a bit on the System Preferences, but let's assume it's the users' icons and their names. To activate a name we'd have to type the first letters. Then, after Return, the password prompt shows. Alternatively one can select any name (like by pressing Arrow Down) and then press Option-Return to be prompted for both any username and its password. I don't know how one can tell which screen is shown, but let's save that for later...

So, to select the first (random) user name and press Option-Return, type a specific user name, hit Return, and type the password:

sudo osascript -e 'tell app "System Events"
  key code 125
  keystroke return using option down
  keystroke "the username"
  delay 1.0
  keystroke return
  delay 1.0
  keystroke "the password"
  delay 1.0
  keystroke return
end tell'

The above shows some error, which as far as I can tell does not limit the usage:

osascript[285] : 3891612: (connectAndCheck) Untrusted apps are not 
    allowed to connect to or launch Window Server before login.
_RegisterApplication(), FAILED TO establish the default connection to
    the WindowServer, _CGSDefaultConnection() is NULL.

Alternatively, use the language specific script from "Script the Login window through Apple Remote Desktop" (maybe one day the comments at that site will show a better solution):

tell process "SecurityAgent"
  set value of text field 1 of group 1 of window 1 to "the username"
  set value of text field 2 of group 1 of window 1 to "the password"
end tell
click button "Log In" of window 1 of application process "SecurityAgent"

But the main problem is: this still needs the password. However: obviously no password is needed when a user has a blank password. In fact, for blank passwords just clicking a user's icon is all that's needed. So, if sending keystrokes using AppleScript is acceptable, then maybe "all" that's left to figure out:

  • Is it possible to temporarily blank out a user's password, to allow for starting (or resuming) the session without knowing that password...?

  • Can one make the AppleScript error-proof? Like:

    • How to tell if the login window is visible? (maybe stat -f%Su /dev/console can help, as that yields root while the login window is displayed)
    • How to tell which login window is shown? (Like: one showing icons and login names, or a dropdown list, or maybe only a password prompt if someone selected to switch to some specific user?)
    • Get rid of the delays.
    • What about that error message?

(A note for testing: when using Screen Sharing it seems that setting the preference When controlling computers: Encrypt passwords and keystrokes only also retains the connection when the login window is shown, or after a user has successfully logged in. When using Encrypt all network data then my Mac needs to re-establish the Screen Sharing connection each time a login is shown or a user is switched.)

Arjan

Posted 2009-09-10T23:17:10.860

Reputation: 29 084

This is a good start, but it has two problems. First, it doesn't work if you're at the login window, which is what I wanted, and it asks for a password, which I'd prefer it didn't. Since it's root, it should be able to switch users without the password. – Sophie Alpert – 2009-09-13T23:45:36.393

Aha. I don't even know how to login as another user when sitting at the computer itself, so no cigar for sudo osascript -e 'tell app "System Events" to keystroke "password" & return'. With the screen locked, entering an administrative user name and password resumes the other user's session. But how to start a session for any user without knowing the password? (Just to be sure, if you know the password: another workaround might be Screen Sharing, which also works for the login screen. You'll need to reconnect the Screen Sharing after a specific user session is started or resumed.) – Arjan – 2009-09-14T07:11:00.440

This is good. I'd prefer a solution without manually simulating keystrokes, though. – Sophie Alpert – 2009-09-15T15:07:12.860

2I wonder if anyone knows how to start a session for somebody else. So, without considering the above answer, just in the daily use of Mac OS X: can an administrator log in as another user, without knowing that user's password? (Just like su on the command prompt, but then for a GUI session. Or just like when the screen is locked, where entering an administrative user name and password resumes the other user's session.) – Arjan – 2009-09-15T15:43:35.017

Perhaps it's not possible to do it without AppleScript keystroking: http://docs.info.apple.com/article.html?path=RemoteDesktop/3.0/en/ARDC869.html

– Sophie Alpert – 2009-09-15T17:50:50.220

Hmmm, good find, that article! If AppleScript and the keystrokes are acceptable, then maybe we should continue the quest then by finding a way to temporarily blank the password. – Arjan – 2009-09-15T23:43:19.777

I'd definitely prefer a solution that doesn't need fake keystroking. – Sophie Alpert – 2009-09-16T02:31:11.147

Okidoki, then I can't help you. – Arjan – 2009-09-16T10:53:17.997

1

I've been investigating this recently.

Put this in your app's PAM stack, or test with sshd:

session    required       pam_launchd.so launchd_session_type=Aqua

That goes a long way towards getting you a graphical session which is pretty close to a switched-out user session. In particular, it's in the right bootstrap namespace and has the correct bootstrap ports (I think). You can check the source for what pam_launchd does; it's using some reasonable-looking private library (vproc_priv.h functions in libvprop) to call the Mach routines for setting up the ports and namespace. It matches with all the (limited) docs Apple provides for the Mach-derived syscalls.

Next, you need to set your audit user-id to the that of the user with the BSM API, or the loginwindow won't talk to you on Lion.

The session looks very close to a switched-out session now if you check "launchctl blist", and some processes and services come to life nicely (like the pasteboard, and so on). In fact, everything except Finder and loginwindow is running. Until loginwindow runs though, you can't launch a graphical application, and the per-session loginwindow process is always spawned as a direct child of the global one. How does one poke the loginwindow process to launch a new loginwindow in the fresh session? I can't find a way to get the last piece in place!

Any help completing this answer gratefully received.

Nicholas Wilson

Posted 2009-09-10T23:17:10.860

Reputation: 224

0

I needed to log the same user into 25 different workstations, in order to do a software update. I was not able to run the 'osascript -e ...' command reliably from SSH sessions, even with sudo privileges. I was, however, able to run it via Apple Remote Desktop. If you have ARD:

  1. select your machines
  2. wake them up and log them out of other users, if needed
  3. choose "Send UNIX Command..." from the "Manage" menu
  4. paste Arjan's script (omitting the word 'sudo') into the command dialog box
  5. select and enter "Run command as: User: root"

I was delighted to find all 25 Mac Minis running Finder as the user, within less than a minute. Just to reiterate, with ARD you don't have to type in the sudo password on every machine. The lines you need to paste into the command dialog are (substituting a valid user name and password):

osascript -e 'tell app "System Events"
  key code 125
  keystroke return using option down
  keystroke "the username"
  delay 1.0
  keystroke return
  delay 1.0
  keystroke "the password"
  delay 1.0
  keystroke return
end tell'

William H. Hooper

Posted 2009-09-10T23:17:10.860

Reputation: 121

0

running the command with sudo allows you to set the script to unreadable by standard users. It's not perfect, but if your admin user is already compromised, the game is over anyway!

chmod u-r scriptname

my script looks like this, it works remotely when one user is already running, to switch to a second user via SSH (tested on Snow Leopard 10.6.3):

#!/bin/bash
#go to login window
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -switchToUserID 503

osascript -e 'tell app "System Events"
keystroke "password"
  delay 1.0
  keystroke return
end tell'

exit

zeigerpuppy

Posted 2009-09-10T23:17:10.860

Reputation: 1