From bfc95ce4e8ac04c43c6eee6bd79f0e84b83ac2e0 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Sat, 2 Feb 2002 03:52:59 +0000 Subject: [PATCH] 2002-02-02 Marcus Brinkmann 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. --- trunk/gpgme/ChangeLog | 96 +++++++ trunk/gpgme/context.h | 11 +- trunk/gpgme/decrypt-verify.c | 24 +- trunk/gpgme/decrypt.c | 54 +--- trunk/gpgme/delete.c | 47 ++-- trunk/gpgme/encrypt.c | 36 +-- trunk/gpgme/engine-gpgsm.c | 214 +++++++++++++-- trunk/gpgme/engine-gpgsm.h | 4 - trunk/gpgme/engine.c | 1 + trunk/gpgme/export.c | 13 +- trunk/gpgme/genkey.c | 28 +- trunk/gpgme/gpgme.c | 1 + trunk/gpgme/import.c | 18 +- trunk/gpgme/keylist.c | 513 +++++++++++++++++++---------------- trunk/gpgme/ops.h | 18 +- trunk/gpgme/passphrase.c | 47 ++-- trunk/gpgme/progress.c | 2 +- trunk/gpgme/rungpg.c | 24 +- trunk/gpgme/sign.c | 31 +-- trunk/gpgme/trustlist.c | 48 ++-- trunk/gpgme/verify.c | 320 +++++++++++----------- trunk/gpgme/version.c | 56 ++-- trunk/gpgme/wait.c | 3 +- 23 files changed, 914 insertions(+), 695 deletions(-) diff --git a/trunk/gpgme/ChangeLog b/trunk/gpgme/ChangeLog index 69dac34..ef528b3 100644 --- a/trunk/gpgme/ChangeLog +++ b/trunk/gpgme/ChangeLog @@ -1,3 +1,99 @@ +2002-02-02 Marcus Brinkmann + + 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 * Makefile.am (MOSTLYCLEANFILES): New variable. diff --git a/trunk/gpgme/context.h b/trunk/gpgme/context.h index 9a467fe..bc0839d 100644 --- a/trunk/gpgme/context.h +++ b/trunk/gpgme/context.h @@ -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. */ diff --git a/trunk/gpgme/decrypt-verify.c b/trunk/gpgme/decrypt-verify.c index 087fffa..bfdc011 100644 --- a/trunk/gpgme/decrypt-verify.c +++ b/trunk/gpgme/decrypt-verify.c @@ -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; } diff --git a/trunk/gpgme/decrypt.c b/trunk/gpgme/decrypt.c index 7346eab..ff834b5 100644 --- a/trunk/gpgme/decrypt.c +++ b/trunk/gpgme/decrypt.c @@ -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; } diff --git a/trunk/gpgme/delete.c b/trunk/gpgme/delete.c index 35ba0fe..5116877 100644 --- a/trunk/gpgme/delete.c +++ b/trunk/gpgme/delete.c @@ -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; } diff --git a/trunk/gpgme/encrypt.c b/trunk/gpgme/encrypt.c index 43d1b2c..37c5096 100644 --- a/trunk/gpgme/encrypt.c +++ b/trunk/gpgme/encrypt.c @@ -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; } - - - - - - - diff --git a/trunk/gpgme/engine-gpgsm.c b/trunk/gpgme/engine-gpgsm.c index b4e0d83..44816d0 100644 --- a/trunk/gpgme/engine-gpgsm.c +++ b/trunk/gpgme/engine-gpgsm.c @@ -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 #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 */ diff --git a/trunk/gpgme/engine-gpgsm.h b/trunk/gpgme/engine-gpgsm.h index 9ebd8d7..995be66 100644 --- a/trunk/gpgme/engine-gpgsm.h +++ b/trunk/gpgme/engine-gpgsm.h @@ -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 */ - - - - diff --git a/trunk/gpgme/engine.c b/trunk/gpgme/engine.c index de17617..1d99321 100644 --- a/trunk/gpgme/engine.c +++ b/trunk/gpgme/engine.c @@ -213,6 +213,7 @@ _gpgme_engine_release (EngineObject engine) xfree (engine); } + void _gpgme_engine_set_verbosity (EngineObject engine, int verbosity) { diff --git a/trunk/gpgme/export.c b/trunk/gpgme/export.c index e113ad3..da86967 100644 --- a/trunk/gpgme/export.c +++ b/trunk/gpgme/export.c @@ -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; } diff --git a/trunk/gpgme/genkey.c b/trunk/gpgme/genkey.c index ca04b4e..94d0e37 100644 --- a/trunk/gpgme/genkey.c +++ b/trunk/gpgme/genkey.c @@ -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; } diff --git a/trunk/gpgme/gpgme.c b/trunk/gpgme/gpgme.c index dbd620d..d4637f0 100644 --- a/trunk/gpgme/gpgme.c +++ b/trunk/gpgme/gpgme.c @@ -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; } diff --git a/trunk/gpgme/import.c b/trunk/gpgme/import.c index f038091..63e4d6d 100644 --- a/trunk/gpgme/import.c +++ b/trunk/gpgme/import.c @@ -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; } diff --git a/trunk/gpgme/keylist.c b/trunk/gpgme/keylist.c index 133da5d..5648e98 100644 --- a/trunk/gpgme/keylist.c +++ b/trunk/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; - - 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; + /* 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 ) +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; + /* 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 ) +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; + 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 ) +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; + 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 */ +/* Note: We are allowed to modify LINE. */ static void -keylist_colon_handler ( GpgmeCtx ctx, char *line ) +keylist_colon_handler (GpgmeCtx ctx, char *line) { - char *p, *pend; - int field = 0; - enum { + 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; + + 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; diff --git a/trunk/gpgme/ops.h b/trunk/gpgme/ops.h index 7b6b90f..5b09a9f 100644 --- a/trunk/gpgme/ops.h +++ b/trunk/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, diff --git a/trunk/gpgme/passphrase.c b/trunk/gpgme/passphrase.c index b821bbe..137c5ae 100644 --- a/trunk/gpgme/passphrase.c +++ b/trunk/gpgme/passphrase.c @@ -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; -} diff --git a/trunk/gpgme/progress.c b/trunk/gpgme/progress.c index f3a23e4..cb19dad 100644 --- a/trunk/gpgme/progress.c +++ b/trunk/gpgme/progress.c @@ -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; } diff --git a/trunk/gpgme/rungpg.c b/trunk/gpgme/rungpg.c index dc3e238..02de004 100644 --- a/trunk/gpgme/rungpg.c +++ b/trunk/gpgme/rungpg.c @@ -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; } diff --git a/trunk/gpgme/sign.c b/trunk/gpgme/sign.c index 7c0a64c..0c2514c 100644 --- a/trunk/gpgme/sign.c +++ b/trunk/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; } diff --git a/trunk/gpgme/trustlist.c b/trunk/gpgme/trustlist.c index 11acbf5..fd704a1 100644 --- a/trunk/gpgme/trustlist.c +++ b/trunk/gpgme/trustlist.c @@ -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; } - diff --git a/trunk/gpgme/verify.c b/trunk/gpgme/verify.c index f1f6cd7..bd66dd5 100644 --- a/trunk/gpgme/verify.c +++ b/trunk/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, " \n"); + ctx->result.verify->notation = dh; + _gpgme_data_append_string (dh, " \n"); } - if ( code == STATUS_NOTATION_DATA ) { - if ( !ctx->result.verify->notation_in_data ) - _gpgme_data_append_string (dh, " "); - _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, " "); + _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, "\n"); - ctx->result.verify->notation_in_data = 0; + if (ctx->result.verify->notation_in_data) + { + _gpgme_data_append_string (dh, "\n"); + ctx->result.verify->notation_in_data = 0; } - if ( code == STATUS_NOTATION_NAME ) { - _gpgme_data_append_string (dh, " "); - _gpgme_data_append_percentstring_for_xml (dh, data); - _gpgme_data_append_string (dh, "\n"); - } - else if ( code == STATUS_POLICY_URL ) { - _gpgme_data_append_string (dh, " "); - _gpgme_data_append_percentstring_for_xml (dh, data); - _gpgme_data_append_string (dh, "\n"); + if (code == STATUS_NOTATION_NAME) + { + _gpgme_data_append_string (dh, " "); + _gpgme_data_append_percentstring_for_xml (dh, data); + _gpgme_data_append_string (dh, "\n"); } - else { - assert (0); + else if (code == STATUS_POLICY_URL) + { + _gpgme_data_append_string (dh, " "); + _gpgme_data_append_percentstring_for_xml (dh, data); + _gpgme_data_append_string (dh, "\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 (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; + if (stop) + return; /* nothing to do */ + + 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->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; - - 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 (code == STATUS_GOODSIG - || code == STATUS_BADSIG || code == STATUS_ERRSIG) { - finish_sig (ctx,0); - if ( ctx->out_of_core ) - return; + char *p; + int i; + + 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->error) + return; } - 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_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_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_END_STREAM: - break; - - case STATUS_EOF: - finish_sig(ctx,1); - break; - - default: - /* ignore all other codes */ - 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_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_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_END_STREAM: + break; + + case STATUS_EOF: + finish_sig (ctx,1); + + /* 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, "\n"); + ctx->result.verify->notation_in_data = 0; + } + _gpgme_data_append_string (dh, "\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, "\n"); - c->result.verify->notation_in_data = 0; - } - _gpgme_data_append_string (dh, "\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; } diff --git a/trunk/gpgme/version.c b/trunk/gpgme/version.c index 27d720b..104f71d 100644 --- a/trunk/gpgme/version.c +++ b/trunk/gpgme/version.c @@ -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 * diff --git a/trunk/gpgme/wait.c b/trunk/gpgme/wait.c index 533a3de..639f207 100644 --- a/trunk/gpgme/wait.c +++ b/trunk/gpgme/wait.c @@ -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; -- 2.26.2