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 <http://www.gnu.org/licenses/>.
28 /* Solaris 8 needs sys/types.h before time.h. */
29 #include <sys/types.h>
35 /* Suppress warning for accessing deprecated member "class". */
36 #define _GPGME_IN_GPGME
44 struct key_queue_item_s
46 struct key_queue_item_s *next;
52 struct _gpgme_op_keylist_result result;
56 /* This points to the last uid in tmp_key. */
57 gpgme_user_id_t tmp_uid;
59 /* This points to the last sig in tmp_uid. */
60 gpgme_key_sig_t tmp_keysig;
62 /* Something new is available. */
64 struct key_queue_item_s *key_queue;
69 release_op_data (void *hook)
71 op_data_t opd = (op_data_t) hook;
72 struct key_queue_item_s *key = opd->key_queue;
75 gpgme_key_unref (opd->tmp_key);
77 /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
78 so we do not need to release them here. */
82 struct key_queue_item_s *next = key->next;
84 gpgme_key_unref (key->key);
90 gpgme_keylist_result_t
91 gpgme_op_keylist_result (gpgme_ctx_t ctx)
97 TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_result", ctx);
99 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
103 TRACE_SUC0 ("result=(null)");
107 TRACE_LOG1 ("truncated = %i", opd->result.truncated);
109 TRACE_SUC1 ("result=%p", &opd->result);
115 keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
117 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
122 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
129 case GPGME_STATUS_TRUNCATED:
130 opd->result.truncated = 1;
141 set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
143 while (*src && !isdigit (*src))
156 /* Note that gpg 1.3 won't print that anymore but only uses
157 the capabilities field. */
158 subkey->disabled = 1;
171 set_mainkey_trust_info (gpgme_key_t key, const char *src)
173 /* First set the trust info of the main key (the first subkey). */
174 set_subkey_trust_info (key->subkeys, src);
176 /* Now set the summarized trust info. */
177 while (*src && !isdigit (*src))
190 /* Note that gpg 1.3 won't print that anymore but only uses
191 the capabilities field. However, it is still used for
192 external key listings. */
206 set_userid_flags (gpgme_key_t key, const char *src)
208 gpgme_user_id_t uid = key->_last_uid;
211 /* Look at letters and stop at the first digit. */
212 while (*src && !isdigit (*src))
225 uid->validity = GPGME_VALIDITY_NEVER;
229 uid->validity = GPGME_VALIDITY_MARGINAL;
233 uid->validity = GPGME_VALIDITY_FULL;
237 uid->validity = GPGME_VALIDITY_ULTIMATE;
246 set_subkey_capability (gpgme_subkey_t subkey, const char *src)
253 subkey->can_encrypt = 1;
257 subkey->can_sign = 1;
261 subkey->can_certify = 1;
265 subkey->can_authenticate = 1;
269 subkey->is_qualified = 1;
273 subkey->disabled = 1;
282 set_mainkey_capability (gpgme_key_t key, const char *src)
284 /* First set the capabilities of the main key (the first subkey). */
285 set_subkey_capability (key->subkeys, src);
293 /* Note, that this flag is also set using the key validity
294 field for backward compatibility with gpg 1.2. We use d
295 and D, so that a future gpg version will be able to
296 disable certain subkeys. Currently it is expected that
297 gpg sets this for the primary key. */
303 key->can_encrypt = 1;
313 key->can_certify = 1;
318 key->can_authenticate = 1;
323 key->is_qualified = 1;
332 set_ownertrust (gpgme_key_t key, const char *src)
334 /* Look at letters and stop at the first digit. */
335 while (*src && !isdigit (*src))
340 key->owner_trust = GPGME_VALIDITY_NEVER;
344 key->owner_trust = GPGME_VALIDITY_MARGINAL;
348 key->owner_trust = GPGME_VALIDITY_FULL;
352 key->owner_trust = GPGME_VALIDITY_ULTIMATE;
356 key->owner_trust = GPGME_VALIDITY_UNKNOWN;
364 /* Parse field 15 of a secret key or subkey. This fields holds a
365 reference to smartcards. FIELD is the content of the field and we
366 are allowed to modify it. */
368 parse_sec_field15 (gpgme_subkey_t subkey, char *field)
372 else if (*field == '#')
374 /* This is a stub for an offline key. We reset the SECRET flag
375 of the subkey here. Note that the secret flag of the entire
376 key will be true even then. */
379 else if (strchr ("01234567890ABCDEFabcdef", *field))
381 /* Fields starts with a hex digit; thus it is a serial number. */
382 subkey->is_cardkey = 1;
383 subkey->card_number = strdup (field);
384 if (!subkey->card_number)
385 return gpg_error_from_syserror ();
396 /* We have read an entire key into tmp_key and should now finish it.
397 It is assumed that this releases tmp_key. */
399 finish_key (gpgme_ctx_t ctx, op_data_t opd)
401 gpgme_key_t key = opd->tmp_key;
405 opd->tmp_keysig = NULL;
408 _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
412 /* Note: We are allowed to modify LINE. */
414 keylist_colon_handler (void *priv, char *line)
416 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
419 RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
420 RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
424 char *field[NR_FIELDS];
430 gpgme_subkey_t subkey = NULL;
431 gpgme_key_sig_t keysig = NULL;
433 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
440 TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx,
441 "key = %p, line = %s", key, line ? line : "(null)");
446 finish_key (ctx, opd);
450 while (line && fields < NR_FIELDS)
452 field[fields++] = line;
453 line = strchr (line, ':');
458 if (!strcmp (field[0], "sig"))
460 else if (!strcmp (field[0], "rev"))
462 else if (!strcmp (field[0], "pub"))
464 else if (!strcmp (field[0], "sec"))
466 else if (!strcmp (field[0], "crt"))
468 else if (!strcmp (field[0], "crs"))
470 else if (!strcmp (field[0], "fpr") && key)
472 else if (!strcmp (field[0], "uid") && key)
474 else if (!strcmp (field[0], "sub") && key)
476 else if (!strcmp (field[0], "ssb") && key)
478 else if (!strcmp (field[0], "spk") && key)
483 /* Only look at signatures immediately following a user ID. For
484 this, clear the user ID pointer when encountering anything but a
486 if (rectype != RT_SIG && rectype != RT_REV)
489 /* Only look at subpackets immediately following a signature. For
490 this, clear the signature pointer when encountering anything but
492 if (rectype != RT_SPK)
493 opd->tmp_keysig = NULL;
501 /* Start a new keyblock. */
502 err = _gpgme_key_new (&key);
505 key->keylist_mode = ctx->keylist_mode;
506 err = _gpgme_key_add_subkey (key, &subkey);
509 gpgme_key_unref (key);
513 if (rectype == RT_SEC || rectype == RT_CRS)
514 key->secret = subkey->secret = 1;
515 if (rectype == RT_CRT || rectype == RT_CRS)
516 key->protocol = GPGME_PROTOCOL_CMS;
517 finish_key (ctx, opd);
520 /* Field 2 has the trust info. */
522 set_mainkey_trust_info (key, field[1]);
524 /* Field 3 has the key length. */
527 int i = atoi (field[2]);
528 /* Ignore invalid values. */
533 /* Field 4 has the public key algorithm. */
536 int i = atoi (field[3]);
537 if (i >= 1 && i < 128)
538 subkey->pubkey_algo = i;
541 /* Field 5 has the long keyid. Allow short key IDs for the
542 output of an external keyserver listing. */
543 if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
544 strcpy (subkey->_keyid, field[4]);
546 /* Field 6 has the timestamp (seconds). */
548 subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
550 /* Field 7 has the expiration time (seconds). */
552 subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
554 /* Field 8 has the X.509 serial number. */
555 if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
557 key->issuer_serial = strdup (field[7]);
558 if (!key->issuer_serial)
559 return gpg_error_from_errno (errno);
562 /* Field 9 has the ownertrust. */
564 set_ownertrust (key, field[8]);
566 /* Field 10 is not used for gpg due to --fixed-list-mode option
567 but GPGSM stores the issuer name. */
568 if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
569 if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
570 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
572 /* Field 11 has the signature class. */
574 /* Field 12 has the capabilities. */
576 set_mainkey_capability (key, field[11]);
578 /* Field 15 carries special flags of a secret key. */
579 if (fields >= 15 && key->secret)
581 err = parse_sec_field15 (subkey, field[14]);
589 /* Start a new subkey. */
590 err = _gpgme_key_add_subkey (key, &subkey);
594 if (rectype == RT_SSB)
597 /* Field 2 has the trust info. */
599 set_subkey_trust_info (subkey, field[1]);
601 /* Field 3 has the key length. */
604 int i = atoi (field[2]);
605 /* Ignore invalid values. */
610 /* Field 4 has the public key algorithm. */
613 int i = atoi (field[3]);
614 if (i >= 1 && i < 128)
615 subkey->pubkey_algo = i;
618 /* Field 5 has the long keyid. */
619 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
620 strcpy (subkey->_keyid, field[4]);
622 /* Field 6 has the timestamp (seconds). */
624 subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
626 /* Field 7 has the expiration time (seconds). */
628 subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
630 /* Field 8 is reserved (LID). */
631 /* Field 9 has the ownertrust. */
632 /* Field 10, the user ID, is n/a for a subkey. */
634 /* Field 11 has the signature class. */
636 /* Field 12 has the capabilities. */
638 set_subkey_capability (subkey, field[11]);
640 /* Field 15 carries special flags of a secret key. */
641 if (fields >= 15 && key->secret)
643 err = parse_sec_field15 (subkey, field[14]);
650 /* Field 2 has the trust info, and field 10 has the user ID. */
653 if (_gpgme_key_append_name (key, field[9], 1))
654 return gpg_error_from_errno (GPG_ERR_ENOMEM); /* FIXME */
658 set_userid_flags (key, field[1]);
659 opd->tmp_uid = key->_last_uid;
665 /* Field 10 has the fingerprint (take only the first one). */
666 if (fields >= 10 && field[9] && *field[9])
668 /* Need to apply it to the last subkey because all subkeys
669 do have fingerprints. */
670 subkey = key->_last_subkey;
673 subkey->fpr = strdup (field[9]);
675 return gpg_error_from_errno (errno);
679 /* Field 13 has the gpgsm chain ID (take only the first one). */
680 if (fields >= 13 && !key->chain_id && *field[12])
682 key->chain_id = strdup (field[12]);
684 return gpg_error_from_errno (errno);
693 /* Start a new (revoked) signature. */
694 assert (opd->tmp_uid == key->_last_uid);
695 keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
697 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
699 /* Field 2 has the calculated trust ('!', '-', '?', '%'). */
704 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
708 keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
712 keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
716 keysig->status = gpg_error (GPG_ERR_GENERAL);
720 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
724 /* Field 4 has the public key algorithm. */
727 int i = atoi (field[3]);
728 if (i >= 1 && i < 128)
729 keysig->pubkey_algo = i;
732 /* Field 5 has the long keyid. */
733 if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
734 strcpy (keysig->_keyid, field[4]);
736 /* Field 6 has the timestamp (seconds). */
738 keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
740 /* Field 7 has the expiration time (seconds). */
742 keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
744 /* Field 11 has the signature class (eg, 0x30 means revoked). */
746 if (field[10][0] && field[10][1])
748 int sig_class = _gpgme_hextobyte (field[10]);
751 keysig->sig_class = sig_class;
752 keysig->class = keysig->sig_class;
753 if (sig_class == 0x30)
756 if (field[10][2] == 'x')
757 keysig->exportable = 1;
760 opd->tmp_keysig = keysig;
764 if (!opd->tmp_keysig)
766 assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
770 /* Field 2 has the subpacket type. */
771 int type = atoi (field[1]);
773 /* Field 3 has the flags. */
774 int flags = atoi (field[2]);
776 /* Field 4 has the length. */
777 int len = atoi (field[3]);
779 /* Field 5 has the data. */
780 char *data = field[4];
782 /* Type 20: Notation data. */
783 /* Type 26: Policy URL. */
784 if (type == 20 || type == 26)
786 gpgme_sig_notation_t notation;
788 keysig = opd->tmp_keysig;
790 /* At this time, any error is serious. */
791 err = _gpgme_parse_notation (¬ation, type, flags, len, data);
795 /* Add a new notation. FIXME: Could be factored out. */
796 if (!keysig->notations)
797 keysig->notations = notation;
798 if (keysig->_last_notation)
799 keysig->_last_notation->next = notation;
800 keysig->_last_notation = notation;
805 /* Unknown record. */
813 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
816 gpgme_ctx_t ctx = (gpgme_ctx_t) data;
817 gpgme_key_t key = (gpgme_key_t) type_data;
820 struct key_queue_item_s *q, *q2;
822 assert (type == GPGME_EVENT_NEXT_KEY);
824 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
829 q = malloc (sizeof *q);
832 gpgme_key_unref (key);
833 /* FIXME return GPGME_Out_Of_Core; */
838 /* FIXME: Use a tail pointer? */
839 if (!(q2 = opd->key_queue))
843 for (; q2->next; q2 = q2->next)
851 /* Start a keylist operation within CTX, searching for keys which
852 match PATTERN. If SECRET_ONLY is true, only secret keys are
855 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
861 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
862 "pattern=%s, secret_only=%i", pattern, secret_only);
864 err = _gpgme_op_reset (ctx, 2);
866 return TRACE_ERR (err);
868 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
869 sizeof (*opd), release_op_data);
872 return TRACE_ERR (err);
874 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
876 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
877 keylist_colon_handler, ctx);
879 return TRACE_ERR (err);
881 err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
883 return TRACE_ERR (err);
887 /* Start a keylist operation within CTX, searching for keys which
888 match PATTERN. If SECRET_ONLY is true, only secret keys are
891 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
892 int secret_only, int reserved)
898 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
899 "secret_only=%i, reserved=0x%x", secret_only, reserved);
901 err = _gpgme_op_reset (ctx, 2);
903 return TRACE_ERR (err);
905 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
906 sizeof (*opd), release_op_data);
909 return TRACE_ERR (err);
911 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
912 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
913 keylist_colon_handler, ctx);
915 return TRACE_ERR (err);
917 err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
918 reserved, ctx->keylist_mode);
919 return TRACE_ERR (err);
923 /* Return the next key from the keylist in R_KEY. */
925 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
928 struct key_queue_item_s *queue_item;
932 TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
935 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
938 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
940 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
943 return TRACE_ERR (err);
945 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
949 err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
951 return TRACE_ERR (err);
954 return TRACE_ERR (gpg_error (GPG_ERR_EOF));
957 assert (opd->key_queue);
959 queue_item = opd->key_queue;
960 opd->key_queue = queue_item->next;
964 *r_key = queue_item->key;
967 return TRACE_SUC2 ("key=%p (%s)", *r_key,
968 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
969 (*r_key)->subkeys->fpr : "invalid");
973 /* Terminate a pending keylist operation within CTX. */
975 gpgme_op_keylist_end (gpgme_ctx_t ctx)
977 TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
980 return gpg_error (GPG_ERR_INV_VALUE);
986 /* Get the key with the fingerprint FPR from the crypto backend. If
987 SECRET is true, get the secret key. */
989 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
996 TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
997 "fpr=%s, secret=%i", fpr, secret);
999 if (!ctx || !r_key || !fpr)
1000 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1002 if (strlen (fpr) < 8) /* We have at least a key ID. */
1003 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1005 /* FIXME: We use our own context because we have to avoid the user's
1006 I/O callback handlers. */
1007 err = gpgme_new (&listctx);
1009 return TRACE_ERR (err);
1011 gpgme_protocol_t proto;
1012 gpgme_engine_info_t info;
1014 /* Clone the relevant state. */
1015 proto = gpgme_get_protocol (ctx);
1016 gpgme_set_protocol (listctx, proto);
1017 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1018 info = gpgme_ctx_get_engine_info (ctx);
1019 while (info && info->protocol != proto)
1022 gpgme_ctx_set_engine_info (listctx, proto,
1023 info->file_name, info->home_dir);
1026 err = gpgme_op_keylist_start (listctx, fpr, secret);
1028 err = gpgme_op_keylist_next (listctx, r_key);
1032 err = gpgme_op_keylist_next (listctx, &key);
1033 if (gpgme_err_code (err) == GPG_ERR_EOF)
1038 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1039 && key && key->subkeys && key->subkeys->fpr
1040 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1042 /* The fingerprint is identical. We assume that this is
1043 the same key and don't mark it as an ambiguous. This
1044 problem may occur with corrupted keyrings and has
1045 been noticed often with gpgsm. In fact gpgsm uses a
1046 similar hack to sort out such duplicates but it can't
1047 do that while listing keys. */
1048 gpgme_key_unref (key);
1053 gpgme_key_unref (key);
1054 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1056 gpgme_key_unref (*r_key);
1059 gpgme_release (listctx);
1062 TRACE_LOG2 ("key=%p (%s)", *r_key,
1063 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1064 (*r_key)->subkeys->fpr : "invalid");
1066 return TRACE_ERR (err);