From 964eb62343b53cf9172d409adacbb58d78896092 Mon Sep 17 00:00:00 2001 From: Joe Marcus Clarke Date: Thu, 9 Sep 2010 14:10:01 -0400 Subject: [PATCH] =?UTF-8?q?Bug=20628904=20=E2=80=93=20Add=20credential=20s?= =?UTF-8?q?upport=20for=20FreeBSD=20and=20fix=20a=20socket=20issue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Zeuthen --- gio/gcredentials.c | 53 +++++++++++++++++++++++++++++++++++ gio/gioenums.h | 4 ++- gio/gsocket.c | 9 ++++-- gio/gunixcredentialsmessage.c | 46 ++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/gio/gcredentials.c b/gio/gcredentials.c index a9c2b5a98..e2cc7ba7c 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -22,6 +22,11 @@ #include "config.h" +#ifdef __FreeBSD__ +#include +#include +#include +#endif #include #include @@ -55,6 +60,9 @@ * unix7 * man page for details. This corresponds to * %G_CREDENTIALS_TYPE_LINUX_UCRED. + * + * On FreeBSD, the native credential type is a struct cmsgcred. + * This corresponds to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED. */ /** @@ -72,6 +80,8 @@ struct _GCredentials #ifdef __linux__ struct ucred native; +#elif defined(__FreeBSD__) + struct cmsgcred native; #else #ifdef __GNUC__ #warning Please add GCredentials support for your OS @@ -120,6 +130,11 @@ g_credentials_init (GCredentials *credentials) credentials->native.pid = getpid (); credentials->native.uid = geteuid (); credentials->native.gid = getegid (); +#elif defined(__FreeBSD__) + memset (&credentials->native, 0, sizeof (struct cmsgcred)); + credentials->native.cmcred_pid = getpid (); + credentials->native.cmcred_euid = geteuid (); + credentials->native.cmcred_gid = getegid (); #endif } @@ -173,6 +188,14 @@ g_credentials_to_string (GCredentials *credentials) g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.gid); if (ret->str[ret->len - 1] == ',') ret->str[ret->len - 1] = '\0'; +#elif defined(__FreeBSD__) + g_string_append (ret, "freebsd-cmsgcred:"); + if (credentials->native.cmcred_pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_pid); + if (credentials->native.cmcred_euid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_euid); + if (credentials->native.cmcred_gid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.cmcred_gid); #else g_string_append (ret, "unknown"); #endif @@ -213,6 +236,9 @@ g_credentials_is_same_user (GCredentials *credentials, #ifdef __linux__ if (credentials->native.uid == other_credentials->native.uid) ret = TRUE; +#elif defined(__FreeBSD__) + if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) + ret = TRUE; #else g_set_error_literal (error, G_IO_ERROR, @@ -263,6 +289,17 @@ g_credentials_get_native (GCredentials *credentials, { ret = &credentials->native; } +#elif defined(__FreeBSD__) + if (native_type != G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED) + { + g_warning ("g_credentials_get_native: Trying to get credentials of type %d but only " + "G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED is supported.", + native_type); + } + else + { + ret = &credentials->native; + } #else g_warning ("g_credentials_get_native: Trying to get credentials but GLib has no support " "for the native credentials type. Please add support."); @@ -302,6 +339,17 @@ g_credentials_set_native (GCredentials *credentials, { memcpy (&credentials->native, native, sizeof (struct ucred)); } +#elif defined(__FreeBSD__) + if (native_type != G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED) + { + g_warning ("g_credentials_set_native: Trying to set credentials of type %d " + "but only G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED is supported.", + native_type); + } + else + { + memcpy (&credentials->native, native, sizeof (struct cmsgcred)); + } #else g_warning ("g_credentials_set_native: Trying to set credentials but GLib has no support " "for the native credentials type. Please add support."); @@ -338,6 +386,8 @@ g_credentials_get_unix_user (GCredentials *credentials, #ifdef __linux__ ret = credentials->native.uid; +#elif defined(__FreeBSD__) + ret = credentials->native.cmcred_euid; #else ret = -1; g_set_error_literal (error, @@ -381,6 +431,9 @@ g_credentials_set_unix_user (GCredentials *credentials, #ifdef __linux__ credentials->native.uid = uid; ret = TRUE; +#elif defined(__FreeBSD__) + credentials->native.cmcred_euid = uid; + ret = TRUE; #else g_set_error_literal (error, G_IO_ERROR, diff --git a/gio/gioenums.h b/gio/gioenums.h index 967b061cc..10eedfdd7 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -1188,6 +1188,7 @@ typedef enum * GCredentialsType: * @G_CREDENTIALS_TYPE_INVALID: Indicates an invalid native credential type. * @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a struct ucred. + * @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a struct cmsgcred. * * Enumeration describing different kinds of native credential types. * @@ -1196,7 +1197,8 @@ typedef enum typedef enum { G_CREDENTIALS_TYPE_INVALID, - G_CREDENTIALS_TYPE_LINUX_UCRED + G_CREDENTIALS_TYPE_LINUX_UCRED, + G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED } GCredentialsType; /** diff --git a/gio/gsocket.c b/gio/gsocket.c index 57be472b8..ba7be0184 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -2928,8 +2928,13 @@ g_socket_send_message (GSocket *socket, for (i = 0; i < num_messages; i++) msg.msg_controllen += CMSG_SPACE (g_socket_control_message_get_size (messages[i])); - msg.msg_control = g_alloca (msg.msg_controllen); - memset (msg.msg_control, '\0', msg.msg_controllen); + if (msg.msg_controllen == 0) + msg.msg_control = NULL; + else + { + msg.msg_control = g_alloca (msg.msg_controllen); + memset (msg.msg_control, '\0', msg.msg_controllen); + } cmsg = CMSG_FIRSTHDR (&msg); for (i = 0; i < num_messages; i++) diff --git a/gio/gunixcredentialsmessage.c b/gio/gunixcredentialsmessage.c index e6dadfb4d..82224ab6b 100644 --- a/gio/gunixcredentialsmessage.c +++ b/gio/gunixcredentialsmessage.c @@ -46,6 +46,13 @@ #include #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 +#elif defined(__FreeBSD__) +#include +#include +#include +#include +#include +#define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1 #else /* TODO: please add support for your UNIX flavor */ #define G_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 0 @@ -79,6 +86,8 @@ g_unix_credentials_message_get_size (GSocketControlMessage *message) { #ifdef __linux__ return sizeof (struct ucred); +#elif defined(__FreeBSD__) + return sizeof (struct cmsgcred); #else return 0; #endif @@ -89,6 +98,8 @@ g_unix_credentials_message_get_level (GSocketControlMessage *message) { #ifdef __linux__ return SOL_SOCKET; +#elif defined(__FreeBSD__) + return SOL_SOCKET; #else return 0; #endif @@ -99,6 +110,8 @@ g_unix_credentials_message_get_msg_type (GSocketControlMessage *message) { #ifdef __linux__ return SCM_CREDENTIALS; +#elif defined(__FreeBSD__) + return SCM_CREDS; #else return 0; #endif @@ -140,6 +153,33 @@ g_unix_credentials_message_deserialize (gint level, out: ; } +#elif defined(__FreeBSD__) + { + GCredentials *credentials; + struct cmsgcred *cred; + + if (level != SOL_SOCKET || type != SCM_CREDS) + { + goto out; + } + if (size < CMSG_LEN (sizeof *cred)) + { + g_warning ("Expected a struct cmsgcred (%" G_GSIZE_FORMAT " bytes) but " + "got %" G_GSIZE_FORMAT " bytes of data", + CMSG_LEN (sizeof *cred), + size); + goto out; + } + + cred = data; + + credentials = g_credentials_new (); + g_credentials_set_native (credentials, G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED, cred); + message = g_unix_credentials_message_new_with_credentials (credentials); + g_object_unref (credentials); + out: + ; + } #endif return message; @@ -155,6 +195,12 @@ g_unix_credentials_message_serialize (GSocketControlMessage *_message, g_credentials_get_native (message->priv->credentials, G_CREDENTIALS_TYPE_LINUX_UCRED), sizeof (struct ucred)); +#elif defined(__FreeBSD__) + memcpy (data, + g_credentials_get_native (message->priv->credentials, + G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED), + sizeof (struct cmsgcred)); + #endif }