1 /* keylist.c - Listing keys.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GPGME; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
39 struct key_queue_item_s
41 struct key_queue_item_s *next;
47 struct _gpgme_op_keylist_result result;
50 gpgme_user_id_t tmp_uid;
51 /* Something new is available. */
53 struct key_queue_item_s *key_queue;
58 release_op_data (void *hook)
60 op_data_t opd = (op_data_t) hook;
61 struct key_queue_item_s *key = opd->key_queue;
64 gpgme_key_unref (opd->tmp_key);
69 struct key_queue_item_s *next = key->next;
71 gpgme_key_unref (key->key);
77 gpgme_keylist_result_t
78 gpgme_op_keylist_result (gpgme_ctx_t ctx)
84 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
94 keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
96 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
101 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
108 case GPGME_STATUS_TRUNCATED:
109 opd->result.truncated = 1;
120 parse_timestamp (char *timestamp)
125 return (time_t) strtoul (timestamp, NULL, 10);
130 set_mainkey_trust_info (gpgme_key_t key, const char *src)
132 /* Look at letters and stop at the first digit. */
133 while (*src && !isdigit (*src))
138 key->subkeys->expired = 1;
142 key->subkeys->revoked = 1;
146 /* Note that gpg 1.3 won't print that anymore but only uses
147 the capabilities field. */
148 key->subkeys->disabled = 1;
152 key->subkeys->invalid = 1;
161 set_userid_flags (gpgme_key_t key, const char *src)
163 gpgme_user_id_t uid = key->_last_uid;
166 /* Look at letters and stop at the first digit. */
167 while (*src && !isdigit (*src))
180 uid->validity = GPGME_VALIDITY_NEVER;
184 uid->validity = GPGME_VALIDITY_MARGINAL;
188 uid->validity = GPGME_VALIDITY_FULL;
192 uid->validity = GPGME_VALIDITY_ULTIMATE;
201 set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
203 /* Look at letters and stop at the first digit. */
204 while (*src && !isdigit (*src))
217 subkey->disabled = 1;
230 set_mainkey_capability (gpgme_key_t key, const char *src)
237 key->subkeys->can_encrypt = 1;
241 key->subkeys->can_sign = 1;
245 key->subkeys->can_certify = 1;
249 key->subkeys->can_authenticate = 1;
254 /* Note, that this flag is also set using the key validity
255 field for backward compatibility with gpg 1.2. We use d
256 and D, so that a future gpg version will be able to
257 disable certain subkeys. Currently it is expected that
258 gpg sets this for the primary key. */
259 key->subkeys->disabled = 1;
263 key->can_encrypt = 1;
271 key->can_certify = 1;
275 key->can_authenticate = 1;
284 set_subkey_capability (gpgme_subkey_t subkey, const char *src)
291 subkey->can_encrypt = 1;
295 subkey->can_sign = 1;
299 subkey->can_certify = 1;
303 subkey->can_authenticate = 1;
311 set_ownertrust (gpgme_key_t key, const char *src)
313 /* Look at letters and stop at the first digit. */
314 while (*src && !isdigit (*src))
319 key->owner_trust = GPGME_VALIDITY_NEVER;
323 key->owner_trust = GPGME_VALIDITY_MARGINAL;
327 key->owner_trust = GPGME_VALIDITY_FULL;
331 key->owner_trust = GPGME_VALIDITY_ULTIMATE;
335 key->owner_trust = GPGME_VALIDITY_UNKNOWN;
343 /* We have read an entire key into tmp_key and should now finish it.
344 It is assumed that this releases tmp_key. */
346 finish_key (gpgme_ctx_t ctx, op_data_t opd)
348 gpgme_key_t key = opd->tmp_key;
354 _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
358 /* Note: We are allowed to modify LINE. */
360 keylist_colon_handler (void *priv, char *line)
362 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
365 RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
366 RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV
370 char *field[NR_FIELDS];
376 gpgme_subkey_t subkey = NULL;
377 gpgme_key_sig_t keysig = NULL;
379 DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
380 ctx, key, line ? line : "(null)");
382 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
392 finish_key (ctx, opd);
396 while (line && fields < NR_FIELDS)
398 field[fields++] = line;
399 line = strchr (line, ':');
404 if (!strcmp (field[0], "sig"))
406 else if (!strcmp (field[0], "rev"))
408 else if (!strcmp (field[0], "pub"))
410 else if (!strcmp (field[0], "sec"))
412 else if (!strcmp (field[0], "crt"))
414 else if (!strcmp (field[0], "crs"))
416 else if (!strcmp (field[0], "fpr") && key)
418 else if (!strcmp (field[0], "uid") && key)
420 else if (!strcmp (field[0], "sub") && key)
422 else if (!strcmp (field[0], "ssb") && key)
427 /* Only look at signatures immediately following a user ID. For
428 this, clear the user ID pointer when encountering anything but a
430 if (rectype != RT_SIG && rectype != RT_REV)
439 /* Start a new keyblock. */
440 err = _gpgme_key_new (&key);
443 err = _gpgme_key_add_subkey (key, &subkey);
446 gpgme_key_unref (key);
450 if (rectype == RT_SEC || rectype == RT_CRS)
452 if (rectype == RT_CRT || rectype == RT_CRS)
453 key->protocol = GPGME_PROTOCOL_CMS;
454 finish_key (ctx, opd);
457 /* Field 2 has the trust info. */
459 set_mainkey_trust_info (key, field[1]);
461 /* Field 3 has the key length. */
464 int i = atoi (field[2]);
465 /* Ignore invalid values. */
470 /* Field 4 has the public key algorithm. */
473 int i = atoi (field[3]);
474 if (i >= 1 && i < 128)
475 subkey->pubkey_algo = i;
478 /* Field 5 has the long keyid. */
479 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
480 strcpy (subkey->_keyid, field[4]);
482 /* Field 6 has the timestamp (seconds). */
484 subkey->timestamp = parse_timestamp (field[5]);
486 /* Field 7 has the expiration time (seconds). */
488 subkey->expires = parse_timestamp (field[6]);
490 /* Field 8 has the X.509 serial number. */
491 if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
493 key->issuer_serial = strdup (field[7]);
494 if (!key->issuer_serial)
495 return gpg_error_from_errno (errno);
498 /* Field 9 has the ownertrust. */
500 set_ownertrust (key, field[8]);
502 /* Field 10 is not used for gpg due to --fixed-list-mode option
503 but GPGSM stores the issuer name. */
504 if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
505 if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
506 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
508 /* Field 11 has the signature class. */
510 /* Field 12 has the capabilities. */
512 set_mainkey_capability (key, field[11]);
517 /* Start a new subkey. */
518 err = _gpgme_key_add_subkey (key, &subkey);
522 if (rectype == RT_SSB)
525 /* Field 2 has the trust info. */
527 set_subkey_trust_info (subkey, field[1]);
529 /* Field 3 has the key length. */
532 int i = atoi (field[2]);
533 /* Ignore invalid values. */
538 /* Field 4 has the public key algorithm. */
541 int i = atoi (field[3]);
542 if (i >= 1 && i < 128)
543 subkey->pubkey_algo = i;
546 /* Field 5 has the long keyid. */
547 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
548 strcpy (subkey->_keyid, field[4]);
550 /* Field 6 has the timestamp (seconds). */
552 subkey->timestamp = parse_timestamp (field[5]);
554 /* Field 7 has the expiration time (seconds). */
556 subkey->expires = parse_timestamp (field[6]);
558 /* Field 8 is reserved (LID). */
559 /* Field 9 has the ownertrust. */
560 /* Field 10, the user ID, is n/a for a subkey. */
562 /* Field 11 has the signature class. */
564 /* Field 12 has the capabilities. */
566 set_subkey_capability (subkey, field[11]);
570 /* Field 2 has the trust info, and field 10 has the user ID. */
573 if (_gpgme_key_append_name (key, field[9]))
574 return gpg_error_from_errno (GPG_ERR_ENOMEM); /* FIXME */
578 set_userid_flags (key, field[1]);
579 opd->tmp_uid = key->_last_uid;
585 /* Field 10 has the fingerprint (take only the first one). */
586 if (fields >= 10 && !key->subkeys->fpr && field[9] && *field[9])
588 key->subkeys->fpr = strdup (field[9]);
589 if (!key->subkeys->fpr)
590 return gpg_error_from_errno (errno);
593 /* Field 13 has the gpgsm chain ID (take only the first one). */
594 if (fields >= 13 && !key->chain_id && *field[12])
596 key->chain_id = strdup (field[12]);
598 return gpg_error_from_errno (errno);
607 /* Start a new (revoked) signature. */
608 assert (opd->tmp_uid == key->_last_uid);
609 keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
611 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
613 /* Field 2 has the calculated trust ('!', '-', '?', '%'). */
618 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
622 keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
626 keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
630 keysig->status = gpg_error (GPG_ERR_GENERAL);
634 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
638 /* Field 4 has the public key algorithm. */
641 int i = atoi (field[3]);
642 if (i >= 1 && i < 128)
643 keysig->pubkey_algo = i;
646 /* Field 5 has the long keyid. */
647 if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
648 strcpy (keysig->_keyid, field[4]);
650 /* Field 6 has the timestamp (seconds). */
652 keysig->timestamp = parse_timestamp (field[5]);
654 /* Field 7 has the expiration time (seconds). */
656 keysig->expires = parse_timestamp (field[6]);
658 /* Field 11 has the signature class (eg, 0x30 means revoked). */
660 if (field[10][0] && field[10][1])
662 int class = _gpgme_hextobyte (field[10]);
665 keysig->class = class;
669 if (field[10][2] == 'x')
670 keysig->exportable = 1;
675 /* Unknown record. */
683 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
686 gpgme_ctx_t ctx = (gpgme_ctx_t) data;
687 gpgme_key_t key = (gpgme_key_t) type_data;
690 struct key_queue_item_s *q, *q2;
692 assert (type == GPGME_EVENT_NEXT_KEY);
694 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
699 q = malloc (sizeof *q);
702 gpgme_key_unref (key);
703 /* FIXME return GPGME_Out_Of_Core; */
708 /* FIXME: Use a tail pointer? */
709 if (!(q2 = opd->key_queue))
713 for (; q2->next; q2 = q2->next)
721 /* Start a keylist operation within CTX, searching for keys which
722 match PATTERN. If SECRET_ONLY is true, only secret keys are
725 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
731 err = _gpgme_op_reset (ctx, 2);
735 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
736 sizeof (*opd), release_op_data);
741 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
743 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
744 keylist_colon_handler, ctx);
748 return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
753 /* Start a keylist operation within CTX, searching for keys which
754 match PATTERN. If SECRET_ONLY is true, only secret keys are
757 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
758 int secret_only, int reserved)
764 err = _gpgme_op_reset (ctx, 2);
768 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
769 sizeof (*opd), release_op_data);
774 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
775 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
776 keylist_colon_handler, ctx);
780 return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
781 reserved, ctx->keylist_mode);
785 /* Return the next key from the keylist in R_KEY. */
787 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
790 struct key_queue_item_s *queue_item;
795 return gpg_error (GPG_ERR_INV_VALUE);
798 return gpg_error (GPG_ERR_INV_VALUE);
800 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
807 err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
812 return gpg_error (GPG_ERR_EOF);
815 assert (opd->key_queue);
817 queue_item = opd->key_queue;
818 opd->key_queue = queue_item->next;
822 *r_key = queue_item->key;
828 /* Terminate a pending keylist operation within CTX. */
830 gpgme_op_keylist_end (gpgme_ctx_t ctx)
833 return gpg_error (GPG_ERR_INV_VALUE);
839 /* Get the key with the fingerprint FPR from the crypto backend. If
840 SECRET is true, get the secret key. */
842 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
850 return gpg_error (GPG_ERR_INV_VALUE);
852 if (strlen (fpr) < 16) /* We have at least a key ID. */
853 return gpg_error (GPG_ERR_INV_VALUE);
855 /* FIXME: We use our own context because we have to avoid the user's
856 I/O callback handlers. */
857 err = gpgme_new (&listctx);
860 gpgme_set_protocol (listctx, gpgme_get_protocol (ctx));
861 gpgme_set_keylist_mode (listctx, ctx->keylist_mode);
862 err = gpgme_op_keylist_start (listctx, fpr, secret);
864 err = gpgme_op_keylist_next (listctx, r_key);
867 err = gpgme_op_keylist_next (listctx, &key);
868 if (gpgme_err_code (err) == GPG_ERR_EOF)
869 err = gpg_error (GPG_ERR_NO_ERROR);
874 gpgme_key_unref (key);
875 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
877 gpgme_key_unref (*r_key);
880 gpgme_release (listctx);