[Pkg-gnupg-commit] [libassuan] 63/437: 2002-11-24 Neal H. Walfield <neal at cs.uml.edu>

Eric Dorland eric at moszumanska.debian.org
Fri May 22 05:33:24 UTC 2015


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository libassuan.

commit 5d0f173af5f4036a3793392899836b0fe7a01376
Author: Neal Walfield <neal at walfield.org>
Date:   Sun Nov 24 18:27:59 2002 +0000

    2002-11-24  Neal H. Walfield  <neal at cs.uml.edu>
    
    	* assuan.h (assuan_sendfd): New prototype.
    	(assuan_receivefd): New prototype.
    	* assuan-buffer.c (assuan_sendfd): New function.
    	(assuan_receivefd): New function.
    	* assuan-handler.c (parse_cmd_input_output): Recognize incoming
    	file descriptors and act appropriately.
    	* assuan-defs.h (struct assuan_io): Add fields sendfd and
    	receivefd.
    	(struct assuan_context_s): Add fields pendingfds and
    	pendingfdscount.
    	* assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
    	new features.
    	* assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
    	descriptors.
    	(domain_reader): Receive file descriptors.
    	(domain_sendfd): New function.
    	(domain_receivefd): New function.
    	(_assuan_domain_init): Update initialization code to reflect new
    	features.
---
 src/ChangeLog               |  22 ++++++++
 src/assuan-buffer.c         |  20 ++++++++
 src/assuan-defs.h           |   8 ++-
 src/assuan-domain-connect.c | 121 ++++++++++++++++++++++++++++++++++++++++++--
 src/assuan-handler.c        |  35 ++++++++-----
 src/assuan-pipe-server.c    |   3 +-
 src/assuan.h                |   6 +++
 7 files changed, 194 insertions(+), 21 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index eeb286d..c88d884 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,25 @@
+2002-11-24  Neal H. Walfield  <neal at cs.uml.edu>
+
+	* assuan.h (assuan_sendfd): New prototype.
+	(assuan_receivefd): New prototype.
+	* assuan-buffer.c (assuan_sendfd): New function.
+	(assuan_receivefd): New function.
+	* assuan-handler.c (parse_cmd_input_output): Recognize incoming
+	file descriptors and act appropriately.
+	* assuan-defs.h (struct assuan_io): Add fields sendfd and
+	receivefd.
+	(struct assuan_context_s): Add fields pendingfds and
+	pendingfdscount.
+	* assuan-pipe-server.c (_assuan_new_context): Update IO to reflect
+	new features.
+	* assuan-domain-connect.c (do_deinit): Cleanup any unreceived file
+	descriptors.
+	(domain_reader): Receive file descriptors.
+	(domain_sendfd): New function.
+	(domain_receivefd): New function.
+	(_assuan_domain_init): Update initialization code to reflect new
+	features.
+
 2002-11-24  Neal H. Walfield  <neal at g10code.de>
 
 	* assuan-domain-connect.c (do_finish): Remove.
diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c
index 8ccd3bd..bbe3990 100644
--- a/src/assuan-buffer.c
+++ b/src/assuan-buffer.c
@@ -437,3 +437,23 @@ assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
 
   return 0;
 }
+
+AssuanError
+assuan_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+  if (! ctx->io->sendfd)
+    return set_error (ctx, Not_Implemented,
+		      "server does not support sending and receiving "
+		      "of file descriptors");
+  return ctx->io->sendfd (ctx, fd);
+}
+
+AssuanError
+assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+{
+  if (! ctx->io->receivefd)
+    return set_error (ctx, Not_Implemented,
+		      "server does not support sending and receiving "
+		      "of file descriptors");
+  return ctx->io->receivefd (ctx, fd);
+}
diff --git a/src/assuan-defs.h b/src/assuan-defs.h
index 6e11bbb..5766024 100644
--- a/src/assuan-defs.h
+++ b/src/assuan-defs.h
@@ -43,6 +43,10 @@ struct assuan_io
   ssize_t (*read) (ASSUAN_CONTEXT, void *, size_t);
   /* Routine to write to output_fd.  */
   ssize_t (*write) (ASSUAN_CONTEXT, const void *, size_t);
+  /* Send a file descriptor.  */
+  AssuanError (*sendfd) (ASSUAN_CONTEXT, int);
+  /* Receive a file descriptor.  */
+  AssuanError (*receivefd) (ASSUAN_CONTEXT, int *);
 };  
 
 struct assuan_context_s
@@ -109,6 +113,9 @@ struct assuan_context_s
   /* Memory allocated.  */
   int domainbufferallocated;
 
+  int *pendingfds;
+  int pendingfdscount;
+
   void (*deinit_handler)(ASSUAN_CONTEXT);  
   int (*accept_handler)(ASSUAN_CONTEXT);
   int (*finish_handler)(ASSUAN_CONTEXT);
