~ubuntu-branches/ubuntu/natty/gnome-keyring/natty-proposed

« back to all changes in this revision

Viewing changes to daemon/pkcs11/gkd-pkcs11-data.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2010-09-01 12:54:04 UTC
  • mfrom: (1.1.64 upstream)
  • Revision ID: james.westby@ubuntu.com-20100901125404-3d96lh3oo4karbv3
Tags: 2.92.92.is.2.31.91-0ubuntu1
* New upstream release
* debian/control:
  - Drop build-depends on libgconf2-dev
  - Build-depend on dh-autoreconf, gnome-common
* debian/rules:
  - Use autoreconf.mk
* debian/gnome-keyring.install:
  - No longer provides a gconf schema
* debian/libgcr0.symbols:
  - Updated
* debian/patches/90_git_pam_headers.patch:
  - Fix incorrect PAM header check
* debian/patches/05_login_unlock_string.patch:
* debian/patches/90_git_keyring_encoding.patch:
  - Applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
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  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  License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General
17
 
 * License along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19
 
 * 02111-1307, USA.
20
 
 */
21
 
 
22
 
#include "config.h"
23
 
 
24
 
#include "gkd-pkcs11-data.h"
25
 
 
26
 
#include "egg/egg-cleanup.h"
27
 
#include "egg/egg-secure-memory.h"
28
 
 
29
 
#include "login/gkd-login.h"
30
 
 
31
 
#include "pkcs11/pkcs11.h"
32
 
 
33
 
#include "prompt/gkd-prompt.h"
34
 
 
35
 
#include <glib.h>
36
 
#include <glib/gi18n.h>
37
 
 
38
 
#include <unistd.h>
39
 
 
40
 
/*
41
 
 * THREADING INFO: These functions are called from multiple threads. All gkd_pkcs11_data_*()
42
 
 * functions here with the exception of gkd_pkcs11_data_free_object() are locked. Again with
43
 
 * the exception of gkd_pkcs11_data_free_object() they must not be called from one another.
44
 
 */
45
 
 
46
 
typedef struct _SlotData {
47
 
        gint open_sessions;
48
 
        GHashTable *session_to_data;
49
 
} SlotData;
50
 
 
51
 
typedef struct _SessionData {
52
 
        gpointer user_data;
53
 
        GDestroyNotify destroy_func;
54
 
} SessionData;
55
 
 
56
 
/* A hash table of CK_SLOT_ID_PTR to SlotData */
57
 
static GHashTable *per_slot_data = NULL;
58
 
G_LOCK_DEFINE_STATIC (pkcs11_data);
59
 
 
60
 
static void
61
 
free_slot_data (gpointer data)
62
 
{
63
 
        SlotData *sdata = data;
64
 
        g_assert (sdata);
65
 
        if (sdata->session_to_data)
66
 
                g_hash_table_destroy (sdata->session_to_data);
67
 
        g_slice_free (SlotData, sdata);
68
 
}
69
 
 
70
 
static void
71
 
free_session_data (gpointer data)
72
 
{
73
 
        SessionData *sdata = data;
74
 
        g_assert (sdata);
75
 
        if (sdata->destroy_func && sdata->user_data)
76
 
                (sdata->destroy_func) (sdata->user_data);
77
 
        g_slice_free (SessionData, sdata);
78
 
}
79
 
 
80
 
static gulong*
81
 
ulong_alloc (CK_ULONG value)
82
 
{
83
 
        return g_slice_dup (CK_ULONG, &value);
84
 
}
85
 
 
86
 
static void
87
 
ulong_free (gpointer ptr_to_ulong)
88
 
{
89
 
        g_slice_free (CK_ULONG, ptr_to_ulong);
90
 
}
91
 
 
92
 
static guint
93
 
ulong_hash (gconstpointer v)
94
 
{
95
 
        const signed char *p = v;
96
 
        guint32 i, h = *p;
97
 
        for(i = 0; i < sizeof (CK_ULONG); ++i)
98
 
                h = (h << 5) - h + *(p++);
99
 
        return h;
100
 
}
101
 
 
102
 
static gboolean
103
 
ulong_equal (gconstpointer v1, gconstpointer v2)
104
 
{
105
 
        return *((const CK_ULONG*)v1) == *((const CK_ULONG*)v2);
106
 
}
107
 
 
108
 
static void
109
 
store_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle,
110
 
                     gpointer data, GDestroyNotify destroy_func)
111
 
{
112
 
        SessionData *sdata;
113
 
        SlotData *slot;
114
 
 
115
 
        /* Because we should have been notified when a session was opened */
116
 
        g_return_if_fail (per_slot_data);
117
 
 
118
 
        slot = g_hash_table_lookup (per_slot_data, &slot_id);
119
 
        g_return_if_fail (slot);
120
 
 
121
 
        /* Delayed allocation because we may never use this on a slot */
122
 
        if (slot->session_to_data == NULL)
123
 
                slot->session_to_data = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free, free_session_data);
124
 
 
125
 
        sdata = g_slice_new0 (SessionData);
126
 
        sdata->user_data = data;
127
 
        sdata->destroy_func = destroy_func;
128
 
        g_hash_table_replace (slot->session_to_data, ulong_alloc (handle), sdata);
