Branch data 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 <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : #include "config.h"
21 : :
22 : : #include "gck/gck.h"
23 : :
24 : : #include "gcr-internal.h"
25 : : #include "gcr-openpgp.h"
26 : : #include "gcr-openssh.h"
27 : : #include "gcr-parser.h"
28 : : #include "gcr-record.h"
29 : : #include "gcr-types.h"
30 : :
31 : : #include "gcr/gcr-marshal.h"
32 : : #include "gcr/gcr-oids.h"
33 : :
34 : : #include "egg/egg-armor.h"
35 : : #include "egg/egg-asn1x.h"
36 : : #include "egg/egg-asn1-defs.h"
37 : : #include "egg/egg-dn.h"
38 : : #include "egg/egg-openssl.h"
39 : : #include "egg/egg-secure-memory.h"
40 : : #include "egg/egg-symkey.h"
41 : :
42 : : #include <glib/gi18n-lib.h>
43 : :
44 : : #include <stdlib.h>
45 : : #include <gcrypt.h>
46 : :
47 : : /**
48 : : * GcrParser:
49 : : *
50 : : * A parser for parsing various types of files or data.
51 : : *
52 : : * A `GcrParser` can parse various certificate and key files such as OpenSSL
53 : : * PEM files, DER encoded certifictes, PKCS#8 keys and so on. Each various
54 : : * format is identified by a value in the [enum@DataFormat] enumeration.
55 : : *
56 : : * In order to parse data, a new parser is created with gcr_parser_new() and
57 : : * then the [signal@Parser::authenticate] and [signal@Parser::parsed] signals
58 : : * should be connected to. Data is then fed to the parser via
59 : : * [method@Parser.parse_data] or [method@Parser.parse_stream].
60 : : *
61 : : * During the [signal@Parser::parsed] signal the attributes that make up the
62 : : * currently parsed item can be retrieved using the
63 : : * [method@Parser.get_parsed_attributes] function.
64 : : */
65 : :
66 : : /**
67 : : * GcrParsed:
68 : : *
69 : : * A parsed item parsed by a #GcrParser.
70 : : */
71 : :
72 : : /**
73 : : * GcrParserClass:
74 : : * @parent_class: The parent class
75 : : * @authenticate: The default handler for the authenticate signal.
76 : : * @parsed: The default handler for the parsed signal.
77 : : *
78 : : * The class for #GcrParser
79 : : */
80 : :
81 : : /**
82 : : * GCR_DATA_ERROR:
83 : : *
84 : : * A domain for data errors with codes from #GcrDataError
85 : : */
86 : :
87 : : /**
88 : : * GcrDataError:
89 : : * @GCR_ERROR_FAILURE: Failed to parse or serialize the data
90 : : * @GCR_ERROR_UNRECOGNIZED: The data was unrecognized or unsupported
91 : : * @GCR_ERROR_CANCELLED: The operation was cancelled
92 : : * @GCR_ERROR_LOCKED: The data was encrypted or locked and could not be unlocked.
93 : : *
94 : : * Values responding to error codes for parsing and serializing data.
95 : : */
96 : :
97 : : enum {
98 : : PROP_0,
99 : : PROP_PARSED_LABEL,
100 : : PROP_PARSED_ATTRIBUTES,
101 : : PROP_PARSED_DESCRIPTION
102 : : };
103 : :
104 : : enum {
105 : : AUTHENTICATE,
106 : : PARSED,
107 : : LAST_SIGNAL
108 : : };
109 : :
110 : : #define SUCCESS 0
111 : :
112 : : static guint signals[LAST_SIGNAL] = { 0 };
113 : :
114 : : struct _GcrParsed {
115 : : gint refs;
116 : : GckBuilder builder;
117 : : GckAttributes *attrs;
118 : : const gchar *description;
119 : : gchar *label;
120 : : GBytes *data;
121 : : gboolean sensitive;
122 : : GcrDataFormat format;
123 : : gchar *filename;
124 : : struct _GcrParsed *next;
125 : : };
126 : :
127 : : struct _GcrParserPrivate {
128 : : GTree *specific_formats;
129 : : gboolean normal_formats;
130 : : GPtrArray *passwords;
131 : : GcrParsed *parsed;
132 : : gchar *filename;
133 : : };
134 : :
135 [ + + + - : 9006 : G_DEFINE_TYPE_WITH_PRIVATE (GcrParser, gcr_parser, G_TYPE_OBJECT);
+ + ]
136 : :
137 : : typedef struct {
138 : : gint ask_state;
139 : : gint seen;
140 : : } PasswordState;
141 : :
142 : : #define PASSWORD_STATE_INIT { 0, 0 }
143 : :
144 : : typedef struct _ParserFormat {
145 : : gint format_id;
146 : : gint (*function) (GcrParser *self, GBytes *data);
147 : : } ParserFormat;
148 : :
149 : : /* Forward declarations */
150 : : static const ParserFormat parser_normal[];
151 : : static const ParserFormat parser_formats[];
152 : : static ParserFormat* parser_format_lookup (gint format_id);
153 : :
154 : 965 : EGG_SECURE_DECLARE (parser);
155 : :
156 : : /* -----------------------------------------------------------------------------
157 : : * QUARK DEFINITIONS
158 : : */
159 : :
160 : : /*
161 : : * PEM STRINGS
162 : : * The xxxxx in: ----- BEGIN xxxxx ------
163 : : */
164 : :
165 : : static GQuark PEM_CERTIFICATE;
166 : : static GQuark PEM_RSA_PRIVATE_KEY;
167 : : static GQuark PEM_DSA_PRIVATE_KEY;
168 : : static GQuark PEM_EC_PRIVATE_KEY;
169 : : static GQuark PEM_ANY_PRIVATE_KEY;
170 : : static GQuark PEM_ENCRYPTED_PRIVATE_KEY;
171 : : static GQuark PEM_PRIVATE_KEY;
172 : : static GQuark PEM_PKCS7;
173 : : static GQuark PEM_PKCS12;
174 : : static GQuark PEM_CERTIFICATE_REQUEST;
175 : : static GQuark PEM_NEW_CERTIFICATE_REQUEST;
176 : : static GQuark PEM_PUBLIC_KEY;
177 : :
178 : : static GQuark ARMOR_PGP_PUBLIC_KEY_BLOCK;
179 : : static GQuark ARMOR_PGP_PRIVATE_KEY_BLOCK;
180 : :
181 : : static void
182 : 3 : init_quarks (void)
183 : : {
184 : : static size_t quarks_inited = 0;
185 : :
186 [ + - + - : 3 : if (g_once_init_enter (&quarks_inited)) {
+ - ]
187 : :
188 : : #define QUARK(name, value) \
189 : : name = g_quark_from_static_string(value)
190 : :
191 : 3 : QUARK (PEM_CERTIFICATE, "CERTIFICATE");
192 : 3 : QUARK (PEM_PRIVATE_KEY, "PRIVATE KEY");
193 : 3 : QUARK (PEM_RSA_PRIVATE_KEY, "RSA PRIVATE KEY");
194 : 3 : QUARK (PEM_DSA_PRIVATE_KEY, "DSA PRIVATE KEY");
195 : 3 : QUARK (PEM_EC_PRIVATE_KEY, "EC PRIVATE KEY");
196 : 3 : QUARK (PEM_ANY_PRIVATE_KEY, "ANY PRIVATE KEY");
197 : 3 : QUARK (PEM_ENCRYPTED_PRIVATE_KEY, "ENCRYPTED PRIVATE KEY");
198 : 3 : QUARK (PEM_PKCS7, "PKCS7");
199 : 3 : QUARK (PEM_PKCS12, "PKCS12");
200 : 3 : QUARK (PEM_CERTIFICATE_REQUEST, "CERTIFICATE REQUEST");
201 : 3 : QUARK (PEM_NEW_CERTIFICATE_REQUEST, "NEW CERTIFICATE REQUEST");
202 : 3 : QUARK (PEM_PUBLIC_KEY, "PUBLIC KEY");
203 : :
204 : 3 : QUARK (ARMOR_PGP_PRIVATE_KEY_BLOCK, "PGP PRIVATE KEY BLOCK");
205 : 3 : QUARK (ARMOR_PGP_PUBLIC_KEY_BLOCK, "PGP PUBLIC KEY BLOCK");
206 : :
207 : : #undef QUARK
208 : :
209 : 3 : g_once_init_leave (&quarks_inited, 1);
210 : : }
211 : 3 : }
212 : :
213 : : /* -----------------------------------------------------------------------------
214 : : * INTERNAL
215 : : */
216 : :
217 : : static void
218 : 26 : parsed_attribute (GcrParsed *parsed,
219 : : CK_ATTRIBUTE_TYPE type,
220 : : gconstpointer data,
221 : : gsize n_data)
222 : : {
223 [ - + ]: 26 : g_assert (parsed != NULL);
224 : 26 : gck_builder_add_data (&parsed->builder, type, data, n_data);
225 : 26 : }
226 : :
227 : : static void
228 : 1998 : parsed_attribute_bytes (GcrParsed *parsed,
229 : : CK_ATTRIBUTE_TYPE type,
230 : : GBytes *data)
231 : : {
232 [ - + ]: 1998 : g_assert (parsed != NULL);
233 : 3996 : gck_builder_add_data (&parsed->builder, type,
234 : 1998 : g_bytes_get_data (data, NULL),
235 : : g_bytes_get_size (data));
236 : 1998 : }
237 : :
238 : : static gboolean
239 : 873 : parsed_asn1_number (GcrParsed *parsed,
240 : : GNode *asn,
241 : : const gchar *part,
242 : : CK_ATTRIBUTE_TYPE type)
243 : : {
244 : : GBytes *value;
245 : :
246 [ - + ]: 873 : g_assert (asn);
247 [ - + ]: 873 : g_assert (parsed);
248 : :
249 : 873 : value = egg_asn1x_get_integer_as_usg (egg_asn1x_node (asn, part, NULL));
250 [ - + ]: 873 : if (value == NULL)
251 : 0 : return FALSE;
252 : :
253 : 873 : parsed_attribute_bytes (parsed, type, value);
254 : 873 : g_bytes_unref (value);
255 : 873 : return TRUE;
256 : : }
257 : :
258 : : static gboolean
259 : 690 : parsed_asn1_element (GcrParsed *parsed,
260 : : GNode *asn,
261 : : const gchar *part,
262 : : CK_ATTRIBUTE_TYPE type)
263 : : {
264 : : GBytes *value;
265 : :
266 [ - + ]: 690 : g_assert (asn);
267 [ - + ]: 690 : g_assert (parsed);
268 : :
269 : 690 : value = egg_asn1x_get_element_raw (egg_asn1x_node (asn, part, NULL));
270 [ - + ]: 690 : if (value == NULL)
271 : 0 : return FALSE;
272 : :
273 : 690 : parsed_attribute_bytes (parsed, type, value);
274 : 690 : g_bytes_unref (value);
275 : 690 : return TRUE;
276 : : }
277 : :
278 : : static gboolean
279 : 46 : parsed_asn1_structure (GcrParsed *parsed,
280 : : GNode *asn,
281 : : CK_ATTRIBUTE_TYPE type)
282 : : {
283 : : GBytes *value;
284 : :
285 [ - + ]: 46 : g_assert (asn);
286 [ - + ]: 46 : g_assert (parsed);
287 : :
288 : 46 : value = egg_asn1x_encode (asn, g_realloc);
289 [ - + ]: 46 : if (value == NULL)
290 : 0 : return FALSE;
291 : :
292 : 46 : parsed_attribute_bytes (parsed, type, value);
293 : 46 : g_bytes_unref (value);
294 : 46 : return TRUE;
295 : : }
296 : :
297 : : static void
298 : 509 : parsed_ulong_attribute (GcrParsed *parsed,
299 : : CK_ATTRIBUTE_TYPE type,
300 : : gulong value)
301 : : {
302 [ - + ]: 509 : g_assert (parsed != NULL);
303 : 509 : gck_builder_add_ulong (&parsed->builder, type, value);
304 : 509 : }
305 : :
306 : : static void
307 : 104 : parsed_boolean_attribute (GcrParsed *parsed,
308 : : CK_ATTRIBUTE_TYPE type,
309 : : gboolean value)
310 : : {
311 [ - + ]: 104 : g_assert (parsed != NULL);
312 : 104 : gck_builder_add_boolean (&parsed->builder, type, value);
313 : 104 : }
314 : :
315 : :
316 : : static void
317 : 774 : parsing_block (GcrParsed *parsed,
318 : : gint format,
319 : : GBytes *data)
320 : : {
321 [ - + ]: 774 : g_assert (parsed != NULL);
322 [ - + ]: 774 : g_assert (data != NULL);
323 [ - + ]: 774 : g_assert (format != 0);
324 [ - + ]: 774 : g_assert (parsed->data == NULL);
325 : :
326 : 774 : parsed->format = format;
327 : 774 : parsed->data = g_bytes_ref (data);
328 : 774 : }
329 : :
330 : : static void
331 : 539 : parsed_description (GcrParsed *parsed,
332 : : CK_OBJECT_CLASS klass)
333 : : {
334 [ - + ]: 539 : g_assert (parsed != NULL);
335 [ + + + + : 539 : switch (klass) {
+ - ]
336 : 104 : case CKO_PRIVATE_KEY:
337 : 104 : parsed->description = _("Private Key");
338 : 104 : break;
339 : 327 : case CKO_CERTIFICATE:
340 : 327 : parsed->description = _("Certificate");
341 : 327 : break;
342 : 66 : case CKO_PUBLIC_KEY:
343 : 66 : parsed->description = _("Public Key");
344 : 66 : break;
345 : 26 : case CKO_GCR_GNUPG_RECORDS:
346 : 26 : parsed->description = _("PGP Key");
347 : 26 : break;
348 : 16 : case CKO_GCR_CERTIFICATE_REQUEST:
349 : 16 : parsed->description = _("Certificate Request");
350 : 16 : break;
351 : 0 : default:
352 : 0 : parsed->description = NULL;
353 : 0 : break;
354 : : }
355 : 539 : }
356 : :
357 : : static void
358 : 535 : parsing_object (GcrParsed *parsed,
359 : : CK_OBJECT_CLASS klass)
360 : : {
361 [ - + ]: 535 : g_assert (parsed != NULL);
362 : :
363 : 535 : gck_builder_clear (&parsed->builder);
364 [ + + ]: 535 : if (parsed->sensitive)
365 : 166 : gck_builder_init_full (&parsed->builder, GCK_BUILDER_SECURE_MEMORY);
366 : : else
367 : 369 : gck_builder_init_full (&parsed->builder, GCK_BUILDER_NONE);
368 : 535 : gck_builder_add_ulong (&parsed->builder, CKA_CLASS, klass);
369 : 535 : parsed_description (parsed, klass);
370 : 535 : }
371 : :
372 : : static void
373 : 4 : parsed_attributes (GcrParsed *parsed,
374 : : GckAttributes *attrs)
375 : : {
376 : : gulong klass;
377 : :
378 [ - + ]: 4 : g_assert (parsed != NULL);
379 [ - + ]: 4 : g_assert (attrs != NULL);
380 : :
381 [ + - ]: 4 : if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass))
382 : 4 : parsed_description (parsed, klass);
383 : 4 : gck_builder_add_all (&parsed->builder, attrs);
384 : 4 : }
385 : :
386 : : static void
387 : 305 : parsed_label (GcrParsed *parsed,
388 : : const gchar *label)
389 : : {
390 [ - + ]: 305 : g_assert (parsed != NULL);
391 [ - + ]: 305 : g_assert (parsed->label == NULL);
392 : 305 : parsed->label = g_strdup (label);
393 : 305 : }
394 : :
395 : : static GcrParsed *
396 : 1466 : push_parsed (GcrParser *self,
397 : : gboolean sensitive)
398 : : {
399 : 1466 : GcrParsed *parsed = g_new0 (GcrParsed, 1);
400 : 1466 : parsed->refs = 0;
401 : 1466 : parsed->sensitive = sensitive;
402 : 1466 : parsed->next = self->pv->parsed;
403 : 1466 : parsed->filename = g_strdup (gcr_parser_get_filename (self));
404 : 1466 : self->pv->parsed = parsed;
405 : 1466 : return parsed;
406 : : }
407 : :
408 : : static void
409 : 1467 : _gcr_parsed_free (GcrParsed *parsed)
410 : : {
411 : 1467 : gck_builder_clear (&parsed->builder);
412 [ + + ]: 1467 : if (parsed->attrs)
413 : 540 : gck_attributes_unref (parsed->attrs);
414 [ + + ]: 1467 : if (parsed->data)
415 : 775 : g_bytes_unref (parsed->data);
416 : 1467 : g_free (parsed->label);
417 : 1467 : g_free (parsed->filename);
418 : 1467 : g_free (parsed);
419 : 1467 : }
420 : :
421 : : static void
422 : 1466 : pop_parsed (GcrParser *self,
423 : : GcrParsed *parsed)
424 : : {
425 [ - + ]: 1466 : g_assert (parsed == self->pv->parsed);
426 : 1466 : self->pv->parsed = parsed->next;
427 : 1466 : _gcr_parsed_free (parsed);
428 : 1466 : }
429 : :
430 : : static gint
431 : 66 : enum_next_password (GcrParser *self, PasswordState *state, const gchar **password)
432 : : {
433 : : gboolean result;
434 : :
435 : : /*
436 : : * Next passes we look through all the passwords that the parser
437 : : * has seen so far. This is because different parts of a encrypted
438 : : * container (such as PKCS#12) often use the same password even
439 : : * if with different algorithms.
440 : : *
441 : : * If we didn't do this and the user chooses enters a password,
442 : : * but doesn't save it, they would get prompted for the same thing
443 : : * over and over, dumb.
444 : : */
445 : :
446 : : /* Look in our list of passwords */
447 [ + + ]: 66 : if (state->seen < self->pv->passwords->len) {
448 [ - + ]: 52 : g_assert (state->seen >= 0);
449 : 52 : *password = g_ptr_array_index (self->pv->passwords, state->seen);
450 : 52 : ++state->seen;
451 : 52 : return SUCCESS;
452 : : }
453 : :
454 : : /* Fire off all the parsed property signals so anyone watching can update their state */
455 : 14 : g_object_notify (G_OBJECT (self), "parsed-description");
456 : 14 : g_object_notify (G_OBJECT (self), "parsed-attributes");
457 : 14 : g_object_notify (G_OBJECT (self), "parsed-label");
458 : :
459 : 14 : g_signal_emit (self, signals[AUTHENTICATE], 0, state->ask_state, &result);
460 : 14 : ++state->ask_state;
461 : :
462 [ - + ]: 14 : if (!result)
463 : 0 : return GCR_ERROR_CANCELLED;
464 : :
465 : : /* Return any passwords added */
466 [ + - ]: 14 : if (state->seen < self->pv->passwords->len) {
467 [ - + ]: 14 : g_assert (state->seen >= 0);
468 : 14 : *password = g_ptr_array_index (self->pv->passwords, state->seen);
469 : 14 : ++state->seen;
470 : 14 : return SUCCESS;
471 : : }
472 : :
473 : 0 : return GCR_ERROR_LOCKED;
474 : : }
475 : :
476 : : static void
477 : 539 : parsed_fire (GcrParser *self,
478 : : GcrParsed *parsed)
479 : : {
480 [ - + + - : 539 : g_assert (GCR_IS_PARSER (self));
+ - - + ]
481 [ - + ]: 539 : g_assert (parsed != NULL);
482 [ - + ]: 539 : g_assert (parsed == self->pv->parsed);
483 [ - + ]: 539 : g_assert (parsed->attrs == NULL);
484 : :
485 : 539 : parsed->attrs = gck_builder_end (&parsed->builder);
486 : :
487 : 539 : g_object_notify (G_OBJECT (self), "parsed-description");
488 : 539 : g_object_notify (G_OBJECT (self), "parsed-attributes");
489 : 539 : g_object_notify (G_OBJECT (self), "parsed-label");
490 : :
491 : 539 : g_signal_emit (self, signals[PARSED], 0);
492 : 539 : }
493 : :
494 : : /* -----------------------------------------------------------------------------
495 : : * RSA PRIVATE KEY
496 : : */
497 : :
498 : : static gint
499 : 188 : parse_der_private_key_rsa (GcrParser *self,
500 : : GBytes *data)
501 : : {
502 : 188 : gint res = GCR_ERROR_UNRECOGNIZED;
503 : 188 : GNode *asn = NULL;
504 : : gulong version;
505 : : GcrParsed *parsed;
506 : :
507 : 188 : parsed = push_parsed (self, TRUE);
508 : :
509 : 188 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data);
510 [ + + ]: 188 : if (!asn)
511 : 135 : goto done;
512 : :
513 : 53 : parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
514 : 53 : parsing_object (parsed, CKO_PRIVATE_KEY);
515 : 53 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
516 : 53 : parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
517 : 53 : res = GCR_ERROR_FAILURE;
518 : :
519 [ - + ]: 53 : if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
520 : 0 : goto done;
521 : :
522 : : /* We only support simple version */
523 [ - + ]: 53 : if (version != 0) {
524 : 0 : res = GCR_ERROR_UNRECOGNIZED;
525 : 0 : g_message ("unsupported version of RSA key: %lu", version);
526 : 0 : goto done;
527 : : }
528 : :
529 [ + - + - ]: 106 : if (!parsed_asn1_number (parsed, asn, "modulus", CKA_MODULUS) ||
530 [ + - ]: 106 : !parsed_asn1_number (parsed, asn, "publicExponent", CKA_PUBLIC_EXPONENT) ||
531 [ + - ]: 106 : !parsed_asn1_number (parsed, asn, "privateExponent", CKA_PRIVATE_EXPONENT) ||
532 [ + - ]: 106 : !parsed_asn1_number (parsed, asn, "prime1", CKA_PRIME_1) ||
533 [ - + ]: 106 : !parsed_asn1_number (parsed, asn, "prime2", CKA_PRIME_2) ||
534 : 53 : !parsed_asn1_number (parsed, asn, "coefficient", CKA_COEFFICIENT))
535 : 0 : goto done;
536 : :
537 : 53 : parsed_fire (self, parsed);
538 : 53 : res = SUCCESS;
539 : :
540 : 188 : done:
541 : 188 : egg_asn1x_destroy (asn);
542 [ - + ]: 188 : if (res == GCR_ERROR_FAILURE)
543 : 0 : g_message ("invalid RSA key");
544 : :
545 : 188 : pop_parsed (self, parsed);
546 : 188 : return res;
547 : : }
548 : :
549 : : /* -----------------------------------------------------------------------------
550 : : * DSA PRIVATE KEY
551 : : */
552 : :
553 : : static gint
554 : 159 : parse_der_private_key_dsa (GcrParser *self,
555 : : GBytes *data)
556 : : {
557 : 159 : gint ret = GCR_ERROR_UNRECOGNIZED;
558 : 159 : GNode *asn = NULL;
559 : : GcrParsed *parsed;
560 : :
561 : 159 : parsed = push_parsed (self, TRUE);
562 : :
563 : 159 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data);
564 [ + + ]: 159 : if (!asn)
565 : 134 : goto done;
566 : :
567 : 25 : parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
568 : 25 : parsing_object (parsed, CKO_PRIVATE_KEY);
569 : 25 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
570 : 25 : parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
571 : 25 : ret = GCR_ERROR_FAILURE;
572 : :
573 [ + - + - ]: 50 : if (!parsed_asn1_number (parsed, asn, "p", CKA_PRIME) ||
574 [ + - ]: 50 : !parsed_asn1_number (parsed, asn, "q", CKA_SUBPRIME) ||
575 [ - + ]: 50 : !parsed_asn1_number (parsed, asn, "g", CKA_BASE) ||
576 : 25 : !parsed_asn1_number (parsed, asn, "priv", CKA_VALUE))
577 : 0 : goto done;
578 : :
579 : 25 : parsed_fire (self, parsed);
580 : 25 : ret = SUCCESS;
581 : :
582 : 159 : done:
583 : 159 : egg_asn1x_destroy (asn);
584 [ - + ]: 159 : if (ret == GCR_ERROR_FAILURE)
585 : 0 : g_message ("invalid DSA key");
586 : :
587 : 159 : pop_parsed (self, parsed);
588 : 159 : return ret;
589 : : }
590 : :
591 : : static gint
592 : 2 : parse_der_private_key_dsa_parts (GcrParser *self,
593 : : GBytes *keydata,
594 : : GNode *params)
595 : : {
596 : 2 : gint ret = GCR_ERROR_UNRECOGNIZED;
597 : 2 : GNode *asn_params = NULL;
598 : 2 : GNode *asn_key = NULL;
599 : : GcrParsed *parsed;
600 : :
601 : 2 : parsed = push_parsed (self, TRUE);
602 : :
603 : 2 : asn_params = egg_asn1x_get_any_as (params, pk_asn1_tab, "DSAParameters");
604 : 2 : asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata);
605 [ + - - + ]: 2 : if (!asn_params || !asn_key)
606 : 0 : goto done;
607 : :
608 : 2 : parsing_object (parsed, CKO_PRIVATE_KEY);
609 : 2 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
610 : 2 : parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
611 : 2 : ret = GCR_ERROR_FAILURE;
612 : :
613 [ + - + - ]: 4 : if (!parsed_asn1_number (parsed, asn_params, "p", CKA_PRIME) ||
614 [ + - ]: 4 : !parsed_asn1_number (parsed, asn_params, "q", CKA_SUBPRIME) ||
615 [ - + ]: 4 : !parsed_asn1_number (parsed, asn_params, "g", CKA_BASE) ||
616 : 2 : !parsed_asn1_number (parsed, asn_key, NULL, CKA_VALUE))
617 : 0 : goto done;
618 : :
619 : 2 : parsed_fire (self, parsed);
620 : 2 : ret = SUCCESS;
621 : :
622 : 2 : done:
623 : 2 : egg_asn1x_destroy (asn_key);
624 : 2 : egg_asn1x_destroy (asn_params);
625 [ - + ]: 2 : if (ret == GCR_ERROR_FAILURE)
626 : 0 : g_message ("invalid DSA key");
627 : :
628 : 2 : pop_parsed (self, parsed);
629 : 2 : return ret;
630 : : }
631 : : /* -----------------------------------------------------------------------------
632 : : * EC PRIVATE KEY
633 : : */
634 : :
635 : : static gint
636 : 136 : parse_der_private_key_ec (GcrParser *self,
637 : : GBytes *data)
638 : : {
639 : 136 : gint ret = GCR_ERROR_UNRECOGNIZED;
640 : 136 : GNode *asn = NULL;
641 : 136 : GBytes *value = NULL;
642 : 136 : GBytes *pub = NULL;
643 : 136 : GNode *asn_q = NULL;
644 : : GcrParsed *parsed;
645 : : guint bits;
646 : : gulong version;
647 : :
648 : 136 : parsed = push_parsed (self, TRUE);
649 : :
650 : 136 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPrivateKey", data);
651 [ + + ]: 136 : if (!asn)
652 : 112 : goto done;
653 : :
654 [ - + ]: 24 : if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
655 : 0 : goto done;
656 : :
657 : : /* We only support simple version */
658 [ - + ]: 24 : if (version != 1) {
659 : 0 : g_message ("unsupported version of EC key: %lu", version);
660 : 0 : goto done;
661 : : }
662 : :
663 : 24 : parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
664 : 24 : parsing_object (parsed, CKO_PRIVATE_KEY);
665 : 24 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
666 : 24 : parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
667 : 24 : ret = GCR_ERROR_FAILURE;
668 : :
669 [ - + ]: 24 : if (!parsed_asn1_element (parsed, asn, "parameters", CKA_EC_PARAMS))
670 : 0 : goto done;
671 : :
672 : 24 : value = egg_asn1x_get_string_as_usg (egg_asn1x_node (asn, "privateKey", NULL), egg_secure_realloc);
673 [ - + ]: 24 : if (!value)
674 : 0 : goto done;
675 : :
676 : 24 : parsed_attribute_bytes (parsed, CKA_VALUE, value);
677 : :
678 : 24 : pub = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "publicKey", NULL), &bits);
679 [ + - - + ]: 24 : if (!pub || bits != 8 * g_bytes_get_size (pub))
680 : 0 : goto done;
681 : 24 : asn_q = egg_asn1x_create (pk_asn1_tab, "ECPoint");
682 [ - + ]: 24 : if (!asn_q)
683 : 0 : goto done;
684 : 24 : egg_asn1x_set_string_as_bytes (asn_q, pub);
685 : :
686 [ - + ]: 24 : if (!parsed_asn1_structure (parsed, asn_q, CKA_EC_POINT))
687 : 0 : goto done;
688 : :
689 : 24 : parsed_fire (self, parsed);
690 : 24 : ret = SUCCESS;
691 : :
692 : 136 : done:
693 [ + + ]: 136 : if (pub)
694 : 24 : g_bytes_unref (pub);
695 [ + + ]: 136 : if (value)
696 : 24 : g_bytes_unref (value);
697 : 136 : egg_asn1x_destroy (asn);
698 : 136 : egg_asn1x_destroy (asn_q);
699 [ - + ]: 136 : if (ret == GCR_ERROR_FAILURE)
700 : 0 : g_message ("invalid EC key");
701 : :
702 : 136 : pop_parsed (self, parsed);
703 : 136 : return ret;
704 : : }
705 : :
706 : : /* -----------------------------------------------------------------------------
707 : : * PRIVATE KEY
708 : : */
709 : :
710 : : static gint
711 : 54 : parse_der_private_key (GcrParser *self,
712 : : GBytes *data)
713 : : {
714 : : gint res;
715 : :
716 : 54 : res = parse_der_private_key_rsa (self, data);
717 [ + - ]: 54 : if (res == GCR_ERROR_UNRECOGNIZED)
718 : 54 : res = parse_der_private_key_dsa (self, data);
719 [ + - ]: 54 : if (res == GCR_ERROR_UNRECOGNIZED)
720 : 54 : res = parse_der_private_key_ec (self, data);
721 : :
722 : 54 : return res;
723 : : }
724 : :
725 : : /* -----------------------------------------------------------------------------
726 : : * SUBJECT PUBLIC KEY
727 : : */
728 : :
729 : : static gint
730 : 20 : handle_subject_public_key_rsa (GcrParser *self,
731 : : GcrParsed *parsed,
732 : : GBytes *key,
733 : : GNode *params)
734 : : {
735 : 20 : gint res = GCR_ERROR_FAILURE;
736 : 20 : GNode *asn = NULL;
737 : :
738 : 20 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", key);
739 [ - + ]: 20 : if (!asn)
740 : 0 : goto done;
741 : :
742 : 20 : parsing_object (parsed, CKO_PUBLIC_KEY);
743 : 20 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_RSA);
744 : :
745 [ + - - + ]: 40 : if (!parsed_asn1_number (parsed, asn, "modulus", CKA_MODULUS) ||
746 : 20 : !parsed_asn1_number (parsed, asn, "publicExponent", CKA_PUBLIC_EXPONENT))
747 : 0 : goto done;
748 : :
749 : 20 : res = SUCCESS;
750 : :
751 : 20 : done:
752 : 20 : egg_asn1x_destroy (asn);
753 : 20 : return res;
754 : : }
755 : :
756 : : static gint
757 : 20 : handle_subject_public_key_dsa (GcrParser *self,
758 : : GcrParsed *parsed,
759 : : GBytes *key,
760 : : GNode *params)
761 : : {
762 : 20 : gint res = GCR_ERROR_FAILURE;
763 : 20 : GNode *key_asn = NULL;
764 : 20 : GNode *param_asn = NULL;
765 : :
766 : 20 : key_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicPart", key);
767 : 20 : param_asn = egg_asn1x_get_any_as (params, pk_asn1_tab, "DSAParameters");
768 : :
769 [ + - - + ]: 20 : if (!key_asn || !param_asn)
770 : 0 : goto done;
771 : :
772 : 20 : parsing_object (parsed, CKO_PUBLIC_KEY);
773 : 20 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_DSA);
774 : :
775 [ + - + - ]: 40 : if (!parsed_asn1_number (parsed, param_asn, "p", CKA_PRIME) ||
776 [ + - ]: 40 : !parsed_asn1_number (parsed, param_asn, "q", CKA_SUBPRIME) ||
777 [ - + ]: 40 : !parsed_asn1_number (parsed, param_asn, "g", CKA_BASE) ||
778 : 20 : !parsed_asn1_number (parsed, key_asn, NULL, CKA_VALUE))
779 : 0 : goto done;
780 : :
781 : 20 : res = SUCCESS;
782 : :
783 : 20 : done:
784 : 20 : egg_asn1x_destroy (key_asn);
785 : 20 : egg_asn1x_destroy (param_asn);
786 : 20 : return res;
787 : : }
788 : :
789 : : static gint
790 : 22 : handle_subject_public_key_ec (GcrParser *self,
791 : : GcrParsed *parsed,
792 : : GBytes *key,
793 : : GNode *params)
794 : : {
795 : 22 : gint ret = GCR_ERROR_FAILURE;
796 : 22 : GBytes *bytes = NULL;
797 : 22 : GNode *asn = NULL;
798 : :
799 : 22 : parsing_object (parsed, CKO_PUBLIC_KEY);
800 : 22 : parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
801 : :
802 : 22 : bytes = egg_asn1x_encode (params, g_realloc);
803 : 22 : parsed_attribute_bytes (parsed, CKA_EC_PARAMS, bytes);
804 : 22 : g_bytes_unref (bytes);
805 : :
806 : 22 : asn = egg_asn1x_create (pk_asn1_tab, "ECPoint");
807 [ - + ]: 22 : if (!asn)
808 : 0 : goto done;
809 : 22 : egg_asn1x_set_string_as_bytes (asn, key);
810 : 22 : parsed_asn1_structure (parsed, asn, CKA_EC_POINT);
811 : 22 : ret = SUCCESS;
812 : 22 : done:
813 : 22 : egg_asn1x_destroy (asn);
814 : 22 : return ret;
815 : : }
816 : :
817 : : static gint
818 : 135 : parse_der_subject_public_key (GcrParser *self,
819 : : GBytes *data)
820 : : {
821 : : GcrParsed *parsed;
822 : : GNode *params;
823 : : GBytes *key;
824 : 135 : GNode *asn = NULL;
825 : : GNode *node;
826 : : GQuark oid;
827 : : guint bits;
828 : : gint ret;
829 : :
830 : 135 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data);
831 [ + + ]: 135 : if (asn == NULL)
832 : 73 : return GCR_ERROR_UNRECOGNIZED;
833 : :
834 : 62 : parsed = push_parsed (self, TRUE);
835 : 62 : parsing_block (parsed, GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, data);
836 : :
837 : 62 : node = egg_asn1x_node (asn, "algorithm", "algorithm", NULL);
838 : 62 : oid = egg_asn1x_get_oid_as_quark (node);
839 : :
840 : 62 : params = egg_asn1x_node (asn, "algorithm", "parameters", NULL);
841 : :
842 : 62 : node = egg_asn1x_node (asn, "subjectPublicKey", NULL);
843 : 62 : key = egg_asn1x_get_bits_as_raw (node, &bits);
844 : :
845 [ + + ]: 62 : if (oid == GCR_OID_PKIX1_RSA)
846 : 20 : ret = handle_subject_public_key_rsa (self, parsed, key, params);
847 : :
848 [ + + ]: 42 : else if (oid == GCR_OID_PKIX1_DSA)
849 : 20 : ret = handle_subject_public_key_dsa (self, parsed, key, params);
850 : :
851 [ + - ]: 22 : else if (oid == GCR_OID_PKIX1_EC)
852 : 22 : ret = handle_subject_public_key_ec (self, parsed, key, params);
853 : :
854 : : else
855 : 0 : ret = GCR_ERROR_UNRECOGNIZED;
856 : :
857 : 62 : g_bytes_unref (key);
858 : :
859 [ + - ]: 62 : if (ret == SUCCESS)
860 : 62 : parsed_fire (self, parsed);
861 : :
862 : 62 : pop_parsed (self, parsed);
863 : :
864 : 62 : egg_asn1x_destroy (asn);
865 : 62 : return ret;
866 : : }
867 : :
868 : : /* -----------------------------------------------------------------------------
869 : : * PKCS8
870 : : */
871 : :
872 : : static gint
873 : 133 : parse_der_pkcs8_plain (GcrParser *self,
874 : : GBytes *data)
875 : : {
876 : : gint ret;
877 : : CK_KEY_TYPE key_type;
878 : : GQuark key_algo;
879 : 133 : GBytes *keydata = NULL;
880 : 133 : GNode *params = NULL;
881 : 133 : GNode *asn = NULL;
882 : : GcrParsed *parsed;
883 : :
884 : 133 : parsed = push_parsed (self, TRUE);
885 : 133 : ret = GCR_ERROR_UNRECOGNIZED;
886 : :
887 : 133 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data);
888 [ + + ]: 133 : if (!asn)
889 : 117 : goto done;
890 : :
891 : 16 : parsing_block (parsed, GCR_FORMAT_DER_PKCS8_PLAIN, data);
892 : 16 : ret = GCR_ERROR_FAILURE;
893 : 16 : key_type = GCK_INVALID;
894 : :
895 : 16 : key_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL));
896 [ - + ]: 16 : if (!key_algo)
897 : 0 : goto done;
898 [ + + ]: 16 : else if (key_algo == GCR_OID_PKIX1_RSA)
899 : 14 : key_type = CKK_RSA;
900 [ + - ]: 2 : else if (key_algo == GCR_OID_PKIX1_DSA)
901 : 2 : key_type = CKK_DSA;
902 [ # # ]: 0 : else if (key_algo == GCR_OID_PKIX1_EC)
903 : 0 : key_type = CKK_EC;
904 : :
905 [ - + ]: 16 : if (key_type == GCK_INVALID) {
906 : 0 : ret = GCR_ERROR_UNRECOGNIZED;
907 : 0 : goto done;
908 : : }
909 : :
910 : 16 : keydata = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "privateKey", NULL));
911 [ - + ]: 16 : if (!keydata)
912 : 0 : goto done;
913 : :
914 : 16 : params = egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL);
915 : :
916 : 16 : ret = SUCCESS;
917 : :
918 : 133 : done:
919 [ + + ]: 133 : if (ret == SUCCESS) {
920 [ + + - - ]: 16 : switch (key_type) {
921 : 14 : case CKK_RSA:
922 : 14 : ret = parse_der_private_key_rsa (self, keydata);
923 : 14 : break;
924 : 2 : case CKK_DSA:
925 : : /* Try the normal sane format */
926 : 2 : ret = parse_der_private_key_dsa (self, keydata);
927 : :
928 : : /* Otherwise try the two part format that everyone seems to like */
929 [ + - + - ]: 2 : if (ret == GCR_ERROR_UNRECOGNIZED && params)
930 : 2 : ret = parse_der_private_key_dsa_parts (self, keydata, params);
931 : 2 : break;
932 : 0 : case CKK_EC:
933 : 0 : ret = parse_der_private_key_ec (self, keydata);
934 : 0 : break;
935 : :
936 : 0 : default:
937 : 0 : g_message ("invalid or unsupported key type in PKCS#8 key");
938 : 0 : ret = GCR_ERROR_UNRECOGNIZED;
939 : 0 : break;
940 : : };
941 : :
942 [ - + ]: 117 : } else if (ret == GCR_ERROR_FAILURE) {
943 : 0 : g_message ("invalid PKCS#8 key");
944 : : }
945 : :
946 [ + + ]: 133 : if (keydata)
947 : 16 : g_bytes_unref (keydata);
948 : 133 : egg_asn1x_destroy (asn);
949 : 133 : pop_parsed (self, parsed);
950 : 133 : return ret;
951 : : }
952 : :
953 : : static gint
954 : 96 : parse_der_pkcs8_encrypted (GcrParser *self,
955 : : GBytes *data)
956 : : {
957 : 96 : PasswordState pstate = PASSWORD_STATE_INIT;
958 : 96 : GNode *asn = NULL;
959 : 96 : gcry_cipher_hd_t cih = NULL;
960 : : gcry_error_t gcry;
961 : : gint ret, r;
962 : : GQuark scheme;
963 : 96 : guchar *crypted = NULL;
964 : 96 : GNode *params = NULL;
965 : : GBytes *cbytes;
966 : : gsize n_crypted;
967 : : const gchar *password;
968 : : GcrParsed *parsed;
969 : : gint l;
970 : :
971 : 96 : parsed = push_parsed (self, FALSE);
972 : 96 : ret = GCR_ERROR_UNRECOGNIZED;
973 : :
974 : 96 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data);
975 [ + + ]: 96 : if (!asn)
976 : 83 : goto done;
977 : :
978 : 13 : parsing_block (parsed, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
979 : 13 : ret = GCR_ERROR_FAILURE;
980 : :
981 : : /* Figure out the type of encryption */
982 : 13 : scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL));
983 [ - + ]: 13 : if (!scheme)
984 : 0 : goto done;
985 : :
986 : 13 : params = egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL);
987 : :
988 : : /* Loop to try different passwords */
989 : : for (;;) {
990 : :
991 [ - + ]: 39 : g_assert (cih == NULL);
992 : :
993 : 39 : r = enum_next_password (self, &pstate, &password);
994 [ - + ]: 39 : if (r != SUCCESS) {
995 : 0 : ret = r;
996 : 0 : break;
997 : : }
998 : :
999 : : /* Parse the encryption stuff into a cipher. */
1000 [ - + ]: 39 : if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih))
1001 : 0 : break;
1002 : :
1003 : 39 : crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL), egg_secure_realloc, &n_crypted);
1004 [ - + ]: 39 : if (!crypted)
1005 : 0 : break;
1006 : :
1007 : 39 : gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
1008 : 39 : gcry_cipher_close (cih);
1009 : 39 : cih = NULL;
1010 : :
1011 [ - + ]: 39 : if (gcry != 0) {
1012 : 0 : g_warning ("couldn't decrypt pkcs8 data: %s", gcry_strerror (gcry));
1013 : 0 : break;
1014 : : }
1015 : :
1016 : : /* Unpad the DER data */
1017 : 39 : l = egg_asn1x_element_length (crypted, n_crypted);
1018 [ + + ]: 39 : if (l > 0)
1019 : 22 : n_crypted = l;
1020 : :
1021 : 39 : cbytes = g_bytes_new_with_free_func (crypted, n_crypted,
1022 : : egg_secure_free, crypted);
1023 : 39 : crypted = NULL;
1024 : :
1025 : : /* Try to parse the resulting key */
1026 : 39 : r = parse_der_pkcs8_plain (self, cbytes);
1027 : 39 : g_bytes_unref (cbytes);
1028 : :
1029 [ + + ]: 39 : if (r != GCR_ERROR_UNRECOGNIZED) {
1030 : 13 : ret = r;
1031 : 13 : break;
1032 : : }
1033 : :
1034 : : /* We assume unrecognized data, is a bad encryption key */
1035 : : }
1036 : :
1037 : 96 : done:
1038 [ - + ]: 96 : if (cih)
1039 : 0 : gcry_cipher_close (cih);
1040 : 96 : egg_asn1x_destroy (asn);
1041 : 96 : egg_secure_free (crypted);
1042 : :
1043 : 96 : pop_parsed (self, parsed);
1044 : 96 : return ret;
1045 : : }
1046 : :
1047 : : static gint
1048 : 36 : parse_der_pkcs8 (GcrParser *self,
1049 : : GBytes *data)
1050 : : {
1051 : : gint ret;
1052 : :
1053 : 36 : ret = parse_der_pkcs8_plain (self, data);
1054 [ + - ]: 36 : if (ret == GCR_ERROR_UNRECOGNIZED)
1055 : 36 : ret = parse_der_pkcs8_encrypted (self, data);
1056 : :
1057 : 36 : return ret;
1058 : : }
1059 : :
1060 : : /* -----------------------------------------------------------------------------
1061 : : * CERTIFICATE
1062 : : */
1063 : :
1064 : : static gint
1065 : 385 : parse_der_certificate (GcrParser *self,
1066 : : GBytes *data)
1067 : : {
1068 : 385 : gchar *name = NULL;
1069 : : GcrParsed *parsed;
1070 : : GNode *node;
1071 : : GNode *asn;
1072 : :
1073 : 385 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data);
1074 [ + + ]: 385 : if (asn == NULL)
1075 : 58 : return GCR_ERROR_UNRECOGNIZED;
1076 : :
1077 : 327 : parsed = push_parsed (self, FALSE);
1078 : :
1079 : 327 : parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data);
1080 : 327 : parsing_object (parsed, CKO_CERTIFICATE);
1081 : 327 : parsed_ulong_attribute (parsed, CKA_CERTIFICATE_TYPE, CKC_X_509);
1082 : :
1083 : 327 : node = egg_asn1x_node (asn, "tbsCertificate", NULL);
1084 [ - + ]: 327 : g_return_val_if_fail (node != NULL, GCR_ERROR_FAILURE);
1085 : :
1086 [ + + ]: 327 : if (gcr_parser_get_parsed_label (self) == NULL)
1087 : 323 : name = egg_dn_read_part (egg_asn1x_node (node, "subject", "rdnSequence", NULL), "CN");
1088 : :
1089 [ + + ]: 327 : if (name != NULL) {
1090 : 281 : parsed_label (parsed, name);
1091 : 281 : g_free (name);
1092 : : }
1093 : :
1094 : 327 : parsed_attribute_bytes (parsed, CKA_VALUE, data);
1095 : 327 : parsed_asn1_element (parsed, node, "subject", CKA_SUBJECT);
1096 : 327 : parsed_asn1_element (parsed, node, "issuer", CKA_ISSUER);
1097 : 327 : parsed_asn1_number (parsed, node, "serialNumber", CKA_SERIAL_NUMBER);
1098 : 327 : parsed_fire (self, parsed);
1099 : :
1100 : 327 : egg_asn1x_destroy (asn);
1101 : :
1102 : 327 : pop_parsed (self, parsed);
1103 : 327 : return SUCCESS;
1104 : : }
1105 : :
1106 : : /* -----------------------------------------------------------------------------
1107 : : * PKCS7
1108 : : */
1109 : :
1110 : : static gint
1111 : 1 : handle_pkcs7_signed_data (GcrParser *self,
1112 : : GNode *content)
1113 : : {
1114 : 1 : GNode *asn = NULL;
1115 : : GNode *node;
1116 : : gint ret;
1117 : : GBytes *certificate;
1118 : : int i;
1119 : :
1120 : 1 : ret = GCR_ERROR_UNRECOGNIZED;
1121 : :
1122 : 1 : asn = egg_asn1x_get_any_as (content, pkix_asn1_tab, "pkcs-7-SignedData");
1123 [ - + ]: 1 : if (!asn)
1124 : 0 : goto done;
1125 : :
1126 : 1 : for (i = 0; TRUE; ++i) {
1127 : :
1128 : 2 : node = egg_asn1x_node (asn, "certificates", i + 1, NULL);
1129 : :
1130 : : /* No more certificates? */
1131 [ + + ]: 2 : if (node == NULL)
1132 : 1 : break;
1133 : :
1134 : 1 : certificate = egg_asn1x_get_element_raw (node);
1135 : 1 : ret = parse_der_certificate (self, certificate);
1136 : 1 : g_bytes_unref (certificate);
1137 : :
1138 [ - + ]: 1 : if (ret != SUCCESS)
1139 : 0 : goto done;
1140 : : }
1141 : :
1142 : : /* TODO: Parse out all the CRLs */
1143 : :
1144 : 1 : ret = SUCCESS;
1145 : :
1146 : 1 : done:
1147 : 1 : egg_asn1x_destroy (asn);
1148 : 1 : return ret;
1149 : : }
1150 : :
1151 : : static gint
1152 : 58 : parse_der_pkcs7 (GcrParser *self,
1153 : : GBytes *data)
1154 : : {
1155 : 58 : GNode *asn = NULL;
1156 : : GNode *node;
1157 : : gint ret;
1158 : 58 : GNode *content = NULL;
1159 : : GQuark oid;
1160 : : GcrParsed *parsed;
1161 : :
1162 : 58 : parsed = push_parsed (self, FALSE);
1163 : 58 : ret = GCR_ERROR_UNRECOGNIZED;
1164 : :
1165 : 58 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data);
1166 [ + + ]: 58 : if (!asn)
1167 : 57 : goto done;
1168 : :
1169 : 1 : parsing_block (parsed, GCR_FORMAT_DER_PKCS7, data);
1170 : 1 : ret = GCR_ERROR_FAILURE;
1171 : :
1172 : 1 : node = egg_asn1x_node (asn, "contentType", NULL);
1173 [ - + ]: 1 : if (!node)
1174 : 0 : goto done;
1175 : :
1176 : 1 : oid = egg_asn1x_get_oid_as_quark (node);
1177 [ - + ]: 1 : g_return_val_if_fail (oid, GCR_ERROR_FAILURE);
1178 : :
1179 : : /* Outer most one must just be plain data */
1180 [ - + ]: 1 : if (oid != GCR_OID_PKCS7_SIGNED_DATA) {
1181 : 0 : g_message ("unsupported outer content type in pkcs7: %s", g_quark_to_string (oid));
1182 : 0 : goto done;
1183 : : }
1184 : :
1185 : 1 : content = egg_asn1x_node (asn, "content", NULL);
1186 [ - + ]: 1 : if (!content)
1187 : 0 : goto done;
1188 : :
1189 : 1 : ret = handle_pkcs7_signed_data (self, content);
1190 : :
1191 : 58 : done:
1192 : 58 : egg_asn1x_destroy (asn);
1193 : 58 : pop_parsed (self, parsed);
1194 : 58 : return ret;
1195 : : }
1196 : :
1197 : : /* -----------------------------------------------------------------------------
1198 : : * PKCS12
1199 : : */
1200 : :
1201 : : static gint
1202 : 5 : handle_pkcs12_cert_bag (GcrParser *self,
1203 : : GBytes *data)
1204 : : {
1205 : 5 : GNode *asn = NULL;
1206 : 5 : GNode *asn_content = NULL;
1207 : 5 : guchar *certificate = NULL;
1208 : 5 : GNode *element = NULL;
1209 : : gsize n_certificate;
1210 : : GBytes *bytes;
1211 : : gint ret;
1212 : :
1213 : 5 : ret = GCR_ERROR_UNRECOGNIZED;
1214 : 5 : asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-CertBag",
1215 : : data, EGG_ASN1X_NO_STRICT);
1216 [ - + ]: 5 : if (!asn)
1217 : 0 : goto done;
1218 : :
1219 : 5 : ret = GCR_ERROR_FAILURE;
1220 : :
1221 : 5 : element = egg_asn1x_node (asn, "certValue", NULL);
1222 [ - + ]: 5 : if (!element)
1223 : 0 : goto done;
1224 : :
1225 : 5 : asn_content = egg_asn1x_get_any_as (element, pkix_asn1_tab, "pkcs-7-Data");
1226 [ - + ]: 5 : if (!asn_content)
1227 : 0 : goto done;
1228 : :
1229 : 5 : certificate = egg_asn1x_get_string_as_raw (asn_content, NULL, &n_certificate);
1230 [ - + ]: 5 : if (!certificate)
1231 : 0 : goto done;
1232 : :
1233 : 5 : bytes = g_bytes_new_take (certificate, n_certificate);
1234 : 5 : ret = parse_der_certificate (self, bytes);
1235 : 5 : g_bytes_unref (bytes);
1236 : :
1237 : 5 : done:
1238 : 5 : egg_asn1x_destroy (asn_content);
1239 : 5 : egg_asn1x_destroy (asn);
1240 : 5 : return ret;
1241 : : }
1242 : :
1243 : : static gchar *
1244 : 9 : parse_pkcs12_bag_friendly_name (GNode *asn)
1245 : : {
1246 : : guint count, i;
1247 : : GQuark oid;
1248 : : GNode *node;
1249 : : GNode *asn_str;
1250 : : gchar *result;
1251 : :
1252 [ - + ]: 9 : if (asn == NULL)
1253 : 0 : return NULL;
1254 : :
1255 : 9 : count = egg_asn1x_count (asn);
1256 [ + + ]: 15 : for (i = 1; i <= count; i++) {
1257 : 14 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, i, "type", NULL));
1258 [ + + ]: 14 : if (oid == GCR_OID_PKCS9_ATTRIBUTE_FRIENDLY) {
1259 : 8 : node = egg_asn1x_node (asn, i, "values", 1, NULL);
1260 [ + - ]: 8 : if (node != NULL) {
1261 : 8 : asn_str = egg_asn1x_get_any_as_string (node, EGG_ASN1X_BMP_STRING);
1262 [ + - ]: 8 : if (asn_str) {
1263 : 8 : result = egg_asn1x_get_bmpstring_as_utf8 (asn_str);
1264 : 8 : egg_asn1x_destroy (asn_str);
1265 : 8 : return result;
1266 : : }
1267 : : }
1268 : : }
1269 : : }
1270 : :
1271 : 1 : return NULL;
1272 : : }
1273 : :
1274 : : static gint
1275 : 16 : handle_pkcs12_bag (GcrParser *self,
1276 : : GBytes *data)
1277 : : {
1278 : 16 : GNode *asn = NULL;
1279 : : gint ret, r;
1280 : 16 : guint count = 0;
1281 : : GQuark oid;
1282 : : GNode *value;
1283 : 16 : GBytes *element = NULL;
1284 : : gchar *friendly;
1285 : : guint i;
1286 : : GcrParsed *parsed;
1287 : :
1288 : 16 : ret = GCR_ERROR_UNRECOGNIZED;
1289 : :
1290 : 16 : asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-SafeContents",
1291 : : data, EGG_ASN1X_NO_STRICT);
1292 [ + + ]: 16 : if (!asn)
1293 : 8 : goto done;
1294 : :
1295 : 8 : ret = GCR_ERROR_FAILURE;
1296 : :
1297 : : /* Get the number of elements in this bag */
1298 : 8 : count = egg_asn1x_count (asn);
1299 : :
1300 : : /*
1301 : : * Now inside each bag are multiple elements. Who comes up
1302 : : * with this stuff?
1303 : : */
1304 [ + + ]: 17 : for (i = 1; i <= count; i++) {
1305 : :
1306 : 9 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, i, "bagId", NULL));
1307 [ - + ]: 9 : if (!oid)
1308 : 0 : goto done;
1309 : :
1310 : 9 : value = egg_asn1x_node (asn, i, "bagValue", NULL);
1311 [ - + ]: 9 : if (!value)
1312 : 0 : goto done;
1313 : :
1314 : 9 : element = egg_asn1x_get_element_raw (value);
1315 : 9 : parsed = push_parsed (self, FALSE);
1316 : :
1317 : 9 : friendly = parse_pkcs12_bag_friendly_name (egg_asn1x_node (asn, i, "bagAttributes", NULL));
1318 [ + + ]: 9 : if (friendly != NULL) {
1319 : 8 : parsed_label (parsed, friendly);
1320 : 8 : g_free (friendly);
1321 : : }
1322 : :
1323 : : /* A normal unencrypted key */
1324 [ - + ]: 9 : if (oid == GCR_OID_PKCS12_BAG_PKCS8_KEY) {
1325 : 0 : r = parse_der_pkcs8_plain (self, element);
1326 : :
1327 : : /* A properly encrypted key */
1328 [ + + ]: 9 : } else if (oid == GCR_OID_PKCS12_BAG_PKCS8_ENCRYPTED_KEY) {
1329 : 4 : r = parse_der_pkcs8_encrypted (self, element);
1330 : :
1331 : : /* A certificate */
1332 [ + - ]: 5 : } else if (oid == GCR_OID_PKCS12_BAG_CERTIFICATE) {
1333 : 5 : r = handle_pkcs12_cert_bag (self, element);
1334 : :
1335 : : /* TODO: GCR_OID_PKCS12_BAG_CRL */
1336 : : } else {
1337 : 0 : r = GCR_ERROR_UNRECOGNIZED;
1338 : : }
1339 : :
1340 [ + - ]: 9 : if (element != NULL)
1341 : 9 : g_bytes_unref (element);
1342 : :
1343 : 9 : pop_parsed (self, parsed);
1344 : :
1345 [ + - + - ]: 9 : if (r == GCR_ERROR_FAILURE ||
1346 [ - + ]: 9 : r == GCR_ERROR_CANCELLED ||
1347 : : r == GCR_ERROR_LOCKED) {
1348 : 0 : ret = r;
1349 : 0 : goto done;
1350 : : }
1351 : : }
1352 : :
1353 : 8 : ret = SUCCESS;
1354 : :
1355 : 16 : done:
1356 : 16 : egg_asn1x_destroy (asn);
1357 : 16 : return ret;
1358 : : }
1359 : :
1360 : : static gint
1361 : 4 : handle_pkcs12_encrypted_bag (GcrParser *self,
1362 : : GNode *bag)
1363 : : {
1364 : 4 : PasswordState pstate = PASSWORD_STATE_INIT;
1365 : 4 : GNode *asn = NULL;
1366 : 4 : gcry_cipher_hd_t cih = NULL;
1367 : : gcry_error_t gcry;
1368 : 4 : guchar *crypted = NULL;
1369 : 4 : GNode *params = NULL;
1370 : : gsize n_crypted;
1371 : : const gchar *password;
1372 : : GBytes *cbytes;
1373 : : GQuark scheme;
1374 : : gint ret, r;
1375 : : gint l;
1376 : :
1377 : 4 : ret = GCR_ERROR_UNRECOGNIZED;
1378 : :
1379 : 4 : asn = egg_asn1x_get_any_as_full (bag, pkix_asn1_tab, "pkcs-7-EncryptedData",
1380 : : EGG_ASN1X_NO_STRICT);
1381 [ - + ]: 4 : if (!asn)
1382 : 0 : goto done;
1383 : :
1384 : 4 : ret = GCR_ERROR_FAILURE;
1385 : :
1386 : : /* Check the encryption schema OID */
1387 : 4 : scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "algorithm", NULL));
1388 [ - + ]: 4 : if (!scheme)
1389 : 0 : goto done;
1390 : :
1391 : 4 : params = egg_asn1x_node (asn, "encryptedContentInfo", "contentEncryptionAlgorithm", "parameters", NULL);
1392 [ + - ]: 4 : if (!params)
1393 : 0 : goto done;
1394 : :
1395 : : /* Loop to try different passwords */
1396 : : for (;;) {
1397 : :
1398 [ - + ]: 12 : g_assert (cih == NULL);
1399 : :
1400 : 12 : r = enum_next_password (self, &pstate, &password);
1401 [ - + ]: 12 : if (r != SUCCESS) {
1402 : 0 : ret = r;
1403 : 0 : goto done;
1404 : : }
1405 : :
1406 : : /* Parse the encryption stuff into a cipher. */
1407 [ - + ]: 12 : if (!egg_symkey_read_cipher (scheme, password, -1, params, &cih)) {
1408 : 0 : ret = GCR_ERROR_FAILURE;
1409 : 0 : goto done;
1410 : : }
1411 : :
1412 : 12 : crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedContentInfo", "encryptedContent", NULL),
1413 : : egg_secure_realloc, &n_crypted);
1414 [ - + ]: 12 : if (!crypted)
1415 : 0 : goto done;
1416 : :
1417 : 12 : gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
1418 : 12 : gcry_cipher_close (cih);
1419 : 12 : cih = NULL;
1420 : :
1421 [ - + ]: 12 : if (gcry != 0) {
1422 : 0 : g_warning ("couldn't decrypt pkcs12 data: %s", gcry_strerror (gcry));
1423 : 0 : goto done;
1424 : : }
1425 : :
1426 : : /* Unpad the DER data */
1427 : 12 : l = egg_asn1x_element_length (crypted, n_crypted);
1428 [ + + ]: 12 : if (l > 0)
1429 : 8 : n_crypted = l;
1430 : :
1431 : 12 : cbytes = g_bytes_new_with_free_func (crypted, n_crypted, egg_secure_free, crypted);
1432 : 12 : crypted = NULL;
1433 : :
1434 : : /* Try to parse the resulting key */
1435 : 12 : r = handle_pkcs12_bag (self, cbytes);
1436 : 12 : g_bytes_unref (cbytes);
1437 : :
1438 [ + + ]: 12 : if (r != GCR_ERROR_UNRECOGNIZED) {
1439 : 4 : ret = r;
1440 : 4 : break;
1441 : : }
1442 : :
1443 : : /* We assume unrecognized data is a bad encryption key */
1444 : : }
1445 : :
1446 : 4 : done:
1447 [ - + ]: 4 : if (cih)
1448 : 0 : gcry_cipher_close (cih);
1449 : 4 : egg_asn1x_destroy (asn);
1450 : 4 : egg_secure_free (crypted);
1451 : 4 : return ret;
1452 : : }
1453 : :
1454 : : static gint
1455 : 4 : handle_pkcs12_safe (GcrParser *self,
1456 : : GBytes *data)
1457 : : {
1458 : 4 : GNode *asn = NULL;
1459 : 4 : GNode *asn_content = NULL;
1460 : : gint ret, r;
1461 : : GNode *bag;
1462 : : GBytes *content;
1463 : : GQuark oid;
1464 : : guint i;
1465 : : GNode *node;
1466 : :
1467 : 4 : ret = GCR_ERROR_UNRECOGNIZED;
1468 : :
1469 : 4 : asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-AuthenticatedSafe",
1470 : : data, EGG_ASN1X_NO_STRICT);
1471 [ - + ]: 4 : if (!asn)
1472 : 0 : goto done;
1473 : :
1474 : 4 : ret = GCR_ERROR_FAILURE;
1475 : :
1476 : : /*
1477 : : * Inside each PKCS12 safe there are multiple bags.
1478 : : */
1479 : 4 : for (i = 0; TRUE; ++i) {
1480 : 12 : node = egg_asn1x_node (asn, i + 1, "contentType", NULL);
1481 : :
1482 : : /* All done? no more bags */
1483 [ + + ]: 12 : if (!node)
1484 : 4 : break;
1485 : :
1486 : 8 : oid = egg_asn1x_get_oid_as_quark (node);
1487 : :
1488 : 8 : bag = egg_asn1x_node (asn, i + 1, "content", NULL);
1489 [ - + ]: 8 : if (!bag)
1490 : 0 : goto done;
1491 : :
1492 : : /* A non encrypted bag, just parse */
1493 [ + + ]: 8 : if (oid == GCR_OID_PKCS7_DATA) {
1494 : :
1495 : 4 : egg_asn1x_destroy (asn_content);
1496 : 4 : asn_content = egg_asn1x_get_any_as_full (bag, pkix_asn1_tab,
1497 : : "pkcs-7-Data", EGG_ASN1X_NO_STRICT);
1498 [ - + ]: 4 : if (!asn_content)
1499 : 0 : goto done;
1500 : :
1501 : 4 : content = egg_asn1x_get_string_as_bytes (asn_content);
1502 [ - + ]: 4 : if (!content)
1503 : 0 : goto done;
1504 : :
1505 : 4 : r = handle_pkcs12_bag (self, content);
1506 : 4 : g_bytes_unref (content);
1507 : :
1508 : : /* Encrypted data first needs decryption */
1509 [ + - ]: 4 : } else if (oid == GCR_OID_PKCS7_ENCRYPTED_DATA) {
1510 : 4 : r = handle_pkcs12_encrypted_bag (self, bag);
1511 : :
1512 : : /* Hmmmm, not sure what this is */
1513 : : } else {
1514 : 0 : g_warning ("unrecognized type of safe content in pkcs12: %s", g_quark_to_string (oid));
1515 : 0 : r = GCR_ERROR_UNRECOGNIZED;
1516 : : }
1517 : :
1518 [ + - + - ]: 8 : if (r == GCR_ERROR_FAILURE ||
1519 [ - + ]: 8 : r == GCR_ERROR_CANCELLED ||
1520 : : r == GCR_ERROR_LOCKED) {
1521 : 0 : ret = r;
1522 : 0 : goto done;
1523 : : }
1524 : : }
1525 : :
1526 : 4 : ret = SUCCESS;
1527 : :
1528 : 4 : done:
1529 : 4 : egg_asn1x_destroy (asn);
1530 : 4 : egg_asn1x_destroy (asn_content);
1531 : 4 : return ret;
1532 : : }
1533 : :
1534 : : static gint
1535 : 4 : verify_pkcs12_safe (GcrParser *self,
1536 : : GNode *asn,
1537 : : GBytes *content)
1538 : : {
1539 : 4 : PasswordState pstate = PASSWORD_STATE_INIT;
1540 : : const gchar *password;
1541 : 4 : gcry_md_hd_t mdh = NULL;
1542 : : const guchar *mac_digest;
1543 : : gsize mac_len;
1544 : 4 : guchar *digest = NULL;
1545 : : gsize n_digest;
1546 : : GQuark algorithm;
1547 : : GNode *mac_data;
1548 : : int ret, r;
1549 : :
1550 : 4 : ret = GCR_ERROR_FAILURE;
1551 : :
1552 : : /*
1553 : : * The MAC is optional (and outside the encryption no less). I wonder
1554 : : * what the designers (ha) of PKCS#12 were trying to achieve
1555 : : */
1556 : :
1557 : 4 : mac_data = egg_asn1x_node (asn, "macData", NULL);
1558 [ - + ]: 4 : if (mac_data == NULL)
1559 : 0 : return SUCCESS;
1560 : :
1561 : 4 : algorithm = egg_asn1x_get_oid_as_quark (egg_asn1x_node (mac_data, "mac",
1562 : : "digestAlgorithm", "algorithm", NULL));
1563 [ - + ]: 4 : if (!algorithm)
1564 : 0 : goto done;
1565 : :
1566 : 4 : digest = egg_asn1x_get_string_as_raw (egg_asn1x_node (mac_data, "mac", "digest", NULL), NULL, &n_digest);
1567 [ - + ]: 4 : if (!digest)
1568 : 0 : goto done;
1569 : :
1570 : : /* Loop to try different passwords */
1571 : : for (;;) {
1572 [ - + ]: 12 : g_assert (mdh == NULL);
1573 : :
1574 : 12 : r = enum_next_password (self, &pstate, &password);
1575 [ - + ]: 12 : if (r != SUCCESS) {
1576 : 0 : ret = r;
1577 : 0 : goto done;
1578 : : }
1579 : :
1580 : : /* Parse the encryption stuff into a cipher. */
1581 [ - + ]: 12 : if (!egg_symkey_read_mac (algorithm, password, -1, mac_data, &mdh, &mac_len)) {
1582 : 0 : ret = GCR_ERROR_FAILURE;
1583 : 0 : goto done;
1584 : : }
1585 : :
1586 : : /* If not the right length, then that's really broken */
1587 [ - + ]: 12 : if (mac_len != n_digest) {
1588 : 0 : r = GCR_ERROR_FAILURE;
1589 : :
1590 : : } else {
1591 : 12 : gcry_md_write (mdh, g_bytes_get_data (content, NULL), g_bytes_get_size (content));
1592 : 12 : mac_digest = gcry_md_read (mdh, 0);
1593 [ - + ]: 12 : g_return_val_if_fail (mac_digest, GCR_ERROR_FAILURE);
1594 [ + + ]: 12 : r = memcmp (mac_digest, digest, n_digest) == 0 ? SUCCESS : GCR_ERROR_LOCKED;
1595 : : }
1596 : :
1597 : 12 : gcry_md_close (mdh);
1598 : 12 : mdh = NULL;
1599 : :
1600 [ + + ]: 12 : if (r != GCR_ERROR_LOCKED) {
1601 : 4 : ret = r;
1602 : 4 : break;
1603 : : }
1604 : : }
1605 : :
1606 : 4 : done:
1607 [ - + ]: 4 : if (mdh)
1608 : 0 : gcry_md_close (mdh);
1609 : 4 : g_free (digest);
1610 : 4 : return ret;
1611 : :
1612 : : }
1613 : :
1614 : : static gint
1615 : 47 : parse_der_pkcs12 (GcrParser *self,
1616 : : GBytes *data)
1617 : : {
1618 : 47 : GNode *asn = NULL;
1619 : : gint ret;
1620 : 47 : GNode *content = NULL;
1621 : 47 : GBytes *string = NULL;
1622 : : GQuark oid;
1623 : : GcrParsed *parsed;
1624 : :
1625 : 47 : parsed = push_parsed (self, FALSE);
1626 : 47 : ret = GCR_ERROR_UNRECOGNIZED;
1627 : :
1628 : : /*
1629 : : * Because PKCS#12 files, the bags specifically, are notorious for
1630 : : * being crappily constructed and are often break rules such as DER
1631 : : * sorting order etc.. we parse the DER in a non-strict fashion.
1632 : : *
1633 : : * The rules in DER are designed for X.509 certificates, so there is
1634 : : * only one way to represent a given certificate (although they fail
1635 : : * at that as well). But with PKCS#12 we don't have such high
1636 : : * requirements, and we can slack off on our validation.
1637 : : */
1638 : :
1639 : 47 : asn = egg_asn1x_create_and_decode_full (pkix_asn1_tab, "pkcs-12-PFX",
1640 : : data, EGG_ASN1X_NO_STRICT);
1641 [ + + ]: 47 : if (!asn)
1642 : 43 : goto done;
1643 : :
1644 : 4 : parsing_block (parsed, GCR_FORMAT_DER_PKCS12, data);
1645 : :
1646 : 4 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "authSafe", "contentType", NULL));
1647 [ - + ]: 4 : if (!oid)
1648 : 0 : goto done;
1649 : :
1650 : : /* Outer most one must just be plain data */
1651 [ - + ]: 4 : if (oid != GCR_OID_PKCS7_DATA) {
1652 : 0 : g_message ("unsupported safe content type in pkcs12: %s", g_quark_to_string (oid));
1653 : 0 : goto done;
1654 : : }
1655 : :
1656 : 4 : content = egg_asn1x_get_any_as (egg_asn1x_node (asn, "authSafe", "content", NULL),
1657 : : pkix_asn1_tab, "pkcs-7-Data");
1658 [ - + ]: 4 : if (!content)
1659 : 0 : goto done;
1660 : :
1661 : 4 : string = egg_asn1x_get_string_as_bytes (content);
1662 [ - + ]: 4 : if (!string)
1663 : 0 : goto done;
1664 : :
1665 : 4 : ret = verify_pkcs12_safe (self, asn, string);
1666 [ - + ]: 4 : if (ret == SUCCESS)
1667 : 4 : ret = handle_pkcs12_safe (self, string);
1668 : :
1669 : 0 : done:
1670 [ + + ]: 47 : if (content)
1671 : 4 : egg_asn1x_destroy (content);
1672 [ + + ]: 47 : if (string)
1673 : 4 : g_bytes_unref (string);
1674 : 47 : egg_asn1x_destroy (asn);
1675 : 47 : pop_parsed (self, parsed);
1676 : 47 : return ret;
1677 : : }
1678 : :
1679 : : /* -----------------------------------------------------------------------------
1680 : : * CERTIFICATE REQUESTS
1681 : : */
1682 : :
1683 : : static gint
1684 : 49 : parse_der_pkcs10 (GcrParser *self,
1685 : : GBytes *data)
1686 : : {
1687 : 49 : GNode *asn = NULL;
1688 : : GNode *node;
1689 : : GcrParsed *parsed;
1690 : 49 : gchar *name = NULL;
1691 : :
1692 : 49 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-10-CertificationRequest", data);
1693 [ + + ]: 49 : if (!asn)
1694 : 37 : return GCR_ERROR_UNRECOGNIZED;
1695 : :
1696 : 12 : parsed = push_parsed (self, FALSE);
1697 : 12 : parsing_block (parsed, GCR_FORMAT_DER_PKCS10, data);
1698 : :
1699 : 12 : parsing_object (parsed, CKO_GCR_CERTIFICATE_REQUEST);
1700 : 12 : parsed_ulong_attribute (parsed, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_PKCS10);
1701 : :
1702 : 12 : node = egg_asn1x_node (asn, "certificationRequestInfo", NULL);
1703 [ - + ]: 12 : g_return_val_if_fail (node != NULL, GCR_ERROR_FAILURE);
1704 : :
1705 [ + - ]: 12 : if (gcr_parser_get_parsed_label (self) == NULL)
1706 : 12 : name = egg_dn_read_part (egg_asn1x_node (node, "subject", "rdnSequence", NULL), "CN");
1707 : :
1708 [ + - ]: 12 : if (name != NULL) {
1709 : 12 : parsed_label (parsed, name);
1710 : 12 : g_free (name);
1711 : : }
1712 : :
1713 : 12 : parsed_attribute_bytes (parsed, CKA_VALUE, data);
1714 : 12 : parsed_asn1_element (parsed, node, "subject", CKA_SUBJECT);
1715 : 12 : parsed_fire (self, parsed);
1716 : :
1717 : 12 : egg_asn1x_destroy (asn);
1718 : :
1719 : 12 : pop_parsed (self, parsed);
1720 : 12 : return SUCCESS;
1721 : : }
1722 : :
1723 : : static gint
1724 : 40 : parse_der_spkac (GcrParser *self,
1725 : : GBytes *data)
1726 : : {
1727 : 40 : GNode *asn = NULL;
1728 : : GcrParsed *parsed;
1729 : :
1730 : 40 : asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SignedPublicKeyAndChallenge", data);
1731 [ + + ]: 40 : if (!asn)
1732 : 36 : return GCR_ERROR_UNRECOGNIZED;
1733 : :
1734 : 4 : parsed = push_parsed (self, FALSE);
1735 : 4 : parsing_block (parsed, GCR_FORMAT_DER_SPKAC, data);
1736 : :
1737 : 4 : parsing_object (parsed, CKO_GCR_CERTIFICATE_REQUEST);
1738 : 4 : parsed_ulong_attribute (parsed, CKA_GCR_CERTIFICATE_REQUEST_TYPE, CKQ_GCR_SPKAC);
1739 : :
1740 : 4 : parsed_attribute_bytes (parsed, CKA_VALUE, data);
1741 : 4 : parsed_fire (self, parsed);
1742 : :
1743 : 4 : egg_asn1x_destroy (asn);
1744 : :
1745 : 4 : pop_parsed (self, parsed);
1746 : 4 : return SUCCESS;
1747 : : }
1748 : :
1749 : : static gint
1750 : 81 : parse_base64_spkac (GcrParser *self,
1751 : : GBytes *dat)
1752 : : {
1753 : 81 : const gchar *PREFIX = "SPKAC=";
1754 : 81 : const gsize PREFIX_LEN = 6;
1755 : :
1756 : : GcrParsed *parsed;
1757 : : guchar *spkac;
1758 : : gsize n_spkac;
1759 : : const guchar *data;
1760 : : GBytes *bytes;
1761 : : gsize n_data;
1762 : : gint ret;
1763 : 81 : data = g_bytes_get_data (dat, &n_data);
1764 : :
1765 [ + - + + ]: 81 : if (n_data > PREFIX_LEN && memcmp (PREFIX, data, PREFIX_LEN))
1766 : 80 : return GCR_ERROR_UNRECOGNIZED;
1767 : :
1768 : 1 : parsed = push_parsed (self, FALSE);
1769 : 1 : parsing_block (parsed, GCR_FORMAT_DER_SPKAC, dat);
1770 : :
1771 : 1 : data += PREFIX_LEN;
1772 : 1 : n_data -= PREFIX_LEN;
1773 : :
1774 : 1 : spkac = g_base64_decode ((const gchar *)data, &n_spkac);
1775 [ + - ]: 1 : if (spkac != NULL) {
1776 : 1 : bytes = g_bytes_new_take (spkac, n_spkac);
1777 : 1 : ret = parse_der_spkac (self, bytes);
1778 : 1 : g_bytes_unref (bytes);
1779 : : } else {
1780 : 0 : ret = GCR_ERROR_FAILURE;
1781 : : }
1782 : :
1783 : 1 : pop_parsed (self, parsed);
1784 : 1 : return ret;
1785 : : }
1786 : :
1787 : : /* -----------------------------------------------------------------------------
1788 : : * OPENPGP
1789 : : */
1790 : :
1791 : : static void
1792 : 26 : on_openpgp_packet (GPtrArray *records,
1793 : : GBytes *outer,
1794 : : gpointer user_data)
1795 : : {
1796 : 26 : GcrParser *self = GCR_PARSER (user_data);
1797 : : GcrParsed *parsed;
1798 : : gchar *string;
1799 : :
1800 : : /*
1801 : : * If it's an openpgp packet that doesn't contain a key, then
1802 : : * just ignore it here.
1803 : : */
1804 [ - + ]: 26 : if (records->len == 0)
1805 : 0 : return;
1806 : :
1807 : 26 : parsed = push_parsed (self, FALSE);
1808 : :
1809 : : /* All we can do is the packet bounds */
1810 : 26 : parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer);
1811 : 26 : parsing_object (parsed, CKO_GCR_GNUPG_RECORDS);
1812 : 26 : string = _gcr_records_format (records);
1813 : 26 : parsed_attribute (parsed, CKA_VALUE, string, strlen (string));
1814 : 26 : parsed_fire (self, parsed);
1815 : 26 : pop_parsed (self, parsed);
1816 : :
1817 : 26 : g_free (string);
1818 : : }
1819 : :
1820 : : static gint
1821 : 56 : parse_openpgp_packets (GcrParser *self,
1822 : : GBytes *data)
1823 : : {
1824 : : gint num_parsed;
1825 : :
1826 : 56 : num_parsed = _gcr_openpgp_parse (data,
1827 : : GCR_OPENPGP_PARSE_KEYS |
1828 : : GCR_OPENPGP_PARSE_ATTRIBUTES |
1829 : : GCR_OPENPGP_PARSE_SIGNATURES,
1830 : : on_openpgp_packet, self);
1831 : :
1832 [ + + ]: 56 : if (num_parsed == 0)
1833 : 40 : return GCR_ERROR_UNRECOGNIZED;
1834 : 16 : return SUCCESS;
1835 : : }
1836 : :
1837 : : /* -----------------------------------------------------------------------------
1838 : : * ARMOR PARSING
1839 : : */
1840 : :
1841 : : static gboolean
1842 : 202 : formats_for_armor_type (GQuark armor_type,
1843 : : gint *inner_format,
1844 : : gint *outer_format)
1845 : : {
1846 : : gint dummy;
1847 [ - + ]: 202 : if (!inner_format)
1848 : 0 : inner_format = &dummy;
1849 [ - + ]: 202 : if (!outer_format)
1850 : 0 : outer_format = &dummy;
1851 : :
1852 [ + + ]: 202 : if (armor_type == PEM_RSA_PRIVATE_KEY) {
1853 : 39 : *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_RSA;
1854 : 39 : *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_RSA;
1855 [ + + ]: 163 : } else if (armor_type == PEM_DSA_PRIVATE_KEY) {
1856 : 39 : *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_DSA;
1857 : 39 : *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_DSA;
1858 [ + + ]: 124 : } else if (armor_type == PEM_EC_PRIVATE_KEY) {
1859 : 1 : *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_EC;
1860 : 1 : *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_EC;
1861 [ - + ]: 123 : } else if (armor_type == PEM_ANY_PRIVATE_KEY) {
1862 : 0 : *inner_format = GCR_FORMAT_DER_PRIVATE_KEY;
1863 : 0 : *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY;
1864 [ - + ]: 123 : } else if (armor_type == PEM_PRIVATE_KEY) {
1865 : 0 : *inner_format = GCR_FORMAT_DER_PKCS8_PLAIN;
1866 : 0 : *outer_format = GCR_FORMAT_PEM_PKCS8_PLAIN;
1867 [ + + ]: 123 : } else if (armor_type == PEM_ENCRYPTED_PRIVATE_KEY) {
1868 : 1 : *inner_format = GCR_FORMAT_DER_PKCS8_ENCRYPTED;
1869 : 1 : *outer_format = GCR_FORMAT_PEM_PKCS8_ENCRYPTED;
1870 [ + + ]: 122 : } else if (armor_type == PEM_CERTIFICATE) {
1871 : 117 : *inner_format = GCR_FORMAT_DER_CERTIFICATE_X509;
1872 : 117 : *outer_format = GCR_FORMAT_PEM_CERTIFICATE_X509;
1873 [ - + ]: 5 : } else if (armor_type == PEM_PKCS7) {
1874 : 0 : *inner_format = GCR_FORMAT_DER_PKCS7;
1875 : 0 : *outer_format = GCR_FORMAT_PEM_PKCS7;
1876 [ + + ]: 5 : } else if (armor_type == PEM_CERTIFICATE_REQUEST) {
1877 : 2 : *inner_format = GCR_FORMAT_DER_PKCS10;
1878 : 2 : *outer_format = GCR_FORMAT_PEM_PKCS10;
1879 [ + + ]: 3 : } else if (armor_type == PEM_NEW_CERTIFICATE_REQUEST) {
1880 : 1 : *inner_format = GCR_FORMAT_DER_PKCS10;
1881 : 1 : *outer_format = GCR_FORMAT_PEM_PKCS10;
1882 [ - + ]: 2 : } else if (armor_type == PEM_PKCS12) {
1883 : 0 : *inner_format = GCR_FORMAT_DER_PKCS12;
1884 : 0 : *outer_format = GCR_FORMAT_PEM_PKCS12;
1885 [ + + ]: 2 : } else if (armor_type == PEM_PUBLIC_KEY) {
1886 : 1 : *inner_format = GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY;
1887 : 1 : *outer_format = GCR_FORMAT_PEM_PUBLIC_KEY;
1888 [ - + ]: 1 : } else if (armor_type == ARMOR_PGP_PRIVATE_KEY_BLOCK) {
1889 : 0 : *inner_format = GCR_FORMAT_OPENPGP_PACKET;
1890 : 0 : *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
1891 [ + - ]: 1 : } else if (armor_type == ARMOR_PGP_PUBLIC_KEY_BLOCK) {
1892 : 1 : *inner_format = GCR_FORMAT_OPENPGP_PACKET;
1893 : 1 : *outer_format = GCR_FORMAT_OPENPGP_ARMOR;
1894 : : } else {
1895 : 0 : return FALSE;
1896 : : }
1897 : :
1898 : 202 : return TRUE;
1899 : : }
1900 : :
1901 : : static gint
1902 : 204 : handle_plain_pem (GcrParser *self,
1903 : : gint format_id,
1904 : : gint want_format,
1905 : : GBytes *data)
1906 : : {
1907 : : ParserFormat *format;
1908 : :
1909 [ + + + - ]: 204 : if (want_format != 0 && want_format != format_id)
1910 : 36 : return GCR_ERROR_UNRECOGNIZED;
1911 : :
1912 : 168 : format = parser_format_lookup (format_id);
1913 [ - + ]: 168 : if (format == NULL)
1914 : 0 : return GCR_ERROR_UNRECOGNIZED;
1915 : :
1916 : 168 : return (format->function) (self, data);
1917 : : }
1918 : :
1919 : : static gint
1920 : 1 : handle_encrypted_pem (GcrParser *self,
1921 : : gint format_id,
1922 : : gint want_format,
1923 : : GHashTable *headers,
1924 : : GBytes *data)
1925 : : {
1926 : 1 : PasswordState pstate = PASSWORD_STATE_INIT;
1927 : : const gchar *password;
1928 : : guchar *decrypted;
1929 : : gsize n_decrypted;
1930 : : const gchar *val;
1931 : : GBytes *dbytes;
1932 : : gint res;
1933 : : gint l;
1934 : :
1935 [ - + + - : 1 : g_assert (GCR_IS_PARSER (self));
+ - - + ]
1936 [ - + ]: 1 : g_assert (headers);
1937 : :
1938 : 1 : val = g_hash_table_lookup (headers, "DEK-Info");
1939 [ - + ]: 1 : if (!val) {
1940 : 0 : g_message ("missing encryption header");
1941 : 0 : return GCR_ERROR_FAILURE;
1942 : : }
1943 : :
1944 : : for (;;) {
1945 : :
1946 : 3 : res = enum_next_password (self, &pstate, &password);
1947 [ - + ]: 3 : if (res != SUCCESS)
1948 : 0 : break;
1949 : :
1950 : : /* Decrypt, this will result in garble if invalid password */
1951 : 3 : decrypted = egg_openssl_decrypt_block (val, password, -1, data, &n_decrypted);
1952 [ - + ]: 3 : if (!decrypted) {
1953 : 0 : res = GCR_ERROR_FAILURE;
1954 : 0 : break;
1955 : : }
1956 : :
1957 : : /* Unpad the DER data */
1958 : 3 : l = egg_asn1x_element_length (decrypted, n_decrypted);
1959 [ + + ]: 3 : if (l > 0)
1960 : 1 : n_decrypted = l;
1961 : :
1962 : 3 : dbytes = g_bytes_new_with_free_func (decrypted, n_decrypted,
1963 : : egg_secure_free, decrypted);
1964 : 3 : decrypted = NULL;
1965 : :
1966 : : /* Try to parse */
1967 : 3 : res = handle_plain_pem (self, format_id, want_format, dbytes);
1968 : 3 : g_bytes_unref (dbytes);
1969 : :
1970 : : /* Unrecognized is a bad password */
1971 [ + + ]: 3 : if (res != GCR_ERROR_UNRECOGNIZED)
1972 : 1 : break;
1973 : : }
1974 : :
1975 : 1 : return res;
1976 : : }
1977 : :
1978 : : typedef struct {
1979 : : GcrParser *parser;
1980 : : gint result;
1981 : : gint want_format;
1982 : : } HandlePemArgs;
1983 : :
1984 : : static void
1985 : 202 : handle_pem_data (GQuark type,
1986 : : GBytes *data,
1987 : : GBytes *outer,
1988 : : GHashTable *headers,
1989 : : gpointer user_data)
1990 : : {
1991 : 202 : HandlePemArgs *args = (HandlePemArgs*)user_data;
1992 : 202 : gint res = GCR_ERROR_FAILURE;
1993 : 202 : gboolean encrypted = FALSE;
1994 : : const gchar *val;
1995 : : gint inner_format;
1996 : : gint outer_format;
1997 : : GcrParsed *parsed;
1998 : :
1999 : : /* Something already failed to parse */
2000 [ - + ]: 202 : if (args->result == GCR_ERROR_FAILURE)
2001 : 0 : return;
2002 : :
2003 [ - + ]: 202 : if (!formats_for_armor_type (type, &inner_format, &outer_format))
2004 : 0 : return;
2005 : :
2006 : 202 : parsed = push_parsed (args->parser, FALSE);
2007 : :
2008 : : /* Fill in information necessary for prompting */
2009 : 202 : parsing_block (parsed, outer_format, outer);
2010 : :
2011 : : /* See if it's encrypted PEM all openssl like*/
2012 [ + + ]: 202 : if (headers) {
2013 : 2 : val = g_hash_table_lookup (headers, "Proc-Type");
2014 [ + + + - ]: 2 : if (val && strcmp (val, "4,ENCRYPTED") == 0)
2015 : 1 : encrypted = TRUE;
2016 : : }
2017 : :
2018 [ + + ]: 202 : if (encrypted)
2019 : 1 : res = handle_encrypted_pem (args->parser, inner_format,
2020 : : args->want_format, headers,
2021 : : data);
2022 : : else
2023 : 201 : res = handle_plain_pem (args->parser, inner_format,
2024 : : args->want_format, data);
2025 : :
2026 : 202 : pop_parsed (args->parser, parsed);
2027 : :
2028 [ + + ]: 202 : if (res != GCR_ERROR_UNRECOGNIZED) {
2029 [ + + ]: 166 : if (args->result == GCR_ERROR_UNRECOGNIZED)
2030 : 67 : args->result = res;
2031 [ - + ]: 99 : else if (res > args->result)
2032 : 0 : args->result = res;
2033 : : }
2034 : : }
2035 : :
2036 : : static gint
2037 : 152 : handle_pem_format (GcrParser *self,
2038 : : gint subformat,
2039 : : GBytes *data)
2040 : : {
2041 : 152 : HandlePemArgs ctx = { self, GCR_ERROR_UNRECOGNIZED, subformat };
2042 : : guint found;
2043 : :
2044 [ - + ]: 152 : if (g_bytes_get_size (data) == 0)
2045 : 0 : return GCR_ERROR_UNRECOGNIZED;
2046 : :
2047 : 152 : found = egg_armor_parse (data, handle_pem_data, &ctx);
2048 : :
2049 [ + + ]: 152 : if (found == 0)
2050 : 49 : return GCR_ERROR_UNRECOGNIZED;
2051 : :
2052 : 103 : return ctx.result;
2053 : : }
2054 : :
2055 : :
2056 : : static gint
2057 : 112 : parse_pem (GcrParser *self,
2058 : : GBytes *data)
2059 : : {
2060 : 112 : return handle_pem_format (self, 0, data);
2061 : : }
2062 : :
2063 : : static gint
2064 : 0 : parse_pem_private_key_rsa (GcrParser *self,
2065 : : GBytes *data)
2066 : : {
2067 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_RSA, data);
2068 : : }
2069 : :
2070 : : static gint
2071 : 0 : parse_pem_private_key_dsa (GcrParser *self,
2072 : : GBytes *data)
2073 : : {
2074 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_DSA, data);
2075 : : }
2076 : :
2077 : : static gint
2078 : 0 : parse_pem_private_key_ec (GcrParser *self,
2079 : : GBytes *data)
2080 : : {
2081 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
2082 : : }
2083 : :
2084 : : static gint
2085 : 0 : parse_pem_public_key (GcrParser *self,
2086 : : GBytes *data)
2087 : : {
2088 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, data);
2089 : : }
2090 : :
2091 : : static gint
2092 : 0 : parse_pem_certificate (GcrParser *self,
2093 : : GBytes *data)
2094 : : {
2095 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_CERTIFICATE_X509, data);
2096 : : }
2097 : :
2098 : : static gint
2099 : 0 : parse_pem_pkcs8_plain (GcrParser *self,
2100 : : GBytes *data)
2101 : : {
2102 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_PLAIN, data);
2103 : : }
2104 : :
2105 : : static gint
2106 : 0 : parse_pem_pkcs8_encrypted (GcrParser *self,
2107 : : GBytes *data)
2108 : : {
2109 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PKCS8_ENCRYPTED, data);
2110 : : }
2111 : :
2112 : : static gint
2113 : 0 : parse_pem_pkcs7 (GcrParser *self,
2114 : : GBytes *data)
2115 : : {
2116 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PKCS7, data);
2117 : : }
2118 : :
2119 : : static gint
2120 : 0 : parse_pem_pkcs10 (GcrParser *self,
2121 : : GBytes *data)
2122 : : {
2123 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PKCS10, data);
2124 : : }
2125 : :
2126 : : static gint
2127 : 0 : parse_pem_pkcs12 (GcrParser *self,
2128 : : GBytes *data)
2129 : : {
2130 : 0 : return handle_pem_format (self, GCR_FORMAT_DER_PKCS12, data);
2131 : : }
2132 : :
2133 : : static gint
2134 : 40 : parse_openpgp_armor (GcrParser *self,
2135 : : GBytes *data)
2136 : : {
2137 : 40 : return handle_pem_format (self, GCR_FORMAT_OPENPGP_PACKET, data);
2138 : : }
2139 : :
2140 : : /* -----------------------------------------------------------------------------
2141 : : * OPENSSH
2142 : : */
2143 : :
2144 : : static void
2145 : 4 : on_openssh_public_key_parsed (GckAttributes *attrs,
2146 : : const gchar *label,
2147 : : const gchar *options,
2148 : : GBytes *outer,
2149 : : gpointer user_data)
2150 : : {
2151 : 4 : GcrParser *self = GCR_PARSER (user_data);
2152 : : GcrParsed *parsed;
2153 : :
2154 : 4 : parsed = push_parsed (self, FALSE);
2155 : 4 : parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer);
2156 : 4 : parsed_attributes (parsed, attrs);
2157 : 4 : parsed_label (parsed, label);
2158 : 4 : parsed_fire (self, parsed);
2159 : 4 : pop_parsed (self, parsed);
2160 : 4 : }
2161 : :
2162 : : static gint
2163 : 45 : parse_openssh_public (GcrParser *self,
2164 : : GBytes *data)
2165 : : {
2166 : : guint num_parsed;
2167 : :
2168 : 45 : num_parsed = _gcr_openssh_pub_parse (data, on_openssh_public_key_parsed, self);
2169 : :
2170 [ + + ]: 45 : if (num_parsed == 0)
2171 : 42 : return GCR_ERROR_UNRECOGNIZED;
2172 : 3 : return SUCCESS;
2173 : : }
2174 : :
2175 : : /* -----------------------------------------------------------------------------
2176 : : * FORMATS
2177 : : */
2178 : :
2179 : : /**
2180 : : * GcrDataFormat:
2181 : : * @GCR_FORMAT_ALL: Represents all the formats, when enabling or disabling
2182 : : * @GCR_FORMAT_INVALID: Not a valid format
2183 : : * @GCR_FORMAT_DER_PRIVATE_KEY: DER encoded private key
2184 : : * @GCR_FORMAT_DER_PRIVATE_KEY_RSA: DER encoded RSA private key
2185 : : * @GCR_FORMAT_DER_PRIVATE_KEY_DSA: DER encoded DSA private key
2186 : : * @GCR_FORMAT_DER_PRIVATE_KEY_EC: DER encoded EC private key
2187 : : * @GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY: DER encoded SubjectPublicKeyInfo
2188 : : * @GCR_FORMAT_DER_CERTIFICATE_X509: DER encoded X.509 certificate
2189 : : * @GCR_FORMAT_DER_PKCS7: DER encoded PKCS#7 container file which can contain certificates
2190 : : * @GCR_FORMAT_DER_PKCS8: DER encoded PKCS#8 file which can contain a key
2191 : : * @GCR_FORMAT_DER_PKCS8_PLAIN: Unencrypted DER encoded PKCS#8 file which can contain a key
2192 : : * @GCR_FORMAT_DER_PKCS8_ENCRYPTED: Encrypted DER encoded PKCS#8 file which can contain a key
2193 : : * @GCR_FORMAT_DER_PKCS10: DER encoded PKCS#10 certificate request file
2194 : : * @GCR_FORMAT_DER_PKCS12: DER encoded PKCS#12 file which can contain certificates and/or keys
2195 : : * @GCR_FORMAT_OPENSSH_PUBLIC: OpenSSH v1 or v2 public key
2196 : : * @GCR_FORMAT_OPENPGP_PACKET: OpenPGP key packet(s)
2197 : : * @GCR_FORMAT_OPENPGP_ARMOR: OpenPGP public or private key armor encoded data
2198 : : * @GCR_FORMAT_PEM: An OpenSSL style PEM file with unspecified contents
2199 : : * @GCR_FORMAT_PEM_PRIVATE_KEY: An OpenSSL style PEM file with a private key
2200 : : * @GCR_FORMAT_PEM_PRIVATE_KEY_RSA: An OpenSSL style PEM file with a private RSA key
2201 : : * @GCR_FORMAT_PEM_PRIVATE_KEY_DSA: An OpenSSL style PEM file with a private DSA key
2202 : : * @GCR_FORMAT_PEM_PRIVATE_KEY_EC: An OpenSSL style PEM file with a private EC key
2203 : : * @GCR_FORMAT_PEM_CERTIFICATE_X509: An OpenSSL style PEM file with an X.509 certificate
2204 : : * @GCR_FORMAT_PEM_PKCS7: An OpenSSL style PEM file containing PKCS#7
2205 : : * @GCR_FORMAT_PEM_PKCS8_PLAIN: Unencrypted OpenSSL style PEM file containing PKCS#8
2206 : : * @GCR_FORMAT_PEM_PKCS8_ENCRYPTED: Encrypted OpenSSL style PEM file containing PKCS#8
2207 : : * @GCR_FORMAT_PEM_PKCS10: An OpenSSL style PEM file containing PKCS#10
2208 : : * @GCR_FORMAT_PEM_PKCS12: An OpenSSL style PEM file containing PKCS#12
2209 : : * @GCR_FORMAT_PEM_PUBLIC_KEY: An OpenSSL style PEM file containing a SubjectPublicKeyInfo
2210 : : * @GCR_FORMAT_DER_SPKAC: DER encoded SPKAC as generated by HTML5 keygen element
2211 : : * @GCR_FORMAT_BASE64_SPKAC: OpenSSL style SPKAC data
2212 : : *
2213 : : * The various format identifiers.
2214 : : */
2215 : :
2216 : : /*
2217 : : * In order of parsing when no formats specified. We put formats earlier
2218 : : * if the parser can quickly detect whether GCR_ERROR_UNRECOGNIZED or not
2219 : : */
2220 : :
2221 : : static const ParserFormat parser_normal[] = {
2222 : : { GCR_FORMAT_PEM, parse_pem },
2223 : : { GCR_FORMAT_BASE64_SPKAC, parse_base64_spkac },
2224 : : { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
2225 : : { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
2226 : : { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
2227 : : { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
2228 : : { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
2229 : : { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
2230 : : { GCR_FORMAT_DER_PKCS8_PLAIN, parse_der_pkcs8_plain },
2231 : : { GCR_FORMAT_DER_PKCS8_ENCRYPTED, parse_der_pkcs8_encrypted },
2232 : : { GCR_FORMAT_DER_PKCS12, parse_der_pkcs12 },
2233 : : { GCR_FORMAT_OPENSSH_PUBLIC, parse_openssh_public },
2234 : : { GCR_FORMAT_OPENPGP_PACKET, parse_openpgp_packets },
2235 : : { GCR_FORMAT_OPENPGP_ARMOR, parse_openpgp_armor },
2236 : : { GCR_FORMAT_DER_PKCS10, parse_der_pkcs10 },
2237 : : { GCR_FORMAT_DER_SPKAC, parse_der_spkac },
2238 : : };
2239 : :
2240 : : /* Must be in format_id numeric order */
2241 : : static const ParserFormat parser_formats[] = {
2242 : : { GCR_FORMAT_DER_PRIVATE_KEY, parse_der_private_key },
2243 : : { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
2244 : : { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
2245 : : { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
2246 : : { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
2247 : : { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
2248 : : { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
2249 : : { GCR_FORMAT_DER_PKCS8, parse_der_pkcs8 },
2250 : : { GCR_FORMAT_DER_PKCS8_PLAIN, parse_der_pkcs8_plain },
2251 : : { GCR_FORMAT_DER_PKCS8_ENCRYPTED, parse_der_pkcs8_encrypted },
2252 : : { GCR_FORMAT_DER_PKCS10, parse_der_pkcs10 },
2253 : : { GCR_FORMAT_DER_SPKAC, parse_der_spkac },
2254 : : { GCR_FORMAT_BASE64_SPKAC, parse_base64_spkac },
2255 : : { GCR_FORMAT_DER_PKCS12, parse_der_pkcs12 },
2256 : : { GCR_FORMAT_OPENSSH_PUBLIC, parse_openssh_public },
2257 : : { GCR_FORMAT_OPENPGP_PACKET, parse_openpgp_packets },
2258 : : { GCR_FORMAT_OPENPGP_ARMOR, parse_openpgp_armor },
2259 : : { GCR_FORMAT_PEM, parse_pem },
2260 : : { GCR_FORMAT_PEM_PRIVATE_KEY_RSA, parse_pem_private_key_rsa },
2261 : : { GCR_FORMAT_PEM_PRIVATE_KEY_DSA, parse_pem_private_key_dsa },
2262 : : { GCR_FORMAT_PEM_CERTIFICATE_X509, parse_pem_certificate },
2263 : : { GCR_FORMAT_PEM_PKCS7, parse_pem_pkcs7 },
2264 : : { GCR_FORMAT_PEM_PKCS8_PLAIN, parse_pem_pkcs8_plain },
2265 : : { GCR_FORMAT_PEM_PKCS8_ENCRYPTED, parse_pem_pkcs8_encrypted },
2266 : : { GCR_FORMAT_PEM_PKCS12, parse_pem_pkcs12 },
2267 : : { GCR_FORMAT_PEM_PKCS10, parse_pem_pkcs10 },
2268 : : { GCR_FORMAT_PEM_PRIVATE_KEY_EC, parse_pem_private_key_ec },
2269 : : { GCR_FORMAT_PEM_PUBLIC_KEY, parse_pem_public_key },
2270 : : };
2271 : :
2272 : : static int
2273 : 1943 : compar_id_to_parser_format (const void *a, const void *b)
2274 : : {
2275 : 1943 : const gint *format_id = a;
2276 : 1943 : const ParserFormat *format = b;
2277 : :
2278 [ - + ]: 1943 : g_assert (format_id);
2279 [ - + ]: 1943 : g_assert (format);
2280 : :
2281 [ + + ]: 1943 : if (format->format_id == *format_id)
2282 : 462 : return 0;
2283 [ + + ]: 1481 : return (*format_id < format->format_id) ? -1 : 1;
2284 : : }
2285 : :
2286 : : static ParserFormat*
2287 : 462 : parser_format_lookup (gint format_id)
2288 : : {
2289 : 462 : return bsearch (&format_id, parser_formats, G_N_ELEMENTS (parser_formats),
2290 : : sizeof (parser_formats[0]), compar_id_to_parser_format);
2291 : : }
2292 : :
2293 : : static gint
2294 : 5886 : compare_pointers (gconstpointer a, gconstpointer b)
2295 : : {
2296 [ - + ]: 5886 : if (a == b)
2297 : 0 : return 0;
2298 [ - + ]: 5886 : return a < b ? -1 : 1;
2299 : : }
2300 : :
2301 : : typedef struct _ForeachArgs {
2302 : : GcrParser *parser;
2303 : : GBytes *data;
2304 : : gint result;
2305 : : } ForeachArgs;
2306 : :
2307 : : static gboolean
2308 : 1382 : parser_format_foreach (gpointer key, gpointer value, gpointer data)
2309 : : {
2310 : 1382 : ForeachArgs *args = data;
2311 : 1382 : ParserFormat *format = key;
2312 : : gint result;
2313 : :
2314 [ - + ]: 1382 : g_assert (format);
2315 [ - + ]: 1382 : g_assert (format->function);
2316 [ - + + - : 1382 : g_assert (GCR_IS_PARSER (args->parser));
+ - - + ]
2317 : :
2318 : 1382 : result = (format->function) (args->parser, args->data);
2319 [ + + ]: 1382 : if (result != GCR_ERROR_UNRECOGNIZED) {
2320 : 424 : args->result = result;
2321 : 424 : return TRUE;
2322 : : }
2323 : :
2324 : : /* Keep going */
2325 : 958 : return FALSE;
2326 : : }
2327 : :
2328 : : /* -----------------------------------------------------------------------------
2329 : : * OBJECT
2330 : : */
2331 : :
2332 : :
2333 : : static GObject*
2334 : 426 : gcr_parser_constructor (GType type, guint n_props, GObjectConstructParam *props)
2335 : : {
2336 : 426 : GcrParser *self = GCR_PARSER (G_OBJECT_CLASS (gcr_parser_parent_class)->constructor(type, n_props, props));
2337 [ - + ]: 426 : g_return_val_if_fail (self, NULL);
2338 : :
2339 : : /* Always try to parse with NULL and empty passwords first */
2340 : 426 : gcr_parser_add_password (self, NULL);
2341 : 426 : gcr_parser_add_password (self, "");
2342 : :
2343 : 426 : return G_OBJECT (self);
2344 : : }
2345 : :
2346 : : static void
2347 : 426 : gcr_parser_init (GcrParser *self)
2348 : : {
2349 : 426 : self->pv = gcr_parser_get_instance_private (self);
2350 : 426 : self->pv->passwords = g_ptr_array_new ();
2351 : 426 : self->pv->normal_formats = TRUE;
2352 : 426 : }
2353 : :
2354 : : static void
2355 : 426 : gcr_parser_dispose (GObject *obj)
2356 : : {
2357 : 426 : GcrParser *self = GCR_PARSER (obj);
2358 : : gsize i;
2359 : :
2360 [ - + ]: 426 : g_assert (!self->pv->parsed);
2361 : :
2362 [ + + ]: 426 : if (self->pv->specific_formats)
2363 : 348 : g_tree_destroy (self->pv->specific_formats);
2364 : 426 : self->pv->specific_formats = NULL;
2365 : :
2366 [ + + ]: 1292 : for (i = 0; i < self->pv->passwords->len; ++i)
2367 : 866 : egg_secure_strfree (g_ptr_array_index (self->pv->passwords, i));
2368 : 426 : g_ptr_array_set_size (self->pv->passwords, 0);
2369 : :
2370 : 426 : G_OBJECT_CLASS (gcr_parser_parent_class)->dispose (obj);
2371 : 426 : }
2372 : :
2373 : : static void
2374 : 426 : gcr_parser_finalize (GObject *obj)
2375 : : {
2376 : 426 : GcrParser *self = GCR_PARSER (obj);
2377 : :
2378 [ - + ]: 426 : g_assert (!self->pv->parsed);
2379 : :
2380 : 426 : g_ptr_array_free (self->pv->passwords, TRUE);
2381 : 426 : self->pv->passwords = NULL;
2382 : :
2383 : 426 : g_free (self->pv->filename);
2384 : 426 : self->pv->filename = NULL;
2385 : :
2386 : 426 : G_OBJECT_CLASS (gcr_parser_parent_class)->finalize (obj);
2387 : 426 : }
2388 : :
2389 : : static void
2390 : 0 : gcr_parser_set_property (GObject *obj, guint prop_id, const GValue *value,
2391 : : GParamSpec *pspec)
2392 : : {
2393 : : switch (prop_id) {
2394 : : default:
2395 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
2396 : 0 : break;
2397 : : }
2398 : 0 : }
2399 : :
2400 : : static void
2401 : 0 : gcr_parser_get_property (GObject *obj, guint prop_id, GValue *value,
2402 : : GParamSpec *pspec)
2403 : : {
2404 : 0 : GcrParser *self = GCR_PARSER (obj);
2405 : :
2406 [ # # # # ]: 0 : switch (prop_id) {
2407 : 0 : case PROP_PARSED_ATTRIBUTES:
2408 : 0 : g_value_set_boxed (value, gcr_parser_get_parsed_attributes (self));
2409 : 0 : break;
2410 : 0 : case PROP_PARSED_LABEL:
2411 : 0 : g_value_set_string (value, gcr_parser_get_parsed_label (self));
2412 : 0 : break;
2413 : 0 : case PROP_PARSED_DESCRIPTION:
2414 : 0 : g_value_set_string (value, gcr_parser_get_parsed_description (self));
2415 : 0 : break;
2416 : 0 : default:
2417 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
2418 : 0 : break;
2419 : : }
2420 : 0 : }
2421 : :
2422 : : static void
2423 : 3 : gcr_parser_class_init (GcrParserClass *klass)
2424 : : {
2425 : 3 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
2426 : : gint i;
2427 : :
2428 : 3 : gobject_class->constructor = gcr_parser_constructor;
2429 : 3 : gobject_class->dispose = gcr_parser_dispose;
2430 : 3 : gobject_class->finalize = gcr_parser_finalize;
2431 : 3 : gobject_class->set_property = gcr_parser_set_property;
2432 : 3 : gobject_class->get_property = gcr_parser_get_property;
2433 : :
2434 : : /**
2435 : : * GcrParser:parsed-attributes:
2436 : : *
2437 : : * Get the attributes that make up the currently parsed item. This is
2438 : : * generally only valid during a [signal@Parser::parsed] signal.
2439 : : */
2440 : 3 : g_object_class_install_property (gobject_class, PROP_PARSED_ATTRIBUTES,
2441 : : g_param_spec_boxed ("parsed-attributes", "Parsed Attributes", "Parsed PKCS#11 attributes",
2442 : : GCK_TYPE_ATTRIBUTES,
2443 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2444 : :
2445 : : /**
2446 : : * GcrParser:parsed-label:
2447 : : *
2448 : : * The label of the currently parsed item. This is generally
2449 : : * only valid during a [signal@Parser::parsed] signal.
2450 : : */
2451 : 3 : g_object_class_install_property (gobject_class, PROP_PARSED_LABEL,
2452 : : g_param_spec_string ("parsed-label", "Parsed Label", "Parsed item label",
2453 : : "",
2454 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2455 : :
2456 : : /**
2457 : : * GcrParser:parsed-description:
2458 : : *
2459 : : * The description of the type of the currently parsed item. This is generally
2460 : : * only valid during a [signal@Parser::parsed] signal.
2461 : : */
2462 : 3 : g_object_class_install_property (gobject_class, PROP_PARSED_DESCRIPTION,
2463 : : g_param_spec_string ("parsed-description", "Parsed Description", "Parsed item description",
2464 : : "",
2465 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
2466 : :
2467 : : /**
2468 : : * GcrParser::authenticate:
2469 : : * @self: the parser
2470 : : * @count: the number of times this item has been authenticated
2471 : : *
2472 : : * This signal is emitted when an item needs to be unlocked or decrypted before
2473 : : * it can be parsed. The @count argument specifies the number of times
2474 : : * the signal has been emitted for a given item. This can be used to
2475 : : * display a message saying the previous password was incorrect.
2476 : : *
2477 : : * Typically the gcr_parser_add_password() function is called in
2478 : : * response to this signal.
2479 : : *
2480 : : * If %FALSE is returned, then the authentication was not handled. If
2481 : : * no handlers return %TRUE then the item is not parsed and an error
2482 : : * with the code %GCR_ERROR_CANCELLED will be raised.
2483 : : *
2484 : : * Returns: Whether the authentication was handled.
2485 : : */
2486 : 3 : signals[AUTHENTICATE] = g_signal_new ("authenticate", GCR_TYPE_PARSER,
2487 : : G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrParserClass, authenticate),
2488 : : g_signal_accumulator_true_handled, NULL, _gcr_marshal_BOOLEAN__INT,
2489 : : G_TYPE_BOOLEAN, 1, G_TYPE_INT);
2490 : :
2491 : : /**
2492 : : * GcrParser::parsed:
2493 : : * @self: the parser
2494 : : *
2495 : : * This signal is emitted when an item is sucessfully parsed. To access
2496 : : * the information about the item use the gcr_parser_get_parsed_label(),
2497 : : * gcr_parser_get_parsed_attributes() and gcr_parser_get_parsed_description()
2498 : : * functions.
2499 : : */
2500 : 3 : signals[PARSED] = g_signal_new ("parsed", GCR_TYPE_PARSER,
2501 : : G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GcrParserClass, parsed),
2502 : : NULL, NULL, NULL,
2503 : : G_TYPE_NONE, 0);
2504 : :
2505 : 3 : init_quarks ();
2506 : 3 : _gcr_initialize_library ();
2507 : :
2508 : : /* Check that the format tables are in order */
2509 [ + + ]: 84 : for (i = 1; i < G_N_ELEMENTS (parser_formats); ++i)
2510 [ - + ]: 81 : g_assert (parser_formats[i].format_id >= parser_formats[i - 1].format_id);
2511 : 3 : }
2512 : :
2513 : : /* -----------------------------------------------------------------------------
2514 : : * PUBLIC
2515 : : */
2516 : :
2517 : : /**
2518 : : * gcr_parser_new:
2519 : : *
2520 : : * Create a new #GcrParser
2521 : : *
2522 : : * Returns: (transfer full): a newly allocated #GcrParser
2523 : : */
2524 : : GcrParser *
2525 : 426 : gcr_parser_new (void)
2526 : : {
2527 : 426 : return g_object_new (GCR_TYPE_PARSER, NULL);
2528 : : }
2529 : :
2530 : : /**
2531 : : * gcr_parser_add_password:
2532 : : * @self: The parser
2533 : : * @password: (nullable): a password to try
2534 : : *
2535 : : * Add a password to the set of passwords to try when parsing locked or encrypted
2536 : : * items. This is usually called from the [signal@Parser::authenticate] signal.
2537 : : */
2538 : : void
2539 : 866 : gcr_parser_add_password (GcrParser *self, const gchar *password)
2540 : : {
2541 [ - + + - : 866 : g_return_if_fail (GCR_IS_PARSER (self));
+ - - + ]
2542 : 866 : g_ptr_array_add (self->pv->passwords, egg_secure_strdup (password));
2543 : : }
2544 : :
2545 : : /**
2546 : : * gcr_parser_parse_bytes:
2547 : : * @self: The parser
2548 : : * @data: the data to parse
2549 : : * @error: A location to raise an error on failure.
2550 : : *
2551 : : * Parse the data. The [signal@Parser::parsed] and
2552 : : * [signal@Parser::authenticate] signals may fire during the parsing.
2553 : : *
2554 : : * Returns: Whether the data was parsed successfully or not.
2555 : : */
2556 : : gboolean
2557 : 426 : gcr_parser_parse_bytes (GcrParser *self,
2558 : : GBytes *data,
2559 : : GError **error)
2560 : : {
2561 : 426 : ForeachArgs args = { self, NULL, GCR_ERROR_UNRECOGNIZED };
2562 : 426 : const gchar *message = NULL;
2563 : : gint i;
2564 : :
2565 [ - + + - : 426 : g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
+ - - + ]
2566 [ - + ]: 426 : g_return_val_if_fail (data != NULL, FALSE);
2567 [ + - - + ]: 426 : g_return_val_if_fail (!error || !*error, FALSE);
2568 : :
2569 [ + + ]: 426 : if (g_bytes_get_size (data) > 0) {
2570 : 424 : args.data = g_bytes_ref (data);
2571 : :
2572 : : /* Just the specific formats requested */
2573 [ + + ]: 424 : if (self->pv->specific_formats) {
2574 : 348 : g_tree_foreach (self->pv->specific_formats, parser_format_foreach, &args);
2575 : :
2576 : : /* All the 'normal' formats */
2577 [ + - ]: 76 : } else if (self->pv->normal_formats) {
2578 [ + - ]: 422 : for (i = 0; i < G_N_ELEMENTS (parser_normal); ++i) {
2579 [ + + ]: 422 : if (parser_format_foreach ((gpointer)(parser_normal + i),
2580 : 422 : (gpointer)(parser_normal + i), &args))
2581 : 76 : break;
2582 : : }
2583 : : }
2584 : :
2585 : 424 : g_bytes_unref (args.data);
2586 : : }
2587 : :
2588 [ + - + - : 426 : switch (args.result) {
- - ]
2589 : 424 : case SUCCESS:
2590 : 424 : return TRUE;
2591 : 0 : case GCR_ERROR_CANCELLED:
2592 : 0 : message = _("The operation was cancelled");
2593 : 0 : break;
2594 : 2 : case GCR_ERROR_UNRECOGNIZED:
2595 : 2 : message = _("Unrecognized or unsupported data.");
2596 : 2 : break;
2597 : 0 : case GCR_ERROR_FAILURE:
2598 : 0 : message = _("Could not parse invalid or corrupted data.");
2599 : 0 : break;
2600 : 0 : case GCR_ERROR_LOCKED:
2601 : 0 : message = _("The data is locked");
2602 : 0 : break;
2603 : 0 : default:
2604 : 0 : g_assert_not_reached ();
2605 : : break;
2606 : : };
2607 : :
2608 : 2 : g_set_error_literal (error, GCR_DATA_ERROR, args.result, message);
2609 : 2 : return FALSE;
2610 : : }
2611 : :
2612 : : /**
2613 : : * gcr_parser_parse_data:
2614 : : * @self: The parser
2615 : : * @data: (array length=n_data): the data to parse
2616 : : * @n_data: The length of the data
2617 : : * @error: A location to raise an error on failure.
2618 : : *
2619 : : * Parse the data. The [signal@Parser::parsed] and [signal@Parser::authenticate]
2620 : : * signals may fire during the parsing.
2621 : : *
2622 : : * A copy of the data will be made. Use [method@Parser.parse_bytes] to avoid
2623 : : * this.
2624 : : *
2625 : : * Returns: Whether the data was parsed successfully or not.
2626 : : */
2627 : : gboolean
2628 : 2 : gcr_parser_parse_data (GcrParser *self,
2629 : : const guchar *data,
2630 : : gsize n_data,
2631 : : GError **error)
2632 : : {
2633 : : GBytes *bytes;
2634 : : gboolean ret;
2635 : :
2636 [ - + + - : 2 : g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
+ - - + ]
2637 [ + + - + ]: 2 : g_return_val_if_fail (data || !n_data, FALSE);
2638 [ + - - + ]: 2 : g_return_val_if_fail (!error || !*error, FALSE);
2639 : :
2640 : 2 : bytes = g_bytes_new (data, n_data);
2641 : 2 : ret = gcr_parser_parse_bytes (self, bytes, error);
2642 : 2 : g_bytes_unref (bytes);
2643 : :
2644 : 2 : return ret;
2645 : : }
2646 : :
2647 : : /**
2648 : : * gcr_parser_format_enable:
2649 : : * @self: The parser
2650 : : * @format: The format identifier
2651 : : *
2652 : : * Enable parsing of the given format. Use %GCR_FORMAT_ALL to enable all the formats.
2653 : : */
2654 : : void
2655 : 348 : gcr_parser_format_enable (GcrParser *self,
2656 : : GcrDataFormat format)
2657 : : {
2658 : : const ParserFormat *form;
2659 : : guint i;
2660 : :
2661 [ - + + - : 348 : g_return_if_fail (GCR_IS_PARSER (self));
+ - - + ]
2662 : :
2663 [ + - ]: 348 : if (!self->pv->specific_formats)
2664 : 348 : self->pv->specific_formats = g_tree_new (compare_pointers);
2665 : :
2666 [ + + ]: 348 : if (format != -1) {
2667 : 294 : form = parser_format_lookup (format);
2668 [ - + ]: 294 : g_return_if_fail (form);
2669 : 294 : g_tree_insert (self->pv->specific_formats,
2670 : : (gpointer)form, (gpointer)form);
2671 : : } else {
2672 [ + + ]: 1566 : for (i = 0; i < G_N_ELEMENTS (parser_formats); i++) {
2673 : 1512 : form = &parser_formats[i];
2674 : 1512 : g_tree_insert (self->pv->specific_formats, (gpointer)form,
2675 : : (gpointer)form);
2676 : : }
2677 : : }
2678 : : }
2679 : :
2680 : : /**
2681 : : * gcr_parser_format_disable:
2682 : : * @self: The parser
2683 : : * @format: The format identifier
2684 : : *
2685 : : * Disable parsing of the given format. Use %GCR_FORMAT_ALL to disable all the formats.
2686 : : */
2687 : : void
2688 : 348 : gcr_parser_format_disable (GcrParser *self,
2689 : : GcrDataFormat format)
2690 : : {
2691 : : ParserFormat *form;
2692 : :
2693 [ - + + - : 348 : g_return_if_fail (GCR_IS_PARSER (self));
+ - - + ]
2694 : :
2695 [ + - ]: 348 : if (format == -1) {
2696 [ - + ]: 348 : if (self->pv->specific_formats)
2697 : 0 : g_tree_destroy (self->pv->specific_formats);
2698 : 348 : self->pv->specific_formats = NULL;
2699 : 348 : self->pv->normal_formats = FALSE;
2700 : : }
2701 : :
2702 [ + - ]: 348 : if (!self->pv->specific_formats)
2703 : 348 : return;
2704 : :
2705 : 0 : form = parser_format_lookup (format);
2706 [ # # ]: 0 : g_return_if_fail (form);
2707 : :
2708 : 0 : g_tree_remove (self->pv->specific_formats, form);
2709 : : }
2710 : :
2711 : : /**
2712 : : * gcr_parser_format_supported:
2713 : : * @self: The parser
2714 : : * @format: The format identifier
2715 : : *
2716 : : * Check whether the given format is supported by the parser.
2717 : : *
2718 : : * Returns: Whether the format is supported.
2719 : : */
2720 : : gboolean
2721 : 0 : gcr_parser_format_supported (GcrParser *self,
2722 : : GcrDataFormat format)
2723 : : {
2724 [ # # # # : 0 : g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
# # # # ]
2725 [ # # ]: 0 : g_return_val_if_fail (format != GCR_FORMAT_ALL, FALSE);
2726 [ # # ]: 0 : g_return_val_if_fail (format != GCR_FORMAT_INVALID, FALSE);
2727 : 0 : return parser_format_lookup (format) ? TRUE : FALSE;
2728 : : }
2729 : :
2730 : : /**
2731 : : * gcr_parser_get_parsed:
2732 : : * @self: a parser
2733 : : *
2734 : : * Get the currently parsed item
2735 : : *
2736 : : * Returns: (transfer none): the currently parsed item
2737 : : */
2738 : : GcrParsed *
2739 : 3 : gcr_parser_get_parsed (GcrParser *self)
2740 : : {
2741 [ - + + - : 3 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2742 : 3 : return self->pv->parsed;
2743 : : }
2744 : :
2745 [ # # # # : 0 : G_DEFINE_BOXED_TYPE (GcrParsed, gcr_parsed, gcr_parsed_ref, gcr_parsed_unref)
# # ]
2746 : :
2747 : : /**
2748 : : * gcr_parser_get_filename:
2749 : : * @self: a parser item
2750 : : *
2751 : : * Get the filename of the parser item.
2752 : : *
2753 : : * Returns: the filename set on the parser, or %NULL
2754 : : */
2755 : : const gchar *
2756 : 1467 : gcr_parser_get_filename (GcrParser *self)
2757 : : {
2758 [ - + + - : 1467 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2759 : 1467 : return self->pv->filename;
2760 : : }
2761 : :
2762 : : /**
2763 : : * gcr_parser_set_filename:
2764 : : * @self: a parser item
2765 : : * @filename: (nullable): a string of the filename of the parser item
2766 : : *
2767 : : * Sets the filename of the parser item.
2768 : : */
2769 : : void
2770 : 1 : gcr_parser_set_filename (GcrParser *self,
2771 : : const gchar *filename)
2772 : : {
2773 [ - + + - : 1 : g_return_if_fail (GCR_IS_PARSER (self));
+ - - + ]
2774 : 1 : g_free (self->pv->filename);
2775 : 1 : self->pv->filename = g_strdup (filename);
2776 : : }
2777 : :
2778 : : /**
2779 : : * gcr_parsed_ref:
2780 : : * @parsed: a parsed item
2781 : : *
2782 : : * Add a reference to a parsed item. An item may not be shared across threads
2783 : : * until it has been referenced at least once.
2784 : : *
2785 : : * Returns: (transfer full): the parsed item
2786 : : */
2787 : : GcrParsed *
2788 : 1 : gcr_parsed_ref (GcrParsed *parsed)
2789 : : {
2790 : : GcrParsed *copy;
2791 : :
2792 [ - + ]: 1 : g_return_val_if_fail (parsed != NULL, NULL);
2793 : :
2794 : : /* Already had a reference */
2795 [ - + ]: 1 : if (g_atomic_int_add (&parsed->refs, 1) >= 1)
2796 : 0 : return parsed;
2797 : :
2798 : : /* If this is the first reference, flatten the stack of parsed */
2799 : 1 : copy = g_new0 (GcrParsed, 1);
2800 : 1 : copy->refs = 1;
2801 : 1 : copy->label = g_strdup (gcr_parsed_get_label (parsed));
2802 : 1 : copy->filename = g_strdup (gcr_parsed_get_filename (parsed));
2803 : 1 : copy->attrs = gcr_parsed_get_attributes (parsed);
2804 : 1 : copy->format = gcr_parsed_get_format (parsed);
2805 [ + - ]: 1 : if (copy->attrs)
2806 : 1 : gck_attributes_ref (copy->attrs);
2807 : 1 : copy->description = gcr_parsed_get_description (parsed);
2808 : 1 : copy->next = NULL;
2809 : :
2810 : : /* Find the block of data to copy */
2811 [ + - ]: 1 : while (parsed != NULL) {
2812 [ + - ]: 1 : if (parsed->data != NULL) {
2813 : 1 : copy->data = g_bytes_ref (parsed->data);
2814 : 1 : copy->sensitive = parsed->sensitive;
2815 : 1 : break;
2816 : : }
2817 : 0 : parsed = parsed->next;
2818 : : }
2819 : :
2820 : 1 : return copy;
2821 : : }
2822 : :
2823 : : /**
2824 : : * gcr_parsed_unref:
2825 : : * @parsed: a parsed item
2826 : : *
2827 : : * Unreferences a parsed item which was referenced with gcr_parsed_ref()
2828 : : */
2829 : : void
2830 : 1 : gcr_parsed_unref (gpointer parsed)
2831 : : {
2832 : 1 : GcrParsed *par = parsed;
2833 : :
2834 [ - + ]: 1 : g_return_if_fail (parsed != NULL);
2835 : :
2836 [ + - ]: 1 : if (g_atomic_int_dec_and_test (&par->refs)) {
2837 : 1 : _gcr_parsed_free (parsed);
2838 : : }
2839 : : }
2840 : :
2841 : : /**
2842 : : * gcr_parser_get_parsed_description:
2843 : : * @self: The parser
2844 : : *
2845 : : * Get a description for the type of the currently parsed item. This is generally
2846 : : * only valid during the [signal@Parser::parsed] signal.
2847 : : *
2848 : : * Returns: (nullable): the description for the current item; this is owned by
2849 : : * the parser and should not be freed
2850 : : */
2851 : : const gchar*
2852 : 186 : gcr_parser_get_parsed_description (GcrParser *self)
2853 : : {
2854 [ - + + - : 186 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2855 [ - + ]: 186 : g_return_val_if_fail (self->pv->parsed != NULL, NULL);
2856 : :
2857 : 186 : return gcr_parsed_get_description (self->pv->parsed);
2858 : : }
2859 : :
2860 : : /**
2861 : : * gcr_parsed_get_description:
2862 : : * @parsed: a parsed item
2863 : : *
2864 : : * Get the descirption for a parsed item.
2865 : : *
2866 : : * Returns: (nullable): the description
2867 : : */
2868 : : const gchar*
2869 : 187 : gcr_parsed_get_description (GcrParsed *parsed)
2870 : : {
2871 [ + - ]: 187 : while (parsed != NULL) {
2872 [ + - ]: 187 : if (parsed->description != NULL)
2873 : 187 : return parsed->description;
2874 : 0 : parsed = parsed->next;
2875 : : }
2876 : :
2877 : 0 : return NULL;
2878 : : }
2879 : :
2880 : : /**
2881 : : * gcr_parser_get_parsed_attributes:
2882 : : * @self: The parser
2883 : : *
2884 : : * Get the attributes which make up the currently parsed item. This is generally
2885 : : * only valid during the [signal@Parser::parsed] signal.
2886 : : *
2887 : : * Returns: (transfer none) (nullable): the attributes for the current item,
2888 : : * which are owned by the parser and should not be freed
2889 : : */
2890 : : GckAttributes *
2891 : 350 : gcr_parser_get_parsed_attributes (GcrParser *self)
2892 : : {
2893 [ - + + - : 350 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2894 [ - + ]: 350 : g_return_val_if_fail (self->pv->parsed != NULL, NULL);
2895 : :
2896 : 350 : return gcr_parsed_get_attributes (self->pv->parsed);
2897 : : }
2898 : :
2899 : : /**
2900 : : * gcr_parsed_get_attributes:
2901 : : * @parsed: a parsed item
2902 : : *
2903 : : * Get the attributes which make up the parsed item.
2904 : : *
2905 : : * Returns: (transfer none) (nullable): the attributes for the item; these
2906 : : * are owned by the parsed item and should not be freed
2907 : : */
2908 : : GckAttributes *
2909 : 351 : gcr_parsed_get_attributes (GcrParsed *parsed)
2910 : : {
2911 [ + - ]: 351 : while (parsed != NULL) {
2912 [ + - ]: 351 : if (parsed->attrs != NULL)
2913 : 351 : return parsed->attrs;
2914 : 0 : parsed = parsed->next;
2915 : : }
2916 : :
2917 : 0 : return NULL;
2918 : : }
2919 : :
2920 : : /**
2921 : : * gcr_parser_get_parsed_label:
2922 : : * @self: The parser
2923 : : *
2924 : : * Get the label of the currently parsed item. This is generally only valid
2925 : : * during the [signal@Parser::parsed] signal.
2926 : : *
2927 : : * Returns: (nullable): the label of the currently parsed item. The value is
2928 : : * owned by the parser and should not be freed.
2929 : : */
2930 : : const gchar*
2931 : 525 : gcr_parser_get_parsed_label (GcrParser *self)
2932 : : {
2933 [ - + + - : 525 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2934 [ - + ]: 525 : g_return_val_if_fail (self->pv->parsed != NULL, NULL);
2935 : :
2936 : 525 : return gcr_parsed_get_label (self->pv->parsed);
2937 : : }
2938 : :
2939 : : /**
2940 : : * gcr_parsed_get_label:
2941 : : * @parsed: a parsed item
2942 : : *
2943 : : * Get the label for the parsed item.
2944 : : *
2945 : : * Returns: (nullable): the label for the item
2946 : : */
2947 : : const gchar*
2948 : 526 : gcr_parsed_get_label (GcrParsed *parsed)
2949 : : {
2950 [ + + ]: 1115 : while (parsed != NULL) {
2951 [ + + ]: 720 : if (parsed->label != NULL)
2952 : 131 : return parsed->label;
2953 : 589 : parsed = parsed->next;
2954 : : }
2955 : :
2956 : 395 : return NULL;
2957 : : }
2958 : :
2959 : : /**
2960 : : * gcr_parser_get_parsed_block:
2961 : : * @self: a parser
2962 : : * @n_block: a location to place the size of the block
2963 : : *
2964 : : * Get the raw data block that represents this parsed object. This is only
2965 : : * valid during the [signal@Parser::parsed] signal.
2966 : : *
2967 : : * Returns: (transfer none) (array length=n_block) (nullable): the raw data
2968 : : * block of the currently parsed item; the value is owned by the parser
2969 : : * and should not be freed
2970 : : */
2971 : : const guchar *
2972 : 2 : gcr_parser_get_parsed_block (GcrParser *self,
2973 : : gsize *n_block)
2974 : : {
2975 [ - + + - : 2 : g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ - - + ]
2976 [ - + ]: 2 : g_return_val_if_fail (n_block != NULL, NULL);
2977 [ - + ]: 2 : g_return_val_if_fail (self->pv->parsed != NULL, NULL);
2978 : :
2979 : 2 : return gcr_parsed_get_data (self->pv->parsed, n_block);
2980 : : }
2981 : :
2982 : :
2983 : : /**
2984 : : * gcr_parser_get_parsed_bytes:
2985 : : * @self: a parser
2986 : : *
2987 : : * Get the raw data block that represents this parsed object. This is only
2988 : : * valid during the [signal@Parser::parsed] signal.
2989 : : *
2990 : : * Returns: (transfer none): the raw data block of the currently parsed item
2991 : : */
2992 : : GBytes *
2993 : 188 : gcr_parser_get_parsed_bytes (GcrParser *self)
2994 : : {
2995 : 188 : return gcr_parsed_get_bytes (self->pv->parsed);
2996 : : }
2997 : :
2998 : : /**
2999 : : * gcr_parsed_get_data:
3000 : : * @parsed: a parsed item
3001 : : * @n_data: location to store size of returned data
3002 : : *
3003 : : * Get the raw data block for the parsed item.
3004 : : *
3005 : : * Returns: (transfer none) (array length=n_data) (nullable): the raw data of
3006 : : * the parsed item, or %NULL
3007 : : */
3008 : : const guchar *
3009 : 4 : gcr_parsed_get_data (GcrParsed *parsed,
3010 : : gsize *n_data)
3011 : : {
3012 : : GBytes *bytes;
3013 : :
3014 [ - + ]: 4 : g_return_val_if_fail (n_data != NULL, NULL);
3015 : :
3016 : 4 : bytes = gcr_parsed_get_bytes (parsed);
3017 [ - + ]: 4 : if (bytes == NULL) {
3018 : 0 : *n_data = 0;
3019 : 0 : return NULL;
3020 : : }
3021 : :
3022 : 4 : return g_bytes_get_data (bytes, n_data);
3023 : : }
3024 : :
3025 : : /**
3026 : : * gcr_parsed_get_bytes:
3027 : : * @parsed: a parsed item
3028 : : *
3029 : : * Get the raw data block for the parsed item.
3030 : : *
3031 : : * Returns: (transfer none): the raw data of the parsed item, or %NULL
3032 : : */
3033 : : GBytes *
3034 : 194 : gcr_parsed_get_bytes (GcrParsed *parsed)
3035 : : {
3036 [ + - ]: 195 : while (parsed != NULL) {
3037 [ + + ]: 195 : if (parsed->data != NULL)
3038 : 194 : return parsed->data;
3039 : 1 : parsed = parsed->next;
3040 : : }
3041 : :
3042 : 0 : return NULL;
3043 : : }
3044 : :
3045 : : /**
3046 : : * gcr_parser_get_parsed_format:
3047 : : * @self: a parser
3048 : : *
3049 : : * Get the format of the raw data block that represents this parsed object.
3050 : : * This corresponds with the data returned from
3051 : : * [method@Parser.get_parsed_block].
3052 : : *
3053 : : * This is only valid during the [signal@Parser::parsed] signal.
3054 : : *
3055 : : * Returns: the data format of the currently parsed item
3056 : : */
3057 : : GcrDataFormat
3058 : 186 : gcr_parser_get_parsed_format (GcrParser *self)
3059 : : {
3060 [ - + + - : 186 : g_return_val_if_fail (GCR_IS_PARSER (self), 0);
+ - - + ]
3061 [ - + ]: 186 : g_return_val_if_fail (self->pv->parsed != NULL, 0);
3062 : :
3063 : 186 : return gcr_parsed_get_format (self->pv->parsed);
3064 : : }
3065 : :
3066 : : /**
3067 : : * gcr_parsed_get_format:
3068 : : * @parsed: a parsed item
3069 : : *
3070 : : * Get the format of the parsed item.
3071 : : *
3072 : : * Returns: the data format of the item
3073 : : */
3074 : : GcrDataFormat
3075 : 187 : gcr_parsed_get_format (GcrParsed *parsed)
3076 : : {
3077 [ + - ]: 188 : while (parsed != NULL) {
3078 [ + + ]: 188 : if (parsed->data != NULL)
3079 : 187 : return parsed->format;
3080 : 1 : parsed = parsed->next;
3081 : : }
3082 : :
3083 : 0 : return 0;
3084 : : }
3085 : :
3086 : : /**
3087 : : * gcr_parsed_get_filename:
3088 : : * @parsed: a parsed item
3089 : : *
3090 : : * Get the filename of the parsed item.
3091 : : *
3092 : : * Returns: (transfer none): the filename of
3093 : : * the parsed item, or %NULL
3094 : : */
3095 : : const gchar *
3096 : 2 : gcr_parsed_get_filename (GcrParsed *parsed)
3097 : : {
3098 [ - + ]: 2 : g_return_val_if_fail (parsed != NULL, NULL);
3099 : 2 : return parsed->filename;
3100 : : }
3101 : : /* ---------------------------------------------------------------------------------
3102 : : * STREAM PARSING
3103 : : */
3104 : :
3105 : : #define GCR_TYPE_PARSING (gcr_parsing_get_type ())
3106 : : #define GCR_PARSING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCR_TYPE_PARSING, GcrParsing))
3107 : : #define GCR_IS_PARSING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCR_TYPE_PARSING))
3108 : :
3109 : : typedef struct _GcrParsing {
3110 : : GObjectClass parent;
3111 : :
3112 : : GcrParser *parser;
3113 : : gboolean async;
3114 : : GCancellable *cancel;
3115 : :
3116 : : /* Failure information */
3117 : : GError *error;
3118 : : gboolean complete;
3119 : :
3120 : : /* Operation state */
3121 : : GInputStream *input;
3122 : : GByteArray *buffer;
3123 : :
3124 : : /* Async callback stuff */
3125 : : GAsyncReadyCallback callback;
3126 : : gpointer user_data;
3127 : :
3128 : : } GcrParsing;
3129 : :
3130 : : typedef struct _GcrParsingClass {
3131 : : GObjectClass parent_class;
3132 : : } GcrParsingClass;
3133 : :
3134 : : /* State forward declarations */
3135 : : static void state_cancelled (GcrParsing *self, gboolean async);
3136 : : static void state_failure (GcrParsing *self, gboolean async);
3137 : : static void state_complete (GcrParsing *self, gboolean async);
3138 : : static void state_parse_buffer (GcrParsing *self, gboolean async);
3139 : : static void state_read_buffer (GcrParsing *self, gboolean async);
3140 : :
3141 : : /* Other forward declarations */
3142 : : static GType gcr_parsing_get_type (void) G_GNUC_CONST;
3143 : : static void gcr_parsing_async_result_init (GAsyncResultIface *iface);
3144 : :
3145 [ + + + - : 16 : G_DEFINE_TYPE_WITH_CODE (GcrParsing, gcr_parsing, G_TYPE_OBJECT,
+ + ]
3146 : : G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, gcr_parsing_async_result_init));
3147 : :
3148 : : #define BLOCK 4096
3149 : :
3150 : : static void
3151 : 4 : next_state (GcrParsing *self, void (*state) (GcrParsing*, gboolean))
3152 : : {
3153 [ - + + - : 4 : g_assert (GCR_IS_PARSING (self));
+ - - + ]
3154 [ - + ]: 4 : g_assert (state);
3155 : :
3156 [ - + - - ]: 4 : if (self->cancel && g_cancellable_is_cancelled (self->cancel))
3157 : 0 : state = state_cancelled;
3158 : :
3159 : 4 : (state) (self, self->async);
3160 : 4 : }
3161 : :
3162 : : static void
3163 : 1 : state_complete (GcrParsing *self, gboolean async)
3164 : : {
3165 [ - + + - : 1 : g_assert (GCR_IS_PARSING (self));
+ - - + ]
3166 [ - + ]: 1 : g_assert (!self->complete);
3167 : 1 : self->complete = TRUE;
3168 [ - + - - ]: 1 : if (async && self->callback != NULL)
3169 : 0 : (self->callback) (G_OBJECT (self->parser), G_ASYNC_RESULT (self), self->user_data);
3170 : 1 : }
3171 : :
3172 : : static void
3173 : 0 : state_failure (GcrParsing *self, gboolean async)
3174 : : {
3175 [ # # # # : 0 : g_assert (GCR_IS_PARSING (self));
# # # # ]
3176 [ # # ]: 0 : g_assert (self->error);
3177 : 0 : next_state (self, state_complete);
3178 : 0 : }
3179 : :
3180 : : static void
3181 : 0 : state_cancelled (GcrParsing *self, gboolean async)
3182 : : {
3183 [ # # # # : 0 : g_assert (GCR_IS_PARSING (self));
# # # # ]
3184 [ # # # # ]: 0 : if (self->cancel && g_cancellable_is_cancelled (self->cancel))
3185 : 0 : g_cancellable_cancel (self->cancel);
3186 [ # # ]: 0 : if (self->error)
3187 : 0 : g_error_free (self->error);
3188 : 0 : self->error = g_error_new_literal (GCR_DATA_ERROR, GCR_ERROR_CANCELLED, _("The operation was cancelled"));
3189 : 0 : next_state (self, state_failure);
3190 : 0 : }
3191 : :
3192 : : static void
3193 : 1 : state_parse_buffer (GcrParsing *self, gboolean async)
3194 : : {
3195 : 1 : GError *error = NULL;
3196 : : GBytes *bytes;
3197 : : gboolean ret;
3198 : :
3199 [ - + + - : 1 : g_assert (GCR_IS_PARSING (self));
+ - - + ]
3200 [ - + ]: 1 : g_assert (self->buffer);
3201 : :
3202 : 1 : bytes = g_byte_array_free_to_bytes (self->buffer);
3203 : 1 : self->buffer = NULL;
3204 : 1 : ret = gcr_parser_parse_bytes (self->parser, bytes, &error);
3205 : 1 : g_bytes_unref (bytes);
3206 : :
3207 [ + - ]: 1 : if (ret == TRUE) {
3208 : 1 : next_state (self, state_complete);
3209 : : } else {
3210 : 0 : g_propagate_error (&self->error, error);
3211 : 0 : next_state (self, state_failure);
3212 : : }
3213 : 1 : }
3214 : :
3215 : : static void
3216 : 2 : complete_read_buffer (GcrParsing *self, gssize count, GError *error)
3217 : : {
3218 [ - + + - : 2 : g_assert (GCR_IS_PARSING (self));
+ - - + ]
3219 [ - + ]: 2 : g_assert (self->buffer);
3220 : :
3221 : : /* A failure */
3222 [ - + ]: 2 : if (count == -1) {
3223 : 0 : g_propagate_error (&self->error, error);
3224 : 0 : next_state (self, state_failure);
3225 : : } else {
3226 : :
3227 [ + - + - ]: 2 : g_return_if_fail (count >= 0 && count <= BLOCK);
3228 : 2 : g_byte_array_set_size (self->buffer, self->buffer->len - (BLOCK - count));
3229 : :
3230 : : /* Finished reading */
3231 [ + + ]: 2 : if (count == 0)
3232 : 1 : next_state (self, state_parse_buffer);
3233 : :
3234 : : /* Read the next block */
3235 : : else
3236 : 1 : next_state (self, state_read_buffer);
3237 : : }
3238 : :
3239 : : }
3240 : :
3241 : : static void
3242 : 0 : on_read_buffer (GObject *obj, GAsyncResult *res, gpointer user_data)
3243 : : {
3244 : 0 : GError *error = NULL;
3245 : : gssize count;
3246 : :
3247 : 0 : count = g_input_stream_read_finish (G_INPUT_STREAM (obj), res, &error);
3248 : 0 : complete_read_buffer (user_data, count, error);
3249 : 0 : }
3250 : :
3251 : : static void
3252 : 2 : state_read_buffer (GcrParsing *self, gboolean async)
3253 : : {
3254 : 2 : GError *error = NULL;
3255 : : gssize count;
3256 : : gsize at;
3257 : :
3258 [ - + + - : 2 : g_assert (GCR_IS_PARSING (self));
+ - - + ]
3259 [ - + + - : 2 : g_assert (G_IS_INPUT_STREAM (self->input));
- + - + ]
3260 : :
3261 [ + + ]: 2 : if (!self->buffer)
3262 : 1 : self->buffer = g_byte_array_sized_new (BLOCK);
3263 : :
3264 : 2 : at = self->buffer->len;
3265 : 2 : g_byte_array_set_size (self->buffer, at + BLOCK);
3266 : :
3267 [ - + ]: 2 : if (async) {
3268 : 0 : g_input_stream_read_async (self->input, self->buffer->data + at,
3269 : : BLOCK, G_PRIORITY_DEFAULT, self->cancel,
3270 : : on_read_buffer, self);
3271 : : } else {
3272 : 2 : count = g_input_stream_read (self->input, self->buffer->data + at,
3273 : : BLOCK, self->cancel, &error);
3274 : 2 : complete_read_buffer (self, count, error);
3275 : : }
3276 : 2 : }
3277 : :
3278 : : static void
3279 : 1 : gcr_parsing_init (GcrParsing *self)
3280 : : {
3281 : :
3282 : 1 : }
3283 : :
3284 : : static void
3285 : 1 : gcr_parsing_finalize (GObject *obj)
3286 : : {
3287 : 1 : GcrParsing *self = GCR_PARSING (obj);
3288 : :
3289 : 1 : g_object_unref (self->parser);
3290 : 1 : self->parser = NULL;
3291 : :
3292 : 1 : g_object_unref (self->input);
3293 : 1 : self->input = NULL;
3294 : :
3295 [ - + ]: 1 : if (self->cancel)
3296 : 0 : g_object_unref (self->cancel);
3297 : 1 : self->cancel = NULL;
3298 : :
3299 : 1 : g_clear_error (&self->error);
3300 : :
3301 [ - + ]: 1 : if (self->buffer)
3302 : 0 : g_byte_array_free (self->buffer, TRUE);
3303 : 1 : self->buffer = NULL;
3304 : :
3305 : 1 : G_OBJECT_CLASS (gcr_parsing_parent_class)->finalize (obj);
3306 : 1 : }
3307 : :
3308 : : static void
3309 : 1 : gcr_parsing_class_init (GcrParsingClass *klass)
3310 : : {
3311 : 1 : G_OBJECT_CLASS (klass)->finalize = gcr_parsing_finalize;
3312 : 1 : }
3313 : :
3314 : : static gpointer
3315 : 0 : gcr_parsing_real_get_user_data (GAsyncResult *base)
3316 : : {
3317 [ # # # # : 0 : g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
# # # # ]
3318 : 0 : return GCR_PARSING (base)->user_data;
3319 : : }
3320 : :
3321 : : static GObject*
3322 : 0 : gcr_parsing_real_get_source_object (GAsyncResult *base)
3323 : : {
3324 [ # # # # : 0 : g_return_val_if_fail (GCR_IS_PARSING (base), NULL);
# # # # ]
3325 : 0 : return G_OBJECT (GCR_PARSING (base)->parser);
3326 : : }
3327 : :
3328 : : static void
3329 : 1 : gcr_parsing_async_result_init (GAsyncResultIface *iface)
3330 : : {
3331 : 1 : iface->get_source_object = gcr_parsing_real_get_source_object;
3332 : 1 : iface->get_user_data = gcr_parsing_real_get_user_data;
3333 : 1 : }
3334 : :
3335 : : static GcrParsing*
3336 : 1 : gcr_parsing_new (GcrParser *parser, GInputStream *input, GCancellable *cancel)
3337 : : {
3338 : : GcrParsing *self;
3339 : :
3340 [ - + + - : 1 : g_assert (GCR_IS_PARSER (parser));
+ - - + ]
3341 [ - + + - : 1 : g_assert (G_IS_INPUT_STREAM (input));
- + - + ]
3342 : :
3343 : 1 : self = g_object_new (GCR_TYPE_PARSING, NULL);
3344 : 1 : self->parser = g_object_ref (parser);
3345 : 1 : self->input = g_object_ref (input);
3346 [ - + ]: 1 : if (cancel)
3347 : 0 : self->cancel = g_object_ref (cancel);
3348 : :
3349 : 1 : return self;
3350 : : }
3351 : :
3352 : : /**
3353 : : * gcr_parser_parse_stream:
3354 : : * @self: The parser
3355 : : * @input: The input stream
3356 : : * @cancellable: An optional cancellation object
3357 : : * @error: A location to raise an error on failure
3358 : : *
3359 : : * Parse items from the data in a #GInputStream. This function may block while
3360 : : * reading from the input stream. Use [method@Parser.parse_stream_async] for
3361 : : * a non-blocking variant.
3362 : : *
3363 : : * The [signal@Parser::parsed] and [signal@Parser::authenticate] signals
3364 : : * may fire during the parsing.
3365 : : *
3366 : : * Returns: Whether the parsing completed successfully or not.
3367 : : */
3368 : : gboolean
3369 : 1 : gcr_parser_parse_stream (GcrParser *self, GInputStream *input, GCancellable *cancellable,
3370 : : GError **error)
3371 : : {
3372 : : GcrParsing *parsing;
3373 : : gboolean result;
3374 : :
3375 [ - + + - : 1 : g_return_val_if_fail (GCR_IS_PARSER (self), FALSE);
+ - - + ]
3376 [ - + + - : 1 : g_return_val_if_fail (G_IS_INPUT_STREAM (input), FALSE);
- + - + ]
3377 [ + - - + ]: 1 : g_return_val_if_fail (!error || !*error, FALSE);
3378 : :
3379 : 1 : parsing = gcr_parsing_new (self, input, cancellable);
3380 : 1 : parsing->async = FALSE;
3381 : :
3382 : 1 : next_state (parsing, state_read_buffer);
3383 [ - + ]: 1 : g_assert (parsing->complete);
3384 : :
3385 : 1 : result = gcr_parser_parse_stream_finish (self, G_ASYNC_RESULT (parsing), error);
3386 : 1 : g_object_unref (parsing);
3387 : :
3388 : 1 : return result;
3389 : : }
3390 : :
3391 : : /**
3392 : : * gcr_parser_parse_stream_async:
3393 : : * @self: The parser
3394 : : * @input: The input stream
3395 : : * @cancellable: An optional cancellation object
3396 : : * @callback: Called when the operation result is ready.
3397 : : * @user_data: Data to pass to callback
3398 : : *
3399 : : * Parse items from the data in a #GInputStream. This function completes
3400 : : * asyncronously and doesn't block.
3401 : : *
3402 : : * The [signal@Parser::parsed] and [signal@Parser::authenticate] signals
3403 : : * may fire during the parsing.
3404 : : */
3405 : : void
3406 : 0 : gcr_parser_parse_stream_async (GcrParser *self, GInputStream *input, GCancellable *cancellable,
3407 : : GAsyncReadyCallback callback, gpointer user_data)
3408 : : {
3409 : : GcrParsing *parsing;
3410 : :
3411 [ # # # # : 0 : g_return_if_fail (GCR_IS_PARSER (self));
# # # # ]
3412 [ # # # # : 0 : g_return_if_fail (G_IS_INPUT_STREAM (input));
# # # # ]
3413 : :
3414 : 0 : parsing = gcr_parsing_new (self, input, cancellable);
3415 : 0 : parsing->async = TRUE;
3416 : 0 : parsing->callback = callback;
3417 : 0 : parsing->user_data = user_data;
3418 : :
3419 : 0 : next_state (parsing, state_read_buffer);
3420 : : }
3421 : :
3422 : : /**
3423 : : * gcr_parser_parse_stream_finish:
3424 : : * @self: The parser
3425 : : * @result:The operation result
3426 : : * @error: A location to raise an error on failure
3427 : : *
3428 : : * Complete an operation to parse a stream.
3429 : : *
3430 : : * Returns: Whether the parsing completed successfully or not.
3431 : : */
3432 : : gboolean
3433 : 1 : gcr_parser_parse_stream_finish (GcrParser *self, GAsyncResult *result, GError **error)
3434 : : {
3435 : : GcrParsing *parsing;
3436 : :
3437 [ - + + - : 1 : g_return_val_if_fail (GCR_IS_PARSING (result), FALSE);
+ - - + ]
3438 [ + - - + ]: 1 : g_return_val_if_fail (!error || !*error, FALSE);
3439 : :
3440 : 1 : parsing = GCR_PARSING (result);
3441 [ - + ]: 1 : g_return_val_if_fail (parsing->complete, FALSE);
3442 : :
3443 [ - + ]: 1 : if (parsing->error) {
3444 : 0 : g_propagate_error (error, parsing->error);
3445 : 0 : return FALSE;
3446 : : }
3447 : :
3448 : 1 : return TRUE;
3449 : : }
|