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 if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
130 year = atoi_4 (timestamp);
134 /* Fixme: We would better use a configure test to see whether
135 mktime can handle dates beyond 2038. */
136 if (sizeof (time_t) <= 4 && year >= 2038)
137 return (time_t)2145914603; /* 2037-12-31 23:23:23 */
139 memset (&buf, 0, sizeof buf);
140 buf.tm_year = year - 1900;
141 buf.tm_mon = atoi_2 (timestamp+4) - 1;
142 buf.tm_mday = atoi_2 (timestamp+6);
143 buf.tm_hour = atoi_2 (timestamp+9);
144 buf.tm_min = atoi_2 (timestamp+11);
145 buf.tm_sec = atoi_2 (timestamp+13);
148 return timegm (&buf);
156 #warning fixme: we must somehow reset TZ here. It is not threadsafe anyway.
160 #endif /* !HAVE_TIMEGM */
163 return (time_t) strtoul (timestamp, NULL, 10);
168 set_mainkey_trust_info (gpgme_key_t key, const char *src)
170 /* Look at letters and stop at the first digit. */
171 while (*src && !isdigit (*src))
176 key->subkeys->expired = 1;
180 key->subkeys->revoked = 1;
184 /* Note that gpg 1.3 won't print that anymore but only uses
185 the capabilities field. */
186 key->subkeys->disabled = 1;
190 key->subkeys->invalid = 1;
199 set_userid_flags (gpgme_key_t key, const char *src)
201 gpgme_user_id_t uid = key->_last_uid;
204 /* Look at letters and stop at the first digit. */
205 while (*src && !isdigit (*src))
218 uid->validity = GPGME_VALIDITY_NEVER;
222 uid->validity = GPGME_VALIDITY_MARGINAL;
226 uid->validity = GPGME_VALIDITY_FULL;
230 uid->validity = GPGME_VALIDITY_ULTIMATE;
239 set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
241 /* Look at letters and stop at the first digit. */
242 while (*src && !isdigit (*src))
255 subkey->disabled = 1;
268 set_mainkey_capability (gpgme_key_t key, const char *src)
275 key->subkeys->can_encrypt = 1;
279 key->subkeys->can_sign = 1;
283 key->subkeys->can_certify = 1;
287 key->subkeys->can_authenticate = 1;
292 /* Note, that this flag is also set using the key validity
293 field for backward compatibility with gpg 1.2. We use d
294 and D, so that a future gpg version will be able to
295 disable certain subkeys. Currently it is expected that
296 gpg sets this for the primary key. */
297 key->subkeys->disabled = 1;
301 key->can_encrypt = 1;
309 key->can_certify = 1;
313 key->can_authenticate = 1;
322 set_subkey_capability (gpgme_subkey_t subkey, const char *src)
329 subkey->can_encrypt = 1;
333 subkey->can_sign = 1;
337 subkey->can_certify = 1;
341 subkey->can_authenticate = 1;
349 set_ownertrust (gpgme_key_t key, const char *src)
351 /* Look at letters and stop at the first digit. */
352 while (*src && !isdigit (*src))
357 key->owner_trust = GPGME_VALIDITY_NEVER;
361 key->owner_trust = GPGME_VALIDITY_MARGINAL;
365 key->owner_trust = GPGME_VALIDITY_FULL;
369 key->owner_trust = GPGME_VALIDITY_ULTIMATE;
373 key->owner_trust = GPGME_VALIDITY_UNKNOWN;
381 /* We have read an entire key into tmp_key and should now finish it.
382 It is assumed that this releases tmp_key. */
384 finish_key (gpgme_ctx_t ctx, op_data_t opd)
386 gpgme_key_t key = opd->tmp_key;
392 _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
396 /* Note: We are allowed to modify LINE. */
398 keylist_colon_handler (void *priv, char *line)
400 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
403 RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
404 RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV
408 char *field[NR_FIELDS];
414 gpgme_subkey_t subkey = NULL;
415 gpgme_key_sig_t keysig = NULL;
417 DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
418 ctx, key, line ? line : "(null)");
420 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
430 finish_key (ctx, opd);
434 while (line && fields < NR_FIELDS)
436 field[fields++] = line;
437 line = strchr (line, ':');
442 if (!strcmp (field[0], "sig"))
444 else if (!strcmp (field[0], "rev"))
446 else if (!strcmp (field[0], "pub"))
448 else if (!strcmp (field[0], "sec"))
450 else if (!strcmp (field[0], "crt"))
452 else if (!strcmp (field[0], "crs"))
454 else if (!strcmp (field[0], "fpr") && key)
456 else if (!strcmp (field[0], "uid") && key)
458 else if (!strcmp (field[0], "sub") && key)
460 else if (!strcmp (field[0], "ssb") && key)
465 /* Only look at signatures immediately following a user ID. For
466 this, clear the user ID pointer when encountering anything but a
468 if (rectype != RT_SIG && rectype != RT_REV)
477 /* Start a new keyblock. */
478 err = _gpgme_key_new (&key);
481 err = _gpgme_key_add_subkey (key, &subkey);
484 gpgme_key_unref (key);
488 if (rectype == RT_SEC || rectype == RT_CRS)
490 if (rectype == RT_CRT || rectype == RT_CRS)
491 key->protocol = GPGME_PROTOCOL_CMS;
492 finish_key (ctx, opd);
495 /* Field 2 has the trust info. */
497 set_mainkey_trust_info (key, field[1]);
499 /* Field 3 has the key length. */
502 int i = atoi (field[2]);
503 /* Ignore invalid values. */
508 /* Field 4 has the public key algorithm. */
511 int i = atoi (field[3]);
512 if (i >= 1 && i < 128)
513 subkey->pubkey_algo = i;
516 /* Field 5 has the long keyid. */
517 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
518 strcpy (subkey->_keyid, field[4]);
520 /* Field 6 has the timestamp (seconds). */
522 subkey->timestamp = parse_timestamp (field[5]);
524 /* Field 7 has the expiration time (seconds). */
526 subkey->expires = parse_timestamp (field[6]);
528 /* Field 8 has the X.509 serial number. */
529 if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
531 key->issuer_serial = strdup (field[7]);
532 if (!key->issuer_serial)
533 return gpg_error_from_errno (errno);
536 /* Field 9 has the ownertrust. */
538 set_ownertrust (key, field[8]);
540 /* Field 10 is not used for gpg due to --fixed-list-mode option
541 but GPGSM stores the issuer name. */
542 if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
543 if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
544 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
546 /* Field 11 has the signature class. */
548 /* Field 12 has the capabilities. */
550 set_mainkey_capability (key, field[11]);
555 /* Start a new subkey. */
556 err = _gpgme_key_add_subkey (key, &subkey);
560 if (rectype == RT_SSB)
563 /* Field 2 has the trust info. */
565 set_subkey_trust_info (subkey, field[1]);
567 /* Field 3 has the key length. */
570 int i = atoi (field[2]);
571 /* Ignore invalid values. */
576 /* Field 4 has the public key algorithm. */
579 int i = atoi (field[3]);
580 if (i >= 1 && i < 128)
581 subkey->pubkey_algo = i;
584 /* Field 5 has the long keyid. */
585 if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
586 strcpy (subkey->_keyid, field[4]);
588 /* Field 6 has the timestamp (seconds). */
590 subkey->timestamp = parse_timestamp (field[5]);
592 /* Field 7 has the expiration time (seconds). */
594 subkey->expires = parse_timestamp (field[6]);
596 /* Field 8 is reserved (LID). */
597 /* Field 9 has the ownertrust. */
598 /* Field 10, the user ID, is n/a for a subkey. */
600 /* Field 11 has the signature class. */
602 /* Field 12 has the capabilities. */
604 set_subkey_capability (subkey, field[11]);
608 /* Field 2 has the trust info, and field 10 has the user ID. */
611 if (_gpgme_key_append_name (key, field[9]))
612 return gpg_error_from_errno (GPG_ERR_ENOMEM); /* FIXME */
616 set_userid_flags (key, field[1]);
617 opd->tmp_uid = key->_last_uid;
623 /* Field 10 has the fingerprint (take only the first one). */
624 if (fields >= 10 && !key->subkeys->fpr && field[9] && *field[9])
626 key->subkeys->fpr = strdup (field[9]);
627 if (!key->subkeys->fpr)
628 return gpg_error_from_errno (errno);
631 /* Field 13 has the gpgsm chain ID (take only the first one). */
632 if (fields >= 13 && !key->chain_id && *field[12])
634 key->chain_id = strdup (field[12]);
636 return gpg_error_from_errno (errno);
645 /* Start a new (revoked) signature. */
646 assert (opd->tmp_uid == key->_last_uid);
647 keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
649 return gpg_error (GPG_ERR_ENOMEM); /* FIXME */
651 /* Field 2 has the calculated trust ('!', '-', '?', '%'). */
656 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
660 keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
664 keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
668 keysig->status = gpg_error (GPG_ERR_GENERAL);
672 keysig->status = gpg_error (GPG_ERR_NO_ERROR);
676 /* Field 4 has the public key algorithm. */
679 int i = atoi (field[3]);
680 if (i >= 1 && i < 128)
681 keysig->pubkey_algo = i;
684 /* Field 5 has the long keyid. */
685 if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
686 strcpy (keysig->_keyid, field[4]);
688 /* Field 6 has the timestamp (seconds). */
690 keysig->timestamp = parse_timestamp (field[5]);
692 /* Field 7 has the expiration time (seconds). */
694 keysig->expires = parse_timestamp (field[6]);
696 /* Field 11 has the signature class (eg, 0x30 means revoked). */
698 if (field[10][0] && field[10][1])
700 int class = _gpgme_hextobyte (field[10]);
703 keysig->class = class;
707 if (field[10][2] == 'x')
708 keysig->exportable = 1;
713 /* Unknown record. */
721 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
724 gpgme_ctx_t ctx = (gpgme_ctx_t) data;
725 gpgme_key_t key = (gpgme_key_t) type_data;
728 struct key_queue_item_s *q, *q2;
730 assert (type == GPGME_EVENT_NEXT_KEY);
732 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
737 q = malloc (sizeof *q);
740 gpgme_key_unref (key);
741 /* FIXME return GPGME_Out_Of_Core; */
746 /* FIXME: Use a tail pointer? */
747 if (!(q2 = opd->key_queue))
751 for (; q2->next; q2 = q2->next)
759 /* Start a keylist operation within CTX, searching for keys which
760 match PATTERN. If SECRET_ONLY is true, only secret keys are
763 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
769 err = _gpgme_op_reset (ctx, 2);
773 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
774 sizeof (*opd), release_op_data);
779 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
781 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
782 keylist_colon_handler, ctx);
786 return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
791 /* Start a keylist operation within CTX, searching for keys which
792 match PATTERN. If SECRET_ONLY is true, only secret keys are
795 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
796 int secret_only, int reserved)
802 err = _gpgme_op_reset (ctx, 2);
806 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
807 sizeof (*opd), release_op_data);
812 _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
813 err = _gpgme_engine_set_colon_line_handler (ctx->engine,
814 keylist_colon_handler, ctx);
818 return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
819 reserved, ctx->keylist_mode);
823 /* Return the next key from the keylist in R_KEY. */
825 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
828 struct key_queue_item_s *queue_item;
833 return gpg_error (GPG_ERR_INV_VALUE);
836 return gpg_error (GPG_ERR_INV_VALUE);
838 err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
845 err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
850 return gpg_error (GPG_ERR_EOF);
853 assert (opd->key_queue);
855 queue_item = opd->key_queue;
856 opd->key_queue = queue_item->next;
860 *r_key = queue_item->key;
866 /* Terminate a pending keylist operation within CTX. */
868 gpgme_op_keylist_end (gpgme_ctx_t ctx)
871 return gpg_error (GPG_ERR_INV_VALUE);
877 /* Get the key with the fingerprint FPR from the crypto backend. If
878 SECRET is true, get the secret key. */
880 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
888 return gpg_error (GPG_ERR_INV_VALUE);
890 if (strlen (fpr) < 16) /* We have at least a key ID. */
891 return gpg_error (GPG_ERR_INV_VALUE);
893 /* FIXME: We use our own context because we have to avoid the user's
894 I/O callback handlers. */
895 err = gpgme_new (&listctx);
898 gpgme_set_protocol (listctx, gpgme_get_protocol (ctx));
899 gpgme_set_keylist_mode (listctx, ctx->keylist_mode);
900 err = gpgme_op_keylist_start (listctx, fpr, secret);
902 err = gpgme_op_keylist_next (listctx, r_key);
905 err = gpgme_op_keylist_next (listctx, &key);
906 if (gpgme_err_code (err) == GPG_ERR_EOF)
907 err = gpg_error (GPG_ERR_NO_ERROR);
912 gpgme_key_unref (key);
913 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
915 gpgme_key_unref (*r_key);
918 gpgme_release (listctx);