minimal build
[platform/upstream/gcr.git] / gcr / gcr-key-mechanisms.c
1 /*
2  * Copyright (C) 2010 Stefan Walter
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation; either version 2.1 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17  * 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #define DEBUG_FLAG GCR_DEBUG_KEY
23 #include "gcr-debug.h"
24 #include "gcr-key-mechanisms.h"
25
26 #include <glib/gi18n-lib.h>
27
28 static gboolean
29 check_have_attributes (GckAttributes *attrs,
30                        const gulong *types,
31                        gsize n_types)
32 {
33         gsize i;
34
35         for (i = 0; i < n_types; i++) {
36                 if (!gck_attributes_find (attrs, types[i]))
37                         return FALSE;
38         }
39
40         return TRUE;
41 }
42
43 static gulong
44 find_first_usable_mechanism (GckObject *key,
45                              GckAttributes *attrs,
46                              const gulong *mechanisms,
47                              gsize n_mechanisms,
48                              gulong action_attr_type)
49 {
50         GckSession *session;
51         GckSlot *slot;
52         GArray *mechs;
53         gboolean can;
54         gsize i;
55
56         if (gck_attributes_find_boolean (attrs, action_attr_type, &can) && !can) {
57                 _gcr_debug ("key not capable of needed action");
58                 return GCK_INVALID;
59         }
60
61         session = gck_object_get_session (key);
62         slot = gck_session_get_slot (session);
63         mechs = gck_slot_get_mechanisms (slot);
64         g_object_unref (slot);
65         g_object_unref (session);
66
67         if (!mechs) {
68                 _gcr_debug ("couldn't get slot mechanisms");
69                 return GCK_INVALID;
70         }
71
72         for (i = 0; i < n_mechanisms; i++) {
73                 if (gck_mechanisms_check (mechs, mechanisms[i], GCK_INVALID))
74                         break;
75         }
76
77         gck_mechanisms_free (mechs);
78
79         if (i < n_mechanisms)
80                 return mechanisms[i];
81         return GCK_INVALID;
82 }
83
84 gulong
85 _gcr_key_mechanisms_check (GckObject *key,
86                            const gulong *mechanisms,
87                            gsize n_mechanisms,
88                            gulong action_attr_type,
89                            GCancellable *cancellable,
90                            GError **error)
91 {
92         gulong attr_types[] = { action_attr_type };
93         GckAttributes *attrs = NULL;
94         gulong result;
95
96         g_return_val_if_fail (GCK_IS_OBJECT (key), GCK_INVALID);
97         g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), GCK_INVALID);
98         g_return_val_if_fail (error == NULL || *error == NULL, GCK_INVALID);
99
100         if (GCK_IS_OBJECT_CACHE (key)) {
101                 attrs = gck_object_cache_get_attributes (GCK_OBJECT_CACHE (key));
102                 if (!check_have_attributes (attrs, attr_types, G_N_ELEMENTS (attr_types))) {
103                         gck_attributes_unref (attrs);
104                         attrs = NULL;
105                 }
106         }
107
108         if (attrs == NULL) {
109                 attrs = gck_object_get_full (key, attr_types, G_N_ELEMENTS (attr_types),
110                                              cancellable, error);
111         }
112
113         if (!attrs)
114                 return GCK_INVALID;
115
116         result = find_first_usable_mechanism (key, attrs, mechanisms, n_mechanisms, action_attr_type);
117         gck_attributes_unref (attrs);
118         return result;
119 }
120
121 typedef struct {
122         gulong *mechanisms;
123         gsize n_mechanisms;
124         gulong action_attr_type;
125         GckAttributes *attrs;
126 } CheckClosure;
127
128 static void
129 check_closure_free (gpointer data)
130 {
131         CheckClosure *closure = data;
132         g_free (closure->mechanisms);
133         gck_attributes_unref (closure->attrs);
134         g_free (closure);
135 }
136
137 static void
138 on_check_get_attributes (GObject *source,
139                          GAsyncResult *result,
140                          gpointer user_data)
141 {
142         GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
143         CheckClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
144         GError *error = NULL;
145
146         closure->attrs = gck_object_cache_lookup_finish (GCK_OBJECT (source), result, &error);
147         if (error != NULL)
148                 g_simple_async_result_take_error (res, error);
149
150         g_simple_async_result_complete (res);
151         g_object_unref (res);
152 }
153
154 void
155 _gcr_key_mechanisms_check_async (GckObject *key,
156                                  const gulong *mechanisms,
157                                  gsize n_mechanisms,
158                                  gulong action_attr_type,
159                                  GCancellable *cancellable,
160                                  GAsyncReadyCallback callback,
161                                  gpointer user_data)
162 {
163         gulong attr_types[] = { action_attr_type };
164         CheckClosure *closure;
165         GSimpleAsyncResult *res;
166
167         g_return_if_fail (GCK_IS_OBJECT (key));
168         g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
169
170         res = g_simple_async_result_new (G_OBJECT (key), callback, user_data,
171                                          _gcr_key_mechanisms_check_async);
172         closure = g_new0 (CheckClosure, 1);
173         closure->mechanisms = g_memdup (mechanisms, n_mechanisms * sizeof (gulong));
174         closure->n_mechanisms = n_mechanisms;
175         closure->action_attr_type = action_attr_type;
176         g_simple_async_result_set_op_res_gpointer (res, closure, check_closure_free);
177
178         gck_object_cache_lookup_async (key, attr_types, G_N_ELEMENTS (attr_types),
179                                        cancellable, on_check_get_attributes, g_object_ref (res));
180
181         g_object_unref (res);
182
183
184 }
185
186 gulong
187 _gcr_key_mechanisms_check_finish (GckObject *key,
188                                   GAsyncResult *result,
189                                   GError **error)
190 {
191         CheckClosure *closure;
192         GSimpleAsyncResult *res;
193
194         g_return_val_if_fail (GCK_IS_OBJECT (key), GCK_INVALID);
195         g_return_val_if_fail (error == NULL || *error == NULL, GCK_INVALID);
196
197         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (key),
198                               _gcr_key_mechanisms_check_async), FALSE);
199
200         res = G_SIMPLE_ASYNC_RESULT (result);
201         if (g_simple_async_result_propagate_error (res, error))
202                 return FALSE;
203
204         closure = g_simple_async_result_get_op_res_gpointer (res);
205
206         return find_first_usable_mechanism (GCK_OBJECT (key), closure->attrs,
207                                             closure->mechanisms, closure->n_mechanisms,
208                                             closure->action_attr_type);
209 }