[telepathy-salut/master] add gibber_unix_transport_wait_credentials

Guillaume Desmottes guillaume.desmottes at collabora.co.uk
Mon May 11 09:52:13 PDT 2009


---
 lib/gibber/gibber-unix-transport.c |  101 +++++++++++++++++++++++++++++++++++-
 lib/gibber/gibber-unix-transport.h |   26 +++++++++
 2 files changed, 126 insertions(+), 1 deletions(-)

diff --git a/lib/gibber/gibber-unix-transport.c b/lib/gibber/gibber-unix-transport.c
index a161574..d4989ec 100644
--- a/lib/gibber/gibber-unix-transport.c
+++ b/lib/gibber/gibber-unix-transport.c
@@ -58,6 +58,10 @@ typedef struct _GibberUnixTransportPrivate GibberUnixTransportPrivate;
 struct _GibberUnixTransportPrivate
 {
   gboolean incoming;
+
+  GibberUnixTransportWaitCredentialsCb wait_creds_cb;
+  gpointer wait_creds_data;
+
   gboolean dispose_has_run;
 };
 
@@ -234,10 +238,105 @@ gibber_unix_transport_send_credentials (GibberUnixTransport *transport,
   return TRUE;
 }
 
+#define BUFSIZE 1024
+
 static GibberFdIOResult
 gibber_unix_transport_read (GibberFdTransport *transport,
     GIOChannel *channel,
     GError **error)
 {
-  return gibber_fd_transport_read (transport, channel, error);
+  GibberUnixTransport *self = GIBBER_UNIX_TRANSPORT (transport);
+  GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self);
+  int fd;
+  guint8 buffer[BUFSIZE];
+  ssize_t bytes_read;
+  GibberBuffer buf;
+  struct iovec iov;
+  struct msghdr msg;
+  char control[CMSG_SPACE (sizeof (struct ucred))];
+  struct cmsghdr *ch;
+  struct ucred *cred;
+  int opt;
+
+  if (priv->wait_creds_cb == NULL)
+    return gibber_fd_transport_read (transport, channel, error);
+
+  /* We are waiting for credentials */
+  fd = transport->fd;
+
+  /* set SO_PASSCRED flag */
+  opt = 1;
+  setsockopt (fd, SOL_SOCKET, SO_PASSCRED, &opt, sizeof (opt));
+
+  memset (buffer, 0, sizeof (buffer));
+  memset (&iov, 0, sizeof (iov));
+  iov.iov_base = buffer;
+  iov.iov_len = sizeof (buffer);
+
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+  msg.msg_control = control;
+  msg.msg_controllen = sizeof (control);
+
+  bytes_read = recvmsg (fd, &msg, 0);
+
+  if (bytes_read == -1)
+    {
+      g_set_error_literal (error, G_IO_CHANNEL_ERROR,
+          g_io_channel_error_from_errno (errno), "recvmsg failed");
+
+      priv->wait_creds_cb = NULL;
+      priv->wait_creds_data = NULL;
+      return GIBBER_FD_IO_RESULT_ERROR;
+    }
+
+  /* unset SO_PASSCRED flag */
+  opt = 0;
+  setsockopt (fd, SOL_SOCKET, SO_PASSCRED, &opt, sizeof (opt));
+
+  buf.data = buffer;
+  buf.length = bytes_read;
+
+  /* extract the credentials */
+  ch = CMSG_FIRSTHDR (&msg);
+  if (ch == NULL)
+    {
+      DEBUG ("Message doesn't contain credentials");
+
+      priv->wait_creds_cb (self, &buf, NULL, priv->wait_creds_data);
+    }
+  else
+    {
+      GibberCredentials credentials;
+
+      cred = (struct ucred *) CMSG_DATA (ch);
+      credentials.pid = cred->pid;
+      credentials.uid = cred->uid;
+      credentials.gid = cred->gid;
+
+      priv->wait_creds_cb (self, &buf, &credentials, priv->wait_creds_data);
+    }
+
+  priv->wait_creds_cb = NULL;
+  priv->wait_creds_data = NULL;
+  return GIBBER_FD_IO_RESULT_SUCCESS;
+}
+
+gboolean
+gibber_unix_transport_wait_credentials (GibberUnixTransport *self,
+    GibberUnixTransportWaitCredentialsCb callback,
+    gpointer user_data)
+{
+  GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self);
+
+  if (priv->wait_creds_cb != NULL)
+    {
+      DEBUG ("already waiting for credentials");
+      return FALSE;
+    }
+
+  priv->wait_creds_cb = callback;
+  priv->wait_creds_data = user_data;
+  return TRUE;
 }
diff --git a/lib/gibber/gibber-unix-transport.h b/lib/gibber/gibber-unix-transport.h
index 8e7003b..a44680e 100644
--- a/lib/gibber/gibber-unix-transport.h
+++ b/lib/gibber/gibber-unix-transport.h
@@ -24,6 +24,16 @@
 
 #include <glib-object.h>
 
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/un.h>
+
 #include "gibber-fd-transport.h"
 
 G_BEGIN_DECLS
@@ -78,6 +88,22 @@ gboolean gibber_unix_transport_connect (GibberUnixTransport *transport,
 gboolean gibber_unix_transport_send_credentials (GibberUnixTransport *transport,
     const guint8 *data, gsize size);
 
+typedef struct {
+    pid_t pid;
+    uid_t uid;
+    gid_t gid;
+} GibberCredentials;
+
+typedef void (*GibberUnixTransportWaitCredentialsCb) (
+    GibberUnixTransport *transport,
+    GibberBuffer *buffer,
+    GibberCredentials *credentials,
+    gpointer user_data);
+
+gboolean gibber_unix_transport_wait_credentials (GibberUnixTransport *transport,
+    GibberUnixTransportWaitCredentialsCb callback,
+    gpointer user_data);
+
 G_END_DECLS
 
 #endif /* #ifndef __GIBBER_UNIX_TRANSPORT_H__*/
-- 
1.5.6.5




More information about the telepathy-commits mailing list