@@ -176,6 +183,5 @@ ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size);
 ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer,
 			      size_t size);
 
-
 #endif /*ASSUAN_DEFS_H*/
 
diff --git a/src/assuan-domain-connect.c b/src/assuan-domain-connect.c
index d50ba1e..b4ce519 100644
--- a/src/assuan-domain-connect.c
+++ b/src/assuan-domain-connect.c
@@ -63,6 +63,17 @@ do_deinit (ASSUAN_CONTEXT ctx)
       free (ctx->domainbuffer);
     }
 
+  if (ctx->pendingfds)
+    {
+      int i;
+
+      assert (ctx->pendingfdscount > 0);
+      for (i = 0; i < ctx->pendingfdscount; i ++)
+	close (ctx->pendingfds[i]);
+
+      free (ctx->pendingfds);
+    }
+
   unlink (ctx->myaddr.sun_path);
 }
 
@@ -80,6 +91,11 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
       struct msghdr msg;
       struct iovec iovec;
       struct sockaddr_un sender;
+      struct 
+      {
+	struct cmsghdr hdr;
+	int fd;
+      } cmsg;
 
       memset (&msg, 0, sizeof (msg));
 
@@ -91,8 +107,8 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
 	  msg.msg_iovlen = 1;
 	  iovec.iov_base = ctx->domainbuffer;
 	  iovec.iov_len = ctx->domainbufferallocated;
-	  msg.msg_control = 0;
-	  msg.msg_controllen = 0;
+	  msg.msg_control = &cmsg;
+	  msg.msg_controllen = sizeof cmsg;
 
 	  /* Peek first: if the buffer we have is too small then it
 	     will be truncated.  */
@@ -144,8 +160,8 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
       msg.msg_iovlen = 1;
       iovec.iov_base = ctx->domainbuffer;
       iovec.iov_len = ctx->domainbufferallocated;
-      msg.msg_control = 0;
-      msg.msg_controllen = 0;
+      msg.msg_control = &cmsg;
+      msg.msg_controllen = sizeof cmsg;
 
       if (strcmp (ctx->serveraddr.sun_path,
 		  ((struct sockaddr_un *) msg.msg_name)->sun_path) != 0)
@@ -167,6 +183,30 @@ domain_reader (ASSUAN_CONTEXT ctx, void *buf, size_t buflen)
 
       ctx->domainbuffersize = len;
       ctx->domainbufferoffset = 0;
+
+      if (sizeof (cmsg) == msg.msg_controllen)
+	/* We received a file descriptor.  */
+	{
+	  void *tmp;
+
+	  tmp = realloc (ctx->pendingfds,
+			 sizeof (int) * (ctx->pendingfdscount + 1));
+	  if (! tmp)
+	    {
+	      LOGERROR1 ("domain_reader: %s\n", strerror (errno));
+	      return -1;
+	    }
+
+	  ctx->pendingfds = tmp;
+	  ctx->pendingfds[ctx->pendingfdscount ++]
+	    = * (int *) CMSG_DATA (&cmsg.hdr);
+
+	  LOGERROR1 ("Received file descriptor %d from peer.\n",
+		     ctx->pendingfds[ctx->pendingfdscount - 1]);
+	}
+
+      if (len == 0)
+	goto start;
     }
 
   /* Return some data to the user.  */
@@ -212,6 +252,74 @@ domain_writer (ASSUAN_CONTEXT ctx, const void *buf, size_t buflen)
   return len;
 }
 
+static AssuanError
+domain_sendfd (ASSUAN_CONTEXT ctx, int fd)
+{
+  struct msghdr msg;
+  struct 
+  {
+    struct cmsghdr hdr;
+    int fd;
+  } cmsg;
+  int len;
+
+  memset (&msg, 0, sizeof (msg));
+
+  msg.msg_name = &ctx->serveraddr;
+  msg.msg_namelen = offsetof (struct sockaddr_un, sun_path)
+    + strlen (ctx->serveraddr.sun_path) + 1;
+
+  msg.msg_iovlen = 0;
+  msg.msg_iov = 0;
+
+  cmsg.hdr.cmsg_level = SOL_SOCKET;
+  cmsg.hdr.cmsg_type = SCM_RIGHTS;
+  cmsg.hdr.cmsg_len = sizeof (cmsg);
+
+  msg.msg_control = &cmsg;
+  msg.msg_controllen = sizeof (cmsg);
+
+  * (int *) CMSG_DATA (&cmsg.hdr) = fd;
+
+  len = sendmsg (ctx->outbound.fd, &msg, 0);
+  if (len < 0)
+    {
+      LOGERROR1 ("domain_sendfd: %s\n", strerror (errno));
+      return ASSUAN_General_Error;
+    }
+  else
+    return 0;
+}
+
+static AssuanError
+domain_receivefd (ASSUAN_CONTEXT ctx, int *fd)
+{
+  if (ctx->pendingfds == 0)
+    {
+      LOGERROR ("No pending file descriptors!\n");
+      return ASSUAN_General_Error;
+    }
+
+  *fd = ctx->pendingfds[0];
+  if (-- ctx->pendingfdscount == 0)
+    {
+      free (ctx->pendingfds);
+      ctx->pendingfds = 0;
+    }
+  else
+    /* Fix the array.  */
+    {
+      memmove (ctx->pendingfds, ctx->pendingfds + 1,
+	       ctx->pendingfdscount * sizeof (int));
+      ctx->pendingfds = realloc (ctx->pendingfds,
+				 ctx->pendingfdscount * sizeof (int));
+    }
+
+  return 0;
+}
+
+
+
 /* Make a connection to the Unix domain socket NAME and return a new
    Assuan context in CTX.  SERVER_PID is currently not used but may
    become handy in the future.  */
@@ -220,7 +328,8 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
 		     int rendezvousfd,
 		     pid_t peer)
 {
-  static struct assuan_io io = { domain_reader, domain_writer };
+  static struct assuan_io io = { domain_reader, domain_writer,
+				 domain_sendfd, domain_receivefd };
 
   AssuanError err;
   ASSUAN_CONTEXT ctx;
@@ -262,6 +371,8 @@ _assuan_domain_init (ASSUAN_CONTEXT *r_ctx,
   ctx->domainbufferoffset = 0;
   ctx->domainbuffersize = 0;
   ctx->domainbufferallocated = 0;
+  ctx->pendingfds = 0;
+  ctx->pendingfdscount = 0;
 
   /* Get usable name and bind to it.  */
 
diff --git a/src/assuan-handler.c b/src/assuan-handler.c
index 6ddfe88..16838b2 100644
--- a/src/assuan-handler.c
+++ b/src/assuan-handler.c
@@ -154,20 +154,27 @@ parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd)
 {
   char *endp;
 
-  if (strncmp (line, "FD=", 3))
-    return set_error (ctx, Syntax_Error, "FD=<n> expected");
-  line += 3;
-  if (!digitp (*line))
-    return set_error (ctx, Syntax_Error, "number required");
-  *rfd = strtoul (line, &endp, 10);
-  /* remove that argument so that a notify handler won't see it */
-  memset (line, ' ', endp? (endp-line):strlen(line));
-
-  if (*rfd == ctx->inbound.fd)
-    return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
-  if (*rfd == ctx->outbound.fd)
-    return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
-  return 0;
+  if (strncmp (line, "FD", 2) != 0 || (line[2] != '=' && line[2] != '\0'))
+    return set_error (ctx, Syntax_Error, "FD[=<n>] expected");
+  line += 2;
+  if (*line == '=')
+    {
+      line ++;
+      if (!digitp (*line))
+	return set_error (ctx, Syntax_Error, "number required");
+      *rfd = strtoul (line, &endp, 10);
+      /* remove that argument so that a notify handler won't see it */
+      memset (line, ' ', endp? (endp-line):strlen(line));
+
+      if (*rfd == ctx->inbound.fd)
+	return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
+      if (*rfd == ctx->outbound.fd)
+	return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
+      return 0;
+    }
+  else
+    /* Our peer has sent the file descriptor.  */
+    return assuan_receivefd (ctx, rfd);
 }
 
 /* Format is INPUT FD=<n> */
diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c
index a0bb3bd..ba269b0 100644
--- a/src/assuan-pipe-server.c
+++ b/src/assuan-pipe-server.c
@@ -51,7 +51,8 @@ int
 _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
 {
   static struct assuan_io io = { _assuan_simple_read,
-				 _assuan_simple_write };
+				 _assuan_simple_write,
+				 0, 0 };
 
   ASSUAN_CONTEXT ctx;
   int rc;
diff --git a/src/assuan.h b/src/assuan.h
index 1972702..59cb153 100644
--- a/src/assuan.h
+++ b/src/assuan.h
@@ -229,6 +229,12 @@ AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line );
 AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
                               const void *buffer, size_t length);
 
+/* The file descriptor must be pending before assuan_receivefd is
+   call.  This means that assuan_sendfd should be called *before* the
+   trigger is sent (normally via assuan_send_data ("I sent you a
+   descriptor")).  */
+AssuanError assuan_sendfd (ASSUAN_CONTEXT ctx, int fd);
+AssuanError assuan_receivefd (ASSUAN_CONTEXT ctx, int *fd);
 
 /*-- assuan-util.c --*/
 void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/libassuan.git



More information about the Pkg-gnupg-commit mailing list