diff --git a/NEWS b/NEWS index 28316001..9ca3e757 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ gpgme_set_include_certs CHANGED DEFAULT GPGME_INCLUDE_CERTS_DEFAULT NEW gpgme_recipient_t NEW gpgme_decrypt_result_t EXTENDED: New field recipients. +gpgme_verify_result_t EXTENDED: New fields pubkey_algo, hash_algo. 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 e4071285..1525f8bf 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,8 @@ 2005-06-03 Marcus Brinkmann + * gpgme.texi (Verify): Add information about new fields in + gpgme_signature_t. + * gpgme.texi (Decrypt): Add gpgme_recipient_t. 2005-05-28 Marcus Brinkmann diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 92289c2e..d5c14de4 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -3861,6 +3861,11 @@ The validity of the signature. @item gpgme_error_t validity_reason If a signature is not valid, this provides a reason why. +@item gpgme_pubkey_algo_t +The public key algorithm used to create this signature. + +@item gpgme_hash_algo_t +The hash algorithm used to create this signature. @end table @end deftp diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 4f78e14a..e028514a 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,10 @@ 2005-06-03 Marcus Brinkmann + * gpgme.h (struct _gpgme_signature): New members pubkey_algo and + hash_algo. + * verify.c (parse_valid_sig): Parse pubkey and hash algo numbers. + (parse_new_sig): Parse pubkey, hash algo and timestamp for ERRSIG. + (_gpgme_decrypt_status_handler): Fix last change. * gpgme.h (struct _gpgme_recipient): New structure. diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 31fffe19..18bd9830 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -1247,6 +1247,12 @@ struct _gpgme_signature gpgme_validity_t validity; gpgme_error_t validity_reason; + + /* The public key algorithm used to create the signature. */ + gpgme_pubkey_algo_t pubkey_algo; + + /* The hash algorithm used to create the signature. */ + gpgme_hash_algo_t hash_algo; }; typedef struct _gpgme_signature *gpgme_signature_t; diff --git a/gpgme/verify.c b/gpgme/verify.c index b2e0fcc4..b7fd147d 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -203,6 +203,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) { gpgme_signature_t sig; char *end = strchr (args, ' '); + char *tail; if (end) { @@ -248,39 +249,70 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) break; case GPGME_STATUS_ERRSIG: - if (end) + /* Parse the pubkey algo. */ + if (!end) + goto parse_err_sig_fail; + errno = 0; + sig->pubkey_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + goto parse_err_sig_fail; + end = tail; + while (*end == ' ') + end++; + + /* Parse the hash algo. */ + if (!*end) + goto parse_err_sig_fail; + errno = 0; + sig->hash_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + goto parse_err_sig_fail; + end = tail; + while (*end == ' ') + end++; + + /* Skip the sig class. */ + end = strchr (end, ' '); + if (!end) + goto parse_err_sig_fail; + while (*end == ' ') + end++; + + /* Parse the timestamp. */ + sig->timestamp = _gpgme_parse_timestamp (end, &tail); + if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' ')) + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + while (*end == ' ') + end++; + + /* Parse the return code. */ + if (end[0] && (!end[1] || end[1] == ' ')) { - int i = 0; - /* The return code is the 6th argument, if it is 9, the - problem is a missing key. */ - while (end && i < 4) + switch (end[0]) { - end = strchr (end, ' '); - if (end) - end++; - i++; - } - if (end && end[0] && (!end[1] || end[1] == ' ')) - { - switch (end[0]) - { - case '4': - sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); - break; - - case '9': - sig->status = gpg_error (GPG_ERR_NO_PUBKEY); - break; - - default: - sig->status = gpg_error (GPG_ERR_GENERAL); - } + case '4': + sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + break; + + case '9': + sig->status = gpg_error (GPG_ERR_NO_PUBKEY); + break; + + default: + sig->status = gpg_error (GPG_ERR_GENERAL); } } else - sig->status = gpg_error (GPG_ERR_GENERAL); - break; + goto parse_err_sig_fail; + goto parse_err_sig_ok; + + parse_err_sig_fail: + sig->status = gpg_error (GPG_ERR_GENERAL); + parse_err_sig_ok: + break; + default: return gpg_error (GPG_ERR_GENERAL); } @@ -299,7 +331,6 @@ static gpgme_error_t parse_valid_sig (gpgme_signature_t sig, char *args) { char *end = strchr (args, ' '); - if (end) { *end = '\0'; @@ -316,6 +347,7 @@ parse_valid_sig (gpgme_signature_t sig, char *args) if (!sig->fpr) return gpg_error_from_errno (errno); + /* Skip the creation date. */ end = strchr (end, ' '); if (end) { @@ -329,6 +361,43 @@ parse_valid_sig (gpgme_signature_t sig, char *args) sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail); if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' ')) return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + + while (*end == ' ') + end++; + /* Skip the signature version. */ + end = strchr (end, ' '); + if (end) + { + while (*end == ' ') + end++; + + /* Skip the reserved field. */ + end = strchr (end, ' '); + if (end) + { + /* Parse the pubkey algo. */ + errno = 0; + sig->pubkey_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + + while (*end == ' ') + end++; + + if (*end) + { + /* Parse the hash algo. */ + + errno = 0; + sig->hash_algo = strtol (end, &tail, 0); + if (errno || end == tail || *tail != ' ') + return gpg_error (GPG_ERR_INV_ENGINE); + end = tail; + } + } + } } return 0; }