129
 
}
130
 
 
131
 
void
132
 
gkd_pkcs11_data_session_store (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle,
133
 
                               gpointer data, GDestroyNotify destroy_func)
134
 
{
135
 
        G_LOCK(pkcs11_data);
136
 
        store_data_unlocked (slot_id, handle, data, destroy_func);
137
 
        G_UNLOCK (pkcs11_data);
138
 
}
139
 
 
140
 
static gpointer
141
 
lookup_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
142
 
{
143
 
        SessionData *sdata;
144
 
        SlotData *slot;
145
 
 
146
 
        /* Because we should have been notified of open session */
147
 
        g_return_val_if_fail (per_slot_data, FALSE);
148
 
 
149
 
        /* Lookup the structure for this slot */
150
 
        slot = g_hash_table_lookup (per_slot_data, &slot_id);
151
 
        if (slot == NULL || slot->session_to_data == NULL)
152
 
                return NULL;
153
 
 
154
 
        sdata = g_hash_table_lookup (slot->session_to_data, &handle);
155
 
        if (sdata == NULL)
156
 
                return NULL;
157
 
 
158
 
        return sdata->user_data;
159
 
}
160
 
 
161
 
gpointer
162
 
gkd_pkcs11_data_session_lookup (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
163
 
{
164
 
        gpointer ret;
165
 
        G_LOCK (pkcs11_data);
166
 
        ret = lookup_data_unlocked (slot_id, handle);
167
 
        G_UNLOCK (pkcs11_data);
168
 
        return ret;
169
 
}
170
 
 
171
 
static void
172
 
remove_data_unlocked (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
173
 
{
174
 
        SlotData *slot;
175
 
 
176
 
        /* Because we should have been notified of open session */
177
 
        g_return_if_fail (per_slot_data);
178
 
 
179
 
        slot = g_hash_table_lookup (per_slot_data, &slot_id);
180
 
        g_assert (slot != NULL && slot->session_to_data != NULL);
181
 
 
182
 
        g_hash_table_remove (slot->session_to_data, &handle);
183
 
}
184
 
 
185
 
void
186
 
gkd_pkcs11_data_session_remove (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
187
 
{
188
 
        G_LOCK (pkcs11_data);
189
 
        remove_data_unlocked (slot_id, handle);
190
 
        G_UNLOCK (pkcs11_data);
191
 
}
192
 
 
193
 
void
194
 
gkd_pkcs11_data_initialized (void)
195
 
{
196
 
        G_LOCK (pkcs11_data);
197
 
        g_warn_if_fail (!per_slot_data);
198
 
        per_slot_data = g_hash_table_new_full (ulong_hash, ulong_equal, ulong_free,
199
 
                                               (GDestroyNotify)free_slot_data);
200
 
        G_UNLOCK (pkcs11_data);
201
 
}
202
 
 
203
 
void
204
 
gkd_pkcs11_data_session_opened (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
205
 
{
206
 
        SlotData *slot;
207
 
 
208
 
        G_LOCK (pkcs11_data);
209
 
 
210
 
        slot = g_hash_table_lookup (per_slot_data, &slot_id);
211
 
        if (slot == NULL) {
212
 
                slot = g_slice_new0 (SlotData);
213
 
                g_hash_table_replace (per_slot_data, ulong_alloc (slot_id), slot);
214
 
        }
215
 
 
216
 
        /* Track how many open sessions there are */
217
 
        ++slot->open_sessions;
218
 
 
219
 
        G_UNLOCK (pkcs11_data);
220
 
}
221
 
 
222
 
void
223
 
gkd_pkcs11_data_session_closed (CK_SLOT_ID slot_id, CK_SESSION_HANDLE handle)
224
 
{
225
 
        SlotData *slot;
226
 
 
227
 
        G_LOCK (pkcs11_data);
228
 
 
229
 
        g_warn_if_fail (per_slot_data);
230
 
 
231
 
        slot = g_hash_table_lookup (per_slot_data, &slot_id);
232
 
        g_warn_if_fail (slot);
233
 
        g_assert (slot->open_sessions > 0);
234
 
 
235
 
        /* Track how many open sessions there are */
236
 
        --(slot->open_sessions);
237
 
        if (slot->open_sessions == 0)
238
 
                g_hash_table_remove (per_slot_data, &slot_id);
239
 
 
240
 
        G_UNLOCK (pkcs11_data);
241
 
}
242
 
 
243
 
void
244
 
gkd_pkcs11_data_session_closed_all (CK_SLOT_ID id)
245
 
{
246
 
        G_LOCK (pkcs11_data);
247
 
 
248
 
        /* Remove all information about this slot */
249
 
        g_warn_if_fail (per_slot_data);
250
 
        g_hash_table_remove (per_slot_data, &id);
251
 
 
252
 
        G_UNLOCK (pkcs11_data);
253
 
}
254
 
 
255
 
void
256
 
gkd_pkcs11_data_finalized (void)
257
 
{
258
 
        G_LOCK (pkcs11_data);
259
 
        g_warn_if_fail (per_slot_data);
260
 
        g_hash_table_destroy (per_slot_data);
261
 
        per_slot_data = NULL;
262
 
        G_UNLOCK (pkcs11_data);
263
 
}