From b8440749f177805ba99a807b5ec80bec39612d0e Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 3 Jun 2005 00:42:08 +0000 Subject: [PATCH] doc/ 2005-06-03 Marcus Brinkmann * gpgme.texi (Decrypt): Add gpgme_recipient_t. gpgme/ 2005-06-03 Marcus Brinkmann * gpgme.h (struct _gpgme_recipient): New structure. (gpgme_recipient_t): New type. (struct _gpgme_op_decrypt_result): Add member recipients. * decrypt.c (op_data_t): New member last_recipient_p. (_gpgme_op_decrypt_init_result): Initialize last_recipient_p. (parse_enc_to): New function. (_gpgme_decrypt_status_handler): Handle status ENC_TO and NO_SECKEY. --- NEWS | 5 +++ doc/ChangeLog | 4 ++ doc/gpgme.texi | 34 ++++++++++++++++- gpgme/ChangeLog | 9 +++++ gpgme/decrypt.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++-- gpgme/gpgme.h | 21 +++++++++++ 6 files changed, 167 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 42d18147..28316001 100644 --- a/NEWS +++ b/NEWS @@ -13,12 +13,17 @@ Noteworthy changes in version 1.1.0 (unreleased) Because the default changes, this is a slight change of the API semantics. We consider it to be a bug fix. + * Information about the recipients of an encrypted text is now + available at decryption time. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgme_set_engine_info NEW gpgme_ctx_get_engine_info NEW gpgme_ctx_set_engine_info NEW gpgme_set_include_certs CHANGED DEFAULT GPGME_INCLUDE_CERTS_DEFAULT NEW +gpgme_recipient_t NEW +gpgme_decrypt_result_t EXTENDED: New field recipients. GPGME_STATUS_SIG_SUBPACKET NEW GPGME_STATUS_NEED_PASSPHRASE_PIN NEW GPGME_STATUS_SC_OP_FAILURE NEW diff --git a/doc/ChangeLog b/doc/ChangeLog index 67519fa7..e4071285 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2005-06-03 Marcus Brinkmann + + * gpgme.texi (Decrypt): Add gpgme_recipient_t. + 2005-05-28 Marcus Brinkmann * gpgme.texi (Key Listing Mode): Fix return type of diff --git a/doc/gpgme.texi b/doc/gpgme.texi index cae9b70c..92289c2e 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -3622,9 +3622,38 @@ operation could be started successfully, and @code{GPG_ERR_INV_VALUE} if @var{cipher} or @var{plain} is not a valid pointer. @end deftypefun +@deftp {Data type} {gpgme_recipient_t} +This is a pointer to a structure used to store information about the +recipient of an encrypted text which is decrypted in a +@code{gpgme_op_decrypt} operation. This information (except for the +status field) is even available before the operation finished +successfully, for example in a passphrase callback. The structure +contains the following members: + +@table @code +@item gpgme_recipient_t next +This is a pointer to the next recipient structure in the linked list, +or @code{NULL} if this is the last element. + +@item gpgme_pubkey_algo_t +The public key algorithm used in the encryption. + +@item unsigned int wrong_key_usage : 1 +This is true if the key was not used according to its policy. + +@item char *keyid +This is the key ID of the key (in hexadecimal digits) used as +recipient. + +@item gpgme_error_t status +This is an error number with the error code GPG_ERR_NO_SECKEY if the +secret key for this recipient is not available, and 0 otherwise. +@end table +@end deftp + @deftp {Data type} {gpgme_decrypt_result_t} This is a pointer to a structure used to store the result of a -@code{gpgme_op_decrypt} operation. After successfully encrypting +@code{gpgme_op_decrypt} operation. After successfully decrypting data, you can retrieve the pointer to the result with @code{gpgme_op_decrypt_result}. The structure contains the following members: @@ -3636,6 +3665,9 @@ algorithm that is not supported. @item unsigned int wrong_key_usage : 1 This is true if the key was not used according to its policy. + +@item gpgme_recipient_t recipient +This is a linked list of recipients to which this message was encrypted. @end table @end deftp diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index a28ece04..52a77d05 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,14 @@ 2005-06-03 Marcus Brinkmann + * gpgme.h (struct _gpgme_recipient): New structure. + (gpgme_recipient_t): New type. + (struct _gpgme_op_decrypt_result): Add member recipients. + * decrypt.c (op_data_t): New member last_recipient_p. + (_gpgme_op_decrypt_init_result): Initialize last_recipient_p. + (parse_enc_to): New function. + (_gpgme_decrypt_status_handler): Handle status ENC_TO and + NO_SECKEY. + * wait-global.c (gpgme_wait): Break out of the fd processing loop after an error. Reported by Igor Belyi . diff --git a/gpgme/decrypt.c b/gpgme/decrypt.c index c235be4a..bbbe2957 100644 --- a/gpgme/decrypt.c +++ b/gpgme/decrypt.c @@ -38,6 +38,11 @@ typedef struct int okay; int failed; + + /* A pointer to the next pointer of the last recipient in the list. + This makes appending new invalid signers painless while + preserving the order. */ + gpgme_recipient_t *last_recipient_p; } *op_data_t; @@ -67,6 +72,60 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx) } +static gpgme_error_t +parse_enc_to (char *args, gpgme_recipient_t *recp) +{ + gpgme_recipient_t rec; + char *tail; + int i; + + rec = malloc (sizeof (*rec)); + if (!rec) + return gpg_error_from_errno (errno); + + rec->next = NULL; + rec->keyid = rec->_keyid; + rec->status = 0; + + for (i = 0; i < sizeof (rec->_keyid) - 1; i++) + { + if (args[i] == '\0' || args[i] == ' ') + break; + + rec->_keyid[i] = args[i]; + } + rec->_keyid[i] = '\0'; + + args = &args[i]; + if (*args != '\0' && *args != ' ') + { + free (rec); + return gpg_error (GPG_ERR_INV_ENGINE); + } + + while (*args == ' ') + args++; + + if (*args) + { + errno = 0; + rec->pubkey_algo = strtol (args, &tail, 0); + if (errno || args == tail || *tail != ' ') + { + /* The crypto backend does not behave. */ + free (rec); + return gpg_error (GPG_ERR_INV_ENGINE); + } + } + + /* FIXME: The key length is always 0 right now, so no need to parse + it. */ + + *recp = rec; + return 0; +} + + gpgme_error_t _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args) @@ -151,7 +210,33 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, } } break; - + + case GPGME_STATUS_ENC_TO: + err = parse_enc_to (args, opd->last_recipient_p); + if (err) + return err; + + opd->last_recipient_p = &(*opd->last_recipient_p)->next; + break; + + case GPGME_STATUS_NO_SECKEY: + { + gpgme_recipient_t rec = opd->result.recipients; + + while (rec) + { + if (!strcmp (rec->keyid, args)) + { + rec->status = gpg_error (GPG_ERR_NO_SECKEY); + break; + } + } + /* FIXME: Is this ok? */ + if (!rec) + return gpg_error (GPG_ERR_INV_ENGINE); + } + break; + default: break; } @@ -175,11 +260,18 @@ decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args) gpgme_error_t _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx) { + gpgme_error_t err; void *hook; op_data_t opd; - return _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, - sizeof (*opd), release_op_data); + err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, + sizeof (*opd), release_op_data); + opd = hook; + if (err) + return err; + + opd->last_recipient_p = &opd->result.recipients; + return 0; } diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 0708d378..31fffe19 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -1080,6 +1080,25 @@ gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[], /* Decryption. */ + +struct _gpgme_recipient +{ + struct _gpgme_recipient *next; + + /* The key ID of key for which the text was encrypted. */ + char *keyid; + + /* Internal to GPGME, do not use. */ + char _keyid[16 + 1]; + + /* The public key algorithm of the recipient key. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The status of the recipient. */ + gpgme_error_t status; +}; +typedef struct _gpgme_recipient *gpgme_recipient_t; + struct _gpgme_op_decrypt_result { char *unsupported_algorithm; @@ -1089,6 +1108,8 @@ struct _gpgme_op_decrypt_result /* Internal to GPGME, do not use. */ int _unused : 31; + + gpgme_recipient_t recipients; }; typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t;