2002-02-02 Marcus Brinkmann <marcus@g10code.de>

This patch has gotten a bit large... mmh.  The main thing that
	happens here is that error values are now not determined in the
	operation function after gpgme_wait completed, but in the status
	handler when EOF is received.  It should always be the case that
	either an error is flagged or EOF is received, so that after a
	gpgme_wait you should never have the situation that no error is
	flagged and EOF is not received.  One problem is that the engine
	status handlers don't have access to the context, a horrible
	kludge works around this for now.  All errors that happen during a
	pending operation should be catched and reported in ctx->error,
	including out-of-core and cancellation.  This rounds up neatly a
	couple of loose ends, and makes it possible to pass up any errors
	in the communication with the backend as well.  As a bonus, there
	will be a function to access gpgme->wait, so that the operations
	can truly be implemented with their _start function.

	* engine-gpgsm.c (gpgsm_status_handler): Horrible kludge to report
	error back to the context.
	* rungpg.c (gpg_status_handler): Same horrible kludge applied here.

	* engine-gpgsm.c (gpgsm_assuan_simple_command): Add error checking.

	* wait.c (_gpgme_wait_on_condition): If canceled, set CTX->error
	to a value indication that.

	* verify.c (add_notation): Set error, not out_of_core.
	(finish_sig): Likewise.
	(gpgme_op_verify_start): Don't clear out_of_core.
	(_gpgme_verify_status_handler): At EOF, clean up the notation data.
	(gpgme_op_verify): And don't do it here.

	* trustlist.c (trustlist_status_handler): Check error, not out_of_core.
	(gpgme_op_trustlist_start): Don't clear out_of_core.
	(gpgme_op_trustlist_next): Check error, not out_of_core.
	(gpgme_op_trustlist_end): Likewise.

	* ops.h (test_and_allocate_result): New macro.
	(_gpgme_passphrase_result): Remove prototype.
	* delete.c (gpgme_op_delete): Return error from context.
	(delete_status_handler): Use macro test_and_allocate_result.
	Perform error checking at EOF.
	(gpgme_op_delete_start): Release result.
	* passphrase.c (_gpgme_passphrase_status_handler): Use macro
	test_and_allocate_result, and perform error checking here.
	(_gpgme_passphrase_result): Function removed.
	* sign.c (gpgme_op_sign_start): Do not set out_of_core to zero.
	(gpgme_op_sign): Just return the error value from the context.
	(sign_status_handler): Only progress if no error is set yet.  If
	we process an EOF, set the resulting error value (if any).
	* decrypt.c (_gpgme_decrypt_result): Function removed.
	(create_result_struct): Function removed.
	(_gpgme_decrypt_status_handler): Use macro test_and_allocate_result,
	caclulate error on EOF, do not progress with errors.
	(_gpgme_decrypt_start): Do not set out_of_core to zero.
	(gpgme_op_decrypt): Just return the error value from the context.
	* encrypt.c (encrypt_status_handler): Perform the error checking
	here.
	(gpgme_op_encrypt_start): Do not clear out_of_core.
	* export.c (export_status_handler): Return if error is set in context.
	(gpgme_op_export_start): Release result.
	(gpgme_op_export): Return error from context.
	* decrypt-verify.c (gpgme_op_decrypt_verify): Return the error in
	the context.
	* genkey.c (genkey_status_handler): Use macro
	test_and_allocate_result.  Perform error checking at EOF.
	(gpgme_op_genkey): Just return the error from context.
	* import.c (gpgme_op_import): Return the error from context.
	(import_status_handler): Use macro test_and_allocate_result.
	* keylist.c (gpgme_op_keylist_start): Do not clear out_of_core.
	(gpgme_op_keylist_next): Return error of context.
	(keylist_colon_handler): Set error instead out_of_code.
	(finish_key): Likewise.

	* context.h: Remove member out_of_core, add member error.
	* gpgme.c (_gpgme_release_result): Clear error flag.

	* engine.h (_gpgme_engine_get_error): New prototype.
	* engine.c (_gpgme_engine_get_error): New function.
	* engine-gpgsm.c (_gpgme_gpgsm_get_error): New function.

	* engine-gpgsm.c (map_assuan_error): New function.
	(gpgsm_assuan_simple_command): Change return type to GpgmeError,
	use the new function to map error values.
	(gpgsm_set_fd): Change return type tp GpgmeError.
	(_gpgme_gpgsm_op_decrypt): Change type of ERR to GpgmeError.
	(gpgsm_set_recipients): Likewise.  Change type of return value
	equivalently.  Adjust error values.
	(_gpgme_gpgsm_op_import): Likewise.
	(_gpgme_gpgsm_op_sign): Likewise.
	(struct gpgsm_object_s): New member error.
	(gpgsm_status_handler): Set error if error occurs.  Determine
	error number from ERR line received.  If assuan_read_line fails,
	terminate the connection.
This commit is contained in:
Marcus Brinkmann 2002-02-02 03:52:59 +00:00
parent 92bbc39616
commit 1f5180f4b0
23 changed files with 918 additions and 699 deletions

View File

@ -1,3 +1,99 @@
2002-02-02 Marcus Brinkmann <marcus@g10code.de>
This patch has gotten a bit large... mmh. The main thing that
happens here is that error values are now not determined in the
operation function after gpgme_wait completed, but in the status
handler when EOF is received. It should always be the case that
either an error is flagged or EOF is received, so that after a
gpgme_wait you should never have the situation that no error is
flagged and EOF is not received. One problem is that the engine
status handlers don't have access to the context, a horrible
kludge works around this for now. All errors that happen during a
pending operation should be catched and reported in ctx->error,
including out-of-core and cancellation. This rounds up neatly a
couple of loose ends, and makes it possible to pass up any errors
in the communication with the backend as well. As a bonus, there
will be a function to access gpgme->wait, so that the operations
can truly be implemented with their _start function.
* engine-gpgsm.c (gpgsm_status_handler): Horrible kludge to report
error back to the context.
* rungpg.c (gpg_status_handler): Same horrible kludge applied here.
* engine-gpgsm.c (gpgsm_assuan_simple_command): Add error checking.
* wait.c (_gpgme_wait_on_condition): If canceled, set CTX->error
to a value indication that.
* verify.c (add_notation): Set error, not out_of_core.
(finish_sig): Likewise.
(gpgme_op_verify_start): Don't clear out_of_core.
(_gpgme_verify_status_handler): At EOF, clean up the notation data.
(gpgme_op_verify): And don't do it here.
* trustlist.c (trustlist_status_handler): Check error, not out_of_core.
(gpgme_op_trustlist_start): Don't clear out_of_core.
(gpgme_op_trustlist_next): Check error, not out_of_core.
(gpgme_op_trustlist_end): Likewise.
* ops.h (test_and_allocate_result): New macro.
(_gpgme_passphrase_result): Remove prototype.
* delete.c (gpgme_op_delete): Return error from context.
(delete_status_handler): Use macro test_and_allocate_result.
Perform error checking at EOF.
(gpgme_op_delete_start): Release result.
* passphrase.c (_gpgme_passphrase_status_handler): Use macro
test_and_allocate_result, and perform error checking here.
(_gpgme_passphrase_result): Function removed.
* sign.c (gpgme_op_sign_start): Do not set out_of_core to zero.
(gpgme_op_sign): Just return the error value from the context.
(sign_status_handler): Only progress if no error is set yet. If
we process an EOF, set the resulting error value (if any).
* decrypt.c (_gpgme_decrypt_result): Function removed.
(create_result_struct): Function removed.
(_gpgme_decrypt_status_handler): Use macro test_and_allocate_result,
caclulate error on EOF, do not progress with errors.
(_gpgme_decrypt_start): Do not set out_of_core to zero.
(gpgme_op_decrypt): Just return the error value from the context.
* encrypt.c (encrypt_status_handler): Perform the error checking
here.
(gpgme_op_encrypt_start): Do not clear out_of_core.
* export.c (export_status_handler): Return if error is set in context.
(gpgme_op_export_start): Release result.
(gpgme_op_export): Return error from context.
* decrypt-verify.c (gpgme_op_decrypt_verify): Return the error in
the context.
* genkey.c (genkey_status_handler): Use macro
test_and_allocate_result. Perform error checking at EOF.
(gpgme_op_genkey): Just return the error from context.
* import.c (gpgme_op_import): Return the error from context.
(import_status_handler): Use macro test_and_allocate_result.
* keylist.c (gpgme_op_keylist_start): Do not clear out_of_core.
(gpgme_op_keylist_next): Return error of context.
(keylist_colon_handler): Set error instead out_of_code.
(finish_key): Likewise.
* context.h: Remove member out_of_core, add member error.
* gpgme.c (_gpgme_release_result): Clear error flag.
* engine.h (_gpgme_engine_get_error): New prototype.
* engine.c (_gpgme_engine_get_error): New function.
* engine-gpgsm.c (_gpgme_gpgsm_get_error): New function.
* engine-gpgsm.c (map_assuan_error): New function.
(gpgsm_assuan_simple_command): Change return type to GpgmeError,
use the new function to map error values.
(gpgsm_set_fd): Change return type tp GpgmeError.
(_gpgme_gpgsm_op_decrypt): Change type of ERR to GpgmeError.
(gpgsm_set_recipients): Likewise. Change type of return value
equivalently. Adjust error values.
(_gpgme_gpgsm_op_import): Likewise.
(_gpgme_gpgsm_op_sign): Likewise.
(struct gpgsm_object_s): New member error.
(gpgsm_status_handler): Set error if error occurs. Determine
error number from ERR line received. If assuan_read_line fails,
terminate the connection.
2002-02-01 Marcus Brinkmann <marcus@g10code.de>
* Makefile.am (MOSTLYCLEANFILES): New variable.

View File

@ -44,12 +44,11 @@ struct gpgme_context_s {
int use_cms;
/* at some points we need to allocate memory but we are not
* able to handle a malloc problem at that point, so we set this
* flag to indicate this condition */
int out_of_core;
int cancel; /* cancel operation request */
/* At some points we need to remember an error which we can't report
immediately. */
GpgmeError error;
/* Cancel operation requested. */
int cancel;
EngineObject engine; /* The running engine process. */

View File

@ -29,6 +29,7 @@
#include "context.h"
#include "ops.h"
static void
decrypt_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
@ -36,6 +37,7 @@ decrypt_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
_gpgme_verify_status_handler (ctx, code, args);
}
GpgmeError
gpgme_op_decrypt_verify_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
{
@ -43,6 +45,7 @@ gpgme_op_decrypt_verify_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
decrypt_verify_status_handler);
}
/**
* gpgme_op_decrypt_verify:
* @ctx: The context
@ -60,20 +63,19 @@ gpgme_op_decrypt_verify (GpgmeCtx ctx,
GpgmeData in, GpgmeData out,
GpgmeSigStat *r_stat)
{
GpgmeError err = gpgme_op_decrypt_verify_start (ctx, in, out);
GpgmeError err;
gpgme_data_release (ctx->notation);
ctx->notation = NULL;
*r_stat = GPGME_SIG_STAT_NONE;
err = gpgme_op_decrypt_verify_start (ctx, in, out);
if (!err)
{
gpgme_wait (ctx, 1);
if (!ctx->result.decrypt || !ctx->result.verify)
err = mk_error (General_Error);
else if (ctx->out_of_core)
err = mk_error (Out_Of_Core);
else
{
err = _gpgme_decrypt_result (ctx);
if (! err)
*r_stat = _gpgme_intersect_stati (ctx->result.verify);
}
err = ctx->error;
if (!err)
*r_stat = _gpgme_intersect_stati (ctx->result.verify);
}
return err;
}

View File

@ -29,12 +29,14 @@
#include "context.h"
#include "ops.h"
struct decrypt_result_s
{
int okay;
int failed;
};
void
_gpgme_release_decrypt_result (DecryptResult result)
{
@ -43,36 +45,23 @@ _gpgme_release_decrypt_result (DecryptResult result)
xfree (result);
}
static GpgmeError
create_result_struct (GpgmeCtx ctx)
{
assert (!ctx->result.decrypt);
ctx->result.decrypt = xtrycalloc (1, sizeof *ctx->result.decrypt);
if (!ctx->result.decrypt)
return mk_error (Out_Of_Core);
return 0;
}
void
_gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
_gpgme_passphrase_status_handler (ctx, code, args);
if (ctx->out_of_core)
if (ctx->error)
return;
if (! ctx->result.decrypt)
{
if (create_result_struct (ctx))
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, decrypt);
switch (code)
{
case STATUS_EOF:
if (ctx->result.decrypt->failed)
ctx->error = mk_error (Decryption_Failed);
else if (!ctx->result.decrypt->okay)
ctx->error = mk_error (No_Data);
break;
case STATUS_DECRYPTION_OKAY:
@ -89,6 +78,7 @@ _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
}
GpgmeError
_gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
void *status_handler)
@ -99,7 +89,6 @@ _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
/* Create a process object. */
_gpgme_engine_release (ctx->engine);
@ -145,6 +134,7 @@ _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
return err;
}
GpgmeError
gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
{
@ -152,28 +142,6 @@ gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
_gpgme_decrypt_status_handler);
}
GpgmeError
_gpgme_decrypt_result (GpgmeCtx ctx)
{
GpgmeError err = 0;
if (!ctx->result.decrypt)
err = mk_error (General_Error);
else if (ctx->out_of_core)
err = mk_error (Out_Of_Core);
else
{
err = _gpgme_passphrase_result (ctx);
if (! err)
{
if (ctx->result.decrypt->failed)
err = mk_error (Decryption_Failed);
else if (!ctx->result.decrypt->okay)
err = mk_error (No_Data);
}
}
return err;
}
/**
* gpgme_op_decrypt:
@ -194,7 +162,7 @@ gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
if (!err)
{
gpgme_wait (ctx, 1);
err = _gpgme_decrypt_result (ctx);
err = ctx->error;
}
return err;
}

View File

@ -57,22 +57,27 @@ _gpgme_release_delete_result (DeleteResult result)
static void
delete_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.delete)
{
ctx->result.delete = xtrycalloc (1, sizeof *ctx->result.delete);
if (!ctx->result.delete)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, delete);
switch (code)
{
case STATUS_EOF:
switch (ctx->result.delete->problem)
{
case DELETE_No_Problem:
break;
case DELETE_No_Such_Key:
ctx->error = mk_error(Invalid_Key);
break;
case DELETE_Must_Delete_Secret_Key:
ctx->error = mk_error(Conflict);
break;
default:
ctx->error = mk_error(General_Error);
break;
}
break;
case STATUS_DELETE_PROBLEM:
@ -105,6 +110,8 @@ gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
@ -147,23 +154,7 @@ gpgme_op_delete (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
if (!err)
{
gpgme_wait (ctx, 1);
if (ctx->result.delete)
{
switch (ctx->result.delete->problem)
{
case DELETE_No_Problem:
break;
case DELETE_No_Such_Key:
err = mk_error(Invalid_Key);
break;
case DELETE_Must_Delete_Secret_Key:
err = mk_error(Conflict);
break;
default:
err = mk_error(General_Error);
break;
}
}
err = ctx->error;
}
return err;
}

View File

@ -100,17 +100,9 @@ append_xml_encinfo (GpgmeData *rdh, char *args)
static void
encrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.encrypt)
{
ctx->result.encrypt = xtrycalloc (1, sizeof *ctx->result.encrypt);
if (!ctx->result.encrypt)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, encrypt);
switch (code)
{
@ -121,6 +113,8 @@ encrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
_gpgme_set_op_info (ctx, ctx->result.encrypt->xmlinfo);
ctx->result.encrypt->xmlinfo = NULL;
}
if (ctx->result.encrypt->no_recipients)
ctx->error = mk_error (No_Recipients);
break;
case STATUS_INV_RECP:
@ -147,7 +141,6 @@ gpgme_op_encrypt_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData plain,
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
/* Do some checks. */
if (!gpgme_recipients_count (recp))
@ -220,28 +213,13 @@ gpgme_op_encrypt (GpgmeCtx ctx, GpgmeRecipients recp,
if (!err)
{
gpgme_wait (ctx, 1);
if (!ctx->result.encrypt)
err = mk_error (General_Error);
else if (ctx->out_of_core)
err = mk_error (Out_Of_Core);
else
{
if (ctx->result.encrypt->no_recipients)
err = mk_error (No_Recipients);
}
/* Old gpg versions don't return status info for invalid
recipients, so we simply check whether we got any output at
all, and if not we assume that we don't have valid
recipients. */
if (!err && gpgme_data_get_type (cipher) == GPGME_DATA_TYPE_NONE)
err = mk_error (No_Recipients);
if (!ctx->error && gpgme_data_get_type (cipher) == GPGME_DATA_TYPE_NONE)
ctx->error = mk_error (No_Recipients);
err = ctx->error;
}
return err;
}

View File

@ -1,6 +1,6 @@
/* engine-gpgsm.c - GpgSM engine
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001 g10 Code GmbH
* Copyright (C) 2001, 2002 g10 Code GmbH
*
* This file is part of GPGME.
*
@ -92,6 +92,7 @@ struct gpgsm_object_s
} colon;
};
const char *
_gpgme_gpgsm_get_version (void)
{
@ -104,6 +105,7 @@ _gpgme_gpgsm_get_version (void)
return gpgsm_version;
}
GpgmeError
_gpgme_gpgsm_check_version (void)
{
@ -112,6 +114,7 @@ _gpgme_gpgsm_check_version (void)
? 0 : mk_error (Invalid_Engine);
}
static void
close_notify_handler (int fd, void *opaque)
{
@ -126,6 +129,7 @@ close_notify_handler (int fd, void *opaque)
gpgsm->message_fd = -1;
}
GpgmeError
_gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
{
@ -217,6 +221,7 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
return err;
}
void
_gpgme_gpgsm_release (GpgsmObject gpgsm)
{
@ -243,7 +248,97 @@ _gpgme_gpgsm_release (GpgsmObject gpgsm)
xfree (gpgsm);
}
static AssuanError
static GpgmeError
map_assuan_error (AssuanError err)
{
switch (err)
{
case ASSUAN_No_Error:
return mk_error (No_Error);
case ASSUAN_General_Error:
return mk_error (General_Error);
case ASSUAN_Out_Of_Core:
return mk_error (Out_Of_Core);
case ASSUAN_Invalid_Value:
return mk_error (Invalid_Value);
case ASSUAN_Read_Error:
return mk_error (Read_Error);
case ASSUAN_Write_Error:
return mk_error (Write_Error);
case ASSUAN_Timeout:
case ASSUAN_Problem_Starting_Server:
case ASSUAN_Not_A_Server:
case ASSUAN_Not_A_Client:
case ASSUAN_Nested_Commands:
case ASSUAN_Invalid_Response:
case ASSUAN_No_Data_Callback:
case ASSUAN_No_Inquire_Callback:
case ASSUAN_Connect_Failed:
case ASSUAN_Accept_Failed:
return mk_error (General_Error);
/* The following error codes are meant as status codes. */
case ASSUAN_Not_Implemented:
return mk_error (Not_Implemented);
case ASSUAN_Canceled:
return mk_error (Canceled);
case ASSUAN_Unsupported_Algorithm:
return mk_error (Not_Implemented); /* XXX Argh. */
/* These are errors internal to GPGME. */
case ASSUAN_No_Data_Available:
case ASSUAN_No_Input:
case ASSUAN_No_Output:
case ASSUAN_Invalid_Command:
case ASSUAN_Unknown_Command:
case ASSUAN_Syntax_Error:
case ASSUAN_Parameter_Error:
case ASSUAN_Parameter_Conflict:
case ASSUAN_Line_Too_Long:
case ASSUAN_Line_Not_Terminated:
case ASSUAN_Invalid_Data:
case ASSUAN_Unexpected_Command:
case ASSUAN_Too_Much_Data:
case ASSUAN_Inquire_Unknown:
case ASSUAN_Inquire_Error:
case ASSUAN_Invalid_Option:
return mk_error (General_Error);
/* These are errors in the server. */
case ASSUAN_Server_Fault:
case ASSUAN_Server_Resource_Problem:
case ASSUAN_Server_IO_Error:
case ASSUAN_Server_Bug:
case ASSUAN_No_Agent:
case ASSUAN_Agent_Error:
return mk_error (Invalid_Engine); /* XXX: Need something more useful. */
case ASSUAN_Bad_Certificate:
case ASSUAN_Bad_Certificate_Path:
case ASSUAN_Missing_Certificate:
case ASSUAN_No_Public_Key:
case ASSUAN_No_Secret_Key:
case ASSUAN_Invalid_Name:
return mk_error(Invalid_Key);
case ASSUAN_Bad_Signature:
return mk_error(Invalid_Key); /* XXX: This is wrong. */
case ASSUAN_Cert_Revoked:
case ASSUAN_No_CRL_For_Cert:
case ASSUAN_CRL_Too_Old:
case ASSUAN_Not_Trusted:
return mk_error(Invalid_Key); /* XXX Some more details would be good. */
default:
return mk_error (General_Error);
}
}
static GpgmeError
gpgsm_assuan_simple_command (ASSUAN_CONTEXT ctx, char *cmd)
{
AssuanError err;
@ -252,13 +347,13 @@ gpgsm_assuan_simple_command (ASSUAN_CONTEXT ctx, char *cmd)
err = assuan_write_line (ctx, cmd);
if (err)
return err;
return map_assuan_error (err);
do
{
err = assuan_read_line (ctx, &line, &linelen);
if (err)
return err;
return map_assuan_error (err);
}
while (*line == '#' || !linelen);
@ -266,12 +361,19 @@ gpgsm_assuan_simple_command (ASSUAN_CONTEXT ctx, char *cmd)
&& line[0] == 'O' && line[1] == 'K'
&& (line[2] == '\0' || line[2] == ' '))
return 0;
else
return ASSUAN_General_Error;
if (linelen >= 4
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& line[3] == ' ')
err = map_assuan_error (atoi (&line[4]));
if (!err)
err = mk_error (General_Error);
}
#define COMMANDLINELEN 40
static AssuanError
static GpgmeError
gpgsm_set_fd (ASSUAN_CONTEXT ctx, const char *which, int fd, const char *opt)
{
char line[COMMANDLINELEN];
@ -284,10 +386,11 @@ gpgsm_set_fd (ASSUAN_CONTEXT ctx, const char *which, int fd, const char *opt)
return gpgsm_assuan_simple_command (ctx, line);
}
GpgmeError
_gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, GpgmeData plain)
{
AssuanError err;
GpgmeError err;
if (!gpgsm)
return mk_error (Invalid_Value);
@ -309,6 +412,7 @@ _gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, GpgmeData plain)
return 0;
}
GpgmeError
_gpgme_gpgsm_op_delete (GpgsmObject gpgsm, GpgmeKey key, int allow_secret)
{
@ -316,10 +420,11 @@ _gpgme_gpgsm_op_delete (GpgsmObject gpgsm, GpgmeKey key, int allow_secret)
return mk_error (Not_Implemented);
}
static AssuanError
static GpgmeError
gpgsm_set_recipients (ASSUAN_CONTEXT ctx, GpgmeRecipients recp)
{
AssuanError err;
GpgmeError err;
char *line;
int linelen;
struct user_id_s *r;
@ -327,7 +432,7 @@ gpgsm_set_recipients (ASSUAN_CONTEXT ctx, GpgmeRecipients recp)
linelen = 10 + 40 + 1; /* "RECIPIENT " + guess + '\0'. */
line = xtrymalloc (10 + 40 + 1);
if (!line)
return ASSUAN_Out_Of_Core;
return mk_error (Out_Of_Core);
strcpy (line, "RECIPIENT ");
for (r = recp->list; r; r = r->next)
{
@ -338,7 +443,7 @@ gpgsm_set_recipients (ASSUAN_CONTEXT ctx, GpgmeRecipients recp)
if (! newline)
{
xfree (line);
return ASSUAN_Out_Of_Core;
return mk_error(Out_Of_Core);
}
line = newline;
linelen = newlen;
@ -356,11 +461,12 @@ gpgsm_set_recipients (ASSUAN_CONTEXT ctx, GpgmeRecipients recp)
return 0;
}
GpgmeError
_gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp,
GpgmeData plain, GpgmeData ciph, int use_armor)
{
AssuanError err;
GpgmeError err;
if (!gpgsm)
return mk_error (Invalid_Value);
@ -372,21 +478,22 @@ _gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp,
gpgsm->input_data = plain;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server, 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
gpgsm->output_data = ciph;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
use_armor ? "--armor" : 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
_gpgme_io_close (gpgsm->message_fd);
err = gpgsm_set_recipients (gpgsm->assuan_ctx, recp);
if (err)
return mk_error (General_Error);
return err;
return 0;
}
GpgmeError
_gpgme_gpgsm_op_export (GpgsmObject gpgsm, GpgmeRecipients recp,
GpgmeData keydata, int use_armor)
@ -395,6 +502,7 @@ _gpgme_gpgsm_op_export (GpgsmObject gpgsm, GpgmeRecipients recp,
return mk_error (Not_Implemented);
}
GpgmeError
_gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, int use_armor)
{
@ -402,10 +510,11 @@ _gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, int use_armor)
return mk_error (Not_Implemented);
}
GpgmeError
_gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata)
{
AssuanError err;
GpgmeError err;
if (!gpgsm)
return mk_error (Invalid_Value);
@ -417,13 +526,14 @@ _gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata)
gpgsm->input_data = keydata;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server, 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
_gpgme_io_close (gpgsm->output_fd);
_gpgme_io_close (gpgsm->message_fd);
return 0;
}
GpgmeError
_gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern,
int secret_only, int keylist_mode)
@ -455,12 +565,13 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern,
return 0;
}
GpgmeError
_gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out,
GpgmeSigMode mode, int use_armor,
int use_textmode, GpgmeCtx ctx /* FIXME */)
{
AssuanError err;
GpgmeError err;
if (!gpgsm)
return mk_error (Invalid_Value);
@ -473,17 +584,18 @@ _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out,
gpgsm->input_data = in;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server, 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
gpgsm->output_data = out;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "OUTPUT", gpgsm->output_fd_server,
use_armor ? "--armor" : 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
_gpgme_io_close (gpgsm->message_fd);
return 0;
}
GpgmeError
_gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern)
{
@ -491,10 +603,11 @@ _gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern)
return mk_error (Not_Implemented);
}
GpgmeError
_gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text)
{
AssuanError err;
GpgmeError err;
if (!gpgsm)
return mk_error (Invalid_Value);
@ -506,17 +619,18 @@ _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text)
gpgsm->input_data = sig;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "INPUT", gpgsm->input_fd_server, 0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
gpgsm->message_data = text;
err = gpgsm_set_fd (gpgsm->assuan_ctx, "MESSAGE", gpgsm->message_fd_server,
0);
if (err)
return mk_error (General_Error); /* FIXME */
return err;
_gpgme_io_close (gpgsm->output_fd);
return 0;
}
static int
status_cmp (const void *ap, const void *bp)
{
@ -526,10 +640,11 @@ status_cmp (const void *ap, const void *bp)
return strcmp (a->name, b->name);
}
static int
gpgsm_status_handler (void *opaque, int pid, int fd)
{
int err;
AssuanError err;
GpgsmObject gpgsm = opaque;
char *line;
size_t linelen;
@ -546,14 +661,30 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
&& (line[3] == '\0' || line[3] == ' ')))
{
/* FIXME Save error somewhere. */
/* XXX: If an error occured, find out what happened, then save the error value
before running the status handler (so it takes precedence). */
if (!err && line[0] == 'E' && line[3] == ' ')
{
err = map_assuan_error (atoi (&line[4]));
if (!err)
err = mk_error (General_Error);
}
if (err)
{
/* XXX Kludge ahead. We really, really, really must not
make use of status.fnc_value. */
GpgmeCtx ctx = (GpgmeCtx) gpgsm->status.fnc_value;
if (!ctx->error)
ctx->error = err;
}
if (gpgsm->status.fnc)
gpgsm->status.fnc (gpgsm->status.fnc_value, STATUS_EOF, "");
/* XXX: If an error occured, try our best to terminate the
connection. */
if (line[0] == 'E')
/* XXX: Try our best to terminate the connection. */
if (err)
assuan_write_line (gpgsm->assuan_ctx, "BYE");
return 1;
}
@ -650,6 +781,7 @@ gpgsm_status_handler (void *opaque, int pid, int fd)
return 0;
}
void
_gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm,
GpgStatusHandler fnc, void *fnc_value)
@ -660,6 +792,7 @@ _gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm,
gpgsm->status.fnc_value = fnc_value;
}
void
_gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm,
GpgColonLineHandler fnc, void *fnc_value)
@ -670,6 +803,7 @@ _gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm,
gpgsm->colon.fnc_value = fnc_value;
}
GpgmeError
_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
{
@ -721,37 +855,44 @@ _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
return err;
}
#else /* ENABLE_GPGSM */
#include <stddef.h>
#include "util.h"
#include "engine-gpgsm.h"
const char *
_gpgme_gpgsm_get_version (void)
{
return NULL;
}
GpgmeError
_gpgme_gpgsm_check_version (void)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_new (GpgsmObject *r_gpgsm)
{
return mk_error (Invalid_Engine);
}
void
_gpgme_gpgsm_release (GpgsmObject gpgsm)
{
return;
}
void
_gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm,
GpgStatusHandler fnc, void *fnc_value)
@ -759,18 +900,21 @@ _gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm,
return;
}
GpgmeError
_gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, GpgmeData plain)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_delete (GpgsmObject gpgsm, GpgmeKey key, int allow_secret)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp,
GpgmeData plain, GpgmeData ciph, int use_armor)
@ -778,6 +922,7 @@ _gpgme_gpgsm_op_encrypt (GpgsmObject gpgsm, GpgmeRecipients recp,
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_export (GpgsmObject gpgsm, GpgmeRecipients recp,
GpgmeData keydata, int use_armor)
@ -785,18 +930,21 @@ _gpgme_gpgsm_op_export (GpgsmObject gpgsm, GpgmeRecipients recp,
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, int use_armor)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern,
int secret_only, int keylist_mode)
@ -804,6 +952,7 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern,
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out,
GpgmeSigMode mode, int use_armor,
@ -812,28 +961,33 @@ _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out,
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_trustlist (GpgsmObject gpgsm, const char *pattern)
{
return mk_error (Invalid_Engine);
}
GpgmeError
_gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeData text)
{
return mk_error (Invalid_Engine);
}
void
_gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm,
GpgColonLineHandler fnc, void *fnc_value)
{
}
GpgmeError
_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque)
_gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque, GpgmeError *errorp)
{
return mk_error (Invalid_Engine);
}
#endif /* ! ENABLE_GPGSM */

View File

@ -59,7 +59,3 @@ GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig,
GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque);
#endif /* ENGINE_GPGSM_H */

View File

@ -213,6 +213,7 @@ _gpgme_engine_release (EngineObject engine)
xfree (engine);
}
void
_gpgme_engine_set_verbosity (EngineObject engine, int verbosity)
{

View File

@ -29,13 +29,18 @@
#include "context.h"
#include "ops.h"
static void
export_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->error)
return;
DEBUG2 ("export_status: code=%d args=`%s'\n", code, args);
/* FIXME: Need to do more */
}
GpgmeError
gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
{
@ -47,6 +52,8 @@ gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
if (err)
@ -76,6 +83,7 @@ gpgme_op_export_start (GpgmeCtx ctx, GpgmeRecipients recp, GpgmeData keydata)
return err;
}
/**
* gpgme_op_export:
* @c: the context
@ -94,6 +102,9 @@ gpgme_op_export (GpgmeCtx ctx, GpgmeRecipients recipients, GpgmeData keydata)
{
GpgmeError err = gpgme_op_export_start (ctx, recipients, keydata);
if (!err)
gpgme_wait (ctx, 1);
{
gpgme_wait (ctx, 1);
err = ctx->error;
}
return err;
}

View File

@ -50,18 +50,9 @@ genkey_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
_gpgme_progress_status_handler (ctx, code, args);
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.genkey)
{
ctx->result.genkey = xtrycalloc (1, sizeof *ctx->result.genkey);
if (!ctx->result.genkey)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, genkey);
switch (code)
{
@ -75,6 +66,13 @@ genkey_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
}
break;
case STATUS_EOF:
/* FIXME: Should return some more useful error value. */
if (!ctx->result.genkey->created_primary
&& !ctx->result.genkey->created_sub)
ctx->error = mk_error (General_Error);
break;
default:
break;
}
@ -228,13 +226,7 @@ gpgme_op_genkey (GpgmeCtx ctx, const char *parms,
if (!err)
{
gpgme_wait (ctx, 1);
/* FIXME: Should return some more useful error value. */
if (!ctx->result.genkey)
err = mk_error (General_Error);
else if (!ctx->result.genkey->created_primary
&& !ctx->result.genkey->created_sub)
err = mk_error (General_Error);
err = ctx->error;
}
return err;
}

View File

@ -91,6 +91,7 @@ _gpgme_release_result (GpgmeCtx ctx)
_gpgme_release_genkey_result (ctx->result.genkey);
memset (&ctx->result, 0, sizeof (ctx->result));
_gpgme_set_op_info (ctx, NULL);
ctx->error = 0;
}

View File

@ -135,17 +135,9 @@ append_xml_impinfo (GpgmeData *rdh, GpgStatusCode code, char *args)
static void
import_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.import)
{
ctx->result.import = xtrycalloc (1, sizeof *ctx->result.import);
if (!ctx->result.import)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, import);
switch (code)
{
@ -156,6 +148,7 @@ import_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
_gpgme_set_op_info (ctx, ctx->result.import->xmlinfo);
ctx->result.import->xmlinfo = NULL;
}
/* XXX Calculate error value. */
break;
case STATUS_IMPORTED:
@ -225,6 +218,9 @@ gpgme_op_import (GpgmeCtx ctx, GpgmeData keydata)
{
GpgmeError err = gpgme_op_import_start (ctx, keydata);
if (!err)
gpgme_wait (ctx, 1);
{
gpgme_wait (ctx, 1);
err = ctx->error;
}
return err;
}

View File

