Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!


Click here to return to the 'Create protected passwordless ssh logins - Part 3 of 3' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Create protected passwordless ssh logins - Part 3 of 3
Authored by: jaysoffian on Jan 12, '04 12:32:01PM
Argh, my less than and greater than signs got swallowed by the submission system. Here's the awk scripts again:

  1. Create ~/Library/Libexec/getenvplist with the following contents:
    #!/bin/sh
    set -e
    PATH=/usr/bin:/bin
    export PATH
    plist=$HOME/.MacOSX/environment.plist
    awk '
            /<key>.*<\/key>/ {
                    s = index($0, "<key>" ) + 5
                    e = index($0, "</key>")
                    key = substr($0, s, e-s)
                    next
            }
            /<string>.*<\/string>/ {
                    s = index($0, "<string>" ) + 8
                    e = index($0, "</string>")
                    string = substr($0, s, e-s)
                    printf "%s=\"%s\"; export %s\n", key, string, key
                    next
            }
    ' $plist
    

  2. Create ~/Library/Libexec/setenvplist with the following contents:
    #!/bin/sh
    set -e
    PATH=/usr/bin:/bin
    export PATH
    plist=$HOME/.MacOSX/environment.plist
    plist_bak="${plist}.bak"
    rm -f $plist_bak
    cp -f "$plist" "$plist_bak"
    awk '
            (in_dict == 0) { print }
            /<dict>/ { 
                    in_dict = 1 
                    next
            }
            /<key>.*<\/key>/ {
                    s = index($0, "<key>" ) + 5
                    e = index($0, "</key>")
                    key = substr($0, s, e-s)
                    next
            }
            /<string>.*<\/string>/ {
                    s = index($0, "<string>" ) + 8
                    e = index($0, "</string>")
                    string = substr($0, s, e-s)
                    keys[key] = string
                    next
            }
            /<\/dict>/ {
                    in_dict = 0
                    for (i = 2; i < ARGC; i++) {
                            split(ARGV[i], a, "=")
                            keys[a[1]] = a[2]
                    }
                    for (key in keys) {
                            val = keys[key]
                            if (length(val) > 0) {
                                    printf "\t<key>%s</key>\n", key
                                    printf "\t<string>%s</string>\n", val
                            }
                    }
                    print
                    next
            }
    ' $plist_bak "$@" > $plist
    plutil -convert xml1 $plist
    

My summary also had some less than and greater than signs swallowed. Here again:

So what's going on here. Let's follow the chain of events.

  1. Upon login, the global com.apple.loginwindow plist is read and /Library/Hooks/LoginHook is executed as root, with the username that just logged in as its argument.

  2. /Library/Hooks/LoginHook then executes /Users/<username>/Hooks/LoginHook (if it exists) as the user.

  3. The per-user LoginHook then runs ~/Library/Libexec/ssh-agent. In the background (so as not to stall the login...) it then waits 2 seconds and calls ~/Library/Libexec/ssh-add.

  4. ~/Library/Libexec/ssh-agent calls the system ssh-agent. This starts up ssh-agent. Upon startup, ssh-agent emits some important environment variables. Namely, SSH_AUTH_SOCK and SSH_AGENT_PID. These are "captured" by ~/Library/Libexec/ssh-agent since it evals the output of "/usr/bin/ssh-agent -s". ~/Library/Libexec/ssh-agent then calls setenvplist to add these variables to ~/.MacOSX/environment.plist. It also adds a couple other ssh related environment variables.

  5. The per-user LoginHook then finishes which allows the login process to continue. loginwindow will read the updated .MacOSX/environment.plist and these environment variables will then be available to any user-run processes.

  6. 2 seconds or so after the per-user LoginHook was run, it runs ~/Library/Libexec/ssh-add. The delay was to give the system time to unlock the default keychain. ~/Library/Libexec/ssh-add sets up DISPLAY and SSH_ASKPASS appropriately then calls the system ssh-add. ssh-add, seeing both DISPLAY and SSH_ASKPASS set, and with stdin redirected from /dev/null, will then execute the SSH_ASKPASS program, which in this case is ~/Library/Libexec/ssh-askpass.

  7. ~/Library/Libexec/ssh-askpass, finally, just executes our keychain utility with the appropriate arguments. That utility will then emit the passphrase on stdout, which is read by /usr/bin/ssh-add (on stdin). /usr/bin/ssh-add then unlocks your ssh keys and provides them to ssh-agent.

Now for what happens on logout:

  1. Upon logout, the global com.apple.loginwindow plist is read and /Library/Hooks/LogoutHook is executed as root, with the username that just logged out as its argument.

  2. /Library/Hooks/LogoutHook then executes /Users/<username>/Hooks/LogoutHook (if it exists) as the user.

  3. The per-user LogoutHook then run getenvplist. This is needed because the user has already been logged out, and the per-user environment variables are no longer available. getenvplist retrieves the variables from .MacOSX/environment.plist and makes them available (which is why the output is "eval'd"). ssh-agent-k is then run which kills the running per-user ssh-agent process.


[ Reply to This | # ]