[128050] trunk/dports/security/gpg-agent

ionic at macports.org ionic at macports.org
Tue Nov 11 18:40:08 PST 2014


Revision: 128050
          https://trac.macports.org/changeset/128050
Author:   ionic at macports.org
Date:     2014-11-11 18:40:07 -0800 (Tue, 11 Nov 2014)
Log Message:
-----------
gpg-agent: add launchd patchset. #43584

Modified Paths:
--------------
    trunk/dports/security/gpg-agent/Portfile

Added Paths:
-----------
    trunk/dports/security/gpg-agent/files/gpg-agent.plist.default
    trunk/dports/security/gpg-agent/files/patch-agent_gpg-agent.c-launchd.diff

Modified: trunk/dports/security/gpg-agent/Portfile
===================================================================
--- trunk/dports/security/gpg-agent/Portfile	2014-11-12 02:28:03 UTC (rev 128049)
+++ trunk/dports/security/gpg-agent/Portfile	2014-11-12 02:40:07 UTC (rev 128050)
@@ -6,6 +6,7 @@
 # When updating gpg-agent, update gnupg2 also if applicable.
 name                gpg-agent
 version             2.0.26
+revision            1
 categories          security mail
 maintainers         ionic openmaintainer
 license             GPL-3+
@@ -25,6 +26,11 @@
 checksums           rmd160  874040ed8fad12067cbe67c8da222b2ad99a5a96 \
                     sha256  7758e30dc382ae7a7167ed41b7f936aa50af5ea2d6fccdef663b5b750b65b8e0
 
+startupitem.location \
+                    LaunchAgents
+
+set launchd_dir     ${prefix}/etc/${startupitem.location}/${startupitem.uniquename}/
+
 configure.args      --enable-agent-only \
                     --with-pinentry-pgm=${prefix}/bin/pinentry
 
@@ -46,11 +52,88 @@
 
 patchfiles          patch-po_Makevars.diff
 
+# DO NOT USE. Maintainer-only helper for debugging purposes. DO NOT USE.
+#configure.cflags-append -g3 -ggdb3 -gdwarf-2 -O0
+
+platform darwin {
+    patchfiles-append        patch-agent_gpg-agent.c-launchd.diff
+    configure.cflags-append  -F/System/Library/Frameworks/CoreFoundation.framework \
+                             -D__APPLE_LAUNCHD__
+
+    if { [tbool startupitem.install] } {
+        notes-append "
+                       A startup item has been installed that will aid in
+                       starting ${name} with launchd. It is disabled
+                       by default. Execute the following command to launch
+                       ${name} at user login:
+
+                       launchctl load -w /Library/${startupitem.location}/${startupitem.plist}
+
+                       To actually start ${name}, log out and back in.
+                     "
+    } else {
+        notes-append "
+                       A startup item was not installed for ${name}.
+                       Some programs which depend on ${name} might not function properly,
+                       most notably eMail clients.
+                       Execute the following command to launch ${name} at user login:
+
+                       launchctl load -w ${launchd_dir}/${startupitem.plist}
+
+                       To actually start ${name}, log out and back in.
+                     "
+    }
+}
+
+post-extract {
+    xinstall -m 644 -W ${filespath} gpg-agent.plist.default ${worksrcpath}
+}
+
+post-configure {
+    reinplace -W "${worksrcpath}" "s|@PREFIX@|${prefix}|g" gpg-agent.plist.default
+    reinplace -W "${worksrcpath}" "s|@LABEL@|${startupitem.uniquename}|g" gpg-agent.plist.default
+
+    if {${os.platform} eq "darwin"} {
+        reinplace -W "${worksrcpath}" "s|@SSH_SUPPORT@||g" gpg-agent.plist.default
+    }
+}
+
 post-destroot {
     # Prevent conflict with gnupg2 port.
     delete ${destroot}${prefix}/share/doc/gnupg/README
+
+    if {${os.platform} eq "darwin"} {
+        xinstall -m 755 -d \
+            ${destroot}${launchd_dir}
+        xinstall -m 444 \
+            ${worksrcpath}/gpg-agent.plist.default \
+            ${destroot}${launchd_dir}${startupitem.plist}.default
+    }
 }
 
