summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2013-09-19 16:09:38 -0400
committerDan Winship <danw@gnome.org>2013-09-19 16:41:24 -0400
commit9fddf5c1f9f88d6c508ae1ba6d0eb3bae15a5bdd (patch)
tree659966698aa67606922e372417735de50797b877
parent257482e6478ef0b803a8b0c4a5203994c5c65ad6 (diff)
downloadglib-wip/danw/creds.tar.gz
gcredentials: add Solaris supportwip/danw/creds
Based on a patch from Igor Pashev. https://bugzilla.gnome.org/show_bug.cgi?id=705029
-rw-r--r--gio/gcredentials.c56
-rw-r--r--gio/gcredentialsprivate.h9
-rw-r--r--gio/gioenums.h4
-rw-r--r--gio/gsocket.c36
-rw-r--r--gio/gunixcredentialsmessage.c2
5 files changed, 97 insertions, 10 deletions
diff --git a/gio/gcredentials.c b/gio/gcredentials.c
index e62344056..6a84727bd 100644
--- a/gio/gcredentials.c
+++ b/gio/gcredentials.c
@@ -65,6 +65,10 @@
*
* On OpenBSD, the native credential type is a <type>struct sockpeercred</type>.
* This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED.
+ *
+ * On Solaris (including OpenSolaris and its derivatives), the native
+ * credential type is a <type>ucred_t</type>. This corresponds to
+ * %G_CREDENTIALS_TYPE_SOLARIS_UCRED.
*/
/**
@@ -86,6 +90,8 @@ struct _GCredentials
struct cmsgcred native;
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
struct sockpeercred native;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ ucred_t *native;
#else
#ifdef __GNUC__
#warning Please add GCredentials support for your OS
@@ -111,7 +117,11 @@ G_DEFINE_TYPE (GCredentials, g_credentials, G_TYPE_OBJECT);
static void
g_credentials_finalize (GObject *object)
{
- G_GNUC_UNUSED GCredentials *credentials = G_CREDENTIALS (object);
+#if G_CREDENTIALS_USE_SOLARIS_UCRED
+ GCredentials *credentials = G_CREDENTIALS (object);
+
+ ucred_free (credentials->native);
+#endif
if (G_OBJECT_CLASS (g_credentials_parent_class)->finalize != NULL)
G_OBJECT_CLASS (g_credentials_parent_class)->finalize (object);
@@ -143,6 +153,8 @@ g_credentials_init (GCredentials *credentials)
credentials->native.pid = getpid ();
credentials->native.uid = geteuid ();
credentials->native.gid = getegid ();
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ credentials->native = ucred_get (P_MYID);
#endif
}
@@ -214,6 +226,19 @@ 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 G_CREDENTIALS_USE_SOLARIS_UCRED
+ g_string_append (ret, "solaris-ucred:");
+ {
+ id_t id;
+ if ((id = ucred_getpid (credentials->native)) != -1)
+ g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) id);
+ if ((id = ucred_geteuid (credentials->native)) != -1)
+ g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) id);
+ if ((id = ucred_getegid (credentials->native)) != -1)
+ g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) id);
+ if (ret->str[ret->len - 1] == ',')
+ ret->str[ret->len - 1] = '\0';
+ }
#else
g_string_append (ret, "unknown");
#endif
@@ -260,6 +285,9 @@ g_credentials_is_same_user (GCredentials *credentials,
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
if (credentials->native.uid == other_credentials->native.uid)
ret = TRUE;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ if (ucred_geteuid (credentials->native) == ucred_geteuid (other_credentials->native))
+ ret = TRUE;
#else
g_set_error_literal (error,
G_IO_ERROR,
@@ -334,7 +362,11 @@ g_credentials_get_native (GCredentials *credentials,
if (!credentials_native_type_check (native_type, "get"))
return NULL;
+#if G_CREDENTIALS_USE_SOLARIS_UCRED
+ return credentials->native;
+#else
return &credentials->native;
+#endif
}
/**
@@ -360,7 +392,11 @@ g_credentials_set_native (GCredentials *credentials,
if (!credentials_native_type_check (native_type, "set"))
return;
+#if G_CREDENTIALS_USE_SOLARIS_UCRED
+ memcpy (credentials->native, native, ucred_size ());
+#else
memcpy (&credentials->native, native, sizeof (credentials->native));
+#endif
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -397,6 +433,8 @@ g_credentials_get_unix_user (GCredentials *credentials,
ret = credentials->native.cmcred_euid;
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
ret = credentials->native.uid;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ ret = ucred_geteuid (credentials->native);
#else
ret = -1;
g_set_error_literal (error,
@@ -439,6 +477,8 @@ g_credentials_get_unix_pid (GCredentials *credentials,
ret = credentials->native.cmcred_pid;
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
ret = credentials->native.pid;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ ret = ucred_getpid (credentials->native);
#else
ret = -1;
g_set_error_literal (error,
@@ -461,7 +501,8 @@ g_credentials_get_unix_pid (GCredentials *credentials,
*
* This operation can fail if #GCredentials is not supported on the
* OS or if the native credentials type does not contain information
- * about the UNIX user.
+ * about the UNIX user. It can also fail if the OS does not allow the
+ * use of "spoofed" credentials.
*
* Returns: %TRUE if @uid was set, %FALSE if error is set.
*
@@ -488,13 +529,24 @@ g_credentials_set_unix_user (GCredentials *credentials,
#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
credentials->native.uid = uid;
ret = TRUE;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ ret = FALSE;
#else
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
_("GCredentials is not implemented on this OS"));
+ ret = FALSE;
#endif
+ if (ret == FALSE && error && !*error)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_PERMISSION_DENIED,
+ _("Credentials spoofing is not possible on this OS"));
+ }
+
return ret;
}
diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h
index d3b5f9725..0ad93fd08 100644
--- a/gio/gcredentialsprivate.h
+++ b/gio/gcredentialsprivate.h
@@ -46,6 +46,15 @@
#define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct sockpeercred))
#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
+#elif defined(__sun__) || defined(__illumos__) || defined (__OpenSolaris_kernel__)
+#include <ucred.h>
+#define G_CREDENTIALS_SUPPORTED 1
+#define G_CREDENTIALS_USE_SOLARIS_UCRED 1
+#define G_CREDENTIALS_NATIVE_TYPE G_CREDENTIALS_TYPE_SOLARIS_UCRED
+#define G_CREDENTIALS_NATIVE_SIZE (ucred_size ())
+#define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
+#define G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED 1
+
#endif
#endif /* __G_CREDENTIALS_PRIVATE_H__ */
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 4ce0855cb..dbbd30b1d 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1337,6 +1337,7 @@ typedef enum
* @G_CREDENTIALS_TYPE_LINUX_UCRED: The native credentials type is a <type>struct ucred</type>.
* @G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED: The native credentials type is a <type>struct cmsgcred</type>.
* @G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED: The native credentials type is a <type>struct sockpeercred</type>. Added in 2.30.
+ * @G_CREDENTIALS_TYPE_SOLARIS_UCRED: The native credentials type is a <type>ucred_t</type>. Added in 2.40.
*
* Enumeration describing different kinds of native credential types.
*
@@ -1347,7 +1348,8 @@ typedef enum
G_CREDENTIALS_TYPE_INVALID,
G_CREDENTIALS_TYPE_LINUX_UCRED,
G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED,
- G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED
+ G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED,
+ G_CREDENTIALS_TYPE_SOLARIS_UCRED
} GCredentialsType;
/**
diff --git a/gio/gsocket.c b/gio/gsocket.c
index e1c6c980f..95d870a27 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -4449,6 +4449,8 @@ g_socket_get_credentials (GSocket *socket,
ret = NULL;
#if G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
+
+#ifdef SO_PEERCRED
{
guint8 native_creds_buf[G_CREDENTIALS_NATIVE_SIZE];
socklen_t optlen = sizeof (native_creds_buf);
@@ -4464,17 +4466,37 @@ g_socket_get_credentials (GSocket *socket,
G_CREDENTIALS_NATIVE_TYPE,
native_creds_buf);
}
- else
+ }
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ {
+ ucred_t *ucred = NULL;
+
+ if (getpeerucred (socket->priv->fd, &ucred) == 0)
{
- int errsv = get_socket_errno ();
- g_set_error (error,
- G_IO_ERROR,
- socket_io_error_from_errno (errsv),
- _("Unable to read socket credentials: %s"),
- socket_strerror (errsv));
+ ret = g_credentials_new ();
+ g_credentials_set_native (ret,
+ G_CREDENTIALS_TYPE_SOLARIS_UCRED,
+ ucred);
+ ucred_free (ucred);
}
}
#else
+ #error "G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED is set but this is no code for this platform"
+#endif
+
+ if (!ret)
+ {
+ int errsv = get_socket_errno ();
+
+ g_set_error (error,
+ G_IO_ERROR,
+ socket_io_error_from_errno (errsv),
+ _("Unable to read socket credentials: %s"),
+ socket_strerror (errsv));
+ }
+
+#else
+
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
diff --git a/gio/gunixcredentialsmessage.c b/gio/gunixcredentialsmessage.c
index 25432a057..351aea77c 100644
--- a/gio/gunixcredentialsmessage.c
+++ b/gio/gunixcredentialsmessage.c
@@ -89,6 +89,8 @@ g_unix_credentials_message_get_msg_type (GSocketControlMessage *message)
return SCM_CREDENTIALS;
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
return SCM_CREDS;
+#elif G_CREDENTIALS_USE_SOLARIS_UCRED
+ return SCM_UCRED;
#elif G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
#error "G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED is set but there is no msg_type defined for this platform"
#else