From 8ae8cb35257f42c905c86eb424759fdfde97eb41 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Fri, 1 Nov 2002 00:45:05 +0000 Subject: Set the virtual method pointers to the import/export methods. 2002-10-31 Jeffrey Stedfast * camel-gpg-context.c (camel_gpg_context_class_init): Set the virtual method pointers to the import/export methods. (camel_gpg_context_init): Set the key_protocol string. (gpg_hash_to_id): Handle 2 more hash types. (gpg_id_to_hash): Same. (gpg_ctx_op_step): Slight fixes to support import/export. (gpg_ctx_parse_status): Fix to hack around the fact that importing keys doesn't write to stdout. (gpg_import_keys): Implemented. (gpg_export_keys): Implemented. * camel-cipher-context.c (camel_cipher_context_class_init): Hook up default virtual methods for import/export. (camel_cipher_import_keys): Implemented. (camel_cipher_export_keys): Implemented. svn path=/trunk/; revision=18475 --- camel/ChangeLog | 18 +++++ camel/camel-cipher-context.c | 101 ++++++++++++++++++++++---- camel/camel-cipher-context.h | 29 ++++++-- camel/camel-gpg-context.c | 164 +++++++++++++++++++++++++++++++++++++++---- camel/camel-gpg-context.h | 1 - 5 files changed, 277 insertions(+), 36 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index 4f5abb9031..24fc87d2bb 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,21 @@ +2002-10-31 Jeffrey Stedfast + + * camel-gpg-context.c (camel_gpg_context_class_init): Set the + virtual method pointers to the import/export methods. + (camel_gpg_context_init): Set the key_protocol string. + (gpg_hash_to_id): Handle 2 more hash types. + (gpg_id_to_hash): Same. + (gpg_ctx_op_step): Slight fixes to support import/export. + (gpg_ctx_parse_status): Fix to hack around the fact that importing + keys doesn't write to stdout. + (gpg_import_keys): Implemented. + (gpg_export_keys): Implemented. + + * camel-cipher-context.c (camel_cipher_context_class_init): Hook + up default virtual methods for import/export. + (camel_cipher_import_keys): Implemented. + (camel_cipher_export_keys): Implemented. + 2002-10-31 Jeffrey Stedfast * Makefile.am: Removed hash-table-utils.[c,h] from the build. diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c index 185002831f..c495a6479c 100644 --- a/camel/camel-cipher-context.c +++ b/camel/camel-cipher-context.c @@ -47,22 +47,28 @@ struct _CamelCipherContextPrivate { #endif }; -static int cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex); -static CamelCipherValidity *cipher_verify (CamelCipherContext *context, CamelCipherHash hash, - CamelStream *istream, CamelStream *sigstream, - CamelException *ex); +static const char *cipher_hash_to_id (CamelCipherContext *context, CamelCipherHash hash); +static CamelCipherHash cipher_id_to_hash (CamelCipherContext *context, const char *id); + +static int cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static CamelCipherValidity *cipher_verify (CamelCipherContext *context, CamelCipherHash hash, + CamelStream *istream, CamelStream *sigstream, + CamelException *ex); static int cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, CamelException *ex); static int cipher_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, CamelException *ex); +static int cipher_import_keys (CamelCipherContext *context, CamelStream *istream, + CamelException *ex); +static int cipher_export_keys (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex); -static const char *cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash); -static CamelCipherHash cipher_id_to_hash(CamelCipherContext *context, const char *id); static CamelObjectClass *parent_class; + static void camel_cipher_context_init (CamelCipherContext *context) { @@ -91,12 +97,14 @@ camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_c { parent_class = camel_type_get_global_classfuncs (camel_object_get_type ()); + camel_cipher_context_class->hash_to_id = cipher_hash_to_id; + camel_cipher_context_class->id_to_hash = cipher_id_to_hash; camel_cipher_context_class->sign = cipher_sign; camel_cipher_context_class->verify = cipher_verify; camel_cipher_context_class->encrypt = cipher_encrypt; camel_cipher_context_class->decrypt = cipher_decrypt; - camel_cipher_context_class->hash_to_id = cipher_hash_to_id; - camel_cipher_context_class->id_to_hash = cipher_id_to_hash; + camel_cipher_context_class->import_keys = cipher_import_keys; + camel_cipher_context_class->export_keys = cipher_export_keys; } CamelType @@ -326,6 +334,73 @@ camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream, return retval; } + +static int +cipher_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("You may not import keys with this cipher")); + + return -1; +} + + +/** + * camel_cipher_import_keys: + * @ctx: Cipher Context + * @istream: input stream (containing keys) + * @ex: exception + * + * Imports a stream of keys/certificates contained within @istream + * into the key/certificate database controlled by @ctx. + * + * Returns 0 on success or -1 on fail. + **/ +int +camel_cipher_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex) +{ + g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1); + g_return_val_if_fail (CAMEL_IS_STREAM (istream), -1); + + return CCC_CLASS (context)->import_keys (context, istream, ex); +} + + +static int +cipher_export_keys (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("You may not export keys with this cipher")); + + return -1; +} + + +/** + * camel_cipher_export_keys: + * @ctx: Cipher Context + * @keys: an array of key ids + * @ostream: output stream + * @ex: exception + * + * Exports the keys/certificates in @keys to the stream @ostream from + * the key/certificate database controlled by @ctx. + * + * Returns 0 on success or -1 on fail. + **/ +int +camel_cipher_export_keys (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex) +{ + g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1); + g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1); + g_return_val_if_fail (keys != NULL, -1); + + return CCC_CLASS (context)->export_keys (context, keys, ostream, ex); +} + + static CamelCipherHash cipher_id_to_hash(CamelCipherContext *context, const char *id) { @@ -337,8 +412,8 @@ CamelCipherHash camel_cipher_id_to_hash(CamelCipherContext *context, const char *id) { g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), CAMEL_CIPHER_HASH_DEFAULT); - - return ((CamelCipherContextClass *)((CamelObject *)context)->klass)->id_to_hash(context, id); + + return CCC_CLASS (context)->id_to_hash (context, id); } static const char * @@ -351,8 +426,8 @@ const char * camel_cipher_hash_to_id(CamelCipherContext *context, CamelCipherHash hash) { g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL); - - return ((CamelCipherContextClass *)((CamelObject *)context)->klass)->hash_to_id(context, hash); + + return CCC_CLASS (context)->hash_to_id (context, hash); } /* Cipher Validity stuff */ diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h index 296d7e5b39..45444c26a0 100644 --- a/camel/camel-cipher-context.h +++ b/camel/camel-cipher-context.h @@ -44,7 +44,9 @@ typedef enum { CAMEL_CIPHER_HASH_MD2, CAMEL_CIPHER_HASH_MD5, CAMEL_CIPHER_HASH_SHA1, - CAMEL_CIPHER_HASH_RIPEMD160 + CAMEL_CIPHER_HASH_RIPEMD160, + CAMEL_CIPHER_HASH_TIGER192, + CAMEL_CIPHER_HASH_HAVAL5160 } CamelCipherHash; typedef struct _CamelCipherContext { @@ -57,12 +59,16 @@ typedef struct _CamelCipherContext { /* these MUST be set by implementors */ const char *sign_protocol; const char *encrypt_protocol; + const char *key_protocol; } CamelCipherContext; typedef struct _CamelCipherContextClass { CamelObjectClass parent_class; - int (*sign) (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelCipherHash (*id_to_hash)(CamelCipherContext *context, const char *id); + const char * (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash); + + int (*sign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelStream *istream, CamelStream *ostream, CamelException *ex); CamelCipherValidity * (*verify) (CamelCipherContext *context, CamelCipherHash hash, @@ -76,9 +82,11 @@ typedef struct _CamelCipherContextClass { int (*decrypt) (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, CamelException *ex); - CamelCipherHash (*id_to_hash)(CamelCipherContext *context, const char *id); - const char * (*hash_to_id)(CamelCipherContext *context, CamelCipherHash hash); + int (*import_keys) (CamelCipherContext *context, CamelStream *istream, + CamelException *ex); + int (*export_keys) (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex); } CamelCipherContextClass; CamelType camel_cipher_context_get_type (void); @@ -87,6 +95,10 @@ CamelCipherContext *camel_cipher_context_new (CamelSession *session); void camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session); +/* cipher context util routines */ +CamelCipherHash camel_cipher_id_to_hash (CamelCipherContext *context, const char *id); +const char * camel_cipher_hash_to_id (CamelCipherContext *context, CamelCipherHash hash); + /* cipher routines */ int camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelStream *istream, CamelStream *ostream, CamelException *ex); @@ -102,9 +114,12 @@ int camel_cipher_encrypt (CamelCipherContext *context, gboolean int camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, CamelException *ex); -/* cipher context util routines */ -CamelCipherHash camel_cipher_id_to_hash (CamelCipherContext *context, const char *id); -const char * camel_cipher_hash_to_id (CamelCipherContext *context, CamelCipherHash hash); +/* key/certificate routines */ +int camel_cipher_import_keys (CamelCipherContext *context, CamelStream *istream, + CamelException *ex); + +int camel_cipher_export_keys (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex); /* CamelCipherValidity utility functions */ CamelCipherValidity *camel_cipher_validity_new (void); diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c index 8d948d0380..929e8f1769 100644 --- a/camel/camel-gpg-context.c +++ b/camel/camel-gpg-context.c @@ -51,20 +51,23 @@ static void camel_gpg_context_class_init (CamelGpgContextClass *klass); static void camel_gpg_context_init (CamelGpgContext *obj); static void camel_gpg_context_finalise (CamelObject *obj); -static int gpg_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex); -static CamelCipherValidity *gpg_verify (CamelCipherContext *context, CamelCipherHash hash, - CamelStream *istream, CamelStream *sigstream, - CamelException *ex); +static const char *gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash); +static CamelCipherHash gpg_id_to_hash (CamelCipherContext *context, const char *id); + +static int gpg_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static CamelCipherValidity *gpg_verify (CamelCipherContext *context, CamelCipherHash hash, + CamelStream *istream, CamelStream *sigstream, + CamelException *ex); static int gpg_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, CamelException *ex); static int gpg_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, CamelException *ex); - -static const char *gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash); -static CamelCipherHash gpg_id_to_hash (CamelCipherContext *context, const char *id); - +static int gpg_import_keys (CamelCipherContext *context, CamelStream *istream, + CamelException *ex); +static int gpg_export_keys (CamelCipherContext *context, GPtrArray *keys, + CamelStream *ostream, CamelException *ex); static CamelCipherContextClass *parent_class = NULL; @@ -95,12 +98,14 @@ camel_gpg_context_class_init (CamelGpgContextClass *klass) parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ())); + cipher_class->hash_to_id = gpg_hash_to_id; + cipher_class->id_to_hash = gpg_id_to_hash; cipher_class->sign = gpg_sign; cipher_class->verify = gpg_verify; cipher_class->encrypt = gpg_encrypt; cipher_class->decrypt = gpg_decrypt; - cipher_class->hash_to_id = gpg_hash_to_id; - cipher_class->id_to_hash = gpg_id_to_hash; + cipher_class->import_keys = gpg_import_keys; + cipher_class->export_keys = gpg_export_keys; } static void @@ -112,6 +117,7 @@ camel_gpg_context_init (CamelGpgContext *context) cipher->sign_protocol = "application/pgp-signature"; cipher->encrypt_protocol = "application/pgp-encrypted"; + cipher->key_protocol = "application/pgp-keys"; } static void @@ -177,6 +183,10 @@ gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash) return "pgp-sha1"; case CAMEL_CIPHER_HASH_RIPEMD160: return "pgp-ripemd160"; + case CAMEL_CIPHER_HASH_TIGER192: + return "pgp-tiger192"; + case CAMEL_CIPHER_HASH_HAVAL5160: + return "pgp-haval-5-160"; } return NULL; @@ -194,6 +204,10 @@ gpg_id_to_hash (CamelCipherContext *context, const char *id) return CAMEL_CIPHER_HASH_SHA1; else if (!strcmp (id, "pgp-ripemd160")) return CAMEL_CIPHER_HASH_RIPEMD160; + else if (!strcmp (id, "tiger192")) + return CAMEL_CIPHER_HASH_TIGER192; + else if (!strcmp (id, "haval-5-160")) + return CAMEL_CIPHER_HASH_HAVAL5160; } return CAMEL_CIPHER_HASH_DEFAULT; @@ -205,6 +219,8 @@ enum _GpgCtxMode { GPG_CTX_MODE_VERIFY, GPG_CTX_MODE_ENCRYPT, GPG_CTX_MODE_DECRYPT, + GPG_CTX_MODE_IMPORT, + GPG_CTX_MODE_EXPORT, }; enum _GpgTrustMetric { @@ -342,7 +358,7 @@ gpg_ctx_set_userid (struct _GpgCtx *gpg, const char *userid) static void gpg_ctx_add_recipient (struct _GpgCtx *gpg, const char *keyid) { - if (gpg->mode != GPG_CTX_MODE_ENCRYPT) + if (gpg->mode != GPG_CTX_MODE_ENCRYPT && gpg->mode != GPG_CTX_MODE_EXPORT) return; if (!gpg->recipients) @@ -543,6 +559,17 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd, g_ptr_array_add (argv, "--output"); g_ptr_array_add (argv, "-"); break; + case GPG_CTX_MODE_IMPORT: + g_ptr_array_add (argv, "--import"); + g_ptr_array_add (argv, "-"); + break; + case GPG_CTX_MODE_EXPORT: + if (gpg->armor) + g_ptr_array_add (argv, "--armor"); + g_ptr_array_add (argv, "--export"); + for (i = 0; i < gpg->recipients->len; i++) + g_ptr_array_add (argv, gpg->recipients->pdata[i]); + break; } g_ptr_array_add (argv, NULL); @@ -838,6 +865,13 @@ gpg_ctx_parse_status (struct _GpgCtx *gpg, CamelException *ex) /* nothing to do, but we know the end is near? */ } break; + case GPG_CTX_MODE_IMPORT: + /* hack to work around the fact that gpg + doesn't write anything to stdout when + importing keys */ + if (!strncmp (status, "IMPORT_RES", 10)) + gpg->seen_eof1 = TRUE; + break; } } @@ -1021,7 +1055,7 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex) gpg->send_passwd = FALSE; } - if (wrsetp && gpg->stdin_fd != -1 && FD_ISSET (gpg->stdin_fd, &wrset)) { + if (gpg->istream && wrsetp && gpg->stdin_fd != -1 && FD_ISSET (gpg->stdin_fd, &wrset)) { char buffer[4096]; ssize_t nread; @@ -1071,6 +1105,12 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex) case GPG_CTX_MODE_DECRYPT: mode = "decrypt"; break; + case GPG_CTX_MODE_IMPORT: + mode = "import keys"; + break; + case GPG_CTX_MODE_EXPORT: + mode = "export keys"; + break; default: g_assert_not_reached (); mode = NULL; @@ -1079,13 +1119,13 @@ gpg_ctx_op_step (struct _GpgCtx *gpg, CamelException *ex) if (gpg->diagnostics->len) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to GPG %s message: %s\n\n%.*s"), + _("Failed to GPG %s: %s\n\n%.*s"), mode, g_strerror (errno), gpg->diagnostics->len, gpg->diagnostics->data); } else { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to GPG %s message: %s\n"), + _("Failed to GPG %s: %s\n"), mode, g_strerror (errno)); } @@ -1475,3 +1515,97 @@ gpg_decrypt (CamelCipherContext *context, CamelStream *istream, return 0; } + +static int +gpg_import_keys (CamelCipherContext *context, CamelStream *istream, CamelException *ex) +{ + struct _GpgCtx *gpg; + + gpg = gpg_ctx_new (context->session); + gpg_ctx_set_mode (gpg, GPG_CTX_MODE_IMPORT); + gpg_ctx_set_istream (gpg, istream); + + if (gpg_ctx_op_start (gpg) == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Failed to execute gpg: %s"), + errno ? g_strerror (errno) : _("Unknown")); + gpg_ctx_free (gpg); + + return -1; + } + + while (!gpg_ctx_op_complete (gpg)) { + if (gpg_ctx_op_step (gpg, ex) == -1) { + gpg_ctx_op_cancel (gpg); + gpg_ctx_free (gpg); + + return -1; + } + } + + if (gpg_ctx_op_wait (gpg) != 0) { + char *diagnostics; + + diagnostics = gpg_ctx_get_diagnostics (gpg); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); + g_free (diagnostics); + + gpg_ctx_free (gpg); + + return -1; + } + + gpg_ctx_free (gpg); + + return 0; +} + +static int +gpg_export_keys (CamelCipherContext *context, GPtrArray *keys, CamelStream *ostream, CamelException *ex) +{ + struct _GpgCtx *gpg; + int i; + + gpg = gpg_ctx_new (context->session); + gpg_ctx_set_mode (gpg, GPG_CTX_MODE_EXPORT); + gpg_ctx_set_armor (gpg, TRUE); + gpg_ctx_set_ostream (gpg, ostream); + + for (i = 0; i < keys->len; i++) { + gpg_ctx_add_recipient (gpg, keys->pdata[i]); + } + + if (gpg_ctx_op_start (gpg) == -1) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Failed to execute gpg: %s"), + errno ? g_strerror (errno) : _("Unknown")); + gpg_ctx_free (gpg); + + return -1; + } + + while (!gpg_ctx_op_complete (gpg)) { + if (gpg_ctx_op_step (gpg, ex) == -1) { + gpg_ctx_op_cancel (gpg); + gpg_ctx_free (gpg); + + return -1; + } + } + + if (gpg_ctx_op_wait (gpg) != 0) { + char *diagnostics; + + diagnostics = gpg_ctx_get_diagnostics (gpg); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); + g_free (diagnostics); + + gpg_ctx_free (gpg); + + return -1; + } + + gpg_ctx_free (gpg); + + return 0; +} diff --git a/camel/camel-gpg-context.h b/camel/camel-gpg-context.h index 6a2f56f304..0d98fed75d 100644 --- a/camel/camel-gpg-context.h +++ b/camel/camel-gpg-context.h @@ -62,4 +62,3 @@ void camel_gpg_context_set_always_trust (CamelGpgContext *ctx, gboolean trust); #endif /* __cplusplus */ #endif /* __CAMEL_GPG_CONTEXT_H__ */ - -- cgit