@ -37,275 +37,310 @@ static void finish_key ( GpgmeCtx ctx );
static void
keylist_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
keylist_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if ( ctx->out_of_core )
return;
if (ctx->error)
return;
switch (code) {
case STATUS_EOF:
finish_key (ctx);
break;
switch (code)
{
case STATUS_EOF:
finish_key (ctx);
break;
default:
/* ignore all other codes */
break;
default:
/* Ignore all other codes. */
break;
}
}
static time_t
parse_timestamp ( char *p )
parse_timestamp (char *p)
{
if (!*p )
return 0;
if (!*p)
return 0;
return (time_t)strtoul (p, NULL, 10);
return (time_t)strtoul (p, NULL, 10);
}
static void
set_mainkey_trust_info ( GpgmeKey key, const char *s )
set_mainkey_trust_info (GpgmeKey key, const char *s)
{
/* look at letters and stop at the first digit */
for (; *s && !my_isdigit (*s); s++ ) {
switch (*s) {
case 'e': key->keys.flags.expired = 1; break;
case 'r': key->keys.flags.revoked = 1; break;
case 'd': key->keys.flags.disabled = 1; break;
case 'i': key->keys.flags.invalid = 1; break;
/* Look at letters and stop at the first digit. */
for (; *s && !my_isdigit (*s); s++)
{
switch (*s)
{
case 'e': key->keys.flags.expired = 1; break;
case 'r': key->keys.flags.revoked = 1; break;
case 'd': key->keys.flags.disabled = 1; break;
case 'i': key->keys.flags.invalid = 1; break;
}
}
}
static void
set_userid_flags ( GpgmeKey key, const char *s )
set_userid_flags (GpgmeKey key, const char *s)
{
/* look at letters and stop at the first digit */
for (; *s && !my_isdigit (*s); s++ ) {
switch (*s) {
case 'r': key->uids->revoked = 1; break;
case 'i': key->uids->invalid = 1; break;
/* Look at letters and stop at the first digit. */
for (; *s && !my_isdigit (*s); s++)
{
switch (*s)
{
case 'r': key->uids->revoked = 1; break;
case 'i': key->uids->invalid = 1; break;
case 'n': key->uids->validity = GPGME_VALIDITY_NEVER; break;
case 'm': key->uids->validity = GPGME_VALIDITY_MARGINAL; break;
case 'f': key->uids->validity = GPGME_VALIDITY_FULL; break;
case 'u': key->uids->validity = GPGME_VALIDITY_ULTIMATE; break;
}
}
}
static void
set_subkey_trust_info ( struct subkey_s *k, const char *s )
{
/* look at letters and stop at the first digit */
for (; *s && !my_isdigit (*s); s++ ) {
switch (*s) {
case 'e': k->flags.expired = 1; break;
case 'r': k->flags.revoked = 1; break;
case 'd': k->flags.disabled = 1; break;
case 'i': k->flags.invalid = 1; break;
}
}
}
static void
set_mainkey_capability ( GpgmeKey key, const char *s )
{
for (; *s ; s++ ) {
switch (*s) {
case 'e': key->keys.flags.can_encrypt = 1; break;
case 's': key->keys.flags.can_sign = 1; break;
case 'c': key->keys.flags.can_certify = 1; break;
case 'E': key->gloflags.can_encrypt = 1; break;
case 'S': key->gloflags.can_sign = 1; break;
case 'C': key->gloflags.can_certify = 1; break;
}
}
}
static void
set_subkey_capability ( struct subkey_s *k, const char *s )
{
for (; *s; s++ ) {
switch (*s) {
case 'e': k->flags.can_encrypt = 1; break;
case 's': k->flags.can_sign = 1; break;
case 'c': k->flags.can_certify = 1; break;
case 'n': key->uids->validity = GPGME_VALIDITY_NEVER; break;
case 'm': key->uids->validity = GPGME_VALIDITY_MARGINAL; break;
case 'f': key->uids->validity = GPGME_VALIDITY_FULL; break;
case 'u': key->uids->validity = GPGME_VALIDITY_ULTIMATE; break;
}
}
}
/* Note: we are allowed to modify line */
static void
keylist_colon_handler ( GpgmeCtx ctx, char *line )
set_subkey_trust_info (struct subkey_s *k, const char *s)
{
char *p, *pend;
int field = 0;
enum {
/* Look at letters and stop at the first digit. */
for (; *s && !my_isdigit (*s); s++)
{
switch (*s)
{
case 'e': k->flags.expired = 1; break;
case 'r': k->flags.revoked = 1; break;
case 'd': k->flags.disabled = 1; break;
case 'i': k->flags.invalid = 1; break;
}
}
}
static void
set_mainkey_capability (GpgmeKey key, const char *s)
{
for (; *s ; s++)
{
switch (*s)
{
case 'e': key->keys.flags.can_encrypt = 1; break;
case 's': key->keys.flags.can_sign = 1; break;
case 'c': key->keys.flags.can_certify = 1; break;
case 'E': key->gloflags.can_encrypt = 1; break;
case 'S': key->gloflags.can_sign = 1; break;
case 'C': key->gloflags.can_certify = 1; break;
}
}
}
static void
set_subkey_capability ( struct subkey_s *k, const char *s)
{
for (; *s; s++)
{
switch (*s)
{
case 'e': k->flags.can_encrypt = 1; break;
case 's': k->flags.can_sign = 1; break;
case 'c': k->flags.can_certify = 1; break;
}
}
}
/* Note: We are allowed to modify LINE. */
static void
keylist_colon_handler (GpgmeCtx ctx, char *line)
{
char *p, *pend;
int field = 0;
enum
{
RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
RT_CRT, RT_CRS
} rectype = RT_NONE;
GpgmeKey key = ctx->tmp_key;
int i;
const char *trust_info = NULL;
struct subkey_s *sk = NULL;
if ( ctx->out_of_core )
return;
if (!line) { /* EOF */
finish_key (ctx);
return;
}
rectype = RT_NONE;
GpgmeKey key = ctx->tmp_key;
int i;
const char *trust_info = NULL;
struct subkey_s *sk = NULL;
for (p = line; p; p = pend) {
field++;
pend = strchr (p, ':');
if (pend)
*pend++ = 0;
if (ctx->error)
return;
if (!line)
{
/* EOF */
finish_key (ctx);
return;
}
for (p = line; p; p = pend)
{
field++;
pend = strchr (p, ':');
if (pend)
*pend++ = 0;
if ( field == 1 ) {
if ( !strcmp ( p, "sig" ) )
rectype = RT_SIG;
else if ( !strcmp ( p, "uid" ) && key ) {
rectype = RT_UID;
key = ctx->tmp_key;
if (field == 1)
{
if (!strcmp (p, "sig"))
rectype = RT_SIG;
else if (!strcmp (p, "uid") && key)
{
rectype = RT_UID;
key = ctx->tmp_key;
}
else if ( !strcmp (p, "sub") && key ) {
/* start a new subkey */
rectype = RT_SUB;
if ( !(sk = _gpgme_key_add_subkey (key)) ) {
ctx->out_of_core=1;
return;
else if (!strcmp (p, "sub") && key)
{
/* Start a new subkey. */
rectype = RT_SUB;
if (!(sk = _gpgme_key_add_subkey (key)))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
}
else if ( !strcmp (p, "ssb") && key ) {
/* start a new secret subkey */
rectype = RT_SSB;
if ( !(sk = _gpgme_key_add_secret_subkey (key)) ) {
ctx->out_of_core=1;
return;
else if (!strcmp (p, "ssb") && key)
{
/* Start a new secret subkey. */
rectype = RT_SSB;
if (!(sk = _gpgme_key_add_secret_subkey (key)))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
}
else if ( !strcmp (p, "pub") ) {
/* start a new keyblock */
if ( _gpgme_key_new ( &key ) ) {
ctx->out_of_core=1; /* the only kind of error we can get*/
return;
else if (!strcmp (p, "pub"))
{
/* Start a new keyblock. */
if (_gpgme_key_new (&key))
{
ctx->error = mk_error (Out_Of_Core); /* the only kind of error we can get*/
return;
}
rectype = RT_PUB;
finish_key ( ctx );
assert ( !ctx->tmp_key );
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if ( !strcmp (p, "sec") ) {
/* start a new keyblock */
if ( _gpgme_key_new_secret ( &key ) ) {
ctx->out_of_core=1; /*the only kind of error we can get*/
else if (!strcmp (p, "sec"))
{
/* Start a new keyblock, */
if (_gpgme_key_new_secret (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
return;
}
rectype = RT_SEC;
finish_key ( ctx );
assert ( !ctx->tmp_key );
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if ( !strcmp (p, "crt") ) {
/* start a new certificate */
if ( _gpgme_key_new ( &key ) ) {
ctx->out_of_core=1; /* the only kind of error we can get*/
else if (!strcmp (p, "crt"))
{
/* Start a new certificate. */
if (_gpgme_key_new (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
return;
}
key->x509 = 1;
rectype = RT_CRT;
finish_key ( ctx );
assert ( !ctx->tmp_key );
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if ( !strcmp (p, "crs") ) {
/* start a new certificate */
if ( _gpgme_key_new_secret ( &key ) ) {
ctx->out_of_core=1; /* the only kind of error we can get*/
return;
else if (!strcmp (p, "crs"))
{
/* Start a new certificate. */
if (_gpgme_key_new_secret (&key))
{
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
return;
}
key->x509 = 1;
rectype = RT_CRS;
finish_key ( ctx );
assert ( !ctx->tmp_key );
ctx->tmp_key = key;
key->x509 = 1;
rectype = RT_CRS;
finish_key (ctx);
assert (!ctx->tmp_key);
ctx->tmp_key = key;
}
else if ( !strcmp ( p, "fpr" ) && key )
rectype = RT_FPR;
else
rectype = RT_NONE;
else if (!strcmp (p, "fpr") && key)
rectype = RT_FPR;
else
rectype = RT_NONE;
}
else if ( rectype == RT_PUB || rectype == RT_SEC
|| rectype == RT_CRT || rectype == RT_CRS)
{
switch (field) {
case 2: /* trust info */
trust_info = p;
set_mainkey_trust_info (key, trust_info);
break;
case 3: /* key length */
i = atoi (p);
if ( i > 1 ) /* ignore invalid values */
key->keys.key_len = i;
break;
case 4: /* pubkey algo */
i = atoi (p);
if ( i > 1 && i < 128 )
key->keys.key_algo = i;
else if (rectype == RT_PUB || rectype == RT_SEC
|| rectype == RT_CRT || rectype == RT_CRS)
{
switch (field)
{
case 2: /* trust info */
trust_info = p;
set_mainkey_trust_info (key, trust_info);
break;
case 3: /* key length */
i = atoi (p);
if (i > 1) /* ignore invalid values */
key->keys.key_len = i;
break;
case 4: /* pubkey algo */
i = atoi (p);
if (i > 1 && i < 128)
key->keys.key_algo = i;
break;
case 5: /* long keyid */
if ( strlen (p) == DIM(key->keys.keyid)-1 )
strcpy (key->keys.keyid, p);
break;
case 6: /* timestamp (seconds) */
key->keys.timestamp = parse_timestamp (p);
break;
case 7: /* valid for n days */
break;
case 8: /* X.509 serial number */
/* fixme: store it */
break;
case 9: /* ownertrust */
break;
case 10: /* not used for gpg due to --fixed-list-mode option
but gpgsm stores the issuer name */
/* fixme: store issuer name */
break;
case 11: /* signature class */
break;
case 12: /* capabilities */
set_mainkey_capability (key, p );
break;
case 13:
pend = NULL; /* we can stop here */
if (strlen (p) == DIM(key->keys.keyid) - 1)
strcpy (key->keys.keyid, p);
break;
case 6: /* timestamp (seconds) */
key->keys.timestamp = parse_timestamp (p);
break;
case 7: /* valid for n days */
break;
case 8: /* X.509 serial number */
/* fixme: store it */
break;
case 9: /* ownertrust */
break;
case 10: /* not used for gpg due to --fixed-list-mode option
but gpgsm stores the issuer name */
/* fixme: store issuer name */
break;
case 11: /* signature class */
break;
case 12: /* capabilities */
set_mainkey_capability (key, p);
break;
case 13:
pend = NULL; /* we can stop here */
break;
}
}
else if ( (rectype == RT_SUB || rectype== RT_SSB) && sk ) {
switch (field) {
else if ((rectype == RT_SUB || rectype== RT_SSB) && sk)
{
switch (field)
{
case 2: /* trust info */
set_subkey_trust_info ( sk, p);
set_subkey_trust_info (sk, p);
break;
case 3: /* key length */
i = atoi (p);
if ( i > 1 ) /* ignore invalid values */
sk->key_len = i;
if (i > 1) /* ignore invalid values */
sk->key_len = i;
break;
case 4: /* pubkey algo */
i = atoi (p);
if ( i > 1 && i < 128 )
sk->key_algo = i;
if (i > 1 && i < 128)
sk->key_algo = i;
break;
case 5: /* long keyid */
if ( strlen (p) == DIM(sk->keyid)-1 )
strcpy (sk->keyid, p);
if (strlen (p) == DIM(sk->keyid) - 1)
strcpy (sk->keyid, p);
break;
case 6: /* timestamp (seconds) */
sk->timestamp = parse_timestamp (p);
@ -321,43 +356,48 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
case 11: /* signature class */
break;
case 12: /* capability */
set_subkey_capability ( sk, p );
set_subkey_capability (sk, p);
break;
case 13:
pend = NULL; /* we can stop here */
break;
}
}
else if ( rectype == RT_UID ) {
switch (field) {
case 2: /* trust info */
trust_info = p; /*save for later */
break;
case 10: /* user ID */
if ( _gpgme_key_append_name ( key, p) )
ctx->out_of_core = 1;
else {
if (trust_info)
set_userid_flags (key, trust_info);
}
pend = NULL; /* we can stop here */
break;
else if (rectype == RT_UID)
{
switch (field)
{
case 2: /* trust info */
trust_info = p; /*save for later */
break;
case 10: /* user ID */
if (_gpgme_key_append_name (key, p))
ctx->error = mk_error (Out_Of_Core); /* The only kind of error we can get*/
else
{
if (trust_info)
set_userid_flags (key, trust_info);
}
pend = NULL; /* we can stop here */
break;
}
}
else if ( rectype == RT_FPR ) {
switch (field) {
case 10: /* fingerprint (take only the first one)*/
if ( !key->keys.fingerprint && *p ) {
key->keys.fingerprint = xtrystrdup (p);
if ( !key->keys.fingerprint )
ctx->out_of_core = 1;
else if (rectype == RT_FPR)
{
switch (field)
{
case 10: /* fingerprint (take only the first one)*/
if (!key->keys.fingerprint && *p)
{
key->keys.fingerprint = xtrystrdup (p);
if (!key->keys.fingerprint)
ctx->error = mk_error (Out_Of_Core);
}
pend = NULL; /* that is all we want */
break;
pend = NULL; /* that is all we want */
break;
}
}
}
}
@ -366,37 +406,41 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
* it. It is assumed that this releases ctx->tmp_key.
*/
static void
finish_key ( GpgmeCtx ctx )
finish_key (GpgmeCtx ctx)
{
GpgmeKey key = ctx->tmp_key;
struct key_queue_item_s *q, *q2;
GpgmeKey key = ctx->tmp_key;
struct key_queue_item_s *q, *q2;
if (key) {
ctx->tmp_key = NULL;
if (key)
{
ctx->tmp_key = NULL;
_gpgme_key_cache_add (key);
_gpgme_key_cache_add (key);
q = xtrymalloc ( sizeof *q );
if ( !q ) {
gpgme_key_release (key);
ctx->out_of_core = 1;
return;
q = xtrymalloc (sizeof *q);
if (!q)
{
gpgme_key_release (key);
ctx->error = mk_error (Out_Of_Core);
return;
}
q->key = key;
q->next = NULL;
/* fixme: lock queue. Use a tail pointer? */
if ( !(q2 = ctx->key_queue) )
ctx->key_queue = q;
else {
for ( ; q2->next; q2 = q2->next )
;
q2->next = q;
q->key = key;
q->next = NULL;
/* FIXME: Lock queue. Use a tail pointer? */
if (!(q2 = ctx->key_queue))
ctx->key_queue = q;
else
{
for (; q2->next; q2 = q2->next)
;
q2->next = q;
}
ctx->key_cond = 1;
/* fixme: unlock queue */
ctx->key_cond = 1;
/* FIXME: Unlock queue. */
}
}
/**
* gpgme_op_keylist_start:
* @c: context
@ -419,7 +463,6 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
if (ctx->engine)
{
@ -457,6 +500,7 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
return err;
}
/**
* gpgme_op_keylist_next:
* @c: Context
@ -482,14 +526,14 @@ gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->out_of_core)
return mk_error (Out_Of_Core);
if (ctx->error)
return ctx->error;
if (!ctx->key_queue)
{
_gpgme_wait_on_condition (ctx, 1, &ctx->key_cond);
if (ctx->out_of_core)
return mk_error (Out_Of_Core);
if (ctx->error)
return ctx->error;
if (!ctx->key_cond)
{
ctx->pending = 0;
@ -508,6 +552,7 @@ gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
return 0;
}
/**
* gpgme_op_keylist_end:
* @c: Context
@ -522,8 +567,8 @@ gpgme_op_keylist_end (GpgmeCtx ctx)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->out_of_core)
return mk_error (Out_Of_Core);
if (ctx->error)
return ctx->error;
ctx->pending = 0;
return 0;

View File

@ -25,6 +25,23 @@
#include "types.h"
#include "rungpg.h"
/* Support macros. */
#define test_and_allocate_result(ctx,field) \
do \
{ \
if (!ctx->result.field) \
{ \
ctx->result.field = xtrycalloc (1, sizeof *ctx->result.field); \
if (!ctx->result.field) \
{ \
ctx->error = mk_error (Out_Of_Core); \
return; \
} \
} \
} \
while (0)
/*-- gpgme.c --*/
void _gpgme_release_result ( GpgmeCtx c );
void _gpgme_set_op_info (GpgmeCtx c, GpgmeData info);
@ -93,7 +110,6 @@ void _gpgme_release_passphrase_result (PassphraseResult result);
void _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgStatusCode code,
char *args);
GpgmeError _gpgme_passphrase_start (GpgmeCtx ctx);
GpgmeError _gpgme_passphrase_result (GpgmeCtx ctx);
/*-- progress.c --*/
void _gpgme_progress_status_handler (GpgmeCtx ctx, GpgStatusCode code,

View File

@ -29,6 +29,7 @@
#include "context.h"
#include "ops.h"
struct passphrase_result_s
{
int no_passphrase;
@ -38,6 +39,7 @@ struct passphrase_result_s
int bad_passphrase;
};
void
_gpgme_release_passphrase_result (PassphraseResult result)
{
@ -48,28 +50,20 @@ _gpgme_release_passphrase_result (PassphraseResult result)
xfree (result);
}
void
_gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.passphrase)
{
ctx->result.passphrase = xtrycalloc (1, sizeof *ctx->result.passphrase);
if (!ctx->result.passphrase)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, passphrase);
switch (code)
{
case STATUS_USERID_HINT:
xfree (ctx->result.passphrase->userid_hint);
if (!(ctx->result.passphrase->userid_hint = xtrystrdup (args)) )
ctx->out_of_core = 1;
if (!(ctx->result.passphrase->userid_hint = xtrystrdup (args)))
ctx->error = mk_error (Out_Of_Core);
break;
case STATUS_BAD_PASSPHRASE:
@ -85,7 +79,7 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
xfree (ctx->result.passphrase->passphrase_info);
ctx->result.passphrase->passphrase_info = xtrystrdup (args);
if (!ctx->result.passphrase->passphrase_info)
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
break;
case STATUS_MISSING_PASSPHRASE:
@ -93,12 +87,18 @@ _gpgme_passphrase_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
ctx->result.passphrase->no_passphrase = 1;
break;
case STATUS_EOF:
if (ctx->result.passphrase->no_passphrase)
ctx->error = mk_error (No_Passphrase);
break;
default:
/* Ignore all other codes. */
break;
}
}
static const char *
command_handler (void *opaque, GpgStatusCode code, const char *key)
{
@ -109,7 +109,7 @@ command_handler (void *opaque, GpgStatusCode code, const char *key)
ctx->result.passphrase = xtrycalloc (1, sizeof *ctx->result.passphrase);
if (!ctx->result.passphrase)
{
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
return NULL;
}
}
@ -146,7 +146,7 @@ command_handler (void *opaque, GpgStatusCode code, const char *key)
+ strlen (passphrase_info) + 3);
if (!buf)
{
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
return NULL;
}
sprintf (buf, "%s\n%s\n%s",
@ -162,6 +162,7 @@ command_handler (void *opaque, GpgStatusCode code, const char *key)
return NULL;
}
GpgmeError
_gpgme_passphrase_start (GpgmeCtx ctx)
{
@ -171,17 +172,3 @@ _gpgme_passphrase_start (GpgmeCtx ctx)
err = _gpgme_engine_set_command_handler (ctx->engine, command_handler, ctx);
return err;
}
GpgmeError
_gpgme_passphrase_result (GpgmeCtx ctx)
{
GpgmeError err = 0;
if (!ctx->result.passphrase)
err = mk_error (General_Error);
else if (ctx->out_of_core)
err = mk_error (Out_Of_Core);
else if (ctx->result.passphrase->no_passphrase)
err = mk_error (No_Passphrase);
return err;
}

View File

@ -44,7 +44,7 @@ _gpgme_progress_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
args_cpy = xtrystrdup (args);
if (!args_cpy)
{
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
return;
}

View File

@ -845,19 +845,23 @@ _gpgme_gpg_spawn( GpgObject gpg, void *opaque )
static int
gpg_status_handler ( void *opaque, int pid, int fd )
gpg_status_handler (void *opaque, int pid, int fd)
{
GpgObject gpg = opaque;
int rc = 0;
GpgObject gpg = opaque;
int err;
assert ( fd == gpg->status.fd[0] );
rc = read_status ( gpg );
if ( rc ) {
DEBUG1 ("gpg_handler: read_status problem %d\n - stop", rc);
return 1;
assert (fd == gpg->status.fd[0]);
err = read_status (gpg);
if (err)
{
/* XXX Horrible kludge. We really must not make use of
fnc_value. */
GpgmeCtx ctx = (GpgmeCtx) gpg->status.fnc_value;
ctx->error = err;
DEBUG1 ("gpg_handler: read_status problem %d\n - stop", err);
return 1;
}
return gpg->status.eof;
return gpg->status.eof;
}

View File

@ -140,17 +140,9 @@ sign_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
_gpgme_passphrase_status_handler (ctx, code, args);
if (ctx->out_of_core)
if (ctx->error)
return;
if (!ctx->result.sign)
{
ctx->result.sign = xtrycalloc (1, sizeof *ctx->result.sign);
if (!ctx->result.sign)
{
ctx->out_of_core = 1;
return;
}
}
test_and_allocate_result (ctx, sign);
switch (code)
{
@ -161,12 +153,14 @@ sign_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
_gpgme_set_op_info (ctx, ctx->result.sign->xmlinfo);
ctx->result.sign->xmlinfo = NULL;
}
if (!ctx->error && !ctx->result.sign->okay)
ctx->error = mk_error (No_Data); /* Hmmm: choose a better error? */
break;
case STATUS_SIG_CREATED:
/* FIXME: We have no error return for multiple signatures. */
append_xml_siginfo (&ctx->result.sign->xmlinfo, args);
ctx->result.sign->okay =1;
ctx->result.sign->okay = 1;
break;
default:
@ -184,7 +178,6 @@ gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
if (mode != GPGME_SIG_MODE_NORMAL
&& mode != GPGME_SIG_MODE_DETACH
@ -264,19 +257,7 @@ gpgme_op_sign (GpgmeCtx ctx, GpgmeData in, GpgmeData out, GpgmeSigMode mode)
if (!err)
{
gpgme_wait (ctx, 1);
if (!ctx->result.sign)
err = mk_error (General_Error);
else if (ctx->out_of_core)
err = mk_error (Out_Of_Core);
else
{
err = _gpgme_passphrase_result (ctx);
if (! err)
{
if (!ctx->result.sign->okay)
err = mk_error (No_Data); /* Hmmm: choose a better error? */
}
}
err = ctx->error;
}
return err;
}

View File

@ -54,7 +54,7 @@ trust_item_new (void)
static void
trustlist_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
if (ctx->out_of_core)
if (ctx->error)
return;
switch (code)
@ -89,7 +89,7 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
GpgmeTrustItem item = NULL;
struct trust_queue_item_s *q, *q2;
if (ctx->out_of_core)
if (ctx->error)
return;
if (!line)
return; /* EOF */
@ -107,7 +107,7 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
q = xtrymalloc (sizeof *q);
if (!q)
{
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
return;
}
q->next = NULL;
@ -115,7 +115,7 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
if (!q->item)
{
xfree (q);
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
return;
}
/* fixme: lock queue, keep a tail pointer */
@ -149,7 +149,7 @@ trustlist_colon_handler (GpgmeCtx ctx, char *line)
case 9: /* user ID */
item->name = xtrystrdup (p);
if (!item->name)
ctx->out_of_core = 1;
ctx->error = mk_error (Out_Of_Core);
break;
}
}
@ -170,15 +170,14 @@ gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
if (ctx->engine)
{
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
}
_gpgme_release_result (ctx);
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
if (err)
@ -207,32 +206,32 @@ gpgme_op_trustlist_start (GpgmeCtx ctx, const char *pattern, int max_level)
GpgmeError
gpgme_op_trustlist_next (GpgmeCtx c, GpgmeTrustItem *r_item)
gpgme_op_trustlist_next (GpgmeCtx ctx, GpgmeTrustItem *r_item)
{
struct trust_queue_item_s *q;
if (!r_item)
return mk_error (Invalid_Value);
*r_item = NULL;
if (!c)
if (!ctx)
return mk_error (Invalid_Value);
if (!c->pending)
if (!ctx->pending)
return mk_error (No_Request);
if (c->out_of_core)
return mk_error (Out_Of_Core);
if (ctx->error)
return ctx->error;
if (!c->trust_queue)
if (!ctx->trust_queue)
{
_gpgme_wait_on_condition (c, 1, &c->key_cond);
if (c->out_of_core)
return mk_error (Out_Of_Core);
if (!c->key_cond)
_gpgme_wait_on_condition (ctx, 1, &ctx->key_cond);
if (ctx->error)
return ctx->error;
if (!ctx->key_cond)
return mk_error (EOF);
c->key_cond = 0;
assert (c->trust_queue);
ctx->key_cond = 0;
assert (ctx->trust_queue);
}
q = c->trust_queue;
c->trust_queue = q->next;
q = ctx->trust_queue;
ctx->trust_queue = q->next;
*r_item = q->item;
xfree (q);
@ -254,8 +253,8 @@ gpgme_op_trustlist_end (GpgmeCtx ctx)
return mk_error (Invalid_Value);
if (!ctx->pending)
return mk_error (No_Request);
if (ctx->out_of_core)
return mk_error (Out_Of_Core);
if (ctx->error)
return ctx->error;
ctx->pending = 0;
return 0;
@ -332,4 +331,3 @@ gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
}
return val;
}

View File

@ -30,6 +30,7 @@
#include "ops.h"
#include "key.h"
struct verify_result_s
{
struct verify_result_s *next;
@ -55,47 +56,53 @@ _gpgme_release_verify_result (VerifyResult result)
}
}
/* FIXME: Check that we are adding this to the correct signature. */
static void
add_notation ( GpgmeCtx ctx, GpgStatusCode code, const char *data )
add_notation (GpgmeCtx ctx, GpgStatusCode code, const char *data)
{
GpgmeData dh = ctx->result.verify->notation;
GpgmeData dh = ctx->result.verify->notation;
if ( !dh ) {
if ( gpgme_data_new ( &dh ) ) {
ctx->out_of_core = 1;
return;
if (!dh)
{
if (gpgme_data_new (&dh))
{
ctx->error = mk_error (Out_Of_Core);
return;
}
ctx->result.verify->notation = dh;
_gpgme_data_append_string (dh, " <notation>\n");
ctx->result.verify->notation = dh;
_gpgme_data_append_string (dh, " <notation>\n");
}
if ( code == STATUS_NOTATION_DATA ) {
if ( !ctx->result.verify->notation_in_data )
_gpgme_data_append_string (dh, " <data>");
_gpgme_data_append_percentstring_for_xml (dh, data);
ctx->result.verify->notation_in_data = 1;
return;
if (code == STATUS_NOTATION_DATA)
{
if (!ctx->result.verify->notation_in_data)
_gpgme_data_append_string (dh, " <data>");
_gpgme_data_append_percentstring_for_xml (dh, data);
ctx->result.verify->notation_in_data = 1;
return;
}
if ( ctx->result.verify->notation_in_data ) {
_gpgme_data_append_string (dh, "</data>\n");
ctx->result.verify->notation_in_data = 0;
if (ctx->result.verify->notation_in_data)
{
_gpgme_data_append_string (dh, "</data>\n");
ctx->result.verify->notation_in_data = 0;
}
if ( code == STATUS_NOTATION_NAME ) {
_gpgme_data_append_string (dh, " <name>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</name>\n");
if (code == STATUS_NOTATION_NAME)
{
_gpgme_data_append_string (dh, " <name>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</name>\n");
}
else if ( code == STATUS_POLICY_URL ) {
_gpgme_data_append_string (dh, " <policy>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</policy>\n");
}
else {
assert (0);
else if (code == STATUS_POLICY_URL)
{
_gpgme_data_append_string (dh, " <policy>");
_gpgme_data_append_percentstring_for_xml (dh, data);
_gpgme_data_append_string (dh, "</policy>\n");
}
else
assert (0);
}
@ -106,115 +113,126 @@ add_notation ( GpgmeCtx ctx, GpgStatusCode code, const char *data )
static void
finish_sig (GpgmeCtx ctx, int stop)
{
if (stop)
return; /* nothing to do */
if (stop)
return; /* nothing to do */
if (ctx->result.verify->collecting) {
VerifyResult res2;
if (ctx->result.verify->collecting)
{
VerifyResult res2;
ctx->result.verify->collecting = 0;
/* create a new result structure */
res2 = xtrycalloc ( 1, sizeof *res2 );
if ( !res2 ) {
ctx->out_of_core = 1;
return;
ctx->result.verify->collecting = 0;
/* Create a new result structure. */
res2 = xtrycalloc (1, sizeof *res2);
if (!res2)
{
ctx->error = mk_error (Out_Of_Core);
return;
}
res2->next = ctx->result.verify;
ctx->result.verify = res2;
res2->next = ctx->result.verify;
ctx->result.verify = res2;
}
ctx->result.verify->collecting = 1;
ctx->result.verify->collecting = 1;
}
void
_gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
{
char *p;
int i;
char *p;
int i;
if ( ctx->out_of_core )
return;
if (!ctx->result.verify)
{
ctx->result.verify = xtrycalloc (1, sizeof *ctx->result.verify);
if (!ctx->result.verify)
{
ctx->out_of_core = 1;
return;
}
}
if (ctx->error)
return;
test_and_allocate_result (ctx, verify);
if (code == STATUS_GOODSIG
|| code == STATUS_BADSIG || code == STATUS_ERRSIG) {
finish_sig (ctx,0);
if ( ctx->out_of_core )
return;
if (code == STATUS_GOODSIG || code == STATUS_BADSIG || code == STATUS_ERRSIG)
{
finish_sig (ctx,0);
if (ctx->error)
return;
}
switch (code) {
case STATUS_NODATA:
ctx->result.verify->status = GPGME_SIG_STAT_NOSIG;
break;
switch (code)
{
case STATUS_NODATA:
ctx->result.verify->status = GPGME_SIG_STAT_NOSIG;
break;
case STATUS_GOODSIG:
/* We only look at VALIDSIG */
break;
case STATUS_GOODSIG:
/* We only look at VALIDSIG */
break;
case STATUS_VALIDSIG:
ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
p = ctx->result.verify->fpr;
for (i=0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++ )
*p++ = args[i];
*p = 0;
/* skip the formatted date */
while ( args[i] && args[i] == ' ')
i++;
while ( args[i] && args[i] != ' ')
i++;
/* and get the timestamp */
ctx->result.verify->timestamp = strtoul (args+i, NULL, 10);
break;
case STATUS_VALIDSIG:
ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
p = ctx->result.verify->fpr;
for (i = 0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++)
*p++ = args[i];
*p = 0;
/* Skip the formatted date. */
while (args[i] && args[i] == ' ')
i++;
while (args[i] && args[i] != ' ')
i++;
/* And get the timestamp. */
ctx->result.verify->timestamp = strtoul (args+i, NULL, 10);
break;
case STATUS_BADSIG:
ctx->result.verify->status = GPGME_SIG_STAT_BAD;
/* store the keyID in the fpr field */
p = ctx->result.verify->fpr;
for (i=0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++ )
*p++ = args[i];
*p = 0;
break;
case STATUS_BADSIG:
ctx->result.verify->status = GPGME_SIG_STAT_BAD;
/* Store the keyID in the fpr field. */
p = ctx->result.verify->fpr;
for (i = 0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++)
*p++ = args[i];
*p = 0;
break;
case STATUS_ERRSIG:
ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
/* FIXME: distinguish between a regular error and a missing key.
* this is encoded in the args. */
/* store the keyID in the fpr field */
p = ctx->result.verify->fpr;
for (i=0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++ )
*p++ = args[i];
*p = 0;
break;
case STATUS_ERRSIG:
ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
/* FIXME: Distinguish between a regular error and a missing key.
This is encoded in the args. */
/* Store the keyID in the fpr field. */
p = ctx->result.verify->fpr;
for (i = 0; i < DIM(ctx->result.verify->fpr)
&& args[i] && args[i] != ' ' ; i++)
*p++ = args[i];
*p = 0;
break;
case STATUS_NOTATION_NAME:
case STATUS_NOTATION_DATA:
case STATUS_POLICY_URL:
add_notation ( ctx, code, args );
break;
case STATUS_NOTATION_NAME:
case STATUS_NOTATION_DATA:
case STATUS_POLICY_URL:
add_notation (ctx, code, args);
break;
case STATUS_END_STREAM:
break;
case STATUS_END_STREAM:
break;
case STATUS_EOF:
finish_sig(ctx,1);
break;
case STATUS_EOF:
finish_sig (ctx,1);
default:
/* ignore all other codes */
break;
/* FIXME: Put all notation data into one XML fragment. */
if (ctx->result.verify->notation)
{
GpgmeData dh = ctx->result.verify->notation;
if (ctx->result.verify->notation_in_data)
{
_gpgme_data_append_string (dh, "</data>\n");
ctx->result.verify->notation_in_data = 0;
}
_gpgme_data_append_string (dh, "</notation>\n");
ctx->notation = dh;
ctx->result.verify->notation = NULL;
}
break;
default:
/* Ignore all other codes. */
break;
}
}
@ -224,11 +242,10 @@ gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData text)
int err = 0;
int pipemode = 0; /* !!text; use pipemode for detached sigs. */
fail_on_pending_request(ctx);
fail_on_pending_request (ctx);
ctx->pending = 1;
_gpgme_release_result (ctx);
ctx->out_of_core = 0;
if (!pipemode)
{
@ -321,42 +338,27 @@ _gpgme_intersect_stati (VerifyResult result)
* the signature itself did go wrong.
**/
GpgmeError
gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text,
GpgmeSigStat *r_stat )
gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData text,
GpgmeSigStat *r_stat)
{
int rc;
GpgmeError err;
if ( !r_stat )
return mk_error (Invalid_Value);
if (!r_stat)
return mk_error (Invalid_Value);
gpgme_data_release (c->notation);
c->notation = NULL;
gpgme_data_release (ctx->notation);
ctx->notation = NULL;
*r_stat = GPGME_SIG_STAT_NONE;
rc = gpgme_op_verify_start ( c, sig, text );
if ( !rc ) {
gpgme_wait (c, 1);
if (!c->result.verify)
rc = mk_error (General_Error);
else if (c->out_of_core)
rc = mk_error (Out_Of_Core);
else {
/* FIXME: Put all notation data into one XML fragment. */
if ( c->result.verify->notation ) {
GpgmeData dh = c->result.verify->notation;
if ( c->result.verify->notation_in_data ) {
_gpgme_data_append_string (dh, "</data>\n");
c->result.verify->notation_in_data = 0;
}
_gpgme_data_append_string (dh, "</notation>\n");
c->notation = dh;
c->result.verify->notation = NULL;
}
*r_stat = _gpgme_intersect_stati (c->result.verify);
}
*r_stat = GPGME_SIG_STAT_NONE;
err = gpgme_op_verify_start (ctx, sig, text);
if (!err)
{
gpgme_wait (ctx, 1);
err = ctx->error;
if (!err)
*r_stat = _gpgme_intersect_stati (ctx->result.verify);
}
return rc;
return err;
}

View File

@ -33,49 +33,49 @@
#include "key.h" /* for key_cache_init */
#include "io.h"
static const char *get_engine_info (void);
static void
do_subsystem_inits (void)
{
static int done = 0;
static int done = 0;
if (done)
return;
_gpgme_sema_subsystem_init ();
_gpgme_key_cache_init ();
if (done)
return;
_gpgme_sema_subsystem_init ();
_gpgme_key_cache_init ();
}
static const char*
parse_version_number ( const char *s, int *number )
parse_version_number (const char *s, int *number)
{
int val = 0;
int val = 0;
if ( *s == '0' && isdigit(s[1]) )
return NULL; /* leading zeros are not allowed */
for ( ; isdigit(*s); s++ ) {
val *= 10;
val += *s - '0';
if (*s == '0' && isdigit(s[1]))
return NULL; /* Leading zeros are not allowed. */
for (; isdigit(*s); s++)
{
val *= 10;
val += *s - '0';
}
*number = val;
return val < 0? NULL : s;
*number = val;
return val < 0 ? NULL : s;
}
static const char *
parse_version_string( const char *s, int *major, int *minor, int *micro )
parse_version_string (const char *s, int *major, int *minor, int *micro)
{
s = parse_version_number ( s, major );
if ( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number ( s, minor );
if ( !s || *s != '.' )
return NULL;
s++;
s = parse_version_number ( s, micro );
if ( !s )
return NULL;
return s; /* patchlevel */
s = parse_version_number (s, major);
if (!s || *s != '.')
return NULL;
s++;
s = parse_version_number (s, minor);
if (!s || *s != '.')
return NULL;
s++;
s = parse_version_number (s, micro);
if (!s)
return NULL;
return s; /* Patchlevel. */
}
const char *

View File

@ -199,7 +199,8 @@ _gpgme_wait_on_condition (GpgmeCtx ctx, int hang, volatile int *cond)
while (hang && !ctx->cancel);
if (ctx->cancel)
{
ctx->cancel = 0; /* fixme: Fix all functions to return a cancel error. */
ctx->cancel = 0;
ctx->error = mk_error (Canceled);
ctx->pending = 0;
}
return ctx;