gkd-secret-secret.c 4.78 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * gnome-keyring
 *
 * Copyright (C) 2008 Stefan Walter
 *
 * This program 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.1 of
 * the License, or (at your option) any later version.
 *
 * This program 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
17 18
 * License along with this program; if not, see
 * <http://www.gnu.org/licenses/>.
19 20 21 22
 */

#include "config.h"

23
#include "gkd-secret-dispatch.h"
24
#include "gkd-secret-error.h"
25
#include "gkd-secret-secret.h"
26 27
#include "gkd-secret-service.h"
#include "gkd-secret-session.h"
28 29 30

#include "egg/egg-secure-memory.h"

31 32
#include <glib-object.h>

33 34
#include <string.h>

35 36
GkdSecretSecret *
gkd_secret_secret_new (GkdSecretSession *session,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
37 38 39 40
		       gconstpointer parameter,
		       gsize n_parameter,
		       gconstpointer value,
		       gsize n_value)
41 42
{
	return gkd_secret_secret_new_take_memory (session,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
43 44 45 46
						  g_memdup (parameter, n_parameter),
						  n_parameter,
						  g_memdup (value, n_value),
						  n_value);
47 48
}

49 50 51 52 53 54 55 56
static void
destroy_with_owned_memory (gpointer data)
{
	GkdSecretSecret *secret = data;
	g_free (secret->parameter);
	g_free (secret->value);
}

57
GkdSecretSecret*
58
gkd_secret_secret_new_take_memory (GkdSecretSession *session,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
59 60
				   gpointer parameter, gsize n_parameter,
				   gpointer value, gsize n_value)
61 62 63
{
	GkdSecretSecret *secret;

64
	g_return_val_if_fail (GKD_SECRET_IS_SESSION (session), NULL);
65

66
	secret = g_slice_new0 (GkdSecretSecret);
67
	secret->session = g_object_ref (session);
68 69 70 71
	secret->parameter = parameter;
	secret->n_parameter = n_parameter;
	secret->value = value;
	secret->n_value = n_value;
72 73 74 75

	secret->destroy_func = destroy_with_owned_memory;
	secret->destroy_data = secret;

76 77 78 79
	return secret;
}

GkdSecretSecret*
80
gkd_secret_secret_parse (GkdSecretService *service,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
81 82 83
			 const char *sender,
			 GVariant *variant,
			 GError **error)
84
{
85
	GkdSecretSecret *secret = NULL;
86
	GkdSecretSession *session;
87
	const char *parameter, *value, *path, *content_type;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
88 89
	gsize n_parameter, n_value;
	GVariant *parameter_variant, *value_variant;
90

91
	g_return_val_if_fail (GKD_SECRET_IS_SERVICE (service), NULL);
92 93
	g_return_val_if_fail (variant, NULL);
	g_return_val_if_fail (sender, NULL);
94

Cosimo Cecchi's avatar
Cosimo Cecchi committed
95
	g_variant_get (variant, "(&o^&ay^&ay&s)", &path, NULL, NULL, &content_type);
96

Cosimo Cecchi's avatar
Cosimo Cecchi committed
97 98
	/* parameter */
	parameter_variant = g_variant_get_child_value (variant, 1);
99
	parameter = g_variant_get_fixed_array (parameter_variant, &n_parameter, sizeof (guchar));
100

Cosimo Cecchi's avatar
Cosimo Cecchi committed
101 102
	/* value */
	value_variant = g_variant_get_child_value (variant, 2);
103
	value = g_variant_get_fixed_array (value_variant, &n_value, sizeof (guchar));
104

105
	/* Try to lookup the session */
106
	session = gkd_secret_service_lookup_session (service, path, sender);
107
	if (session == NULL) {
108
		g_set_error_literal (error, GKD_SECRET_ERROR,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
109
				     GKD_SECRET_ERROR_NO_SESSION,
110 111
				     "The session wrapping the secret does not exist");
		goto out;
112 113
	}

114
	secret = g_slice_new0 (GkdSecretSecret);
115
	secret->session = g_object_ref (session);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
116
	secret->parameter = g_memdup (parameter, n_parameter);
117
	secret->n_parameter = n_parameter;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
118
	secret->value = g_memdup (value, n_value);
119 120
	secret->n_value = n_value;

121
 out:
Cosimo Cecchi's avatar
Cosimo Cecchi committed
122 123
	g_variant_unref (parameter_variant);
	g_variant_unref (value_variant);
124

125
	return secret;
126 127
}

128 129
GVariant *
gkd_secret_secret_append (GkdSecretSecret *secret)
130
{
131
	const gchar *content_type = "text/plain";
132
	const gchar *path;
133
	GVariant *parameter, *value;
134

135
	path = gkd_secret_dispatch_get_object_path (GKD_SECRET_DISPATCH (secret->session));
136
	g_return_val_if_fail (path, NULL);
137

138 139 140 141 142 143
	parameter = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
					       secret->parameter, secret->n_parameter,
					       sizeof (guchar));
	value = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
					   secret->value, secret->n_value,
					   sizeof (guchar));
144

145
	return g_variant_new ("(o@ay@ays)", path, parameter, value, content_type);
146 147 148 149 150 151 152 153 154 155
}

void
gkd_secret_secret_free (gpointer data)
{
	GkdSecretSecret *secret;

	if (!data)
		return;

156 157
	secret = data;

158 159 160 161 162 163 164 165 166 167 168
	/*
	 * These are not usually actual plain text secrets. However in
	 * the case that they are, we want to clear them from memory.
	 *
	 * This is not foolproof in any way. If they're plaintext, they would
	 * have been sent over DBus, and through all sorts of processes.
	 */

	egg_secure_clear (secret->parameter, secret->n_parameter);
	egg_secure_clear (secret->value, secret->n_value);

169 170
	g_object_unref (secret->session);

171 172 173 174 175
	/* Call the destructor of memory */
	if (secret->destroy_func)
		(secret->destroy_func) (secret->destroy_data);

	g_slice_free (GkdSecretSecret, secret);
176
}