[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