summaryrefslogtreecommitdiff
path: root/src/polkitbackend/polkitbackendlocalauthorizationstore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/polkitbackend/polkitbackendlocalauthorizationstore.c')
-rw-r--r--src/polkitbackend/polkitbackendlocalauthorizationstore.c776
1 files changed, 0 insertions, 776 deletions
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
deleted file mode 100644
index f40a943..0000000
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.c
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * 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., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz@redhat.com>
- */
-
-#include "config.h"
-
-#include <netdb.h>
-#include <string.h>
-#include <polkit/polkit.h>
-#include "polkitbackendlocalauthorizationstore.h"
-
-/* <internal>
- * SECTION:polkitbackendlocalauthorizationstore
- * @title: PolkitBackendLocalAuthorizationStore
- * @short_description: Watches a directory for authorization files
- *
- * #PolkitBackendLocalAuthorizationStore is a utility class to watch
- * and read authorization files from a directory.
- */
-
-struct _PolkitBackendLocalAuthorizationStorePrivate
-{
- GFile *directory;
- gchar *extension;
-
- GFileMonitor *directory_monitor;
-
- /* List of LocalAuthorization objects */
- GList *authorizations;
-
- gboolean has_data;
-};
-
-enum
-{
- PROP_0,
- PROP_DIRECTORY,
- PROP_EXTENSION,
-};
-
-enum
-{
- CHANGED_SIGNAL,
- LAST_SIGNAL,
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-static void polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store);
-
-static void polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store);
-
-G_DEFINE_TYPE (PolkitBackendLocalAuthorizationStore, polkit_backend_local_authorization_store, G_TYPE_OBJECT);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
- gchar *id;
-
- /* Identities with glob support */
- GList *identity_specs;
-
- /* Netgroup identity strings, which can not support glob syntax */
- GList *netgroup_identities;
-
- GList *action_specs;
-
- PolkitImplicitAuthorization result_any;
- PolkitImplicitAuthorization result_inactive;
- PolkitImplicitAuthorization result_active;
-
- GHashTable *return_value;
-} LocalAuthorization;
-
-static void
-local_authorization_free (LocalAuthorization *authorization)
-{
- g_free (authorization->id);
- g_list_foreach (authorization->identity_specs, (GFunc) g_pattern_spec_free, NULL);
- g_list_free (authorization->identity_specs);
- g_list_free_full (authorization->netgroup_identities, g_free);
- g_list_foreach (authorization->action_specs, (GFunc) g_pattern_spec_free, NULL);
- g_list_free (authorization->action_specs);
- if (authorization->return_value != NULL)
- g_hash_table_unref (authorization->return_value);
- g_free (authorization);
-}
-
-
-static LocalAuthorization *
-local_authorization_new (GKeyFile *key_file,
- const gchar *filename,
- const gchar *group,
- GError **error)
-{
- LocalAuthorization *authorization;
- gchar **identity_strings;
- gchar **action_strings;
- gchar *result_any_string;
- gchar *result_inactive_string;
- gchar *result_active_string;
- gchar **return_value_strings;
- guint n;
-
- identity_strings = NULL;
- action_strings = NULL;
- result_any_string = NULL;
- result_inactive_string = NULL;
- result_active_string = NULL;
- return_value_strings = NULL;
-
- authorization = g_new0 (LocalAuthorization, 1);
-
- identity_strings = g_key_file_get_string_list (key_file,
- group,
- "Identity",
- NULL,
- error);
- if (identity_strings == NULL)
- {
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
- for (n = 0; identity_strings[n] != NULL; n++)
- {
- /* Put netgroup entries in a seperate list from other identities who support glob syntax */
- if (g_str_has_prefix (identity_strings[n], "unix-netgroup:"))
- authorization->netgroup_identities = g_list_prepend (authorization->netgroup_identities,
- g_strdup (identity_strings[n] + sizeof "unix-netgroup:" - 1));
- else
- authorization->identity_specs = g_list_prepend (authorization->identity_specs,
- g_pattern_spec_new (identity_strings[n]));
- }
-
- action_strings = g_key_file_get_string_list (key_file,
- group,
- "Action",
- NULL,
- error);
- if (action_strings == NULL)
- {
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
- for (n = 0; action_strings[n] != NULL; n++)
- {
- authorization->action_specs = g_list_prepend (authorization->action_specs,
- g_pattern_spec_new (action_strings[n]));
- }
-
- authorization->result_any = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
- authorization->result_inactive = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
- authorization->result_active = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
-
- result_any_string = g_key_file_get_string (key_file,
- group,
- "ResultAny",
- NULL);
- if (result_any_string != NULL)
- {
- if (!polkit_implicit_authorization_from_string (result_any_string,
- &authorization->result_any))
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Cannot parse ResultAny string `%s'", result_any_string);
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
- }
-
- result_inactive_string = g_key_file_get_string (key_file,
- group,
- "ResultInactive",
- NULL);
- if (result_inactive_string != NULL)
- {
- if (!polkit_implicit_authorization_from_string (result_inactive_string,
- &authorization->result_inactive))
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Cannot parse ResultInactive string `%s'", result_inactive_string);
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
- }
-
- result_active_string = g_key_file_get_string (key_file,
- group,
- "ResultActive",
- NULL);
- if (result_active_string != NULL)
- {
- if (!polkit_implicit_authorization_from_string (result_active_string,
- &authorization->result_active))
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Cannot parse ResultActive string `%s'", result_active_string);
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
- }
-
- if (result_any_string == NULL && result_inactive_string == NULL && result_active_string == NULL)
- {
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "Must have at least one of ResultAny, ResultInactive and ResultActive");
- local_authorization_free (authorization);
- authorization = NULL;
- goto out;
- }
-
- return_value_strings = g_key_file_get_string_list (key_file,
- group,
- "ReturnValue",
- NULL,
- error);
- if (return_value_strings != NULL)
- {
- for (n = 0; return_value_strings[n] != NULL; n++)
- {
- gchar *p;
- const gchar *key;
- const gchar *value;
-
- p = strchr (return_value_strings[n], '=');
- if (p == NULL)
- {
- g_warning ("Item `%s' in ReturnValue is malformed. Ignoring.",
- return_value_strings[n]);
- continue;
- }
-
- *p = '\0';
- key = return_value_strings[n];
- value = p + 1;
-
- if (authorization->return_value == NULL)
- {
- authorization->return_value = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- g_free);
- }
- g_hash_table_insert (authorization->return_value, g_strdup (key), g_strdup (value));
- }
- }
-
- authorization->id = g_strdup_printf ("%s::%s", filename, group);
-
- out:
- g_strfreev (identity_strings);
- g_free (action_strings);
- g_free (result_any_string);
- g_free (result_inactive_string);
- g_free (result_active_string);
- g_strfreev (return_value_strings);
- return authorization;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-polkit_backend_local_authorization_store_init (PolkitBackendLocalAuthorizationStore *store)
-{
- store->priv = G_TYPE_INSTANCE_GET_PRIVATE (store,
- POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
- PolkitBackendLocalAuthorizationStorePrivate);
-}
-
-static void
-polkit_backend_local_authorization_store_finalize (GObject *object)
-{
- PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
- if (store->priv->directory != NULL)
- g_object_unref (store->priv->directory);
- g_free (store->priv->extension);
-
- if (store->priv->directory_monitor != NULL)
- g_object_unref (store->priv->directory_monitor);
-
- g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
- g_list_free (store->priv->authorizations);
-
- if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize (object);
-}
-
-
-static void
-polkit_backend_local_authorization_store_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
- switch (prop_id)
- {
- case PROP_DIRECTORY:
- g_value_set_object (value, store->priv->directory);
- break;
-
- case PROP_EXTENSION:
- g_value_set_string (value, store->priv->extension);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-polkit_backend_local_authorization_store_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
- switch (prop_id)
- {
- case PROP_DIRECTORY:
- store->priv->directory = g_value_dup_object (value);
- break;
-
- case PROP_EXTENSION:
- store->priv->extension = g_value_dup_string (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-directory_monitor_changed (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event_type,
- gpointer user_data)
-{
- PolkitBackendLocalAuthorizationStore *store;
-
- store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (user_data);
-
- if (file != NULL)
- {
- gchar *name;
-
- name = g_file_get_basename (file);
-
- //g_debug ("event_type=%d file=%p name=%s", event_type, file, name);
-
- if (!g_str_has_prefix (name, ".") &&
- !g_str_has_prefix (name, "#") &&
- g_str_has_suffix (name, store->priv->extension) &&
- (event_type == G_FILE_MONITOR_EVENT_CREATED ||
- event_type == G_FILE_MONITOR_EVENT_DELETED ||
- event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
- {
-
- //g_debug ("match");
-
- /* now throw away all caches */
- polkit_backend_local_authorization_store_purge (store);
- g_signal_emit_by_name (store, "changed");
- }
-
- g_free (name);
- }
-}
-
-static void
-polkit_backend_local_authorization_store_constructed (GObject *object)
-{
- PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
- GError *error;
-
- error = NULL;
- store->priv->directory_monitor = g_file_monitor_directory (store->priv->directory,
- G_FILE_MONITOR_NONE,
- NULL,
- &error);
- if (store->priv->directory_monitor == NULL)
- {
- gchar *dir_name;
- dir_name = g_file_get_uri (store->priv->directory);
- g_warning ("Error monitoring directory %s: %s", dir_name, error->message);
- g_free (dir_name);
- g_error_free (error);
- }
- else
- {
- g_signal_connect (store->priv->directory_monitor,
- "changed",
- (GCallback) directory_monitor_changed,
- store);
- }
-
- if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed != NULL)
- G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed (object);
-}
-
-static void
-polkit_backend_local_authorization_store_class_init (PolkitBackendLocalAuthorizationStoreClass *klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->get_property = polkit_backend_local_authorization_store_get_property;
- gobject_class->set_property = polkit_backend_local_authorization_store_set_property;
- gobject_class->constructed = polkit_backend_local_authorization_store_constructed;
- gobject_class->finalize = polkit_backend_local_authorization_store_finalize;
-
- g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorizationStorePrivate));
-
- /**
- * PolkitBackendLocalAuthorizationStore:directory:
- *
- * The directory to watch for authorization files.
- */
- g_object_class_install_property (gobject_class,
- PROP_DIRECTORY,
- g_param_spec_object ("directory",
- "Directory",
- "The directory to watch for configuration files",
- G_TYPE_FILE,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB |
- G_PARAM_STATIC_NICK));
-
- /**
- * PolkitBackendLocalAuthorizationStore:extension:
- *
- * The file extension for files to consider, e.g. <quote>.pkla</quote>.
- */
- g_object_class_install_property (gobject_class,
- PROP_EXTENSION,
- g_param_spec_string ("extension",
- "Extension",
- "The extension of files to consider",
- NULL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_BLURB |
- G_PARAM_STATIC_NICK));
-
- /**
- * PolkitBackendConfiguStore::changed:
- * @store: A #PolkitBackendLocalAuthorizationStore.
- *
- * Emitted when configuration files in #PolkitBackendConfiguStore:directory changes.
- */
- signals[CHANGED_SIGNAL] = g_signal_new ("changed",
- POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (PolkitBackendLocalAuthorizationStoreClass, changed),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-}
-
-/**
- * polkit_backend_local_authorization_store_new:
- * @directory: The directory to watch.
- * @extension: The extension of files to consider e.g. <quote>.pkla</quote>.
- *
- * Creates a new #PolkitBackendLocalAuthorizationStore object that
- * reads authorizations from @directory with file extension
- * @extension. To watch for configuration changes, connect to the
- * #PolkitBackendLocalAuthorizationStore::changed signal.
- *
- * Returns: A #PolkitBackendLocalAuthorizationStore. Free with
- * g_object_unref().
- **/
-PolkitBackendLocalAuthorizationStore *
-polkit_backend_local_authorization_store_new (GFile *directory,
- const gchar *extension)
-{
- PolkitBackendLocalAuthorizationStore *store;
-
- store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (g_object_new (POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
- "directory", directory,
- "extension", extension,
- NULL));
-
- return store;
-}
-
-static void
-polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store)
-{
- gchar *path;
-
- path = g_file_get_path (store->priv->directory);
- g_debug ("Dropping all .pkla caches for directory `%s'", path);
- g_free (path);
-
- g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
- g_list_free (store->priv->authorizations);
- store->priv->authorizations = NULL;
-
- store->priv->has_data = FALSE;
-}
-
-static void
-polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store)
-{
- GFileEnumerator *enumerator;
- GFileInfo *file_info;
- GError *error;
- GList *files;
- GList *l;
-
- files = NULL;
-
- if (store->priv->has_data)
- goto out;
-
- polkit_backend_local_authorization_store_purge (store);
-
- error = NULL;
- enumerator = g_file_enumerate_children (store->priv->directory,
- "standard::name",
- G_FILE_QUERY_INFO_NONE,
- NULL,
- &error);
- if (enumerator == NULL)
- {
- gchar *dir_name;
- dir_name = g_file_get_uri (store->priv->directory);
- g_warning ("Error enumerating files in %s: %s", dir_name, error->message);
- g_free (dir_name);
- g_error_free (error);
- goto out;
- }
-
- while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
- {
- const gchar *name;
-
- name = g_file_info_get_name (file_info);
-
- /* only consider files with the appropriate extension */
- if (g_str_has_suffix (name, store->priv->extension) && name[0] != '.')
- files = g_list_prepend (files, g_file_get_child (store->priv->directory, name));
-
- g_object_unref (file_info);
- }
- g_object_unref (enumerator);
- if (error != NULL)
- {
- g_warning ("Error enumerating files: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- /* process files; highest priority comes first */
- for (l = files; l != NULL; l = l->next)
- {
- GFile *file = G_FILE (l->data);
- gchar *filename;
- GKeyFile *key_file;
-
- filename = g_file_get_path (file);
-
- key_file = g_key_file_new ();
-
- error = NULL;
- if (!g_key_file_load_from_file (key_file,
- filename,
- G_KEY_FILE_NONE,
- &error))
- {
- g_warning ("Error loading key-file %s: %s", filename, error->message);
- g_error_free (error);
- error = NULL;
- g_key_file_free (key_file);
- }
- else
- {
- gchar **groups;
- guint n;
-
- groups = g_key_file_get_groups (key_file, NULL);
- for (n = 0; groups[n] != NULL; n++)
- {
- LocalAuthorization *authorization;
-
- error = NULL;
- authorization = local_authorization_new (key_file, filename, groups[n], &error);
- if (authorization == NULL)
- {
- g_warning ("Error parsing group `%s' in file `%s': %s",
- groups[n],
- filename,
- error->message);
- g_error_free (error);
- }
- else
- {
- store->priv->authorizations = g_list_prepend (store->priv->authorizations,
- authorization);
- }
- }
- g_strfreev (groups);
-
- store->priv->authorizations = g_list_reverse (store->priv->authorizations);
-
- g_key_file_free (key_file);
- }
-
- g_free (filename);
- }
-
- store->priv->has_data = TRUE;
-
- out:
- g_list_foreach (files, (GFunc) g_object_unref, NULL);
- g_list_free (files);
-}
-
-/**
- * polkit_backend_local_authorization_store_lookup:
- * @store: A #PolkitBackendLocalAuthorizationStore.
- * @identity: The identity to check for.
- * @action_id: The action id to check for.
- * @details: Details for @action.
- * @out_result_any: Return location for the result for any subjects if the look up matched.
- * @out_result_inactive: Return location for the result for subjects in local inactive sessions if the look up matched.
- * @out_result_active: Return location for the result for subjects in local active sessions if the look up matched.
- *
- * Checks if an authorization entry from @store matches @identity,
- * @action_id and @details. May append information to @details if
- * found.
- *
- * Returns: %TRUE if @store has an authorization entry that matches
- * @identity, @action_id and @details. Otherwise %FALSE.
- */
-gboolean
-polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorizationStore *store,
- PolkitIdentity *identity,
- const gchar *action_id,
- PolkitDetails *details,
- PolkitImplicitAuthorization *out_result_any,
- PolkitImplicitAuthorization *out_result_inactive,
- PolkitImplicitAuthorization *out_result_active)
-{
- GList *l, *ll;
- gboolean ret;
- gchar *identity_string;
-
- g_return_val_if_fail (POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE (store), FALSE);
- g_return_val_if_fail (POLKIT_IS_IDENTITY (identity), FALSE);
- g_return_val_if_fail (action_id != NULL, FALSE);
- g_return_val_if_fail (POLKIT_IS_DETAILS (details), FALSE);
- g_return_val_if_fail (out_result_any != NULL, FALSE);
- g_return_val_if_fail (out_result_inactive != NULL, FALSE);
- g_return_val_if_fail (out_result_active != NULL, FALSE);
-
- ret = FALSE;
- identity_string = NULL;
-
- polkit_backend_local_authorization_store_ensure (store);
-
- for (l = store->priv->authorizations; l != NULL; l = l->next)
- {
- LocalAuthorization *authorization = l->data;
-
- /* first match the action */
- for (ll = authorization->action_specs; ll != NULL; ll = ll->next)
- {
- if (g_pattern_match_string ((GPatternSpec *) ll->data, action_id))
- break;
- }
- if (ll == NULL)
- continue;
-
- /* then match the identity against identity specs */
- if (identity_string == NULL)
- identity_string = polkit_identity_to_string (identity);
- for (ll = authorization->identity_specs; ll != NULL; ll = ll->next)
- {
- if (g_pattern_match_string ((GPatternSpec *) ll->data, identity_string))
- break;
- }
-
- /* if no identity specs matched and identity is a user, match against netgroups */
- if (ll == NULL && POLKIT_IS_UNIX_USER (identity))
- {
- PolkitUnixUser *user_identity = POLKIT_UNIX_USER (identity);
- const gchar *user_name = polkit_unix_user_get_name (user_identity);
- if (!user_name)
- continue;
-
- for (ll = authorization->netgroup_identities; ll != NULL; ll = ll->next)
- {
- if (innetgr ((const gchar *) ll->data, NULL, user_name, NULL))
- break;
- }
- }
-
- if (ll == NULL)
- continue;
-
- /* Yay, a match! However, keep going since subsequent authorization entries may modify the result */
- *out_result_any = authorization->result_any;
- *out_result_inactive = authorization->result_inactive;
- *out_result_active = authorization->result_active;
- ret = TRUE;
-
- if (details != NULL && authorization->return_value != NULL)
- {
- GHashTableIter iter;
- const gchar *key;
- const gchar *value;
-
- g_hash_table_iter_init (&iter, authorization->return_value);
- while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
- {
- polkit_details_insert (details, key, value);
- }
- }
-
-#if 0
- g_debug ("authorization with id `%s' matched action_id `%s' for identity `%s'",
- authorization->id,
- action_id,
- polkit_identity_to_string (identity));
-#endif
- }
-
- g_free (identity_string);
-
- return ret;
-}