+post-activate {
+    if {${os.platform} eq "darwin"} {
+        xinstall -m 644 \
+            ${launchd_dir}${startupitem.plist}.default \
+            ${launchd_dir}${startupitem.plist}
+
+        # install the plist, if startupitem.install is set
+        if {[tbool startupitem.install]} {
+            ln -sf "${launchd_dir}${startupitem.plist}" "/Library/${startupitem.location}"
+        }
+    }
+}
+
+post-deactivate {
+    if {${os.platform} eq "darwin"} {
+        delete ${launchd_dir}${startupitem.plist}
+
+        if { [tbool startupitem.install] } {
+           delete "/Library/${startupitem.location}/${startupitem.plist}"
+        }
+    }
+}
+
 variant no_pinentry description {Do not use pinentry to handle user input} {
     depends_lib-delete      port:pinentry
     configure.args-delete   --with-pinentry-pgm=${prefix}/bin/pinentry

Added: trunk/dports/security/gpg-agent/files/gpg-agent.plist.default
===================================================================
--- trunk/dports/security/gpg-agent/files/gpg-agent.plist.default	                        (rev 0)
+++ trunk/dports/security/gpg-agent/files/gpg-agent.plist.default	2014-11-12 02:40:07 UTC (rev 128050)
@@ -0,0 +1,55 @@
+<?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>@LABEL@</string>
+
+	<!-- Please uncomment on 10.4; OnDemand doesn't work properly there. -->
+	<!--
+	<key>OnDemand</key>
+	<false />
+	-->
+
+	<key>ProgramArguments</key>
+	<array>
+		<string>@PREFIX@/bin/gpg-agent</string>
+		<string>--write-env-file</string>
+		<string>--no-use-standard-socket</string>
+		<string>--launchd</string>
+		<!-- at SSH_SUPPORT@
+		<string>--enable-ssh-support</string>
+		@SSH_SUPPORT at -->
+	</array>
+
+	<key>RunAtLoad</key>
+	<true/>
+
+	<!-- Restart the job, should it crash. -->
+	<key>KeepAlive</key>
+	<dict>
+		<key>SuccessfulExit</key>
+		<false />
+	</dict>
+
+	<key>ServiceIPC</key>
+	<true/>
+
+	<key>Sockets</key>
+	<dict>
+		<key>Listeners_agent</key>
+		<dict>
+			<key>SecureSocketWithKey</key>
+			<string>GPG_AGENT_INFO</string>
+		</dict>
+
+		<!-- at SSH_SUPPORT@
+		<key>Listeners_ssh</key>
+		<dict>
+			<key>SecureSocketWithKey</key>
+			<string>SSH_AUTH_SOCK</string>
+		</dict>
+		@SSH_SUPPORT at -->
+	</dict>
+</dict>
+</plist>

Added: trunk/dports/security/gpg-agent/files/patch-agent_gpg-agent.c-launchd.diff
===================================================================
--- trunk/dports/security/gpg-agent/files/patch-agent_gpg-agent.c-launchd.diff	                        (rev 0)
+++ trunk/dports/security/gpg-agent/files/patch-agent_gpg-agent.c-launchd.diff	2014-11-12 02:40:07 UTC (rev 128050)
@@ -0,0 +1,392 @@
+--- agent/gpg-agent.c.old
++++ agent/gpg-agent.c
+@@ -47,6 +47,79 @@
+ #include <unistd.h>
+ #include <signal.h>
+ #include <pth.h>
++#ifdef __APPLE_LAUNCHD__
++# include <launch.h>
++
++extern char **environ;
++
++# define GPG_ENV_SOCKET_AGENT "GPG_AGENT_INFO"
++# define GPG_ENV_SOCKET_SSH "SSH_AUTH_SOCK"
++# define GPG_ENV_PID_SSH "SSH_AGENT_PID"
++# define GPG_SOCKET_NAME_AGENT "Listeners_agent"
++# define GPG_SOCKET_NAME_SSH "Listeners_ssh"
++
++# define PASS_ENV_VAR_TO_LAUNCHD(KEY, VALUE)                                               \
++do                                                                                         \
++  {                                                                                        \
++    launch_data_t resp, msg, tmp, tmp_value;                                               \
++    msg = launch_data_alloc (LAUNCH_DATA_DICTIONARY);                                      \
++    tmp = launch_data_alloc (LAUNCH_DATA_DICTIONARY);                                      \
++                                                                                           \
++    if (!VALUE || !KEY || (strlen (KEY) == 0)) {                                           \
++      log_error ("invalid key or value given: `" #KEY "', `" #VALUE "'.\n");               \
++      exit (1);                                                                            \
++    }                                                                                      \
++                                                                                           \
++    char *value_start = strchr (VALUE, '=');                                               \
++    if (!value_start)                                                                      \
++      value_start = VALUE;                                                                 \
++    else                                                                                   \
++      ++value_start;                                                                       \
++                                                                                           \
++    tmp_value = launch_data_new_string (value_start); /* Skip variable name                \
++                                                       * and equal sign */                 \
++    launch_data_dict_insert (tmp, tmp_value, KEY);                                         \
++    launch_data_dict_insert (msg, tmp, "SetUserEnvironment");                              \
++                                                                                           \
++    resp = launch_msg (msg);                                                               \
++                                                                                           \
++    if (!resp) {                                                                           \
++      log_error ("failed to pass environment variable `" KEY "' to launchd: %s\n",         \
++                 strerror (errno));                                                        \
++      exit (1);                                                                            \
++    }                                                                                      \
++    launch_data_free (resp);                                                               \
++    launch_data_free (msg); /* Do NOT launch_data_free() neither on tmp, nor tmp_value */  \
++  }                                                                                        \
++while (0)
++
++# define REMOVE_ENV_VAR_FROM_LAUNCHD(ENV_VAR_NAME)                                                \
++do                                                                                                \
++  {                                                                                               \
++    launch_data_t resp, msg, tmp;                                                                 \
++    msg = launch_data_alloc (LAUNCH_DATA_DICTIONARY);                                             \
++                                                                                                  \
++    if (!ENV_VAR_NAME || (strlen (ENV_VAR_NAME) == 0)) {                                          \
++      log_error ("invalid environment variable name given: `" #ENV_VAR_NAME "'.\n");              \
++      exit (1);                                                                                   \
++    }                                                                                             \
++                                                                                                  \
++    tmp = launch_data_new_string (ENV_VAR_NAME);                                                  \
++    launch_data_dict_insert (msg, tmp, "UnsetUserEnvironment");                                   \
++                                                                                                  \
++    resp = launch_msg (msg);                                                                      \
++                                                                                                  \
++    if (!resp) {                                                                                  \
++      log_error ("failed to remove environment variable `" ENV_VAR_NAME "' from launchd: %s\n",   \
++                 strerror (errno));                                                               \
++    }                                                                                             \
++    launch_data_free (resp);                                                                      \
++    launch_data_free (msg); /* Do NOT launch_data_free() on tmp */                                \
++  }                                                                                               \
++while (0)
++
++
++#endif // __APPLE_LAUNCHD__
+ 
+ #define JNLIB_NEED_LOG_LOGV
+ #define JNLIB_NEED_AFLOCAL
+@@ -85,6 +158,9 @@
+   oLogFile,
+   oServer,
+   oDaemon,
++#ifdef __APPLE_LAUNCHD__
++  oLaunchd,
++#endif
+   oBatch,
+ 
+   oPinentryProgram,
+@@ -133,6 +209,9 @@
+   { 301, NULL, 0, N_("@Options:\n ") },
+ 
+   { oDaemon,   "daemon",     0, N_("run in daemon mode (background)") },
++#ifdef __APPLE_LAUNCHD__
++  { oLaunchd,  "launchd",    0, N_("run controlled by launchd (foreground)") },
++#endif
+   { oServer,   "server",     0, N_("run in server mode (foreground)") },
+   { oVerbose, "verbose",     0, N_("verbose") },
+   { oQuiet,	"quiet",     0, N_("be somewhat more quiet") },
+@@ -475,6 +554,19 @@
+ {
+   remove_socket (socket_name);
+   remove_socket (socket_name_ssh);
++
++#ifdef __APPLE_LAUNCHD__
++  /* Remove environment variables from launchd. */
++  /* launchd handles this. */
++  /*
++  REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_SOCKET_AGENT);
++
++  if (opt.ssh_support) {
++    REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_SOCKET_SSH);
++    REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_PID_SSH);
++  }
++  */
++#endif // __APPLE_LAUNCHD__
+ }
+ 
+ 
+@@ -596,6 +688,9 @@
+   int nogreeting = 0;
+   int pipe_server = 0;
+   int is_daemon = 0;
++#ifdef __APPLE_LAUNCHD__
++  int launchd_child = 0;
++#endif
+   int nodetach = 0;
+   int csh_style = 0;
+   char *logfile = NULL;
+@@ -816,6 +911,9 @@
+         case oSh: csh_style = 0; break;
+         case oServer: pipe_server = 1; break;
+         case oDaemon: is_daemon = 1; break;
++#ifdef __APPLE_LAUNCHD__
++        case oLaunchd: launchd_child = 1; break;
++#endif
+ 
+         case oDisplay: default_display = xstrdup (pargs.r.ret_str); break;
+         case oTTYname: default_ttyname = xstrdup (pargs.r.ret_str); break;
+@@ -858,6 +956,19 @@
+         default : pargs.err = configfp? 1:2; break;
+ 	}
+     }
++
++  /* When running under launchd control, only start for real users ie UID >= 500
++   *
++   * Do this check early to avoid filling logs */
++
++#ifdef __APPLE_LAUNCHD__
++  if (launchd_child && geteuid() < 500)
++    {
++      log_error ("launchd only supported for real users - i.e., UID >= 500\n");
++      exit (1);
++    }
++#endif
++
+   if (configfp)
+     {
+       fclose( configfp );
+@@ -983,7 +1094,11 @@
+   /* If this has been called without any options, we merely check
+      whether an agent is already running.  We do this here so that we
+      don't clobber a logfile but print it directly to stderr. */
++#ifdef __APPLE_LAUNCHD__
++  if (!pipe_server && !is_daemon && !launchd_child)
++#else
+   if (!pipe_server && !is_daemon)
++#endif
+     {
+       log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
+       check_for_running_agent (0, 0);
+@@ -1045,6 +1160,217 @@
+       agent_deinit_default_ctrl (ctrl);
+       xfree (ctrl);
+     }
++#ifdef __APPLE_LAUNCHD__
++  else if (launchd_child)
++    { /* launchd-compatible mode */
++      gnupg_fd_t fd, fd_ssh = GNUPG_INVALID_FD;
++      pid_t pid;
++
++      /* Remove the DISPLAY variable so that a pinentry does not
++       * default to a specific display.  There is still a default
++       * display when gpg-agent was started using --display or a
++       * client requested this using an OPTION command.  Note, that we
++       * don't do this when running in reverse daemon mode (i.e. when
++       * exec the program given as arguments). */
++
++      if (!opt.keep_display && !argc)
++        unsetenv ("DISPLAY");
++
++      fflush (NULL);
++      pid = getpid ();
++
++      /* Disable SSH support for good. */
++      opt.ssh_support = 0;
++
++      /* Quick-check to see if SSH support was requested but another application is
++       * providing an SSH auth socket via launchd. */
++      if (opt.ssh_support) {
++        REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_SOCKET_SSH);
++
++        if (getenv (GPG_ENV_SOCKET_SSH) != NULL) {
++          log_error ("another program is already providing SSH agent support via launchd. "
++                     "disabling SSH agent support in gpg-agent.\n");
++          opt.ssh_support = 0;
++        }
++      }
++
++      /* Fetch socket from launchd. */
++      launch_data_t checkin_request, checkin_response;
++
++      /* EHLO launchd */
++      if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL) {
++        log_error ("unable to create launchd checkin string.\n");
++        exit (1);
++      }
++
++      /* any answer */
++      if ((checkin_response = launch_msg (checkin_request)) == NULL) {
++        log_error ("unable to obtain launchd checkin answer.\n");
++        exit (1);
++      }
++
++      /* not 250 :( */
++      if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response)) {
++        int cur_errno = errno;
++        log_error ("launchd checkin failed: %s\n", strerror (cur_errno));
++        exit (1);
++      }
++
++      /* 250 */
++      launch_data_t socket_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS);
++      if (socket_dict == NULL) {
++        log_error ("no sockets returned by launchd.\n");
++        exit (1);
++      }
++
++      {
++        size_t need_sockets = 1;
++
++        if (opt.ssh_support)
++          ++need_sockets;
++
++        size_t got_sockets = launch_data_dict_get_count (socket_dict);
++
++        if (got_sockets < need_sockets) {
++          log_error ("launchd returned less seconds than necessary. "
++                     "needed: %zu, given: %zu.\n", need_sockets, got_sockets);
++          exit (1);
++        }
++
++        if (got_sockets > need_sockets)
++          log_info ("launchd returned more sockets than needed - ignoring extraneous ones.\n");
++
++        /* Fetch FD array. */
++        launch_data_t data_array_agent, data_array_ssh;
++        if ((data_array_agent = launch_data_dict_lookup (socket_dict, GPG_SOCKET_NAME_AGENT)) == NULL) {
++          log_error ("no agent socket defined in launchd plist file.\n");
++          exit (1);
++        }
++
++        if (opt.ssh_support &&
++            ((data_array_ssh = launch_data_dict_lookup (socket_dict, GPG_SOCKET_NAME_SSH)) == NULL)) {
++          log_error ("no ssh socket defined in launchd plist file.\n");
++          exit (1);
++        }
++
++        size_t fd_count_agent, fd_count_ssh;
++        if ((fd_count_agent = launch_data_array_get_count (data_array_agent)) > 1)
++          log_info ("launchd returned more than one file descriptor for the agent socket - ignoring extraneous ones.\n");
++        else if (fd_count_agent == 0) {
++          log_error ("no file descriptor returned for the agent socket.\n");
++          exit (1);
++        }
++        else {
++          launch_data_t cur = launch_data_array_get_index (data_array_agent, 0);
++          fd = launch_data_get_fd (cur);
++        }
++
++        if (opt.ssh_support && ((fd_count_ssh = launch_data_array_get_count (data_array_ssh)) > 1))
++          log_info ("launchd returned more than one file descriptor for the ssh socket - ignoring extraneous ones.\n");
++        else if (opt.ssh_support && (fd_count_ssh == 0)) {
++          log_error ("no file descriptor returned for the ssh socket.\n");
++          exit (1);
++        }
++        else if (opt.ssh_support) {
++          launch_data_t cur = launch_data_array_get_index (data_array_ssh, 0);
++          fd_ssh = launch_data_get_fd (cur);
++        }
++      }
++
++      char *gpg_socket = getenv (GPG_ENV_SOCKET_AGENT);
++      if (!gpg_socket) {
++        log_error ("no agent socket environment variable defined by launchd.\n");
++        exit (1);
++      }
++
++      char *ssh_socket = getenv (GPG_ENV_SOCKET_SSH);
++      if (opt.ssh_support && !ssh_socket) {
++        log_error ("no ssh socket environment variable defined by launchd.\n");
++        exit (1);
++      }
++
++      socket_name = strndup (gpg_socket, strlen (gpg_socket));
++      if (opt.ssh_support)
++        socket_name_ssh = strndup (ssh_socket, strlen (ssh_socket));
++
++      /* Remove internal environment variables from launchd. */
++      /* launchd handles this. */
++      /*
++      REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_SOCKET_AGENT);
++      if (opt.ssh_support)
++        REMOVE_ENV_VAR_FROM_LAUNCHD (GPG_ENV_SOCKET_SSH);
++      */
++
++      launch_data_free (checkin_response);
++      launch_data_free (checkin_request);
++
++      char *infostr, *infostr_ssh_sock, *infostr_ssh_pid;
++
++      /* Create the info string: <name>:<pid>:<protocol_version> */
++      if (asprintf (&infostr, GPG_ENV_SOCKET_AGENT "=%s:%lu:1",
++                    socket_name, (ulong)pid ) < 0) {
++        log_error ("out of core\n");
++        kill (pid, SIGTERM);
++        exit (1);
++      }
++
++      if (opt.ssh_support) {
++        if (asprintf (&infostr_ssh_sock, GPG_ENV_SOCKET_SSH "=%s",
++                      socket_name_ssh) < 0) {
++          log_error ("out of core\n");
++          exit (1);
++        }
++        if (asprintf (&infostr_ssh_pid, GPG_ENV_PID_SSH "=%u",
++                      pid) < 0) {
++          log_error ("out of core\n");
++          exit (1);
++        }
++      }
++
++      if (env_file_name) {
++        FILE *fp;
++
++        fp = fopen (env_file_name, "w");
++        if (!fp)
++          log_error (_("error creating `%s': %s\n"),
++                       env_file_name, strerror (errno));
++        else {
++          fputs (infostr, fp);
++          putc ('\n', fp);
++
++          if (opt.ssh_support) {
++            fputs (infostr_ssh_sock, fp);
++            putc ('\n', fp);
++            fputs (infostr_ssh_pid, fp);
++            putc ('\n', fp);
++          }
++
++          fclose (fp);
++        }
++      }
++
++      /* Pass environment variables back to launchd. */
++      /* launchd handles this. */
++      /* PASS_ENV_VAR_TO_LAUNCHD (GPG_ENV_SOCKET_AGENT, infostr);
++
++      if (opt.ssh_support) {
++        PASS_ENV_VAR_TO_LAUNCHD (GPG_ENV_SOCKET_SSH, infostr_ssh_sock);
++        PASS_ENV_VAR_TO_LAUNCHD (GPG_ENV_PID_SSH, infostr_ssh_pid);
++      }
++      */
++
++      {
++        struct sigaction sa;
++
++        sa.sa_handler = SIG_IGN;
++        sigemptyset (&sa.sa_mask);
++        sa.sa_flags = 0;
++        sigaction (SIGPIPE, &sa, NULL);
++      }
++
++      handle_connections (fd, fd_ssh);
++    }
++#endif // __APPLE_LAUNCHD__
+   else if (!is_daemon)
+     ; /* NOTREACHED */
+   else
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/macports-changes/attachments/20141111/0b3c87dc/attachment-0001.html>


More information about the macports-changes mailing list