X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgcredentials.c;h=6673afddd460611b1051961161351c2ed13c0542;hb=fd643b87ab7bc232274c5cd6f9c175d5f6f9ecb9;hp=40d6757eeb9f15f3b8f301b8d58776d39a6fc125;hpb=efb1a054b0858b4475941892f53bbc5186065df9;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gcredentials.c b/gio/gcredentials.c index 40d6757..6673afd 100644 --- a/gio/gcredentials.c +++ b/gio/gcredentials.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: David Zeuthen */ @@ -23,31 +21,26 @@ #include "config.h" #include - -#ifdef __linux__ -#define __USE_GNU -#include -#include -#include #include -#endif #include #include "gcredentials.h" +#include "gcredentialsprivate.h" +#include "gnetworking.h" #include "gioerror.h" +#include "gioenumtypes.h" #include "glibintl.h" -#include "gioalias.h" /** * SECTION:gcredentials * @short_description: An object containing credentials * @include: gio/gio.h * - * The #GCredentials type is a reference-counted wrapper for the - * native credentials type. This information is typically used for - * identifying, authenticating and authorizing other processes. + * The #GCredentials type is a reference-counted wrapper for native + * credentials. This information is typically used for identifying, + * authenticating and authorizing other processes. * * Some operating systems supports looking up the credentials of the * remote peer of a communication endpoint - see e.g. @@ -58,28 +51,78 @@ * #GUnixCredentialsMessage, g_unix_connection_send_credentials() and * g_unix_connection_receive_credentials() for details. * - * On Linux, the native credential type is a struct ucred - see - * the unix(7) man page for details. + * On Linux, the native credential type is a struct ucred - see the + * unix(7) man page for details. This corresponds to + * %G_CREDENTIALS_TYPE_LINUX_UCRED. + * + * On FreeBSD, Debian GNU/kFreeBSD, and GNU/Hurd, the native + * credential type is a struct cmsgcred. This corresponds + * to %G_CREDENTIALS_TYPE_FREEBSD_CMSGCRED. + * + * On NetBSD, the native credential type is a struct unpcbid. + * This corresponds to %G_CREDENTIALS_TYPE_NETBSD_UNPCBID. + * + * On OpenBSD, the native credential type is a struct sockpeercred. + * This corresponds to %G_CREDENTIALS_TYPE_OPENBSD_SOCKPEERCRED. + * + * On Solaris (including OpenSolaris and its derivatives), the native + * credential type is a ucred_t. This corresponds to + * %G_CREDENTIALS_TYPE_SOLARIS_UCRED. */ -struct _GCredentialsPrivate +/** + * GCredentials: + * + * The #GCredentials structure contains only private data and + * should only be accessed using the provided API. + * + * Since: 2.26 + */ +struct _GCredentials { -#ifdef __linux__ + /*< private >*/ + GObject parent_instance; + +#if G_CREDENTIALS_USE_LINUX_UCRED struct ucred native; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + struct cmsgcred native; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + struct unpcbid 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 -#endif - guint foo; + #ifdef __GNUC__ + #warning Please add GCredentials support for your OS + #endif #endif }; +/** + * GCredentialsClass: + * + * Class structure for #GCredentials. + * + * Since: 2.26 + */ +struct _GCredentialsClass +{ + /*< private >*/ + GObjectClass parent_class; +}; + 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); @@ -91,8 +134,6 @@ g_credentials_class_init (GCredentialsClass *klass) { GObjectClass *gobject_class; - g_type_class_add_private (klass, sizeof (GCredentialsPrivate)); - gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = g_credentials_finalize; } @@ -100,11 +141,25 @@ g_credentials_class_init (GCredentialsClass *klass) static void g_credentials_init (GCredentials *credentials) { - credentials->priv = G_TYPE_INSTANCE_GET_PRIVATE (credentials, G_TYPE_CREDENTIALS, GCredentialsPrivate); -#ifdef __linux__ - credentials->priv->native.pid = getpid (); - credentials->priv->native.uid = getuid (); - credentials->priv->native.gid = getgid (); +#if G_CREDENTIALS_USE_LINUX_UCRED + credentials->native.pid = getpid (); + credentials->native.uid = geteuid (); + credentials->native.gid = getegid (); +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + memset (&credentials->native, 0, sizeof (struct cmsgcred)); + credentials->native.cmcred_pid = getpid (); + credentials->native.cmcred_euid = geteuid (); + credentials->native.cmcred_gid = getegid (); +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + credentials->native.unp_pid = getpid (); + credentials->native.unp_euid = geteuid (); + credentials->native.unp_egid = getegid (); +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + 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 } @@ -148,16 +203,56 @@ g_credentials_to_string (GCredentials *credentials) g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL); ret = g_string_new ("GCredentials:"); -#ifdef __linux__ - g_string_append (ret, "linux:"); - if (credentials->priv->native.pid != -1) - g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.pid); - if (credentials->priv->native.uid != -1) - g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.uid); - if (credentials->priv->native.gid != -1) - g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->priv->native.gid); +#if G_CREDENTIALS_USE_LINUX_UCRED + g_string_append (ret, "linux-ucred:"); + if (credentials->native.pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); + if (credentials->native.uid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); + if (credentials->native.gid != -1) + 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_FREEBSD_CMSGCRED + 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); +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + g_string_append (ret, "netbsd-unpcbid:"); + if (credentials->native.unp_pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_pid); + if (credentials->native.unp_euid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_euid); + if (credentials->native.unp_egid != -1) + g_string_append_printf (ret, "gid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.unp_egid); + ret->str[ret->len - 1] = '\0'; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + g_string_append (ret, "openbsd-sockpeercred:"); + if (credentials->native.pid != -1) + g_string_append_printf (ret, "pid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.pid); + if (credentials->native.uid != -1) + g_string_append_printf (ret, "uid=%" G_GINT64_FORMAT ",", (gint64) credentials->native.uid); + if (credentials->native.gid != -1) + 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 @@ -195,8 +290,20 @@ g_credentials_is_same_user (GCredentials *credentials, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); ret = FALSE; -#ifdef __linux__ - if (credentials->priv->native.uid == other_credentials->priv->native.uid) +#if G_CREDENTIALS_USE_LINUX_UCRED + if (credentials->native.uid == other_credentials->native.uid) + ret = TRUE; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid) + ret = TRUE; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + if (credentials->native.unp_euid == other_credentials->native.unp_euid) + ret = TRUE; +#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, @@ -208,55 +315,109 @@ g_credentials_is_same_user (GCredentials *credentials, return ret; } +static gboolean +credentials_native_type_check (GCredentialsType requested_type, + const char *op) +{ + GEnumClass *enum_class; + GEnumValue *requested; +#if G_CREDENTIALS_SUPPORTED + GEnumValue *supported; +#endif + +#if G_CREDENTIALS_SUPPORTED + if (requested_type == G_CREDENTIALS_NATIVE_TYPE) + return TRUE; +#endif + + enum_class = g_type_class_ref (g_credentials_type_get_type ()); + requested = g_enum_get_value (enum_class, requested_type); + +#if G_CREDENTIALS_SUPPORTED + supported = g_enum_get_value (enum_class, G_CREDENTIALS_NATIVE_TYPE); + g_assert (supported); + g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s " + "but only %s is supported on this platform.", + op, op, + requested ? requested->value_name : "(unknown)", + supported->value_name); +#else + g_warning ("g_credentials_%s_native: Trying to %s credentials of type %s " + "but there is no support for GCredentials on this platform.", + op, op, + requested ? requested->value_name : "(unknown)"); +#endif + + g_type_class_unref (enum_class); + return FALSE; +} + /** - * g_credentials_get_native: + * g_credentials_get_native: (skip) * @credentials: A #GCredentials. + * @native_type: The type of native credentials to get. * - * Gets a pointer to the native credentials structure. - * - * Returns: The pointer or %NULL if there is no #GCredentials support - * for the OS. Do not free the returned data, it is owned by + * Gets a pointer to native credentials of type @native_type from * @credentials. * + * It is a programming error (which will cause an warning to be + * logged) to use this method if there is no #GCredentials support for + * the OS or if @native_type isn't supported by the OS. + * + * Returns: The pointer to native credentials or %NULL if the + * operation there is no #GCredentials support for the OS or if + * @native_type isn't supported by the OS. Do not free the returned + * data, it is owned by @credentials. + * * Since: 2.26 */ gpointer -g_credentials_get_native (GCredentials *credentials) +g_credentials_get_native (GCredentials *credentials, + GCredentialsType native_type) { - gpointer ret; g_return_val_if_fail (G_IS_CREDENTIALS (credentials), NULL); -#ifdef __linux__ - ret = &credentials->priv->native; + if (!credentials_native_type_check (native_type, "get")) + return NULL; + +#if G_CREDENTIALS_USE_SOLARIS_UCRED + return credentials->native; +#elif G_CREDENTIALS_SUPPORTED + return &credentials->native; #else - ret = NULL; + g_assert_not_reached (); #endif - - return ret; } /** * g_credentials_set_native: * @credentials: A #GCredentials. + * @native_type: The type of native credentials to set. * @native: A pointer to native credentials. * - * Copies the native credentials from @native into @credentials. + * Copies the native credentials of type @native_type from @native + * into @credentials. * * It is a programming error (which will cause an warning to be * logged) to use this method if there is no #GCredentials support for - * the OS. + * the OS or if @native_type isn't supported by the OS. * * Since: 2.26 */ void -g_credentials_set_native (GCredentials *credentials, - gpointer native) +g_credentials_set_native (GCredentials *credentials, + GCredentialsType native_type, + gpointer native) { -#ifdef __linux__ - memcpy (&credentials->priv->native, native, sizeof (struct ucred)); + if (!credentials_native_type_check (native_type, "set")) + return; + +#if G_CREDENTIALS_USE_SOLARIS_UCRED + memcpy (credentials->native, native, ucred_size ()); +#elif G_CREDENTIALS_SUPPORTED + memcpy (&credentials->native, native, sizeof (credentials->native)); #else - g_warning ("g_credentials_set_native: Trying to set credentials but GLib has no support " - "for the native credentials type. Please add support."); + g_assert_not_reached (); #endif } @@ -288,8 +449,16 @@ g_credentials_get_unix_user (GCredentials *credentials, g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1); g_return_val_if_fail (error == NULL || *error == NULL, -1); -#ifdef __linux__ - ret = credentials->priv->native.uid; +#if G_CREDENTIALS_USE_LINUX_UCRED + ret = credentials->native.uid; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + ret = credentials->native.cmcred_euid; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + ret = credentials->native.unp_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, @@ -302,6 +471,52 @@ g_credentials_get_unix_user (GCredentials *credentials, } /** + * g_credentials_get_unix_pid: + * @credentials: A #GCredentials + * @error: Return location for error or %NULL. + * + * Tries to get the UNIX process identifier from @credentials. This + * method is only available on UNIX platforms. + * + * 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 process ID. + * + * Returns: The UNIX process ID, or -1 if @error is set. + * + * Since: 2.36 + */ +pid_t +g_credentials_get_unix_pid (GCredentials *credentials, + GError **error) +{ + pid_t ret; + + g_return_val_if_fail (G_IS_CREDENTIALS (credentials), -1); + g_return_val_if_fail (error == NULL || *error == NULL, -1); + +#if G_CREDENTIALS_USE_LINUX_UCRED + ret = credentials->native.pid; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + ret = credentials->native.cmcred_pid; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + ret = credentials->native.unp_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, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("GCredentials does not contain a process ID on this OS")); +#endif + + return ret; +} + +/** * g_credentials_set_unix_user: * @credentials: A #GCredentials. * @uid: The UNIX user identifier to set. @@ -312,7 +527,8 @@ g_credentials_get_unix_user (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. * @@ -330,19 +546,33 @@ g_credentials_set_unix_user (GCredentials *credentials, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); ret = FALSE; -#ifdef __linux__ - credentials->priv->native.uid = uid; +#if G_CREDENTIALS_USE_LINUX_UCRED + credentials->native.uid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED + credentials->native.cmcred_euid = uid; + ret = TRUE; +#elif G_CREDENTIALS_USE_NETBSD_UNPCBID + credentials->native.unp_euid = uid; ret = TRUE; +#elif G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED + credentials->native.uid = uid; + ret = TRUE; +#elif !G_CREDENTIALS_SPOOFING_SUPPORTED + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_PERMISSION_DENIED, + _("Credentials spoofing is not possible on this OS")); + 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 return ret; } -#endif /* G_OS_UNIX */ -#define __G_CREDENTIALS_C__ -#include "gioaliasdef.c" +#endif /* G_OS_UNIX */