Last active
February 16, 2020 06:45
-
-
Save dotsam/30d179ef9e005a149b118b72a13e32e7 to your computer and use it in GitHub Desktop.
launchd gpg-agent wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
<plist version="1.0"> | |
<dict> | |
<key>Label</key> | |
<string>ca.samedwards.gpg-agent</string> | |
<key>ProgramArguments</key> | |
<array> | |
<string>/usr/local/bin/gpg-agent-wrapper</string> | |
<string>/usr/local/bin/gpg-agent</string> | |
<string>--homedir</string> | |
<string>/Users/sam/.gnupg</string> | |
<string>--supervised</string> | |
</array> | |
<key>Sockets</key> | |
<dict> | |
<key>ssh</key> | |
<dict> | |
<key>SecureSocketWithKey</key> | |
<string>SSH_AUTH_SOCK</string> | |
<key>SockPathMode</key> | |
<integer>448</integer> | |
</dict> | |
<key>browser</key> | |
<dict> | |
<key>SocketFamily</key> | |
<string>Unix</string> | |
<key>SockPathMode</key> | |
<integer>448</integer> | |
<key>SockPathName</key> | |
<string>/Users/sam/.gnupg/S.gpg-agent.browser</string> | |
</dict> | |
<key>extra</key> | |
<dict> | |
<key>SocketFamily</key> | |
<string>Unix</string> | |
<key>SockPathMode</key> | |
<integer>448</integer> | |
<key>SockPathName</key> | |
<string>/Users/sam/.gnupg/S.gpg-agent.extra</string> | |
</dict> | |
<key>std</key> | |
<dict> | |
<key>SocketFamily</key> | |
<string>Unix</string> | |
<key>SockPathMode</key> | |
<integer>448</integer> | |
<key>SockPathName</key> | |
<string>/Users/sam/.gnupg/S.gpg-agent</string> | |
</dict> | |
</dict> | |
</dict> | |
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple wrapper to activate launchd sockets | |
// and set them up in the same way systemd would | |
// so that we can use gpg-agent in --supervised mode | |
#include <errno.h> | |
#include <err.h> | |
#include <unistd.h> | |
#include <launch.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
int get_launchd_socket(const char *sockName) | |
{ | |
// Get our sockets from launchd | |
int *fds = NULL; | |
size_t count = 0; | |
errno = launch_activate_socket(sockName, &fds, &count); | |
if (errno != 0 || fds == NULL || count < 1) | |
{ | |
warn("Error getting socket FD from launchd"); | |
return 0; | |
} | |
if (count != 1) | |
{ | |
warnx("Expected one FD from launchd, got %zu. Only using first socket.", count); | |
} | |
// Unset FD_CLOEXEC bit | |
fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD, 0) & ~FD_CLOEXEC); | |
if (fds) | |
{ | |
free(fds); | |
} | |
return 1; | |
} | |
int main(int argc, char **argv) | |
{ | |
// List of sockets we're going to check for | |
const char *sockets[] = { | |
"ssh", | |
"browser", | |
"extra", | |
"std"}; | |
int fds = 0; | |
char *fdsString = NULL; | |
char *fdNames = NULL; | |
char *tmpfdNames = NULL; | |
// Activate the sockets and count and store names | |
for (int i = 0; i < sizeof(sockets) / sizeof(sockets[0]); i++) | |
{ | |
if (get_launchd_socket(sockets[i])) | |
{ | |
fds++; | |
asprintf(&fdNames, (tmpfdNames == NULL ? "%s%s" : "%s:%s"), (tmpfdNames == NULL ? "" : tmpfdNames), sockets[i]); | |
if (tmpfdNames) | |
{ | |
free(tmpfdNames); | |
} | |
tmpfdNames = fdNames; | |
} | |
} | |
// Set the ENV var for our PID | |
char *pidString = NULL; | |
asprintf(&pidString, "%ld", (long)getpid()); | |
setenv("LISTEN_PID", pidString, 0); | |
free(pidString); | |
// Set the number of FDs we've opened | |
asprintf(&fdsString, "%d", fds); | |
setenv("LISTEN_FDS", fdsString, 0); | |
free(fdsString); | |
// And their names | |
setenv("LISTEN_FDNAMES", (fdNames == NULL ? "" : fdNames), 0); | |
free(fdNames); | |
// Launch the command we were passed | |
++argv; | |
if (*argv) | |
{ | |
execvp(*argv, argv); | |
err(1, "Error executing command"); | |
} | |
else | |
{ | |
errx(1, "No command specified"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment