1 /* keylist.c - Listing keys.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007,
4 2008, 2009 g10 Code GmbH
6 This file is part of GPGME.
8 GPGME is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 GPGME is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this program; if not, see <https://www.gnu.org/licenses/>.
28 #ifdef HAVE_SYS_TYPES_H
29 /* Solaris 8 needs sys/types.h before time.h. */
30 # include <sys/types.h>
38 /* Suppress warning for accessing deprecated member "class". */
39 #define _GPGME_IN_GPGME
47 struct key_queue_item_s
49 struct key_queue_item_s *next;
55 struct _gpgme_op_keylist_result result;
57 /* The error code from ERROR keydb_search. */
58 gpgme_error_t keydb_search_err;
62 /* This points to the last uid in tmp_key. */
63 gpgme_user_id_t tmp_uid;
65 /* This points to the last sig in tmp_uid. */
66 gpgme_key_sig_t tmp_keysig;
68 /* Something new is available. */
70 struct key_queue_item_s *key_queue;
75 release_op_data (void *hook)
77 op_data_t opd = (op_data_t) hook;
78 struct key_queue_item_s *key = opd->key_queue;
81 gpgme_key_unref (opd->tmp_key);
83 /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
84 so we do not need to release them here. */
88 struct key_queue_item_s *next = key->next;
90 gpgme_key_unref (key->key);
96 gpgme_keylist_result_t
97 gpgme_op_keylist_result (gpgme_ctx_t ctx)
103 TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_result", ctx);
105 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
109 TRACE_SUC0 ("result=(null)");
113 TRACE_LOG1 ("truncated = %i", opd->result.truncated);
115 TRACE_SUC1 ("result=%p", &opd->result);
121 keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
123 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
130 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
137 case GPGME_STATUS_TRUNCATED:
138 opd->result.truncated = 1;
141 case GPGME_STATUS_ERROR:
142 err = _gpgme_parse_failure (args);
143 if (!opd->keydb_search_err && !strcmp (args, "keydb_search"))
144 opd->keydb_search_err = err;
156 set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
158 while (*src && !isdigit (*src))
171 /* Note that gpg 1.3 won't print that anymore but only uses
172 the capabilities field. */
173 subkey->disabled = 1;
186 set_mainkey_trust_info (gpgme_key_t key, const char *src)
188 /* First set the trust info of the main key (the first subkey). */
189 set_subkey_trust_info (key->subkeys, src);
191 /* Now set the summarized trust info. */
192 while (*src && !isdigit (*src))
205 /* Note that gpg 1.3 won't print that anymore but only uses
206 the capabilities field. However, it is still used for
207 external key listings. */
221 set_userid_flags (gpgme_key_t key, const char *src)
223 gpgme_user_id_t uid = key->_last_uid;
226 /* Look at letters and stop at the first digit. */
227 while (*src && !isdigit (*src))
240 uid->validity = GPGME_VALIDITY_NEVER;
244 uid->validity = GPGME_VALIDITY_MARGINAL;
248 uid->validity = GPGME_VALIDITY_FULL;
252 uid->validity = GPGME_VALIDITY_ULTIMATE;
261 set_subkey_capability (gpgme_subkey_t subkey, const char *src)
268 subkey->can_encrypt = 1;
272 subkey->can_sign = 1;
276 subkey->can_certify = 1;
280 subkey->can_authenticate = 1;
284 subkey->is_qualified = 1;
288 subkey->disabled = 1;
297 set_mainkey_capability (gpgme_key_t key, const char *src)
299 /* First set the capabilities of the main key (the first subkey). */
300 set_subkey_capability (key->subkeys, src);
308 /* Note, that this flag is also set using the key validity
309 field for backward compatibility with gpg 1.2. We use d
310 and D, so that a future gpg version will be able to
311 disable certain subkeys. Currently it is expected that
312 gpg sets this for the primary key. */
318 key->can_encrypt = 1;
328 key->can_certify = 1;
333 key->can_authenticate = 1;
338 key->is_qualified = 1;
347 set_ownertrust (gpgme_key_t key, const char *src)
349 /* Look at letters and stop at the first digit. */
350 while (*src && !isdigit (*src))
355 key->owner_trust = GPGME_VALIDITY_NEVER;
359 key->owner_trust = GPGME_VALIDITY_MARGINAL;
363 key->owner_trust = GPGME_VALIDITY_FULL;
367 key->owner_trust = GPGME_VALIDITY_ULTIMATE;
371 key->owner_trust = GPGME_VALIDITY_UNKNOWN;
379 static gpgme_keyorg_t
380 parse_keyorg (const char *string)
382 switch (atoi (string))
384 case 0: return GPGME_KEYORG_UNKNOWN;
387 return GPGME_KEYORG_KS;
388 case 3: return GPGME_KEYORG_DANE;
389 case 4: return GPGME_KEYORG_WKD;
390 case 5: return GPGME_KEYORG_URL;
391 case 6: return GPGME_KEYORG_FILE;
392 case 7: return GPGME_KEYORG_SELF;
393 default: return GPGME_KEYORG_OTHER;
398 /* Parse field 15 of a secret key or subkey. This fields holds a
399 reference to smartcards. FIELD is the content of the field and we
400 are allowed to modify it. */
402 parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field)
406 else if (*field == '#')
408 /* This is a stub for an offline key. We reset the SECRET flag
409 of the subkey here. Note that the secret flag of the entire
410 key will be true even then. We even explicitly set
411 key->secret to make it works for GPGME_KEYLIST_MODE_WITH_SECRET. */
415 else if (strchr ("01234567890ABCDEFabcdef", *field))
417 /* Fields starts with a hex digit; thus it is a serial number. */
419 subkey->is_cardkey = 1;
420 subkey->card_number = strdup (field);
421 if (!subkey->card_number)
422 return gpg_error_from_syserror ();
424 else if (*field == '+')
438 /* Parse a tfs record. */
440 parse_tfs_record (gpgme_user_id_t uid, char **field, int nfield)
443 gpgme_tofu_info_t ti;
446 /* We add only the first TOFU record in case future versions emit
451 /* Check that we have enough fields and that the version is supported. */
452 if (nfield < 8 || atoi(field[1]) != 1)
453 return trace_gpg_error (GPG_ERR_INV_ENGINE);
455 ti = calloc (1, sizeof *ti);
457 return gpg_error_from_syserror ();
459 /* Note that we allow a value of up to 7 which is what we can store
460 * in the ti->validity. */
461 err = _gpgme_strtoul_field (field[2], &uval);
466 /* Parse the sign-count. */
467 err = _gpgme_strtoul_field (field[3], &uval);
470 if (uval > USHRT_MAX)
472 ti->signcount = uval;
474 /* Parse the encr-count. */
475 err = _gpgme_strtoul_field (field[4], &uval);
478 if (uval > USHRT_MAX)
480 ti->encrcount = uval;
482 /* Parse the policy. */
483 if (!strcmp (field[5], "none"))
484 ti->policy = GPGME_TOFU_POLICY_NONE;
485 else if (!strcmp (field[5], "auto"))
486 ti->policy = GPGME_TOFU_POLICY_AUTO;
487 else if (!strcmp (field[5], "good"))
488 ti->policy = GPGME_TOFU_POLICY_GOOD;
489 else if (!strcmp (field[5], "bad"))
490 ti->policy = GPGME_TOFU_POLICY_BAD;
491 else if (!strcmp (field[5], "ask"))
492 ti->policy = GPGME_TOFU_POLICY_ASK;
493 else /* "unknown" and invalid policy strings. */
494 ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
496 /* Parse first and last seen timestamps. */
497 err = _gpgme_strtoul_field (field[6], &uval);
500 ti->signfirst = uval;
501 err = _gpgme_strtoul_field (field[7], &uval);
508 /* This condition is only to allow for gpg 2.1.15 - can
509 * eventually be removed. */
510 err = _gpgme_strtoul_field (field[8], &uval);
513 ti->encrfirst = uval;
514 err = _gpgme_strtoul_field (field[9], &uval);
526 return trace_gpg_error (GPG_ERR_INV_ENGINE);
530 /* We have read an entire key into tmp_key and should now finish it.
531 It is assumed that this releases tmp_key. */
533 finish_key (gpgme_ctx_t ctx, op_data_t opd)
535 gpgme_key_t key = opd->tmp_key;
539 opd->tmp_keysig = NULL;
542 _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
546 /* Note: We are allowed to modify LINE. */
548 keylist_colon_handler (void *priv, char *line)
550 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
553 RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_GRP,
554 RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
558 char *field[NR_FIELDS];
564 gpgme_subkey_t subkey = NULL;
565 gpgme_key_sig_t keysig = NULL;
567 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
574 TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx,
575 "key = %p, line = %s", key, line ? line : "(null)");
580 finish_key (ctx, opd);
584 while (line && fields < NR_FIELDS)
586 field[fields++] = line;
587 line = strchr (line, ':');
592 if (!strcmp (field[0], "sig"))
594 else if (!strcmp (field[0], "rev"))
596 else if (!strcmp (field[0], "pub"))
598 else if (!strcmp (field[0], "sec"))
600 else if (!strcmp (field[0], "crt"))
602 else if (!strcmp (field[0], "crs"))
604 else if (!strcmp (field[0], "fpr") && key)
606 else if (!strcmp (field[0], "grp") && key)
608 else if (!strcmp (field[0], "uid") && key)
610 else if (!strcmp (field[0], "tfs") && key)
612 else if (!strcmp (field[0], "sub") && key)
614 else if (!strcmp (field[0], "ssb") && key)
616 else if (!strcmp (field[0], "spk") && key)
621 /* Only look at signature and trust info records immediately
622 following a user ID. For this, clear the user ID pointer when
623 encountering anything but a signature or trust record. */
624 if (rectype != RT_SIG && rectype != RT_REV && rectype != RT_TFS)
627 /* Only look at subpackets immediately following a signature. For
628 this, clear the signature pointer when encountering anything but
630 if (rectype != RT_SPK)
631 opd->tmp_keysig = NULL;
639 /* Start a new keyblock. */
640 err = _gpgme_key_new (&key);
643 key->keylist_mode = ctx->keylist_mode;
644 err = _gpgme_key_add_subkey (key, &subkey);
647 gpgme_key_unref (key);
651 if (rectype == RT_SEC || rectype == RT_CRS)
652 key->secret = subkey->secret = 1;
653 if (rectype == RT_CRT || rectype == RT_CRS)
654 key->protocol = GPGME_PROTOCOL_CMS;
655 finish_key (ctx, opd);
658 /* Field 2 has the trust info. */
660 set_mainkey_trust_info (key, field[1]);
662 /* Field 3 has the key length. */
665 int i = atoi (field[2]);
666 /* Ignore invalid values. */
671 /* Field 4 has the public key algorithm. */
674 int i = atoi (field[3]);
675 if (i >= 1 && i < 128)
676 subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
679 /* Field 5 has the long keyid. Allow short key IDs for the
680 output of an external keyserver listing. */
681 if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
682 strcpy (subkey->_keyid, field[4]);
684 /* Field 6 has the timestamp (seconds). */
686 subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
688 /* Field 7 has the expiration time (seconds). */
690 subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
692 /* Field 8 has the X.509 serial number. */
693 if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
695 key->issuer_serial = strdup (field[7]);
696 if (!key->issuer_serial)
697 return gpg_error_from_syserror ();
700 /* Field 9 has the ownertrust. */
702 set_ownertrust (key, field[8]);
704 /* Field 10 is not used for gpg due to --fixed-list-mode option
705 but GPGSM stores the issuer name. */
706 if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
707 if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
708 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
710 /* Field 11 has the signature class. */
712 /* Field 12 has the capabilities. */
714 set_mainkey_capability (key, field[11]);
716 /* Field 15 carries special flags of a secret key. */
719 || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
721 err = parse_sec_field15 (key, subkey, field[14]);
726 /* Field 17 has the curve name for ECC. */
727 if (fields >= 17 && *field[16])
729 subkey->curve = strdup (field[16]);
731 return gpg_error_from_syserror ();
734 /* Field 18 has the compliance flags. */
735 if (fields >= 17 && *field[17])
736 PARSE_COMPLIANCE_FLAGS (field[17], subkey);
740 key->last_update = _gpgme_parse_timestamp_ul (field[18]);
741 key->origin = parse_keyorg (field[19]);
748 /* Start a new subkey. */
749 err = _gpgme_key_add_subkey (key, &subkey);
753 if (rectype == RT_SSB)
756 /* Field 2 has the trust info. */
758 set_subkey_trust_info (subkey, field[1]);
760 /* Field 3 has the key length. */
763 int i = atoi (field[2]);
764 /* Ignore invalid values. */
769 /* Field 4 has the public key algorithm. */
772 int i = atoi (field[3]);
773 if (i >= 1 && i < 128)
774 subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
777 /* Field 5 has the long keyid. */
778 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
779 strcpy (subkey->_keyid, field[4]);
781 /* Field 6 has the timestamp (seconds). */
783 subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
785 /* Field 7 has the expiration time (seconds). */
787 subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
789 /* Field 8 is reserved (LID). */
790 /* Field 9 has the ownertrust. */
791 /* Field 10, the user ID, is n/a for a subkey. */
793 /* Field 11 has the signature class. */
795 /* Field 12 has the capabilities. */
797 set_subkey_capability (subkey, field[11]);
799 /* Field 15 carries special flags of a secret key. */
802 || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
804 err = parse_sec_field15 (key, subkey, field[14]);
809 /* Field 17 has the curve name for ECC. */
810 if (fields >= 17 && *field[16])
812 subkey->curve = strdup (field[16]);
814 return gpg_error_from_syserror ();
817 /* Field 18 has the compliance flags. */
818 if (fields >= 17 && *field[17])
819 PARSE_COMPLIANCE_FLAGS (field[17], subkey);
824 /* Field 2 has the trust info, and field 10 has the user ID. */
827 if (_gpgme_key_append_name (key, field[9], 1))
828 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
831 set_userid_flags (key, field[1]);
832 opd->tmp_uid = key->_last_uid;
835 opd->tmp_uid->last_update = _gpgme_parse_timestamp_ul (field[18]);
836 opd->tmp_uid->origin = parse_keyorg (field[19]);
844 err = parse_tfs_record (opd->tmp_uid, field, fields);
851 /* Field 10 has the fingerprint (take only the first one). */
852 if (fields >= 10 && field[9] && *field[9])
854 /* Need to apply it to the last subkey because all subkeys
855 do have fingerprints. */
856 subkey = key->_last_subkey;
859 subkey->fpr = strdup (field[9]);
861 return gpg_error_from_syserror ();
863 /* If this is the first subkey, store the fingerprint also
864 in the KEY object. */
865 if (subkey == key->subkeys)
867 if (key->fpr && strcmp (key->fpr, subkey->fpr))
869 /* FPR already set but mismatch: Should never happen. */
870 return trace_gpg_error (GPG_ERR_INTERNAL);
874 key->fpr = strdup (subkey->fpr);
876 return gpg_error_from_syserror ();
881 /* Field 13 has the gpgsm chain ID (take only the first one). */
882 if (fields >= 13 && !key->chain_id && *field[12])
884 key->chain_id = strdup (field[12]);
886 return gpg_error_from_syserror ();
891 /* Field 10 has the keygrip. */
892 if (fields >= 10 && field[9] && *field[9])
894 /* Need to apply it to the last subkey because all subkeys
896 subkey = key->_last_subkey;
897 if (!subkey->keygrip)
899 subkey->keygrip = strdup (field[9]);
900 if (!subkey->keygrip)
901 return gpg_error_from_syserror ();
911 /* Start a new (revoked) signature. */
912 assert (opd->tmp_uid == key->_last_uid);
913 keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
915 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
917 /* Field 2 has the calculated trust ('!', '-', '?', '%'). */
922 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
926 keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
930 keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
934 keysig->status = gpg_error (GPG_ERR_GENERAL);
938 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
942 /* Field 4 has the public key algorithm. */
945 int i = atoi (field[3]);
946 if (i >= 1 && i < 128)
947 keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
950 /* Field 5 has the long keyid. */
951 if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
952 strcpy (keysig->_keyid, field[4]);
954 /* Field 6 has the timestamp (seconds). */
956 keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
958 /* Field 7 has the expiration time (seconds). */
960 keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
962 /* Field 11 has the signature class (eg, 0x30 means revoked). */
964 if (field[10][0] && field[10][1])
966 int sig_class = _gpgme_hextobyte (field[10]);
969 keysig->sig_class = sig_class;
970 keysig->class = keysig->sig_class;
971 if (sig_class == 0x30)
974 if (field[10][2] == 'x')
975 keysig->exportable = 1;
978 opd->tmp_keysig = keysig;
982 if (!opd->tmp_keysig)
984 assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
988 /* Field 2 has the subpacket type. */
989 int type = atoi (field[1]);
991 /* Field 3 has the flags. */
992 int flags = atoi (field[2]);
994 /* Field 4 has the length. */
995 int len = atoi (field[3]);
997 /* Field 5 has the data. */
998 char *data = field[4];
1000 /* Type 20: Notation data. */
1001 /* Type 26: Policy URL. */
1002 if (type == 20 || type == 26)
1004 gpgme_sig_notation_t notation;
1006 keysig = opd->tmp_keysig;
1008 /* At this time, any error is serious. */
1009 err = _gpgme_parse_notation (¬ation, type, flags, len, data);
1013 /* Add a new notation. FIXME: Could be factored out. */
1014 if (!keysig->notations)
1015 keysig->notations = notation;
1016 if (keysig->_last_notation)
1017 keysig->_last_notation->next = notation;
1018 keysig->_last_notation = notation;
1023 /* Unknown record. */
1031 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
1034 gpgme_ctx_t ctx = (gpgme_ctx_t) data;
1035 gpgme_key_t key = (gpgme_key_t) type_data;
1038 struct key_queue_item_s *q, *q2;
1040 assert (type == GPGME_EVENT_NEXT_KEY);
1042 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
1047 q = malloc (sizeof *q);
1050 gpgme_key_unref (key);
1051 /* FIXME return GPGME_Out_Of_Core; */
1056 /* FIXME: Use a tail pointer? */
1057 if (!(q2 = opd->key_queue))
1061 for (; q2->next; q2 = q2->next)
1069 /* Start a keylist operation within CTX, searching for keys which
1070 match PATTERN. If SECRET_ONLY is true, only secret keys are
1073 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
1080 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
1081 "pattern=%s, secret_only=%i", pattern, secret_only);
1084 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1086 err = _gpgme_op_reset (ctx, 2);
1088 return TRACE_ERR (err);
1090 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
1091 sizeof (*opd), release_op_data);
1094 return TRACE_ERR (err);
1096 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
1098 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
1099 keylist_colon_handler, ctx);
1101 return TRACE_ERR (err);
1104 flags |= GPGME_ENGINE_FLAG_OFFLINE;
1106 err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
1107 ctx->keylist_mode, flags);
1108 return TRACE_ERR (err);
1112 /* Start a keylist operation within CTX, searching for keys which
1113 match PATTERN. If SECRET_ONLY is true, only secret keys are
1116 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
1117 int secret_only, int reserved)
1124 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
1125 "secret_only=%i, reserved=0x%x", secret_only, reserved);
1128 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1130 err = _gpgme_op_reset (ctx, 2);
1132 return TRACE_ERR (err);
1134 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
1135 sizeof (*opd), release_op_data);
1138 return TRACE_ERR (err);
1140 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
1141 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
1142 keylist_colon_handler, ctx);
1144 return TRACE_ERR (err);
1147 flags |= GPGME_ENGINE_FLAG_OFFLINE;
1149 err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
1150 reserved, ctx->keylist_mode,
1152 return TRACE_ERR (err);
1156 /* Start a keylist operation within CTX to show keys contained
1159 gpgme_op_keylist_from_data_start (gpgme_ctx_t ctx, gpgme_data_t data,
1166 TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_from_data_start", ctx);
1168 if (!ctx || !data || reserved)
1169 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1171 err = _gpgme_op_reset (ctx, 2);
1173 return TRACE_ERR (err);
1175 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
1176 sizeof (*opd), release_op_data);
1179 return TRACE_ERR (err);
1181 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
1182 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
1183 keylist_colon_handler, ctx);
1185 return TRACE_ERR (err);
1187 err = _gpgme_engine_op_keylist_data (ctx->engine, data);
1188 return TRACE_ERR (err);
1192 /* Return the next key from the keylist in R_KEY. */
1194 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
1197 struct key_queue_item_s *queue_item;
1201 TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
1204 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1207 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1209 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
1212 return TRACE_ERR (err);
1214 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1216 if (!opd->key_queue)
1218 err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
1220 return TRACE_ERR (err);
1223 return TRACE_ERR (opd->keydb_search_err? opd->keydb_search_err
1224 /**/ : gpg_error (GPG_ERR_EOF));
1227 assert (opd->key_queue);
1229 queue_item = opd->key_queue;
1230 opd->key_queue = queue_item->next;
1231 if (!opd->key_queue)
1234 *r_key = queue_item->key;
1237 return TRACE_SUC2 ("key=%p (%s)", *r_key,
1238 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1239 (*r_key)->subkeys->fpr : "invalid");
1243 /* Terminate a pending keylist operation within CTX. */
1245 gpgme_op_keylist_end (gpgme_ctx_t ctx)
1247 TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
1250 return gpg_error (GPG_ERR_INV_VALUE);
1256 /* Get the key with the fingerprint FPR from the crypto backend. If
1257 SECRET is true, get the secret key. */
1259 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
1262 gpgme_ctx_t listctx;
1264 gpgme_key_t result, key;
1266 TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
1267 "fpr=%s, secret=%i", fpr, secret);
1269 if (!ctx || !r_key || !fpr)
1270 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1274 if (strlen (fpr) < 8) /* We have at least a key ID. */
1275 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1277 /* FIXME: We use our own context because we have to avoid the user's
1278 I/O callback handlers. */
1279 err = gpgme_new (&listctx);
1281 return TRACE_ERR (err);
1283 gpgme_protocol_t proto;
1284 gpgme_engine_info_t info;
1286 /* Clone the relevant state. */
1287 proto = gpgme_get_protocol (ctx);
1288 gpgme_set_protocol (listctx, proto);
1289 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1290 info = gpgme_ctx_get_engine_info (ctx);
1291 while (info && info->protocol != proto)
1294 gpgme_ctx_set_engine_info (listctx, proto,
1295 info->file_name, info->home_dir);
1298 err = gpgme_op_keylist_start (listctx, fpr, secret);
1300 err = gpgme_op_keylist_next (listctx, &result);
1304 err = gpgme_op_keylist_next (listctx, &key);
1305 if (gpgme_err_code (err) == GPG_ERR_EOF)
1310 && result && result->subkeys && result->subkeys->fpr
1311 && key && key->subkeys && key->subkeys->fpr
1312 && !strcmp (result->subkeys->fpr, key->subkeys->fpr))
1314 /* The fingerprint is identical. We assume that this is
1315 the same key and don't mark it as an ambiguous. This
1316 problem may occur with corrupted keyrings and has
1317 been noticed often with gpgsm. In fact gpgsm uses a
1318 similar hack to sort out such duplicates but it can't
1319 do that while listing keys. */
1320 gpgme_key_unref (key);
1325 gpgme_key_unref (key);
1326 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1328 gpgme_key_unref (result);
1332 gpgme_release (listctx);
1336 TRACE_LOG2 ("key=%p (%s)", *r_key,
1337 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1338 (*r_key)->subkeys->fpr : "invalid");
1340 return TRACE_ERR (err);