diff options
| author | Marcus Brinkmann <[email protected]> | 2003-04-28 23:59:03 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2003-04-28 23:59:03 +0000 | 
| commit | 30cdf132842cec187e428af413dbc2c8fafa341b (patch) | |
| tree | db677058ae833586200d7660791f39e776efc8fc | |
| parent | 2003-04-28 Marcus Brinkmann <[email protected]> (diff) | |
| download | gpgme-30cdf132842cec187e428af413dbc2c8fafa341b.tar.gz gpgme-30cdf132842cec187e428af413dbc2c8fafa341b.zip | |
doc/
2003-04-28  Marcus Brinkmann  <[email protected]>
	* gpgme.texi (Verify): Rewritten to take into account new and
	deprecated functions and data types.
gpgme/
2003-04-28  Marcus Brinkmann  <[email protected]>
	* gpgme.h (struct _gpgme_sig_notation): New structure.
	(GpgmeSigNotation): New type.
	(struct _gpgme_signature): New structure.
	(GpgmeSignature): New type.
	(struct _gpgme_op_verify_result): New structure.
	(GpgmeVerifyResult): New type.
	(gpgme_op_verify_result): New prototype.
	(gpgme_get_notation): Remove prototype.
	* ops.h (_gpgme_op_verify_init_result): New prototype.
	(_gpgme_verify_status_handler): Change first argument to void *.
	* util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error):
	New prototypes.
	* conversion.c (_gpgme_decode_percent_string): New function.
	(gnupg_errors): New static global.
	(_gpgme_map_gnupg_error): New function.
	* gpgme.c (gpgme_release): Don't release CTX->notation.
	(gpgme_get_notation): Remove function.
	* decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call
	_gpgme_op_verify_init_result.
	* verify.c: Do not include <stdio.h>, <assert.h> and "key.h", but
	do include "gpgme.h".
	(struct verify_result): Replace with ...
	(op_data_t): ... this type.
	(release_verify_result): Remove function.
	(release_op_data): New function.
	(is_token): Remove function.
	(skip_token): Remove function.
	(copy_token): Remove function.
	(gpgme_op_verify_result): New function.
	(calc_sig_summary): Rewritten.
	(finish_sig): Remove function.
	(parse_new_sig): New function.
	(parse_valid_sig): New function.
	(parse_notation): New function.
	(parse_trust): New function.
	(parse_error): New function.
	(_gpgme_verify_status_handler): Rewritten.  Change first argument
	to void *.
	(_gpgme_op_verify_start): Rework error handling.  Call
	_gpgme_op_verify_init_result.
	(gpgme_op_verify): Do not release or clear CTX->notation.
	(gpgme_get_sig_status): Rewritten.
	(gpgme_get_sig_string_attr): Likewise.
	(gpgme_get_sig_ulong_attr): Likewise.
	(gpgme_get_sig_key): Likewise.
| -rw-r--r-- | NEWS | 19 | ||||
| -rw-r--r-- | TODO | 7 | ||||
| -rw-r--r-- | doc/ChangeLog | 3 | ||||
| -rw-r--r-- | doc/gpgme.texi | 465 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 46 | ||||
| -rw-r--r-- | gpgme/conversion.c | 172 | ||||
| -rw-r--r-- | gpgme/decrypt-verify.c | 4 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 21 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 92 | ||||
| -rw-r--r-- | gpgme/ops.h | 7 | ||||
| -rw-r--r-- | gpgme/sign.c | 2 | ||||
| -rw-r--r-- | gpgme/util.h | 10 | ||||
| -rw-r--r-- | gpgme/verify.c | 1024 | ||||
| -rw-r--r-- | tests/gpg/t-verify.c | 282 | ||||
| -rw-r--r-- | tests/gpgsm/t-verify.c | 36 | 
15 files changed, 1399 insertions, 791 deletions
| @@ -86,14 +86,17 @@ Noteworthy changes in version 0.4.1 (unreleased)     information about the result of an encryption operation in     a GpgmeEncryptResult object. - * The new gpgme_op_encrypt_result function provides detailed -   information about the result of an encryption operation in -   a GpgmeEncryptResult object. -   * The new gpgme_op_decrypt_result function provides detailed     information about the result of an encryption operation in     a GpgmeDecryptResult object. + * The new gpgme_op_verify_result function provides detailed +   information about the result of an verify operation in +   a GpgmeVerifyResult object.  Because of this, the GPGME_SIG_STAT_* +   values, gpgme_get_sig_status, gpgme_get_sig_ulong_attr, +   gpgme_get_sig_string_attr and gpgme_get_sig_key are now deprecated, +   and gpgme_get_notation is removed. +   * Interface changes relative to the 0.4.0 release:  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  GpgmeIOCb			CHANGED: Return type from void to GpgmeError. @@ -136,6 +139,14 @@ GpgmeEncryptResult		NEW  gpgme_op_encrypt_result		NEW  GpgmeDecryptResult		NEW  gpgme_op_decrypt_result		NEW +GpgmeVerifyResult		NEW +gpgme_op_verify_result		NEW +gpgme_get_notation		REMOVED: Access verify result directly instead. +gpgme_get_sig_key		DEPRECATED: Use gpgme_get_key with fingerprint. +gpgme_get_sig_ulong_attr	DEPRECATED: Use verify result directly. +gpgme_get_sig_string_attr	DEPRECATED: Use verify result directly. +GPGME_SIG_STAT_*		DEPRECATED: Use error value in sig status. +gpgme_get_sig_status		DEPRECATED: Use verify result directly.  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Noteworthy changes in version 0.4.0 (2002-12-23) @@ -14,6 +14,13 @@ Hey Emacs, this is -*- outline -*- mode!  *** GPGME_Busy, GPGME_No_Request  *** GPGME_No_Passphrase  *** GPGME_Invalid_Recipient, GPGME_No_Recipients +*** GPGME_No_Passphrase +*** gpgme_op_import_ext +*** gpgme_get_sig_key +*** gpgme_get_sig_ulong_attr +*** gpgme_get_sig_string_attr +*** GPGME_SIG_STAT_* +*** gpgme_get_sig_status  * Thread support:  ** Build thread modules for static linking (which just suck in the diff --git a/doc/ChangeLog b/doc/ChangeLog index 778625e4..653c216b 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,5 +1,8 @@  2003-04-28  Marcus Brinkmann  <[email protected]> +	* gpgme.texi (Verify): Rewritten to take into account new and +	deprecated functions and data types. +  	* gpgme.texi (Decrypt): Descript gpgme_op_decrypt_result and  	GpgmeDecryptResult. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 4e15fa07..a05a0e64 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -2805,56 +2805,6 @@ next operation is started on the context.  @cindex signature, verification  @cindex cryptographic operation, verification  @cindex cryptographic operation, signature check -@cindex signature, status - -@deftp {Data type} {enum GpgmeSigStat} -@tindex GpgmeSigStat -The @code{GpgmeSigStat} type holds the result of a signature check, or -the combined result of all signatures.  The following results are -possible: - -@table @code -@item GPGME_SIG_STAT_NONE -This status should not occur in normal operation. - -@item GPGME_SIG_STAT_GOOD -This status indicates that the signature is valid.  For the combined -result this status means that all signatures are valid. - -@item GPGME_SIG_STAT_GOOD_EXP -This status indicates that the signature is valid but expired.  For -the combined result this status means that all signatures are valid -and expired. - -@item GPGME_SIG_STAT_GOOD_EXPKEY -This status indicates that the signature is valid but the key used to -verify the signature has expired.  For the combined result this status -means that all signatures are valid and all keys are expired. - -@item GPGME_SIG_STAT_BAD -This status indicates that the signature is invalid.  For the combined -result this status means that all signatures are invalid. - -@item GPGME_SIG_STAT_NOKEY -This status indicates that the signature could not be verified due to -a missing key.  For the combined result this status means that all -signatures could not be checked due to missing keys. - -@item GPGME_SIG_STAT_NOSIG -This status indicates that the signature data provided was not a real -signature. - -@item GPGME_SIG_STAT_ERROR -This status indicates that there was some other error which prevented -the signature verification. - -@item GPGME_SIG_STAT_DIFF -For the combined result this status means that at least two signatures -have a different status.  You can get each key's status with -@code{gpgme_get_sig_status}. -@end table -@end deftp -  @deftypefun GpgmeError gpgme_op_verify (@w{GpgmeCtx @var{ctx}}, @w{GpgmeData @var{sig}}, @w{GpgmeData @var{signed_text}}, @w{GpgmeData @var{plain}})  The function @code{gpgme_op_verify} verifies that the signature in the @@ -2867,7 +2817,7 @@ writable data object that will contain the plaintext after successful  verification.  The results of the individual signature verifications can be retrieved -with @code{gpgme_get_sig_status} and @code{gpgme_get_sig_key}. +with @code{gpgme_op_verify_result}.  The function returns @code{GPGME_No_Error} if the operation could be  completed successfully, @code{GPGME_Invalid_Value} if @var{ctx}, @@ -2889,76 +2839,41 @@ started successfully, @code{GPGME_Invalid_Value} if @var{ctx},  data to verify.  @end deftypefun -@deftypefun {const char *} gpgme_get_sig_status (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeSigStat *@var{r_stat}}, @w{time_t *@var{r_created}}) -The function @code{gpgme_get_sig_status} receives information about a -signature after the @code{gpgme_op_verify} or -@code{gpgme_op_verify_decrypt} operation.  A single detached signature -can contain signatures by more than one key.  The @var{idx} specifies -which signature's information should be retrieved, starting from -@var{0}. - -The status of the signature will be returned in @var{r_stat} if it is -not @code{NULL}.  The creation time stamp of the signature will be -returned in @var{r_created} if it is not @var{NULL}. - -The function returns a statically allocated string that contains the -fingerprint of the key which signed the plaintext, or @code{NULL} if -@var{ctx} is not a valid pointer, the operation is still pending, or -no verification could be performed. -@end deftypefun - -@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{what}}, @w{int @var{whatidx}}) -This function is similar to @code{gpgme_get_sig_status} but may be used -to retrieve more detailed information.  @var{ctx} should be the context -used for the last signature verification, @var{idx} is used to enumerate -over all signatures starting with @code{0} and @var{whatidx} should be -@code{0} unless otherwise stated. +@deftp {Data type} {GpgmeSigNotation} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_verify} operation.  The structure contains the +following members: -The following values may be used for @var{what}:  @table @code -@item GPGME_ATTR_FPR -Return the fingerprint of the key used to create the signature. +@item GpgmeSigNotation next +This is a pointer to the next new signature notation structure in the +linked list, or @code{NULL} if this is the last element. -@item GPGME_ATTR_ERRTOK -Return a token with a more detailed error description.  A @var{whatidx} -of @code{0} returns an error token associated with validity calculation, -a value of @code{1} return an error token related to the certificate -checking. +@item char *name +The name of the notation field.  If this is @code{NULL}, then the +member @code{value} will contain a policy URL. +@item char *value +The value of the notation field.  If @code{name} is @code{NULL}, then +this is a policy URL.  @end table -@end deftypefun - -@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{whatidx}}) -This function is similar to @code{gpgme_get_sig_string_attr} but used -for attributes which can be represented by an @code{unsigned long} data -type.  @var{ctx} should be the context used for the last signature -verification, @var{idx} is used to enumerate over all signatures -starting with @code{0} and @var{whatidx} should be @code{0} unless -otherwise stated. - -The following values may be used for @var{what}: -@table @code -@item GPGME_ATTR_CREATED -Return the creation time of the signature in seconds since Epoch.  This -is the same value as returned by @code{gpgme_get_sig_status}. - -@item GPGME_ATTR_EXPIRE -Return the expiration time of the signature in seconds since Epoch.  +@end deftp -@item GPGME_ATTR_VALIDITY -Returns the validity of the key used to create the signature.  This is a -shortcut function which avoids an extra key lookup.  The value returned -is one of @code{GPGME_VALIDITY_UNKNOWN}, @code{GPGME_VALIDITY_NEVER}, -@code{GPGME_VALIDITY_MARGINAL} or @code{GPGME_VALIDITY_FULL}. +@deftp {Data type} {GpgmeSignature} +This is a pointer to a structure used to store a part of the result of +a @code{gpgme_op_verify} operation.  The structure contains the +following members: -@item GPGME_ATTR_SIG_STATUS -This is the same value as returned by @code{gpgme_get_sig_status}. +@table @code +@item GpgmeSignature next +This is a pointer to the next new signature structure in the linked +list, or @code{NULL} if this is the last element. -@item GPGME_ATTR_SIG_SUMMARY -This returns a bit vector giving a summary of the signature status. -Itprovides an easy interface to a defined semantic of the signature -status.  Checking just one bit is sufficient to see whether a signature -is valid without any restrictions. +@item unsigned int summary; +This is a bit vector giving a summary of the signature status.  It +provides an easy interface to a defined semantic of the signature +status.  Checking just one bit is sufficient to see whether a +signature is valid without any restrictions.  The defined bits are:    @table @code @@ -2999,44 +2914,316 @@ The defined bits are:    @item GPGME_SIGSUM_SYS_ERROR    A system error occured.  +  @end table + +@item char *fpr +This is the fingerprint or key ID of the signature. +@item GpgmeError status +This is the status of the signature.  In particular, the following +status codes are of interest: + +  @table @code +  @item GPGME_No_Error +  This status indicates that the signature is valid.  For the combined +  result this status means that all signatures are valid. + +  @item GPGME_Sig_Expired +  This status indicates that the signature is valid but expired.  For +  the combined result this status means that all signatures are valid +  and expired. + +  @item GPGME_Key_Expired +  This status indicates that the signature is valid but the key used to +  verify the signature has expired.  For the combined result this status +  means that all signatures are valid and all keys are expired. + +  @item GPGME_Bad_Signature +  This status indicates that the signature is invalid.  For the combined +  result this status means that all signatures are invalid. + +  @item GPGME_No_Public_Key +  This status indicates that the signature could not be verified due to +  a missing key.  For the combined result this status means that all +  signatures could not be checked due to missing keys. + +  @item GPGME_General_Error +  This status indicates that there was some other error which prevented +  the signature verification.    @end table +@item GpgmeSigNotation notations +This is a linked list with the notation data and policy URLs. + +@item unsigned long timestamp +The creation timestamp of this signature. + +@item unsigned long exp_timestamp +The expiration timestamp of this signature, or 0 if the signature does +not expire. + +@item int wrong_key_usage : 1; + +@item GpgmeValidity validity + +@item GpgmeError validity_reason  @end table +@end deftp + +@deftp {Data type} {GpgmeVerifyResult} +This is a pointer to a structure used to store the result of a +@code{gpgme_op_verify} operation.  After successfully verifying a +signature, you can retrieve the pointer to the result with +@code{gpgme_op_verify_result}.  The structure contains the following +member: + +@table @code +@item GpgmeSignature signatures +A linked list with information about all signatures for which a +verification was attempted. +@end table +@end deftp + +@deftypefun GpgmeSignResult gpgme_op_verify_result (@w{GpgmeCtx @var{ctx}}) +The function @code{gpgme_op_verify_result} returns a +@code{GpgmeVerifyResult} pointer to a structure holding the result of +a @code{gpgme_op_verify} operation.  The pointer is only valid if the +last operation on the context was a @code{gpgme_op_verify} or +@code{gpgme_op_verify_start} operation, and if this operation finished +successfully.  The returned pointer is only valid until the next +operation is started on the context.  @end deftypefun -@deftypefun {const char *} gpgme_get_sig_key (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeKey *@var{r_key}}) -The function @code{gpgme_get_sig_status} receives a @code{GpgmeKey} -object for the key which was used to verify the signature after the -@code{gpgme_op_verify} or @code{gpgme_op_verify_decrypt} operation.  A -single detached signature can contain signatures by more than one key. -The @var{idx} specifies which signature's information should be -retrieved, starting from @var{0}.  The key will have on reference for -the user. +The following interfaces are deprecated and only provided for backward +compatibility.  Don't use them.  They will be removed in a future +version of @acronym{GPGME}. -The function is a convenient way to retrieve the keys belonging to the -fingerprints returned by @code{gpgme_get_sig_status}. +@deftp {Data type} {enum GpgmeSigStat} +@tindex GpgmeSigStat +The @code{GpgmeSigStat} type holds the result of a signature check, or +the combined result of all signatures.  The following results are +possible: -The function returns @code{GPGME_No_Error} if the key could be -returned, @code{GPGME_Invalid_Value} if @var{r_key} is not a valid -pointer, @code{GPGME_Invalid_Key} if the fingerprint is not valid, -@code{GPGME_EOF} if @var{idx} is too large, or some other error value -if a problem occurred requesting the key. +@table @code +@item GPGME_SIG_STAT_NONE +This status should not occur in normal operation. + +@item GPGME_SIG_STAT_GOOD +This status indicates that the signature is valid.  For the combined +result this status means that all signatures are valid. + +@item GPGME_SIG_STAT_GOOD_EXP +This status indicates that the signature is valid but expired.  For +the combined result this status means that all signatures are valid +and expired. + +@item GPGME_SIG_STAT_GOOD_EXPKEY +This status indicates that the signature is valid but the key used to +verify the signature has expired.  For the combined result this status +means that all signatures are valid and all keys are expired. + +@item GPGME_SIG_STAT_BAD +This status indicates that the signature is invalid.  For the combined +result this status means that all signatures are invalid. + +@item GPGME_SIG_STAT_NOKEY +This status indicates that the signature could not be verified due to +a missing key.  For the combined result this status means that all +signatures could not be checked due to missing keys. + +@item GPGME_SIG_STAT_NOSIG +This status indicates that the signature data provided was not a real +signature. + +@item GPGME_SIG_STAT_ERROR +This status indicates that there was some other error which prevented +the signature verification. + +@item GPGME_SIG_STAT_DIFF +For the combined result this status means that at least two signatures +have a different status.  You can get each key's status with +@code{gpgme_get_sig_status}. +@end table +@end deftp + +@deftypefun {const char *} gpgme_get_sig_status (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeSigStat *@var{r_stat}}, @w{time_t *@var{r_created}}) +The function @code{gpgme_get_sig_status} is equivalent to: +  +@example +  GpgmeVerifyResult result; +  GpgmeSignature sig; + +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; + +  while (sig && idx) +    @{ +      sig = sig->next; +      idx--; +    @} +  if (!sig || idx) +    return NULL; + +  if (r_stat) +    @{ +      switch (sig->status) +	@{ +	case GPGME_No_Error: +	  *r_stat = GPGME_SIG_STAT_GOOD; +	  break; +	   +	case GPGME_Bad_Signature: +	  *r_stat = GPGME_SIG_STAT_BAD; +	  break; +	   +	case GPGME_No_Public_Key: +	  *r_stat = GPGME_SIG_STAT_NOKEY; +	  break; +	   +	case GPGME_No_Data: +	  *r_stat = GPGME_SIG_STAT_NOSIG; +	  break; +	   +	case GPGME_Sig_Expired: +	  *r_stat = GPGME_SIG_STAT_GOOD_EXP; +	  break; +	   +	case GPGME_Key_Expired: +	  *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY; +	  break; +	   +	default: +	  *r_stat = GPGME_SIG_STAT_ERROR; +	  break; +	@} +    @} +  if (r_created) +    *r_created = sig->timestamp; +  return sig->fpr; +@end example +@end deftypefun + +@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{what}}, @w{int @var{whatidx}}) +The function @code{gpgme_get_sig_string_attr} is equivalent to: +  +@example +  GpgmeVerifyResult result; +  GpgmeSignature sig; + +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; + +  while (sig && idx) +    @{ +      sig = sig->next; +      idx--; +    @} +  if (!sig || idx) +    return NULL; + +  switch (what) +    @{ +    case GPGME_ATTR_FPR: +      return sig->fpr; + +    case GPGME_ATTR_ERRTOK: +      if (whatidx == 1) +        return sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; +      else +	return ""; +    default: +      break; +    @} + +  return NULL; +@end example +@end deftypefun + +@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{whatidx}}) +The function @code{gpgme_get_sig_ulong_attr} is equivalent to: +  +@example +  GpgmeVerifyResult result; +  GpgmeSignature sig; + +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; + +  while (sig && idx) +    @{ +      sig = sig->next; +      idx--; +    @} +  if (!sig || idx) +    return 0; + +  switch (what) +    @{ +    case GPGME_ATTR_CREATED: +      return sig->timestamp; + +    case GPGME_ATTR_EXPIRE: +      return sig->exp_timestamp; + +    case GPGME_ATTR_VALIDITY: +      return (unsigned long) sig->validity; + +    case GPGME_ATTR_SIG_STATUS: +      switch (sig->status) +	@{ +	case GPGME_No_Error: +	  return GPGME_SIG_STAT_GOOD; +	   +	case GPGME_Bad_Signature: +	  return GPGME_SIG_STAT_BAD; +	   +	case GPGME_No_Public_Key: +	  return GPGME_SIG_STAT_NOKEY; +	   +	case GPGME_No_Data: +	  return GPGME_SIG_STAT_NOSIG; +	   +	case GPGME_Sig_Expired: +	  return GPGME_SIG_STAT_GOOD_EXP; +	   +	case GPGME_Key_Expired: +	  return GPGME_SIG_STAT_GOOD_EXPKEY; +	   +	default: +	  return GPGME_SIG_STAT_ERROR; +	@} + +    case GPGME_ATTR_SIG_SUMMARY: +      return sig->summary; + +    default: +      break; +    @} +  return 0; +@end example  @end deftypefun -@deftypefun {char *} gpgme_get_notation (@w{GpgmeCtx @var{ctx}}) -The function @code{gpgme_get_notation} can be used to retrieve -notation data from the last signature check in the context @var{ctx}. +@deftypefun {const char *} gpgme_get_sig_key (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeKey *@var{r_key}}) +The function @code{gpgme_get_sig_key} is equivalent to: + +@example +  GpgmeVerifyResult result; +  GpgmeSignature sig; + +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; -If there is notation data available from the last signature check, -this function may be used to return this notation data as a string. -The string is an XML representation of that data embedded in a -<notation> container.  The user has to release the string with -@code{free}. +  while (sig && idx) +    @{ +      sig = sig->next; +      idx--; +    @} +  if (!sig || idx) +    return GPGME_EOF; -The function returns a string if the notation data is available or -@code{NULL} if there is no such data available. +  return gpgme_get_key (ctx, sig->fpr, r_key, 0, 0); +@end example  @end deftypefun @@ -3204,7 +3391,7 @@ The hash algorithm used to create this signature.  @item unsigned long class  The signature class of this signature. -@item long int created +@item long int timestamp  The creation timestamp of this signature.  @item char *fpr diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 720dc7b0..c371ce3f 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,51 @@  2003-04-28  Marcus Brinkmann  <[email protected]> +	* gpgme.h (struct _gpgme_sig_notation): New structure. +	(GpgmeSigNotation): New type. +	(struct _gpgme_signature): New structure. +	(GpgmeSignature): New type. +	(struct _gpgme_op_verify_result): New structure. +	(GpgmeVerifyResult): New type. +	(gpgme_op_verify_result): New prototype. +	(gpgme_get_notation): Remove prototype. +	* ops.h (_gpgme_op_verify_init_result): New prototype. +	(_gpgme_verify_status_handler): Change first argument to void *. +	* util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error): +	New prototypes. +	* conversion.c (_gpgme_decode_percent_string): New function. +	(gnupg_errors): New static global. +	(_gpgme_map_gnupg_error): New function. +	* gpgme.c (gpgme_release): Don't release CTX->notation. +	(gpgme_get_notation): Remove function. +	* decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call +	_gpgme_op_verify_init_result. +	* verify.c: Do not include <stdio.h>, <assert.h> and "key.h", but +	do include "gpgme.h". +	(struct verify_result): Replace with ... +	(op_data_t): ... this type. +	(release_verify_result): Remove function. +	(release_op_data): New function. +	(is_token): Remove function. +	(skip_token): Remove function. +	(copy_token): Remove function. +	(gpgme_op_verify_result): New function. +	(calc_sig_summary): Rewritten. +	(finish_sig): Remove function. +	(parse_new_sig): New function. +	(parse_valid_sig): New function. +	(parse_notation): New function. +	(parse_trust): New function. +	(parse_error): New function. +	(_gpgme_verify_status_handler): Rewritten.  Change first argument +	to void *. +	(_gpgme_op_verify_start): Rework error handling.  Call +	_gpgme_op_verify_init_result. +	(gpgme_op_verify): Do not release or clear CTX->notation. +	(gpgme_get_sig_status): Rewritten. +	(gpgme_get_sig_string_attr): Likewise. +	(gpgme_get_sig_ulong_attr): Likewise. +	(gpgme_get_sig_key): Likewise. +  	* gpgme.h (struct _gpgme_op_decrypt_result): New structure.  	(GpgmeDecryptResult): New type.  	(gpgme_op_decrypt_result): New prototype. diff --git a/gpgme/conversion.c b/gpgme/conversion.c index 5b2cb67a..57e2f514 100644 --- a/gpgme/conversion.c +++ b/gpgme/conversion.c @@ -161,6 +161,178 @@ _gpgme_decode_c_string (const char *src, char **destp, int len)    return 0;  } + +/* Decode the percent escaped string SRC and store the result in the +   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a +   large enough buffer is allocated with malloc and *DESTP is set to +   the result.  Currently, LEN is only used to specify if allocation +   is desired or not, the caller is expected to make sure that *DESTP +   is large enough if LEN is not zero.  */ +GpgmeError +_gpgme_decode_percent_string (const char *src, char **destp, int len) +{ +  char *dest; + +  /* Set up the destination buffer.  */ +  if (len) +    { +      if (len < strlen (src) + 1) +	return GPGME_General_Error; + +      dest = *destp; +    } +  else +    { +      /* The converted string will never be larger than the original +	 string.  */ +      dest = malloc (strlen (src) + 1); +      if (!dest) +	return GPGME_Out_Of_Core; + +      *destp = dest; +    } + +  /* Convert the string.  */ +  while (*src) +    { +      if (*src != '%') +	{ +	  *(dest++) = *(src++); +	  continue; +	} +      else +	{ +	  int val = _gpgme_hextobyte (&src[1]); +	   +	  if (val == -1) +	    { +	      /* Should not happen.  */ +	      *(dest++) = *(src++); +	      if (*src) +		*(dest++) = *(src++); +	      if (*src) +		*(dest++) = *(src++); +	    } +	  else +	    { +	      if (!val) +		{ +		  /* A binary zero is not representable in a C +		     string.  */ +		  *(dest++) = '\\'; +		  *(dest++) = '0';  +		} +	      else  +		*((unsigned char *) dest++) = val; +	      src += 3; +	    } +	} +    } +  *(dest++) = 0; + +  return 0; +} + + +static struct +{ +  char *name; +  GpgmeError err; +} gnupg_errors[] = +  { +    { "EOF", GPGME_EOF }, +    { "No_Error", GPGME_No_Error }, +    { "General_Error", GPGME_General_Error }, +    { "Out_Of_Core", GPGME_Out_Of_Core }, +    { "Invalid_Value", GPGME_Invalid_Value }, +    { "IO_Error", GPGME_General_Error }, +    { "Resource_Limit", GPGME_General_Error }, +    { "Internal_Error", GPGME_General_Error }, +    { "Bad_Certificate", GPGME_Invalid_Key }, +    { "Bad_Certificate_Chain", GPGME_General_Error }, +    { "Missing_Certificate", GPGME_No_Public_Key }, +    { "No_Data", GPGME_No_Data }, +    { "Bad_Signature", GPGME_Bad_Signature }, +    { "Not_Implemented", GPGME_Not_Implemented }, +    { "Conflict", GPGME_Conflict }, +    { "Bug", GPGME_General_Error }, +    { "Read_Error", GPGME_General_Error }, +    { "Write_Error", GPGME_General_Error }, +    { "Invalid_Line", GPGME_General_Error }, +    { "Incomplete_Line", GPGME_General_Error }, +    { "Invalid_Response", GPGME_General_Error }, +    { "Agent_Error", GPGME_General_Error }, +    { "No_Public_Key", GPGME_No_Public_Key }, +    { "No_Secret_Key", GPGME_No_Secret_Key }, +    { "File_Open_Error", GPGME_General_Error }, +    { "File_Create_Error", GPGME_General_Error }, +    { "File_Error", GPGME_General_Error }, +    { "Not_Supported", GPGME_General_Error }, +    { "Invalid_Data", GPGME_General_Error }, +    { "Assuan_Server_Fault", GPGME_General_Error }, +    { "Assuan_Error", GPGME_General_Error }, +    { "Invalid_Session_Key", GPGME_General_Error }, +    { "Invalid_Sexp", GPGME_General_Error }, +    { "Unsupported_Algorithm", GPGME_Unsupported_Algorithm }, +    { "No_PIN_Entry", GPGME_Invalid_Engine }, +    { "PIN_Entry_Error", GPGME_Invalid_Engine }, +    { "Bad_PIN", GPGME_Bad_Passphrase }, +    { "Bad_Passphrase", GPGME_Bad_Passphrase }, +    { "Invalid_Name", GPGME_General_Error }, +    { "Bad_Public_Key", GPGME_General_Error }, +    { "Bad_Secret_Key", GPGME_General_Error }, +    { "Bad_Data", GPGME_General_Error }, +    { "Invalid_Parameter", GPGME_General_Error }, +    { "Tribute_to_D_A", GPGME_General_Error }, +    { "No_Dirmngr", GPGME_Invalid_Engine }, +    { "Dirmngr_Error", GPGME_General_Error }, +    { "Certificate_Revoked", GPGME_Key_Revoked }, +    { "No_CRL_Known", GPGME_No_CRL_Known }, +    { "CRL_Too_Old", GPGME_CRL_Too_Old }, +    { "Line_Too_Long", GPGME_General_Error }, +    { "Not_Trusted", GPGME_Key_Not_Trusted }, +    { "Canceled", GPGME_Canceled }, +    { "Bad_CA_Certificate", GPGME_General_Error }, +    { "Certificate_Expired", GPGME_Key_Expired }, +    { "Certificate_Too_Young", GPGME_Invalid_Key }, +    { "Unsupported_Certificate", GPGME_General_Error }, +    { "Unknown_Sexp", GPGME_General_Error }, +    { "Unsupported_Protection", GPGME_General_Error }, +    { "Corrupted_Protection", GPGME_General_Error }, +    { "Ambiguous_Name", GPGME_Ambiguous_Specification }, +    { "Card_Error", GPGME_General_Error }, +    { "Card_Reset", GPGME_General_Error }, +    { "Card_Removed", GPGME_General_Error }, +    { "Invalid_Card", GPGME_General_Error }, +    { "Card_Not_Present", GPGME_General_Error }, +    { "No_PKCS15_App", GPGME_General_Error }, +    { "Not_Confirmed", GPGME_General_Error }, +    { "Configuration_Error", GPGME_General_Error }, +    { "No_Policy_Match", GPGME_Policy_Mismatch }, +    { "Invalid_Index", GPGME_General_Error }, +    { "Invalid_Id", GPGME_General_Error }, +    { "No_Scdaemon", GPGME_Invalid_Engine }, +    { "Scdaemon_Error", GPGME_General_Error }, +    { "Unsupported_Protocol", GPGME_General_Error }, +    { "Bad_PIN_Method", GPGME_General_Error }, +    { "Card_Not_Initialized", GPGME_General_Error }, +    { "Unsupported_Operation", GPGME_General_Error }, +    { "Wrong_Key_Usage", GPGME_Wrong_Key_Usage } +  }; +     + +GpgmeError +_gpgme_map_gnupg_error (char *err) +{ +  int i; + +  for (i = 0; i < DIM (gnupg_errors); i++) +    if (!strcmp (gnupg_errors[i].name, err)) +      return gnupg_errors[i].err; + +  return GPGME_General_Error; +} +  GpgmeError  _gpgme_data_append (GpgmeData dh, const char *buffer, size_t length) diff --git a/gpgme/decrypt-verify.c b/gpgme/decrypt-verify.c index 0a94522a..f365b165 100644 --- a/gpgme/decrypt-verify.c +++ b/gpgme/decrypt-verify.c @@ -48,6 +48,10 @@ _gpgme_op_decrypt_verify_start (GpgmeCtx ctx, int synchronous,    if (err)      return err; +  err = _gpgme_op_verify_init_result (ctx); +  if (err) +    return err; +    if (!cipher)      return GPGME_No_Data;    if (!plain) diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index 72f502a2..dbcd406f 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -68,7 +68,6 @@ gpgme_release (GpgmeCtx ctx)    _gpgme_fd_table_deinit (&ctx->fdt);    _gpgme_release_result (ctx);    gpgme_key_release (ctx->tmp_key); -  gpgme_data_release (ctx->notation);    gpgme_signers_clear (ctx);    if (ctx->signers)      free (ctx->signers); @@ -95,26 +94,6 @@ _gpgme_release_result (GpgmeCtx ctx)  /** - * gpgme_get_notation: - * @c: the context - * - * If there is notation data available from the last signature check, - * this function may be used to return this notation data as a string. - * The string is an XML represantaton of that data embedded in a - * %<notation> container. - * - * Return value: An XML string or NULL if no notation data is available. - **/ -char * -gpgme_get_notation (GpgmeCtx ctx) -{ -  if (!ctx->notation) -    return NULL; -  return _gpgme_data_get_as_string (ctx->notation); -} - - -/**   * gpgme_get_op_info:   * @c: the context   * @reserved: diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 0071f06b..4ee92121 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -188,23 +188,6 @@ typedef enum    }  GpgmeSigStat; -/* Flags used with the GPGME_ATTR_SIG_SUMMARY.  */ -enum  -  { -    GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid.  */ -    GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good.  */ -    GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad.  */ -    GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked.  */ -    GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired.  */ -    GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired.  */ -    GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing.  */ -    GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */ -    GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */ -    GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */ -    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured.  */ -  }; - -  /* The available signature modes.  */  typedef enum    { @@ -406,9 +389,6 @@ GpgmeError gpgme_new (GpgmeCtx *ctx);  /* Release the context CTX.  */  void gpgme_release (GpgmeCtx ctx); -/* Retrieve more info about performed signature check.  */ -char *gpgme_get_notation (GpgmeCtx ctx); -  /* Set the protocol to be used by CTX to PROTO.  */  GpgmeError gpgme_set_protocol (GpgmeCtx ctx, GpgmeProtocol proto); @@ -831,7 +811,7 @@ struct _gpgme_new_signature    GpgmePubKeyAlgo pubkey_algo;    GpgmeHashAlgo hash_algo;    unsigned long class; -  long int created; +  long int timestamp;    char *fpr;  };  typedef struct _gpgme_new_signature *GpgmeNewSignature; @@ -856,6 +836,75 @@ GpgmeError gpgme_op_sign (GpgmeCtx ctx,  			  GpgmeSigMode mode); +/* Verify.  */ +struct _gpgme_sig_notation +{ +  struct _gpgme_sig_notation *next; + +  /* If NAME is a null pointer, then VALUE contains a policy URL +     rather than a notation.  */ +  char *name; +  char *value; +}; +typedef struct _gpgme_sig_notation *GpgmeSigNotation; + +/* Flags used for the SUMMARY field in a GpgmeSignature.  */ +enum  +  { +    GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid.  */ +    GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good.  */ +    GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad.  */ +    GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked.  */ +    GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired.  */ +    GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired.  */ +    GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing.  */ +    GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */ +    GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */ +    GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */ +    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured.  */ +  }; + +struct _gpgme_signature +{ +  struct _gpgme_signature *next; + +  /* A summary of the signature status.  */ +  unsigned int summary; + +  /* The fingerprint or key ID of the signature.  */ +  char *fpr; + +  /* The status of the signature.  */ +  GpgmeError status; + +  /* Notation data and policy URLs.  */ +  GpgmeSigNotation notations; + +  /* Signature creation time.  */ +  unsigned long timestamp; + +  /* Signature exipration time or 0.  */ +  unsigned long exp_timestamp; + +  int wrong_key_usage : 1; + +  /* Internal to GPGME, do not use.  */ +  int _unused : 31; + +  GpgmeValidity validity; +  GpgmeError validity_reason; +}; +typedef struct _gpgme_signature *GpgmeSignature; + +struct _gpgme_op_verify_result +{ +  GpgmeSignature signatures; +}; +typedef struct _gpgme_op_verify_result *GpgmeVerifyResult; + +/* Retrieve a pointer to the result of the verify operation.  */ +GpgmeVerifyResult gpgme_op_verify_result (GpgmeCtx ctx); +  /* Verify within CTX that SIG is a valid signature for TEXT.  */  GpgmeError gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig,  				  GpgmeData signed_text, GpgmeData plaintext); @@ -863,6 +912,7 @@ GpgmeError gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig,  			    GpgmeData signed_text, GpgmeData plaintext); +/* Import.  */  enum    {      /* The key was new.  */ diff --git a/gpgme/ops.h b/gpgme/ops.h index 165a5172..ffc2bdbe 100644 --- a/gpgme/ops.h +++ b/gpgme/ops.h @@ -1,4 +1,4 @@ -/* ops.h - internal operations stuff  +/* ops.h - Internal operation support.     Copyright (C) 2000 Werner Koch (dd9jn)     Copyright (C) 2001, 2002, 2003 g10 Code GmbH @@ -73,8 +73,9 @@ GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);  GpgmeError _gpgme_parse_inv_userid (char *args, GpgmeInvalidUserID *userid); -/*-- verify.c --*/ -GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, +/* From verify.c.  */ +GpgmeError _gpgme_op_verify_init_result (GpgmeCtx ctx); +GpgmeError _gpgme_verify_status_handler (void *priv, GpgmeStatusCode code,  					 char *args); diff --git a/gpgme/sign.c b/gpgme/sign.c index 260aa5f7..413865dc 100644 --- a/gpgme/sign.c +++ b/gpgme/sign.c @@ -149,7 +149,7 @@ parse_sig_created (char *args, GpgmeNewSignature *sigp)      }    args = tail; -  sig->created = strtol (args, &tail, 0); +  sig->timestamp = strtol (args, &tail, 0);    if (errno || args == tail || *tail != ' ')      {        /* The crypto backend does not behave.  */ diff --git a/gpgme/util.h b/gpgme/util.h index 2734115e..70b7de9a 100644 --- a/gpgme/util.h +++ b/gpgme/util.h @@ -74,5 +74,15 @@ int _gpgme_hextobyte (const unsigned char *str);     is large enough if LEN is not zero.  */  GpgmeError _gpgme_decode_c_string (const char *src, char **destp, int len); +/* Decode the percent escaped string SRC and store the result in the +   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a +   large enough buffer is allocated with malloc and *DESTP is set to +   the result.  Currently, LEN is only used to specify if allocation +   is desired or not, the caller is expected to make sure that *DESTP +   is large enough if LEN is not zero.  */ +GpgmeError _gpgme_decode_percent_string (const char *src, char **destp, +					 int len); + +GpgmeError _gpgme_map_gnupg_error (char *err);  #endif /* UTIL_H */ diff --git a/gpgme/verify.c b/gpgme/verify.c index 3b63491f..85854cdb 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -21,391 +21,520 @@  #if HAVE_CONFIG_H  #include <config.h>  #endif -#include <stdio.h>  #include <stdlib.h>  #include <string.h> -#include <assert.h> +#include <errno.h> +#include "gpgme.h"  #include "util.h"  #include "context.h"  #include "ops.h" -#include "key.h" - -struct verify_result + +typedef struct  { -  GpgmeSigStat status; -  GpgmeSigStat expstatus;	/* Only used by finish_sig.  */ -  GpgmeData notation;		/* We store an XML fragment here.  */ -  int collecting;		/* Private to finish_sig().  */ -  int notation_in_data;		/* Private to add_notation().  */ -  char fpr[41];			/* Fingerprint of a good signature or keyid of -				   a bad one.  */ -  ulong timestamp;		/* Signature creation time.  */ -  ulong exptimestamp;		/* Signature exipration time or 0.  */ -  GpgmeValidity validity; -  int wrong_key_usage;   -  char trust_errtok[31];	/* Error token send with the trust status.  */ -}; -typedef struct verify_result *VerifyResult; +  struct _gpgme_op_verify_result result; + +  GpgmeSignature current_sig; +} *op_data_t;  static void -release_verify_result (void *hook) +release_op_data (void *hook)  { -  VerifyResult result = (VerifyResult) hook; +  op_data_t opd = (op_data_t) hook; +  GpgmeSignature sig = opd->result.signatures; -  gpgme_data_release (result->notation); -} +  while (sig) +    { +      GpgmeSignature next = sig->next; +      GpgmeSigNotation notation = sig->notations; +      while (notation) +	{ +	  GpgmeSigNotation next_nota = notation->next; -/* Check whether STRING starts with TOKEN and return true in this -   case.  This is case insensitive.  If NEXT is not NULL return the -   number of bytes to be added to STRING to get to the next token; a -   returned value of 0 indicates end of line.  */ -static int  -is_token (const char *string, const char *token, size_t *next) -{ -  size_t n = 0; +	  if (notation->name) +	    free (notation->name); +	  if (notation->value) +	    free (notation->value); +	  notation = next_nota; +	} -  for (;*string && *token && *string == *token; string++, token++, n++) -    ; -  if (*token || (*string != ' ' && !*string)) -    return 0; -  if (next) -    { -      for (; *string == ' '; string++, n++) -        ; -      *next = n; +      if (sig->fpr) +	free (sig->fpr); +      free (sig); +      sig = next;      } -  return 1;  } -static int -skip_token (const char *string, size_t *next) + +GpgmeVerifyResult +gpgme_op_verify_result (GpgmeCtx ctx)  { -  size_t n = 0; +  op_data_t opd; +  GpgmeError err; -  for (;*string && *string != ' '; string++, n++) -    ; -  for (;*string == ' '; string++, n++) -    ; -  if (!*string) -    return 0; -  if (next) -    *next = n; -  return 1; -} +  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd, -1, NULL); +  if (err || !opd) +    return NULL; +  return &opd->result; +} -static size_t -copy_token (const char *string, char *buffer, size_t length) + +/* Build a summary vector from RESULT. */ +static void +calc_sig_summary (GpgmeSignature sig)  { -  const char *s = string; -  char *p = buffer; -  size_t i; - -  for (i = 1; i < length && *s && *s != ' ' ; i++) -    *p++ = *s++; -  *p = 0; -  /* continue scanning in case the copy was truncated */ -  while (*s && *s != ' ') -    s++; -  return s - string; -} +  unsigned long sum = 0; +  if (sig->validity == GPGME_VALIDITY_FULL +      || sig->validity == GPGME_VALIDITY_ULTIMATE) +    { +      if (sig->status == GPGME_No_Error +	  || sig->status == GPGME_Sig_Expired +	  || sig->status == GPGME_Key_Expired) +	sum |= GPGME_SIGSUM_GREEN; +    } +  else if (sig->validity == GPGME_VALIDITY_NEVER) +    { +      if (sig->status == GPGME_No_Error +	  || sig->status == GPGME_Sig_Expired +	  || sig->status == GPGME_Key_Expired) +	sum |= GPGME_SIGSUM_RED; +    } +  else if (sig->status == GPGME_Bad_Signature) +    sum |= GPGME_SIGSUM_RED; +   +  /* FIXME: handle the case when key and message are expired. */ +  if (sig->status == GPGME_Sig_Expired) +    sum |= GPGME_SIGSUM_SIG_EXPIRED; +  else if (sig->status == GPGME_Key_Expired) +    sum |= GPGME_SIGSUM_KEY_EXPIRED; +  else if (sig->status == GPGME_No_Public_Key) +    sum |= GPGME_SIGSUM_KEY_MISSING; +  else if (sig->status) +    sum |= GPGME_SIGSUM_SYS_ERROR; +   +  if (sig->validity_reason == GPGME_Key_Revoked) +    sum |= GPGME_SIGSUM_KEY_REVOKED; +  else if (sig->validity_reason == GPGME_No_CRL_Known) +    sum |= GPGME_SIGSUM_CRL_MISSING; +  else if (sig->validity_reason == GPGME_CRL_Too_Old) +    sum |= GPGME_SIGSUM_CRL_TOO_OLD; +  else if (sig->validity_reason == GPGME_Policy_Mismatch) +    sum |= GPGME_SIGSUM_BAD_POLICY; +  else if (sig->validity_reason) +    sum |= GPGME_SIGSUM_SYS_ERROR; +   +  if (sig->wrong_key_usage) +    sum |= GPGME_SIGSUM_BAD_POLICY; +   +  /* Set the valid flag when the signature is unquestionable +     valid. */ +  if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN)) +    sum |= GPGME_SIGSUM_VALID; +   +  sig->summary = sum; +} +   -/* FIXME: Check that we are adding this to the correct signature.  */  static GpgmeError -add_notation (VerifyResult result, GpgmeStatusCode code, const char *notation) +parse_new_sig (op_data_t opd, GpgmeStatusCode code, char *args)  { -  GpgmeData dh = result->notation; +  GpgmeSignature sig; +  char *end = strchr (args, ' '); -  if (!dh) +  if (end)      { -      if (gpgme_data_new (&dh)) -	return GPGME_Out_Of_Core; -      result->notation = dh; -      _gpgme_data_append_string (dh, "  <notation>\n"); +      *end = '\0'; +      end++;      } -  if (code == GPGME_STATUS_NOTATION_DATA) +  sig = calloc (1, sizeof (*sig)); +  if (!sig) +    return GPGME_Out_Of_Core; +  if (!opd->result.signatures) +    opd->result.signatures = sig; +  if (opd->current_sig) +    opd->current_sig->next = sig; +  opd->current_sig = sig; + +  switch (code)      { -      if (!result->notation_in_data) -	_gpgme_data_append_string (dh, "  <data>"); -      _gpgme_data_append_percentstring_for_xml (dh, notation); -      result->notation_in_data = 1; -      return 0; +    case GPGME_STATUS_GOODSIG: +      sig->status = GPGME_No_Error; +      break; + +    case GPGME_STATUS_EXPSIG: +      sig->status = GPGME_Sig_Expired; +      break; + +    case GPGME_STATUS_EXPKEYSIG: +      sig->status = GPGME_Key_Expired; +      break; + +    case GPGME_STATUS_BADSIG: +      sig->status = GPGME_Bad_Signature; +      break; + +    case GPGME_STATUS_ERRSIG: +      if (end) +	{ +	  int i = 0; +	  /* The return code is the 6th argument, if it is 9, the +	     problem is a missing key.  */ +	  while (end && i < 4) +	    end = strchr (end, ' '); +	  if (end && end[0] && (!end[1] || !end[1] == ' ')) +	    { +	      switch (end[0]) +		{ +		case '4': +		  sig->status = GPGME_Unsupported_Algorithm; +		  break; + +		case 9: +		  sig->status = GPGME_No_Public_Key; +		  break; + +		default: +		  sig->status = GPGME_General_Error; +		} +	    } +	} +      else +	sig->status = GPGME_General_Error; +      break; + +    default: +      return GPGME_General_Error;      } -  if (result->notation_in_data) +  if (*args)      { -      _gpgme_data_append_string (dh, "</data>\n"); -      result->notation_in_data = 0; +      sig->fpr = strdup (args); +      if (!sig->fpr) +	return GPGME_Out_Of_Core;      } +  return 0; +} -  if (code == GPGME_STATUS_NOTATION_NAME) + +static GpgmeError +parse_valid_sig (GpgmeSignature sig, char *args) +{ +  char *end = strchr (args, ' '); + +  if (end)      { -      _gpgme_data_append_string (dh, "  <name>"); -      _gpgme_data_append_percentstring_for_xml (dh, notation); -      _gpgme_data_append_string (dh, "</name>\n"); +      *end = '\0'; +      end++;      } -  else if (code == GPGME_STATUS_POLICY_URL) + +  if (!*args) +    /* We require at least the fingerprint.  */ +    return GPGME_General_Error; + +  if (sig->fpr) +    free (sig->fpr); +  sig->fpr = strdup (args); +  if (!sig->fpr) +    return GPGME_Out_Of_Core; + +  end = strchr (end, ' '); +  if (end)      { -      _gpgme_data_append_string (dh, "  <policy>"); -      _gpgme_data_append_percentstring_for_xml (dh, notation); -      _gpgme_data_append_string (dh, "</policy>\n"); +      char *tail; +      errno = 0; +      sig->timestamp = strtol (end, &tail, 0); +      if (errno || end == tail || (*tail && *tail != ' ')) +	return GPGME_General_Error; +      end = tail; +      +      sig->exp_timestamp = strtol (end, &tail, 0); +      if (errno || end == tail || (*tail && *tail != ' ')) +	return GPGME_General_Error;      } -  else -    assert (0);    return 0;  } -/* Finish a pending signature info collection.  */ -static void -finish_sig (VerifyResult result) +static GpgmeError +parse_notation (GpgmeSignature sig, GpgmeStatusCode code, char *args)  { -  struct ctx_op_data *op_data; - -  /* We intimately know that gpgme_op_data_lookup appends the data to -     the op_data structure.  We can use this here to change the type -     knowing only the hook value.  */ -  op_data = (struct ctx_op_data *) ((void *) result -				    - sizeof (struct ctx_op_data)); -  op_data->type = OPDATA_VERIFY; -} +  GpgmeError err; +  GpgmeSigNotation *lastp = &sig->notations; +  GpgmeSigNotation notation = sig->notations; +  char *end = strchr (args, ' '); +  if (end) +    *end = '\0'; -GpgmeError -_gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args) -{ -  VerifyResult result; -  GpgmeError err; -  char *p; -  size_t n; -  int i; +  if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL) +    { +      /* FIXME: We could keep a pointer to the last notation in the list.  */ +      while (notation && notation->value) +	{ +	  lastp = ¬ation->next; +	  notation = notation->next; +	} -  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result, -			       -1, NULL); -  if (err) -    return err; +      if (notation) +	/* There is another notation name without data for the +	   previous one.  The crypto backend misbehaves.  */ +	return GPGME_General_Error; + +      notation = malloc (sizeof (*sig)); +      if (!notation) +	return GPGME_Out_Of_Core; +      notation->next = NULL; -  if (code == GPGME_STATUS_GOODSIG || code == GPGME_STATUS_EXPSIG -      || code == GPGME_STATUS_EXPKEYSIG || code == GPGME_STATUS_BADSIG -      || code == GPGME_STATUS_ERRSIG) +      if (code == GPGME_STATUS_NOTATION_NAME) +	{ +	  int len = strlen (args) + 1; + +	  notation->name = malloc (len); +	  if (!notation->name) +	    { +	      free (notation); +	      return GPGME_Out_Of_Core; +	    } +	  err = _gpgme_decode_percent_string (args, ¬ation->name, len); +	  if (err) +	    return err; + +	  notation->value = NULL; +	} +      else +	{ +	  int len = strlen (args) + 1; + +	  notation->name = NULL; +	  notation->value = malloc (len); +	  if (!notation->value) +	    { +	      free (notation); +	      return GPGME_Out_Of_Core; +	    } +	  err = _gpgme_decode_percent_string (args, ¬ation->value, len); +	  if (err) +	    return err; +	} +      *lastp = notation; +    } +  else if (code == GPGME_STATUS_NOTATION_DATA)      { -      /* A new signature starts.  */ -      if (result) -	finish_sig (result); -      err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result, -				   sizeof (*result), release_verify_result); +      int len = strlen (args) + 1; +      char *dest; + +      /* FIXME: We could keep a pointer to the last notation in the list.  */ +      while (notation && notation->next) +	{ +	  lastp = ¬ation->next; +	  notation = notation->next; +	} + +      if (!notation || !notation->name) +	/* There is notation data without a previous notation +	   name.  The crypto backend misbehaves.  */ +	return GPGME_General_Error; +       +      if (!notation->value) +	{ +	  dest = notation->value = malloc (len); +	  if (!dest) +	    return GPGME_Out_Of_Core; +	} +      else +	{ +	  int cur_len = strlen (notation->value); +	  dest = realloc (notation->value, len + strlen (notation->value)); +	  if (!dest) +	    return GPGME_Out_Of_Core; +	  notation->value = dest; +	  dest += cur_len; +	} +       +      err = _gpgme_decode_percent_string (args, &dest, len);        if (err)  	return err;      } +  else +    return GPGME_General_Error; +  return 0; +} + + +static GpgmeError +parse_trust (GpgmeSignature sig, GpgmeStatusCode code, char *args) +{ +  char *end = strchr (args, ' '); + +  if (end) +    *end = '\0';    switch (code)      { -    case GPGME_STATUS_NODATA: -    case GPGME_STATUS_UNEXPECTED: -      if (!result) -	return GPGME_General_Error; -      result->status = GPGME_SIG_STAT_NOSIG; +    case GPGME_STATUS_TRUST_UNDEFINED: +    default: +      sig->validity = GPGME_VALIDITY_UNKNOWN;        break; -    case GPGME_STATUS_GOODSIG: -      if (!result) -	return GPGME_General_Error; -      result->expstatus = GPGME_SIG_STAT_GOOD; +    case GPGME_STATUS_TRUST_NEVER: +      sig->validity = GPGME_VALIDITY_NEVER;        break; -    case GPGME_STATUS_EXPSIG: -      if (!result) -	return GPGME_General_Error; -      result->expstatus = GPGME_SIG_STAT_GOOD_EXP; +    case GPGME_STATUS_TRUST_MARGINAL: +      sig->validity = GPGME_VALIDITY_MARGINAL;        break; -    case GPGME_STATUS_EXPKEYSIG: -      if (!result) -	return GPGME_General_Error; -      result->expstatus = GPGME_SIG_STAT_GOOD_EXPKEY; +    case GPGME_STATUS_TRUST_FULLY: +    case GPGME_STATUS_TRUST_ULTIMATE: +      sig->validity = GPGME_VALIDITY_FULL;        break; +    } -    case GPGME_STATUS_VALIDSIG: -      if (!result) -	return GPGME_General_Error; -      result->status = GPGME_SIG_STAT_GOOD; -      i = copy_token (args, result->fpr, DIM (result->fpr)); -      /* Skip the formatted date.  */ -      while (args[i] && args[i] == ' ') -	i++; -      while (args[i] && args[i] != ' ') -	i++; -      /* And get the timestamp.  */ -      result->timestamp = strtoul (args + i, &p, 10); -      if (args[i]) -        result->exptimestamp = strtoul (p, NULL, 10); -      break; +  if (*args) +    sig->validity_reason = _gpgme_map_gnupg_error (args); + +  return 0; +} -    case GPGME_STATUS_BADSIG: -      if (!result) -	return GPGME_General_Error; -      result->status = GPGME_SIG_STAT_BAD; -      /* Store the keyID in the fpr field.  */ -      copy_token (args, result->fpr, DIM (result->fpr)); -      break; +static GpgmeError +parse_error (GpgmeSignature sig, char *args) +{ +  GpgmeError err; +  char *where = strchr (args, ' '); +  char *which; + +  if (where) +    { +      *where = '\0'; +      which = where + 1; + +      where = strchr (which, ' '); +      if (where) +	*where = '\0'; + +      where = args;       +    } +  else +    return GPGME_General_Error; + +  err = _gpgme_map_gnupg_error (which); + +  if (!strcmp (where, "verify.findkey")) +    sig->status = err; +  else if (!strcmp (where, "verify.keyusage") && err == GPGME_Wrong_Key_Usage) +    sig->wrong_key_usage = 1; + +  return 0; +} + + +GpgmeError +_gpgme_verify_status_handler (void *priv, GpgmeStatusCode code, char *args) +{ +  GpgmeCtx ctx = (GpgmeCtx) priv; +  GpgmeError err; +  op_data_t opd; +  GpgmeSignature sig; + +  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd, -1, NULL); +  if (err) +    return err; + +  sig = opd->current_sig; + +  switch (code) +    { +    case GPGME_STATUS_GOODSIG: +    case GPGME_STATUS_EXPSIG: +    case GPGME_STATUS_EXPKEYSIG: +    case GPGME_STATUS_BADSIG:      case GPGME_STATUS_ERRSIG: -      if (!result) +      if (sig) +	calc_sig_summary (sig); +      return parse_new_sig (opd, code, args); + +    case GPGME_STATUS_VALIDSIG: +      return sig ? parse_valid_sig (sig, args) : GPGME_General_Error; + +    case GPGME_STATUS_NODATA: +    case GPGME_STATUS_UNEXPECTED: +      if (!sig)  	return GPGME_General_Error; -      /* The return code is the 6th argument, if it is 9, the problem -	 is a missing key.  Note that this is not emitted by gpgsm */ -      for (p = args, i = 0; p && *p && i < 5; i++) -        { -          p = strchr (p, ' '); -          if (p) -            while (*p == ' ') -              p++; -        } -      if (p && *(p++) == '9' && (*p == '\0' || *p == ' ')) -	result->status = GPGME_SIG_STAT_NOKEY; -      else -	result->status = GPGME_SIG_STAT_ERROR; -      /* Store the keyID in the fpr field.  */ -      copy_token (args, result->fpr, DIM (result->fpr)); +      sig->status = GPGME_No_Data;        break;      case GPGME_STATUS_NOTATION_NAME:      case GPGME_STATUS_NOTATION_DATA:      case GPGME_STATUS_POLICY_URL: -      if (!result) -	return GPGME_General_Error; -      err = add_notation (result, code, args); -      if (err) -	return err; -      break; +      return sig ? parse_notation (sig, code, args) : GPGME_General_Error;      case GPGME_STATUS_TRUST_UNDEFINED: -      if (!result) -	return GPGME_General_Error; -      result->validity = GPGME_VALIDITY_UNKNOWN; -      copy_token (args, result->trust_errtok, -                  DIM(result->trust_errtok)); -      break;      case GPGME_STATUS_TRUST_NEVER: -      if (!result) -	return GPGME_General_Error; -      result->validity = GPGME_VALIDITY_NEVER; -      copy_token (args, result->trust_errtok, -                  DIM(result->trust_errtok)); -      break;      case GPGME_STATUS_TRUST_MARGINAL: -      if (!result) -	return GPGME_General_Error; -      if (result->status == GPGME_SIG_STAT_GOOD) -        result->validity = GPGME_VALIDITY_MARGINAL; -      copy_token (args, result->trust_errtok, -                  DIM(result->trust_errtok)); -      break;      case GPGME_STATUS_TRUST_FULLY:      case GPGME_STATUS_TRUST_ULTIMATE: -      if (!result) -	return GPGME_General_Error; -      if (result->status == GPGME_SIG_STAT_GOOD) -        result->validity = GPGME_VALIDITY_FULL; -      break; - -    case GPGME_STATUS_END_STREAM: -      break; +      return sig ? parse_trust (sig, code, args) : GPGME_General_Error;      case GPGME_STATUS_ERROR: -      if (!result) -	return GPGME_General_Error; -      /* Generic error, we need this for gpgsm (and maybe for gpg in future) -         to get error descriptions. */ -      if (is_token (args, "verify.findkey", &n) && n) -        { -          args += n; -          if (is_token (args, "No_Public_Key", NULL)) -            result->status = GPGME_SIG_STAT_NOKEY; -          else -            result->status = GPGME_SIG_STAT_ERROR; - -        } -      else if (skip_token (args, &n) && n) -        { -          args += n; -          if (is_token (args, "Wrong_Key_Usage", NULL)) -            result->wrong_key_usage = 1; -        } -      break; +      return sig ? parse_error (sig, args) : GPGME_General_Error;      case GPGME_STATUS_EOF: -      if (result) -	{ -	  finish_sig (result); - -	  /* FIXME: Put all notation data into one XML fragment.  */ -	  if (result->notation) -	    { -	      GpgmeData dh = result->notation; -	       -	      if (result->notation_in_data) -		{ -		  _gpgme_data_append_string (dh, "</data>\n"); -		  result->notation_in_data = 0; -		} -	      _gpgme_data_append_string (dh, "</notation>\n"); -	      ctx->notation = dh; -	      result->notation = NULL; -	    } -	} +      if (sig) +	calc_sig_summary (sig);        break; -  +      default: -      /* Ignore all other codes.  */        break;      }    return 0;  } +GpgmeError +_gpgme_op_verify_init_result (GpgmeCtx ctx) +{   +  op_data_t opd; + +  return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd, +				sizeof (*opd), release_op_data); +} + +  static GpgmeError -_gpgme_op_verify_start (GpgmeCtx ctx, int synchronous, -			GpgmeData sig, GpgmeData signed_text, GpgmeData plaintext) +_gpgme_op_verify_start (GpgmeCtx ctx, int synchronous, GpgmeData sig, +			GpgmeData signed_text, GpgmeData plaintext)  { -  int err = 0; +  GpgmeError err;    err = _gpgme_op_reset (ctx, synchronous);    if (err) -    goto leave; +    return err; + +  err = _gpgme_op_verify_init_result (ctx); +  if (err) +    return err;    _gpgme_engine_set_status_handler (ctx->engine, _gpgme_verify_status_handler,  				    ctx); -  /* Check the supplied data.  */    if (!sig) -    { -      err = GPGME_No_Data; -      goto leave; -    } +    return GPGME_No_Data;    if (!signed_text && !plaintext) -    { -      err = GPGME_Invalid_Value; -      goto leave; -    } -  err = _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext); +    return GPGME_Invalid_Value; - leave: -  if (err) -    { -      _gpgme_engine_release (ctx->engine); -      ctx->engine = NULL; -    } -  return err; +  return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);  } +/* Decrypt ciphertext CIPHER and make a signature verification within +   CTX and store the resulting plaintext in PLAIN.  */  GpgmeError  gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,  		       GpgmeData plaintext) @@ -414,226 +543,166 @@ gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,  } -/** - * gpgme_op_verify: - * @c: the context - * @sig: the signature data - * @text: the signed text - *  - * Perform a signature check on the signature given in @sig.  If @text - * is a new and uninitialized data object, it is assumed that @sig - * contains a normal or cleartext signature, and the plaintext is - * returned in @text upon successful verification. - * - * If @text is initialized, it is assumed that @sig is a detached - * signature for the material given in @text. - * - * Return value: 0 on success or an errorcode if something not related to - *               the signature itself did go wrong. - **/ +/* Decrypt ciphertext CIPHER and make a signature verification within +   CTX and store the resulting plaintext in PLAIN.  */  GpgmeError  gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,  		 GpgmeData plaintext)  {    GpgmeError err; -  gpgme_data_release (ctx->notation); -  ctx->notation = NULL; -        err = _gpgme_op_verify_start (ctx, 1, sig, signed_text, plaintext);    if (!err)      err = _gpgme_wait_one (ctx);    return err;  } + +/* Compatibility interfaces.  */ -/** - * gpgme_get_sig_status: - * @c: Context - * @idx: Index of the signature starting at 0 - * @r_stat: Returns the status - * @r_created: Returns the creation timestamp - *  - * Return information about an already verified signatures.  - * - * The result of this operation is returned in @r_stat which can take these - * values: - *  GPGME_SIG_STAT_NONE:  No status - should not happen - *  GPGME_SIG_STAT_GOOD:  The signature is valid  - *  GPGME_SIG_STAT_BAD:   The signature is not valid - *  GPGME_SIG_STAT_NOKEY: The signature could not be checked due to a - *                        missing key - *  GPGME_SIG_STAT_NOSIG: This is not a signature - *  GPGME_SIG_STAT_ERROR: Due to some other error the check could not be done. - *  GPGME_SIG_STAT_DIFF:  There is more than 1 signature and they have not - *                        the same status. - *  GPGME_SIG_STAT_GOOD_EXP:  The signature is good but has expired. - *  GPGME_SIG_STAT_GOOD_KEYEXP:  The signature is good but the key has expired. - * - *  - * Return value: The fingerprint or NULL in case of an problem or - *               when there are no more signatures. - **/ -const char * -gpgme_get_sig_status (GpgmeCtx ctx, int idx, -                      GpgmeSigStat *r_stat, time_t *r_created) +/* Get the key used to create signature IDX in CTX and return it in +   R_KEY.  */ +GpgmeError +gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key)  { -  struct ctx_op_data *op_data; -  VerifyResult result; +  GpgmeVerifyResult result; +  GpgmeSignature sig; -  if (!ctx) -    return NULL;	/* No results yet or verification error.  */ +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; -  op_data = ctx->op_data; -  while (op_data) -    { -      while (op_data && op_data->type != OPDATA_VERIFY) -	op_data = op_data->next; -      if (idx-- == 0) -	break; -      op_data = op_data->next;	 -    } -  if (!op_data) -    return NULL;	/* No more signatures.  */ - -  result = (VerifyResult) op_data->hook; -  if (r_stat) -    *r_stat = result->status; -  if (r_created) -    *r_created = result->timestamp; -  return result->fpr; -} - - -/* Build a summary vector from RESULT. */ -static unsigned long -calc_sig_summary (VerifyResult result) -{ -  unsigned long sum = 0; - -  if (result->validity == GPGME_VALIDITY_FULL -     || result->validity == GPGME_VALIDITY_ULTIMATE) -    { -      if (result->status == GPGME_SIG_STAT_GOOD -          || result->status == GPGME_SIG_STAT_GOOD_EXP -          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY) -        sum |= GPGME_SIGSUM_GREEN; -    } -  else if (result->validity == GPGME_VALIDITY_NEVER) +  while (sig && idx)      { -      if (result->status == GPGME_SIG_STAT_GOOD -          || result->status == GPGME_SIG_STAT_GOOD_EXP -          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY) -        sum |= GPGME_SIGSUM_RED; +      sig = sig->next; +      idx--;      } -  else if (result->status == GPGME_SIG_STAT_BAD) -    sum |= GPGME_SIGSUM_RED; - -  /* fixme: handle the case when key and message are expired. */ -  if (result->status == GPGME_SIG_STAT_GOOD_EXP) -    sum |= GPGME_SIGSUM_SIG_EXPIRED; -  else if (result->status == GPGME_SIG_STAT_GOOD_EXPKEY) -    sum |= GPGME_SIGSUM_KEY_EXPIRED; -  else if (result->status == GPGME_SIG_STAT_NOKEY) -    sum |= GPGME_SIGSUM_KEY_MISSING; -  else if (result->status == GPGME_SIG_STAT_ERROR) -    sum |= GPGME_SIGSUM_SYS_ERROR; - -  if ( !strcmp (result->trust_errtok, "Certificate_Revoked")) -    sum |= GPGME_SIGSUM_KEY_REVOKED; -  else if ( !strcmp (result->trust_errtok, "No_CRL_Known")) -    sum |= GPGME_SIGSUM_CRL_MISSING; -  else if ( !strcmp (result->trust_errtok, "CRL_Too_Old")) -    sum |= GPGME_SIGSUM_CRL_TOO_OLD; -  else if ( !strcmp (result->trust_errtok, "No_Policy_Match")) -    sum |= GPGME_SIGSUM_BAD_POLICY; -  else if (*result->trust_errtok) -    sum |= GPGME_SIGSUM_SYS_ERROR; - -  if (result->wrong_key_usage) -    sum |= GPGME_SIGSUM_BAD_POLICY; - -  /* Set the valid flag when the signature is unquestionable -     valid. */ -  if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN)) -    sum |= GPGME_SIGSUM_VALID; +  if (!sig || idx) +    return GPGME_EOF; -  return sum; +  return gpgme_get_key (ctx, sig->fpr, r_key, 0, 0);  } -const char * -gpgme_get_sig_string_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int whatidx) +/* Retrieve the signature status of signature IDX in CTX after a +   successful verify operation in R_STAT (if non-null).  The creation +   time stamp of the signature is returned in R_CREATED (if non-null). +   The function returns a string containing the fingerprint.  */ +const char *gpgme_get_sig_status (GpgmeCtx ctx, int idx, +                                  GpgmeSigStat *r_stat, time_t *r_created)  { -  struct ctx_op_data *op_data; -  VerifyResult result; +  GpgmeVerifyResult result; +  GpgmeSignature sig; -  if (!ctx) -    return NULL;	/* No results yet or verification error.  */ +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; -  op_data = ctx->op_data; -  while (op_data) +  while (sig && idx)      { -      while (op_data && op_data->type != OPDATA_VERIFY) -	op_data = op_data->next; -      if (idx-- == 0) -	break; -      op_data = op_data->next;	 +      sig = sig->next; +      idx--;      } -  if (!op_data) -    return NULL;	/* No more signatures.  */ +  if (!sig || idx) +    return NULL; -  result = (VerifyResult) op_data->hook; -  switch (what) +  if (r_stat)      { -    case GPGME_ATTR_FPR: -      return result->fpr; -    case GPGME_ATTR_ERRTOK: -      if (whatidx == 1) -        return result->wrong_key_usage? "Wrong_Key_Usage":""; -      else -        return result->trust_errtok; -    default: -      break; +      switch (sig->status) +	{ +	case GPGME_No_Error: +	  *r_stat = GPGME_SIG_STAT_GOOD; +	  break; +	   +	case GPGME_Bad_Signature: +	  *r_stat = GPGME_SIG_STAT_BAD; +	  break; +	   +	case GPGME_No_Public_Key: +	  *r_stat = GPGME_SIG_STAT_NOKEY; +	  break; +	   +	case GPGME_No_Data: +	  *r_stat = GPGME_SIG_STAT_NOSIG; +	  break; +	   +	case GPGME_Sig_Expired: +	  *r_stat = GPGME_SIG_STAT_GOOD_EXP; +	  break; +	   +	case GPGME_Key_Expired: +	  *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY; +	  break; +	   +	default: +	  *r_stat = GPGME_SIG_STAT_ERROR; +	  break; +	}      } -  return NULL; +  if (r_created) +    *r_created = sig->timestamp; +  return sig->fpr;  } -unsigned long -gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int reserved) +/* Retrieve certain attributes of a signature.  IDX is the index +   number of the signature after a successful verify operation.  WHAT +   is an attribute where GPGME_ATTR_EXPIRE is probably the most useful +   one.  WHATIDX is to be passed as 0 for most attributes . */ +unsigned long gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, +                                        GpgmeAttr what, int whatidx)  { -  struct ctx_op_data *op_data; -  VerifyResult result; +  GpgmeVerifyResult result; +  GpgmeSignature sig; -  if (!ctx) -    return 0;	/* No results yet or verification error.  */ +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; -  op_data = ctx->op_data; -  while (op_data) +  while (sig && idx)      { -      while (op_data && op_data->type != OPDATA_VERIFY) -	op_data = op_data->next; -      if (idx-- == 0) -	break; -      op_data = op_data->next;	 +      sig = sig->next; +      idx--;      } -  if (!op_data) -    return 0;	/* No more signatures.  */ +  if (!sig || idx) +    return 0; -  result = (VerifyResult) op_data->hook;    switch (what)      {      case GPGME_ATTR_CREATED: -      return result->timestamp; +      return sig->timestamp; +      case GPGME_ATTR_EXPIRE: -      return result->exptimestamp; +      return sig->exp_timestamp; +      case GPGME_ATTR_VALIDITY: -      return (unsigned long) result->validity; +      return (unsigned long) sig->validity; +      case GPGME_ATTR_SIG_STATUS: -      return (unsigned long) result->status; +      switch (sig->status) +	{ +	case GPGME_No_Error: +	  return GPGME_SIG_STAT_GOOD; +	   +	case GPGME_Bad_Signature: +	  return GPGME_SIG_STAT_BAD; +	   +	case GPGME_No_Public_Key: +	  return GPGME_SIG_STAT_NOKEY; +	   +	case GPGME_No_Data: +	  return GPGME_SIG_STAT_NOSIG; +	   +	case GPGME_Sig_Expired: +	  return GPGME_SIG_STAT_GOOD_EXP; +	   +	case GPGME_Key_Expired: +	  return GPGME_SIG_STAT_GOOD_EXPKEY; +	   +	default: +	  return GPGME_SIG_STAT_ERROR; +	} +      case GPGME_ATTR_SIG_SUMMARY: -      return calc_sig_summary (result); +      return sig->summary; +      default:        break;      } @@ -641,39 +710,36 @@ gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int reserved)  } -/** - * gpgme_get_sig_key: - * @c: context - * @idx: Index of the signature starting at 0 - * @r_key: Returns the key object - *  - * Return a key object which was used to check the signature.  - *  - * Return value: An Errorcode or 0 for success. GPGME_EOF is returned to - *               indicate that there are no more signatures.  - **/ -GpgmeError -gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key) +const char *gpgme_get_sig_string_attr (GpgmeCtx ctx, int idx, +                                      GpgmeAttr what, int whatidx)  { -  struct ctx_op_data *op_data; -  VerifyResult result; +  GpgmeVerifyResult result; +  GpgmeSignature sig; -  if (!ctx || !r_key) -    return GPGME_Invalid_Value; +  result = gpgme_op_verify_result (ctx); +  sig = result->signatures; -  op_data = ctx->op_data; -  while (op_data) +  while (sig && idx)      { -      while (op_data && op_data->type != OPDATA_VERIFY) -	op_data = op_data->next; -      if (idx-- == 0) -	break; -      op_data = op_data->next;	 +      sig = sig->next; +      idx--;      } -  if (!op_data) -    return GPGME_EOF; +  if (!sig || idx) +    return NULL; + +  switch (what) +    { +    case GPGME_ATTR_FPR: +      return sig->fpr; -  result = (VerifyResult) op_data->hook; +    case GPGME_ATTR_ERRTOK: +      if (whatidx == 1) +        return sig->wrong_key_usage ? "Wrong_Key_Usage" : ""; +      else +	return ""; +    default: +      break; +    } -  return gpgme_get_key (ctx, result->fpr, r_key, 0, 0); +  return NULL;  } diff --git a/tests/gpg/t-verify.c b/tests/gpg/t-verify.c index 1dcca5db..7b5bc36e 100644 --- a/tests/gpg/t-verify.c +++ b/tests/gpg/t-verify.c @@ -112,6 +112,7 @@ status_string (GpgmeSigStat status)      return s;  } +  static const char *  validity_string (GpgmeValidity val)  { @@ -132,138 +133,181 @@ validity_string (GpgmeValidity val)  static void -print_sig_stat ( GpgmeCtx ctx, GpgmeSigStat status ) +print_sig_stat (GpgmeCtx ctx, GpgmeSigStat status)  { -    const char *s; -    time_t created; -    int idx; -    GpgmeKey key; +  const char *s; +  time_t created; +  int idx; +  GpgmeKey key; -    printf ("Verification Status: %s\n", status_string (status)); +  printf ("Verification Status: %s\n", status_string (status)); -    for(idx=0; (s=gpgme_get_sig_status (ctx, idx, &status, &created)); idx++ ) { -        printf ("sig %d: created: %lu expires: %lu status: %s\n", -                idx, (unsigned long)created,  -                gpgme_get_sig_ulong_attr (ctx, idx, GPGME_ATTR_EXPIRE, 0), -                status_string(status) ); -        printf ("sig %d: fpr/keyid: `%s' validity: %s\n", -                idx, s, -                validity_string (gpgme_get_sig_ulong_attr -                                 (ctx, idx, GPGME_ATTR_VALIDITY, 0)) ); -        if ( !gpgme_get_sig_key (ctx, idx, &key) ) { -            char *p = gpgme_key_get_as_xml ( key ); -            printf ("sig %d: key object:\n%s\n", idx, p ); -            free (p); -            gpgme_key_release (key); +  for (idx = 0; (s = gpgme_get_sig_status (ctx, idx, &status, &created)); idx++) +    { +      printf ("sig %d: created: %lu expires: %lu status: %s\n", +	      idx, (unsigned long) created,  +	      gpgme_get_sig_ulong_attr (ctx, idx, GPGME_ATTR_EXPIRE, 0), +	      status_string (status)); +      printf ("sig %d: fpr/keyid: `%s' validity: %s\n", +	      idx, s, +	      validity_string (gpgme_get_sig_ulong_attr +			       (ctx, idx, GPGME_ATTR_VALIDITY, 0))); +      if (!gpgme_get_sig_key (ctx, idx, &key)) +	{ +	  char *p = gpgme_key_get_as_xml (key); +	  printf ("sig %d: key object:\n%s\n", idx, p); +	  free (p); +	  gpgme_key_release (key);          }      }  }  int  -main (int argc, char **argv ) +main (int argc, char *argv[])  { -    GpgmeCtx ctx; -    GpgmeError err; -    GpgmeData sig, text; -    GpgmeSigStat status; -    char *nota; -    int n = 0; -    size_t len; -    int j; - -    err = gpgme_new (&ctx); -    fail_if_err (err); +  GpgmeCtx ctx; +  GpgmeError err; +  GpgmeData sig, text; +  GpgmeSigStat status; +  GpgmeVerifyResult result; +  GpgmeSigNotation notation; +  char *nota; +  int n = 0; +  size_t len; +  int j; -  do { -    err = gpgme_data_new_from_mem ( &text, -                                    test_text1, strlen (test_text1), 0 ); -    fail_if_err (err); -  #if 1 -    err = gpgme_data_new_from_mem ( &sig, -                                    test_sig1, strlen (test_sig1), 0 ); -  #else -    err = gpgme_data_new_from_file ( &sig, "xx1", 1 ); -  #endif -    fail_if_err (err); +  err = gpgme_new (&ctx); +  fail_if_err (err); -    puts ("checking a valid message:\n"); -    err = gpgme_op_verify (ctx, sig, text, NULL); -    fail_if_err (err); -    if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) -      { -	fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); -	exit (1); -      } -    print_sig_stat (ctx, status); -    if (status != GPGME_SIG_STAT_GOOD) -      { -	fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); -	exit (1); -      } - -    if ((nota = gpgme_get_notation (ctx))) -        printf ("---Begin Notation---\n%s---End Notation---\n", nota ); - -    puts ("checking a manipulated message:\n"); -    gpgme_data_release (text); -    err = gpgme_data_new_from_mem (&text, -				   test_text1f, strlen (test_text1f), 0); -    fail_if_err (err); -    gpgme_data_rewind (sig); -    err = gpgme_op_verify (ctx, sig, text, NULL); -    fail_if_err (err); -    if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) -      { -	fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); -	exit (1); -      } -    print_sig_stat (ctx, status); -    if (status != GPGME_SIG_STAT_BAD) -      { -	fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); -	exit (1); -      } -    if ((nota = gpgme_get_notation (ctx))) -        printf ("---Begin Notation---\n%s---End Notation---\n", nota ); +  do +    { +      err = gpgme_data_new_from_mem (&text, +				     test_text1, strlen (test_text1), 0); +      fail_if_err (err); +#if 1 +      err = gpgme_data_new_from_mem (&sig, +				     test_sig1, strlen (test_sig1), 0); +#else +      err = gpgme_data_new_from_file (&sig, "xx1", 1); +#endif +      fail_if_err (err); -    puts ("checking a normal signature:"); -    gpgme_data_release (sig); -    gpgme_data_release (text); -    err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0); -    fail_if_err (err); -    err = gpgme_data_new (&text); -    fail_if_err (err); -    err = gpgme_op_verify (ctx, sig, NULL, text); -    fail_if_err (err); -    if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) -      { -	fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); -	exit (1); -      } +      puts ("checking a valid message:\n"); +      err = gpgme_op_verify (ctx, sig, text, NULL); +      fail_if_err (err); +      if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) +	{ +	  fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); +	  exit (1); +	} +      print_sig_stat (ctx, status); +      if (status != GPGME_SIG_STAT_GOOD) +	{ +	  fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); +	  exit (1); +	} -    nota = gpgme_data_release_and_get_mem (text, &len); -    for (j = 0; j < len; j++) +      result = gpgme_op_verify_result (ctx); +      notation = result->signatures->notations; +      if (notation) +	{ +	  printf ("---Begin Notation---\n"); +	  while (notation) +	    { +	      if (notation->name) +		printf ("%s: %s\n", notation->name, notation->value); +	      else +		printf ("Policy URL: %s\n", notation->value); +	      notation = notation->next; +	    } +	  printf ("---End Notation---\n"); +	} +       +      puts ("checking a manipulated message:\n"); +      gpgme_data_release (text); +      err = gpgme_data_new_from_mem (&text, +				     test_text1f, strlen (test_text1f), 0); +      fail_if_err (err); +      gpgme_data_rewind (sig); +      err = gpgme_op_verify (ctx, sig, text, NULL); +      fail_if_err (err); +      if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) +	{ +	  fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); +	  exit (1); +	} +      print_sig_stat (ctx, status); +      if (status != GPGME_SIG_STAT_BAD) +	{ +	  fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); +	  exit (1); +	} +      result = gpgme_op_verify_result (ctx); +      notation = result->signatures->notations; +      if (notation) +	{ +	  printf ("---Begin Notation---\n"); +	  while (notation) +	    { +	      if (notation->name) +		printf ("%s: %s\n", notation->name, notation->value); +	      else +		printf ("Policy URL: %s\n", notation->value); +	      notation = notation->next; +	    } +	  printf ("---End Notation---\n"); +	} +       +      puts ("checking a normal signature:"); +      gpgme_data_release (sig); +      gpgme_data_release (text); +      err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0); +      fail_if_err (err); +      err = gpgme_data_new (&text); +      fail_if_err (err); +      err = gpgme_op_verify (ctx, sig, NULL, text); +      fail_if_err (err); +      if (!gpgme_get_sig_status (ctx, 0, &status, NULL)) +	{ +	  fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__); +	  exit (1); +	} +       +      nota = gpgme_data_release_and_get_mem (text, &len); +      for (j = 0; j < len; j++)        putchar (nota[j]); -    if (strncmp (nota, test_text1, strlen (test_text1))) -      { -	fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__); -	exit (1); -      } -    -    print_sig_stat (ctx, status); -    if (status != GPGME_SIG_STAT_GOOD) -      { -	fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); -	exit (1); -      } - -    if ((nota = gpgme_get_notation (ctx))) -      printf ("---Begin Notation---\n%s---End Notation---\n", nota); +      if (strncmp (nota, test_text1, strlen (test_text1))) +	{ +	  fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__); +	  exit (1); +	} +       +      print_sig_stat (ctx, status); +      if (status != GPGME_SIG_STAT_GOOD) +	{ +	  fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__); +	  exit (1); +	} +      result = gpgme_op_verify_result (ctx); +      notation = result->signatures->notations; +      if (notation) +	{ +	  printf ("---Begin Notation---\n"); +	  while (notation) +	    { +	      if (notation->name) +		printf ("%s: %s\n", notation->name, notation->value); +	      else +		printf ("Policy URL: %s\n", notation->value); +	      notation = notation->next; +	    } +	  printf ("---End Notation---\n"); +	} +       +      gpgme_data_release (sig);       +    } +  while (argc > 1 && !strcmp (argv[1], "--loop") && ++n < 20); -    gpgme_data_release (sig); -  -} while ( argc > 1 && !strcmp( argv[1], "--loop" ) && ++n < 20 ); -      gpgme_release (ctx); -     -    return 0; +  gpgme_release (ctx); +  return 0;  } diff --git a/tests/gpgsm/t-verify.c b/tests/gpgsm/t-verify.c index 0a48b3cb..282cf2b8 100644 --- a/tests/gpgsm/t-verify.c +++ b/tests/gpgsm/t-verify.c @@ -169,6 +169,8 @@ main (int argc, char **argv )      GpgmeError err;      GpgmeData sig, text;      GpgmeSigStat status; +    GpgmeVerifyResult result; +    GpgmeSigNotation notation;      char *nota;      int n = 0; @@ -194,8 +196,21 @@ main (int argc, char **argv )        }      print_sig_stat (ctx, status); -    if ( (nota=gpgme_get_notation (ctx)) ) -        printf ("---Begin Notation---\n%s---End Notation---\n", nota); +    result = gpgme_op_verify_result (ctx); +    notation = result->signatures->notations; +    if (notation) +      { +	printf ("---Begin Notation---\n"); +	while (notation) +	  { +	    if (notation->name) +	      printf ("%s: %s\n", notation->name, notation->value); +	    else +	      printf ("Policy URL: %s\n", notation->value); +	    notation = notation->next; +	  } +	printf ("---End Notation---\n"); +      }            puts ("checking a manipulated message:\n");      gpgme_data_release (text); @@ -212,8 +227,21 @@ main (int argc, char **argv )        }      print_sig_stat (ctx, status); -    if ((nota=gpgme_get_notation (ctx))) -        printf ("---Begin Notation---\n%s---End Notation---\n", nota); +    result = gpgme_op_verify_result (ctx); +    notation = result->signatures->notations; +    if (notation) +      { +	printf ("---Begin Notation---\n"); +	while (notation) +	  { +	    if (notation->name) +	      printf ("%s: %s\n", notation->name, notation->value); +	    else +	      printf ("Policy URL: %s\n", notation->value); +	    notation = notation->next; +	  } +	printf ("---End Notation---\n"); +      }      gpgme_data_release (sig);      gpgme_data_release (text); | 
