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:
parent
92bbc39616
commit
1f5180f4b0
@ -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.
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
@ -106,6 +111,8 @@ gpgme_op_delete_start (GpgmeCtx ctx, const GpgmeKey key, int allow_secret)
|
||||
ctx->engine = NULL;
|
||||
}
|
||||
|
||||
_gpgme_release_result (ctx);
|
||||
|
||||
err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
|
||||
: GPGME_PROTOCOL_OpenPGP, &ctx->engine);
|
||||
if (err)
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -213,6 +213,7 @@ _gpgme_engine_release (EngineObject engine)
|
||||
xfree (engine);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gpgme_engine_set_verbosity (EngineObject engine, int verbosity)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
543
gpgme/keylist.c
543
gpgme/keylist.c
@ -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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
18
gpgme/ops.h
18
gpgme/ops.h
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
31
gpgme/sign.c
31
gpgme/sign.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
296
gpgme/verify.c
296
gpgme/verify.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user