Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 Stefan Walter
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "gkm-secret.h"
24 :
25 : #include "egg/egg-secure-memory.h"
26 :
27 : #include <string.h>
28 :
29 : struct _GkmSecret {
30 : GObject parent;
31 : guchar *memory;
32 : gsize n_memory;
33 : };
34 :
35 1968 : G_DEFINE_TYPE (GkmSecret, gkm_secret, G_TYPE_OBJECT);
36 :
37 179 : EGG_SECURE_DECLARE (secret);
38 :
39 : /* -----------------------------------------------------------------------------
40 : * OBJECT
41 : */
42 :
43 : static void
44 344 : gkm_secret_init (GkmSecret *self)
45 : {
46 :
47 344 : }
48 :
49 : static void
50 344 : gkm_secret_dispose (GObject *obj)
51 : {
52 344 : GkmSecret *self = GKM_SECRET (obj);
53 :
54 344 : egg_secure_clear (self->memory, self->n_memory);
55 :
56 344 : G_OBJECT_CLASS (gkm_secret_parent_class)->dispose (obj);
57 344 : }
58 :
59 : static void
60 344 : gkm_secret_finalize (GObject *obj)
61 : {
62 344 : GkmSecret *self = GKM_SECRET (obj);
63 :
64 344 : egg_secure_free (self->memory);
65 344 : self->memory = NULL;
66 344 : self->n_memory = 0;
67 :
68 344 : G_OBJECT_CLASS (gkm_secret_parent_class)->finalize (obj);
69 344 : }
70 :
71 : static void
72 42 : gkm_secret_class_init (GkmSecretClass *klass)
73 : {
74 42 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
75 42 : gobject_class->dispose = gkm_secret_dispose;
76 42 : gobject_class->finalize = gkm_secret_finalize;
77 42 : }
78 :
79 : /* -----------------------------------------------------------------------------
80 : * PUBLIC
81 : */
82 :
83 : GkmSecret*
84 344 : gkm_secret_new (const guchar *data, gssize n_data)
85 : {
86 344 : GkmSecret *secret = g_object_new (GKM_TYPE_SECRET, NULL);
87 :
88 344 : if (data) {
89 179 : if (n_data == -1) {
90 52 : secret->memory = (guchar*)egg_secure_strdup ((const gchar*)data);
91 52 : secret->n_memory = strlen ((const gchar*)data);
92 : } else {
93 127 : secret->memory = egg_secure_alloc (n_data + 1);
94 127 : memcpy (secret->memory, data, n_data);
95 127 : secret->n_memory = n_data;
96 : }
97 : } else {
98 165 : secret->memory = NULL;
99 165 : secret->n_memory = 0;
100 : }
101 :
102 344 : return secret;
103 : }
104 :
105 : GkmSecret*
106 218 : gkm_secret_new_from_login (CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
107 : {
108 218 : if (n_pin == (CK_ULONG)-1)
109 1 : return gkm_secret_new ((const guchar*)pin, -1);
110 : else
111 217 : return gkm_secret_new ((const guchar*)pin, (gssize)n_pin);
112 : }
113 :
114 : GkmSecret*
115 49 : gkm_secret_new_from_password (const gchar *password)
116 : {
117 49 : return gkm_secret_new ((const guchar*)password, -1);
118 : }
119 :
120 : const guchar*
121 28 : gkm_secret_get (GkmSecret *self, gsize *n_data)
122 : {
123 28 : g_return_val_if_fail (GKM_IS_SECRET (self), NULL);
124 28 : g_return_val_if_fail (n_data, NULL);
125 28 : *n_data = self->n_memory;
126 28 : return self->memory;
127 : }
128 :
129 : const gchar*
130 92 : gkm_secret_get_password (GkmSecret *self, gsize *n_data)
131 : {
132 92 : g_return_val_if_fail (GKM_IS_SECRET (self), NULL);
133 92 : g_return_val_if_fail (n_data, NULL);
134 92 : *n_data = self->n_memory;
135 92 : return (gchar*)self->memory;
136 : }
137 :
138 : gboolean
139 5 : gkm_secret_equal (GkmSecret *self, GkmSecret *other)
140 : {
141 5 : g_return_val_if_fail (GKM_IS_SECRET (self), FALSE);
142 5 : g_return_val_if_fail (GKM_IS_SECRET (other), FALSE);
143 5 : if (self == other)
144 1 : return TRUE;
145 4 : return gkm_secret_equals (self, other->memory, other->n_memory);
146 : }
147 :
148 : gboolean
149 179 : gkm_secret_equals (GkmSecret *self, const guchar* pin, gssize n_pin)
150 : {
151 179 : g_return_val_if_fail (GKM_IS_SECRET (self), FALSE);
152 :
153 : /* In case they're different somewhere */
154 179 : if (n_pin == (CK_ULONG)-1)
155 20 : n_pin = -1;
156 :
157 179 : if (n_pin == -1 && pin != NULL)
158 20 : n_pin = strlen ((const gchar*)pin);
159 :
160 : /* The same length */
161 179 : if (n_pin != self->n_memory)
162 28 : return FALSE;
163 :
164 : /* Two null passwords */
165 151 : if (!pin && !self->memory)
166 124 : return TRUE;
167 :
168 : /* For our purposes a null password equals an empty password */
169 27 : if (n_pin == 0)
170 4 : return TRUE;
171 :
172 : /* One null, one not null */
173 23 : if (!pin || !self->memory)
174 0 : return FALSE;
175 :
176 : /* Compare actual memory */
177 23 : return memcmp (pin, self->memory, n_pin) == 0;
178 : }
179 :
180 : gboolean
181 0 : gkm_secret_is_trivially_weak (GkmSecret *self)
182 : {
183 0 : return gkm_secret_equals (self, NULL, 0) ||
184 0 : gkm_secret_equals (self, (const guchar*)"", 0);
185 : }
|