Commit 55cfa233 authored by Corentin Noël's avatar Corentin Noël

Create SignonSecurityContext and send ACL as a(ss)

This increases the compatibility with gsignond
parent 10ba32e0
......@@ -83,5 +83,11 @@
*_finish() in your #GAsyncReadyCallback to get the result of the
operation.
</para>
<para>
signon_identity_info_get_access_control_list() and
signon_identity_info_set_access_control_list() now make use of the new
#SignonSecurityContext structure that replaces the simple security
context string.
</para>
</section>
</chapter>
......@@ -5,6 +5,7 @@ libsignon_glib_public_headers = files(
'signon-identity.h',
'signon-identity-info.h',
'signon-glib.h',
'signon-security-context.h',
'signon-types.h',
)
......@@ -20,6 +21,7 @@ libsignon_glib_public_sources = files(
'signon-errors.c',
'signon-identity.c',
'signon-identity-info.c',
'signon-security-context.c',
)
libsignon_glib_sources = libsignon_glib_public_sources + files(
......
......@@ -43,7 +43,10 @@ G_DEFINE_BOXED_TYPE (SignonIdentityInfo, signon_identity_info,
static GVariant *
signon_variant_new_string (const gchar *string)
{
return g_variant_new_string (string != NULL ? string : "");
if (string == NULL || !g_utf8_validate (string, -1, NULL))
return g_variant_new_string ("");
return g_variant_new_string (string);
}
static const gchar *identity_info_get_secret (const SignonIdentityInfo *info)
......@@ -88,7 +91,8 @@ void signon_identity_info_set_methods (SignonIdentityInfo *info,
SignonIdentityInfo *
signon_identity_info_new_from_variant (GVariant *variant)
{
GVariant *method_map;
GVariant *method_map = NULL;
GVariant *acl_var = NULL;
if (!variant)
return NULL;
......@@ -135,8 +139,8 @@ signon_identity_info_new_from_variant (GVariant *variant)
&method_map))
{
GVariantIter iter;
gchar *method;
gchar **mechanisms;
gchar *method = NULL;
gchar **mechanisms = NULL;
g_variant_iter_init (&iter, method_map);
while (g_variant_iter_next (&iter, "{s^as}", &method, &mechanisms))
......@@ -146,10 +150,28 @@ signon_identity_info_new_from_variant (GVariant *variant)
g_variant_unref (method_map);
}
g_variant_lookup (variant,
"ACL",
"^as",
&info->access_control_list);
if (g_variant_lookup (variant,
"ACL",
"a(ss)",
&acl_var))
{
GVariantIter iter;
GVariant *child = NULL;
GList *acl_list = NULL;
g_variant_iter_init (&iter, acl_var);
while ((child = g_variant_iter_next_value (&iter)))
{
SignonSecurityContext *ctx = signon_security_context_new_from_variant (child);
if (ctx != NULL)
acl_list = g_list_append (acl_list, ctx);
g_variant_unref (child);
}
info->access_control_list = acl_list;
g_variant_unref (acl_var);
}
g_variant_lookup (variant,
"Type",
......@@ -219,11 +241,20 @@ signon_identity_info_to_variant (const SignonIdentityInfo *self)
if (self->access_control_list != NULL)
{
GVariantBuilder acl_builder;
g_variant_builder_init (&acl_builder, (const GVariantType *)"a(ss)");
GList *l;
for (l = self->access_control_list; l != NULL; l = l->next)
{
GVariant* acl_var = signon_security_context_to_variant (l->data);
if (acl_var != NULL)
g_variant_builder_add_value (&acl_builder, acl_var);
}
g_variant_builder_add (&builder, "{sv}",
"ACL",
g_variant_new_strv ((const gchar * const *)
self->access_control_list,
-1));
g_variant_builder_end (&acl_builder));
}
g_variant_builder_add (&builder, "{sv}",
......@@ -271,7 +302,8 @@ void signon_identity_info_free (SignonIdentityInfo *info)
g_hash_table_destroy (info->methods);
g_strfreev (info->realms);
g_strfreev (info->access_control_list);
g_list_free_full (info->access_control_list, (GDestroyNotify)signon_security_context_free);
g_slice_free (SignonIdentityInfo, info);
}
......@@ -402,12 +434,14 @@ const gchar* const *signon_identity_info_get_realms (const SignonIdentityInfo *i
*
* Get an array of ACL statements of the identity.
*
* Returns: (transfer none): a %NULL terminated array of ACL statements.
* Returns: (transfer full) (element-type SignonSecurityContext): a #GList of
* #SignonSecurityContext representing ACL statements.
* Each element should be freed with signon_security_context_copy() after use.
*/
const gchar* const *signon_identity_info_get_access_control_list (const SignonIdentityInfo *info)
GList *signon_identity_info_get_access_control_list (const SignonIdentityInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return (const gchar* const *)info->access_control_list;
return g_list_copy_deep (info->access_control_list, (GCopyFunc)signon_security_context_copy, NULL);
}
/**
......@@ -535,20 +569,42 @@ void signon_identity_info_set_realms (SignonIdentityInfo *info,
/**
* signon_identity_info_set_access_control_list:
* @info: the #SignonIdentityInfo.
* @access_control_list: (array zero-terminated=1): a %NULL-terminated list
* of ACL security domains.
* @access_control_list: (element-type SignonSecurityContext): a #GList of
* #SignonSecurityContext representing ACL security domains.
*
* Specifies the ACL for this identity. The actual meaning of the ACL depends
* on the security framework used by signond.
*/
void signon_identity_info_set_access_control_list (SignonIdentityInfo *info,
const gchar* const *access_control_list)
GList *access_control_list)
{
g_return_if_fail (info != NULL);
if (info->access_control_list) g_strfreev (info->access_control_list);
if (info->access_control_list) g_list_free_full (info->access_control_list, (GDestroyNotify)signon_security_context_free);
info->access_control_list = g_list_copy_deep (access_control_list, (GCopyFunc)signon_security_context_copy, NULL);
}
/**
* signon_identity_info_add_access_control:
* @info: the #SignonIdentityInfo.
* @system_context: the system context to add.
* @application_context: the application context to add.
*
* Add an ACL to this identity. This is a helper function.
*/
void signon_identity_info_add_access_control (SignonIdentityInfo *info,
const gchar *system_context,
const gchar *application_context)
{
SignonSecurityContext *ctx = NULL;
g_return_if_fail (info != NULL);
g_return_if_fail (system_context != NULL);
g_return_if_fail (application_context != NULL);
info->access_control_list = g_strdupv ((gchar **)access_control_list);
ctx = signon_security_context_new_from_values (system_context, application_context);
info->access_control_list = g_list_append (info->access_control_list, ctx);
}
/**
......
......@@ -66,7 +66,7 @@ gboolean signon_identity_info_get_storing_secret (const SignonIdentityInfo *info
const gchar *signon_identity_info_get_caption (const SignonIdentityInfo *info);
const GHashTable *signon_identity_info_get_methods (const SignonIdentityInfo *info);
const gchar* const *signon_identity_info_get_realms (const SignonIdentityInfo *info);
const gchar* const *signon_identity_info_get_access_control_list (const SignonIdentityInfo *info);
GList *signon_identity_info_get_access_control_list (const SignonIdentityInfo *info);
SignonIdentityType signon_identity_info_get_identity_type (const SignonIdentityInfo *info);
void signon_identity_info_set_username (SignonIdentityInfo *info, const gchar *username);
......@@ -80,7 +80,7 @@ void signon_identity_info_remove_method (SignonIdentityInfo *info, const gchar *
void signon_identity_info_set_realms (SignonIdentityInfo *info,
const gchar* const *realms);
void signon_identity_info_set_access_control_list (SignonIdentityInfo *info,
const gchar* const *access_control_list);
GList *access_control_list);
void signon_identity_info_set_identity_type (SignonIdentityInfo *info,
SignonIdentityType type);
......
......@@ -38,6 +38,7 @@
#include "signon-identity.h"
#include "signon-auth-session.h"
#include "signon-security-context.h"
G_BEGIN_DECLS
......@@ -50,10 +51,16 @@ struct _SignonIdentityInfo
gboolean store_secret;
GHashTable *methods;
gchar **realms;
gchar **access_control_list;
GList *access_control_list;
gint type;
};
struct _SignonSecurityContext
{
gchar *system_context;
gchar *application_context;
};
#define SIGNOND_SERVICE_PREFIX "com.google.code.AccountsSSO.SingleSignOn"
#define SIGNON_DBUS_ERROR_PREFIX SIGNOND_SERVICE_PREFIX ".Error."
#define SIGNOND_DAEMON_OBJECTPATH "/com/google/code/AccountsSSO/SingleSignOn"
......@@ -118,6 +125,14 @@ G_GNUC_INTERNAL
GVariant *
signon_identity_info_to_variant (const SignonIdentityInfo *self);
G_GNUC_INTERNAL
SignonSecurityContext *
signon_security_context_new_from_variant (GVariant *variant);
G_GNUC_INTERNAL
GVariant *
signon_security_context_to_variant (const SignonSecurityContext *self);
G_GNUC_INTERNAL
void signon_identity_info_set_methods (SignonIdentityInfo *self,
const GHashTable *methods);
......
/* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libsignon-glib
*
* Copyright (C) 2009-2010 Nokia Corporation.
* Copyright (C) 2011-2016 Canonical Ltd.
*
* Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
* SECTION:signon-security-context
* @title: SignonSecurityContext
* @short_description: Security context for #SignonIdentityInfo.
*
* Security context information for a #SignonIdentity.
*/
#include "signon-security-context.h"
#include "signon-internals.h"
G_DEFINE_BOXED_TYPE (SignonSecurityContext, signon_security_context,
(GBoxedCopyFunc)signon_security_context_copy,
(GBoxedFreeFunc)signon_security_context_free);
SignonSecurityContext *
signon_security_context_new_from_variant (GVariant *variant)
{
gchar *system_context = NULL;
gchar *application_context = NULL;
SignonSecurityContext *ctx;
g_return_val_if_fail (variant != NULL, NULL);
g_variant_get (variant, "(ss)", &system_context, &application_context);
ctx = signon_security_context_new_from_values (system_context, application_context);
g_free (system_context);
g_free (application_context);
return ctx;
}
GVariant *
signon_security_context_to_variant (const SignonSecurityContext *ctx)
{
g_return_val_if_fail (ctx != NULL, NULL);
return g_variant_new ("(ss)", ctx->system_context, ctx->application_context);
}
/*
* Public methods:
*/
/**
* signon_security_context_new:
*
* Creates a new #SignonSecurityContext item.
*
* Returns: (transfer full): a new #SignonSecurityContext item.
*/
SignonSecurityContext *
signon_security_context_new (void)
{
SignonSecurityContext *ctx = g_slice_new0 (SignonSecurityContext);
ctx->system_context = g_strdup ("");
ctx->application_context = g_strdup ("");
return ctx;
}
/**
* signon_security_context_new_from_values:
* @system_context: system security context
* @application_context: application security context
*
* Creates a new #SignonSecurityContext item.
*
* Returns: (transfer full): a new #SignonSecurityContext item.
*/
SignonSecurityContext *
signon_security_context_new_from_values (const gchar *system_context, const gchar *application_context)
{
SignonSecurityContext *ctx = signon_security_context_new ();
if (system_context != NULL)
signon_security_context_set_system_context (ctx, system_context);
if (application_context != NULL)
signon_security_context_set_application_context (ctx, application_context);
return ctx;
}
/**
* signon_security_context_free:
* @ctx: the #SignonSecurityContext.
*
* Destroys the given #SignonSecurityContext item.
*/
void
signon_security_context_free (SignonSecurityContext *ctx)
{
if (ctx == NULL) return;
g_free (ctx->system_context);
g_free (ctx->application_context);
g_slice_free (SignonSecurityContext, ctx);
}
/**
* signon_security_context_copy:
* @other: the #SignonSecurityContext.
*
* Get a newly-allocated copy of @info.
*
* Returns: (transfer full): a copy of the given #SignonIdentityInfo, or %NULL on failure.
*/
SignonSecurityContext *
signon_security_context_copy (const SignonSecurityContext *other)
{
g_return_val_if_fail (other != NULL, NULL);
SignonSecurityContext *ctx = signon_security_context_new ();
signon_security_context_set_system_context (ctx, signon_security_context_get_system_context (other));
signon_security_context_set_application_context (ctx, signon_security_context_get_application_context (other));
return ctx;
}
/**
* signon_security_context_get_application_context:
* @ctx: the #SignonSecurityContext.
*
* Get the application context of @ctx.
*
* Returns: the application context.
*/
const gchar *
signon_security_context_get_application_context (const SignonSecurityContext *ctx)
{
g_return_val_if_fail (ctx != NULL, NULL);
return ctx->application_context;
}
/**
* signon_security_context_get_system_context:
* @ctx: the #SignonSecurityContext.
*
* Get the system context of @ctx.
*
* Returns: the system context.
*/
const gchar *
signon_security_context_get_system_context (const SignonSecurityContext *ctx)
{
g_return_val_if_fail (ctx != NULL, NULL);
return ctx->system_context;
}
/**
* signon_security_context_set_application_context:
* @ctx: the #SignonSecurityContext.
* @application_context: the application context.
*
* Sets the application context.
*/
void
signon_security_context_set_application_context (SignonSecurityContext *ctx, const gchar *application_context)
{
g_return_if_fail (ctx != NULL);
if (ctx->application_context) g_free (ctx->application_context);
if (application_context != NULL)
ctx->application_context = g_strdup (application_context);
else
ctx->application_context = g_strdup ("");
}
/**
* signon_security_context_set_system_context:
* @ctx: the #SignonSecurityContext.
* @system_context: the system context.
*
* Sets the system context.
*/
void
signon_security_context_set_system_context (SignonSecurityContext *ctx, const gchar *system_context)
{
g_return_if_fail (ctx != NULL);
if (ctx->system_context) g_free (ctx->system_context);
if (system_context != NULL)
ctx->system_context = g_strdup (system_context);
else
ctx->system_context = g_strdup ("");
}
/* vi: set et sw=4 ts=4 cino=t0,(0: */
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of libsignon-glib
*
* Copyright (C) 2018 elementary, Inc
*
* Contact: Corentin Noël <corentin@elementary.io>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef _SIGNON_SECURITY_CONTEXT_H_
#define _SIGNON_SECURITY_CONTEXT_H_
#include <glib-object.h>
G_BEGIN_DECLS
/**
* SignonSecurityContext:
*
* Opaque struct. Use the accessor functions below.
*/
typedef struct _SignonSecurityContext SignonSecurityContext;
GType signon_security_context_get_type (void) G_GNUC_CONST;
SignonSecurityContext *signon_security_context_new (void);
SignonSecurityContext *signon_security_context_new_from_values (const gchar *system_context, const gchar *application_context);
void signon_security_context_free (SignonSecurityContext *ctx);
SignonSecurityContext *signon_security_context_copy (const SignonSecurityContext *other);
const gchar *signon_security_context_get_application_context (const SignonSecurityContext *ctx);
const gchar *signon_security_context_get_system_context (const SignonSecurityContext *ctx);
void signon_security_context_set_application_context (SignonSecurityContext *ctx, const gchar *application_context);
void signon_security_context_set_system_context (SignonSecurityContext *ctx, const gchar *system_context);
G_END_DECLS
#endif /* _SIGNON_SECURITY_CONTEXT_H_ */
......@@ -658,7 +658,7 @@ START_TEST(test_auth_session_process_after_store)
{
SignonIdentityInfo *info = NULL;
SignonIdentity *identity = NULL;
const gchar *const acl[] = { "*", NULL };
GList *acl = g_list_append (NULL, signon_security_context_new_from_values ("*", "*"));
SignonAuthSession *auth_session = NULL;
GError *error = NULL;
......@@ -674,6 +674,8 @@ START_TEST(test_auth_session_process_after_store)
signon_identity_info_set_username (info, "Nice user");
signon_identity_info_set_access_control_list (info, acl);
g_list_free_full (acl, (GDestroyNotify)signon_security_context_free);
/*
* This auth session will get an updated Identity ID when the identity
* get created.
......@@ -746,7 +748,7 @@ static guint
new_identity()
{
SignonIdentity *identity;
const gchar *const acl[] = { "*", NULL };
GList *acl = g_list_append (NULL, signon_security_context_new_from_values ("*", "*"));
guint id = 0;
identity = signon_identity_new(NULL, NULL);
......@@ -756,7 +758,9 @@ new_identity()
signon_identity_info_set_username (info, "James Bond");
signon_identity_info_set_secret (info, "007", TRUE);
signon_identity_info_set_caption (info, "caption");
signon_identity_info_set_access_control_list (info, acl);
g_list_free_full (acl, (GDestroyNotify)signon_security_context_free);
signon_identity_store_info (identity,
info,
......@@ -904,7 +908,7 @@ static void identity_verify_secret_cb (GObject *source_object,
START_TEST(test_verify_secret_identity)
{
const gchar *const acl[] = { "*", NULL };
GList *acl = g_list_append (NULL, signon_security_context_new_from_values ("*", "*"));
g_debug("%s", G_STRFUNC);
SignonIdentity *idty = signon_identity_new(NULL, NULL);
......@@ -919,8 +923,10 @@ START_TEST(test_verify_secret_identity)
signon_identity_info_set_username (info, "James Bond");
signon_identity_info_set_secret (info, secret, TRUE);
signon_identity_info_set_caption (info, "caption");
signon_identity_info_set_access_control_list (info, acl);
add_methods_to_identity_info (info);
g_list_free_full (acl, (GDestroyNotify)signon_security_context_free);
signon_identity_store_info (idty,
info,
......@@ -1069,7 +1075,7 @@ static void identity_info_cb (GObject *source_object,
static SignonIdentityInfo *create_standard_info()
{
const gchar *const acl[] = { "*", NULL };
GList *acl = g_list_append (NULL, signon_security_context_new_from_values ("*", "*"));
g_debug("%s", G_STRFUNC);
SignonIdentityInfo *info = signon_identity_info_new ();
signon_identity_info_set_username (info, "James Bond");
......@@ -1086,15 +1092,16 @@ static SignonIdentityInfo *create_standard_info()
signon_identity_info_set_method (info, "method1", (const gchar **)mechanisms);
signon_identity_info_set_method (info, "method2", (const gchar **)mechanisms);
signon_identity_info_set_method (info, "method3", (const gchar **)mechanisms);
signon_identity_info_set_access_control_list (info, acl);
g_list_free_full (acl, (GDestroyNotify)signon_security_context_free);
return info;
}
START_TEST(test_info_identity)
{
const gchar *const acl[] = { "*", NULL };
GList *acl = g_list_append (NULL, signon_security_context_new_from_values ("*", "*"));
g_debug("%s", G_STRFUNC);
SignonIdentity *idty = signon_identity_new();
fail_unless (idty != NULL);
......@@ -1114,8 +1121,10 @@ START_TEST(test_info_identity)
signon_identity_info_set_username (info, "James Bond");
signon_identity_info_set_secret (info, "007", TRUE);
signon_identity_info_set_caption (info, "caption");
signon_identity_info_set_access_control_list (info, acl);
add_methods_to_identity_info (info);
g_list_free_full (acl, (GDestroyNotify)signon_security_context_free);
signon_identity_store_info (idty,
info,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment