From dc85c5917e3e18ed10253f5e066b0c130550d093 Mon Sep 17 00:00:00 2001 From: hiro Date: Wed, 20 Jul 2005 08:03:30 +0000 Subject: rfc2015.c: unified indent and minor fixes. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@439 ee746299-78ed-0310-b773-934348b2243d --- src/rfc2015.c | 2145 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 1070 insertions(+), 1075 deletions(-) (limited to 'src/rfc2015.c') diff --git a/src/rfc2015.c b/src/rfc2015.c index 22025310..0aded39e 100644 --- a/src/rfc2015.c +++ b/src/rfc2015.c @@ -48,93 +48,89 @@ #include "sigstatus.h" #include "rfc2015.h" -#define DIM(v) (sizeof(v)/sizeof((v)[0])) +#define DIM(v) (sizeof(v) / sizeof((v)[0])) -static char *content_names[] = { - "Content-Type", - "Content-Disposition", - "Content-Transfer-Encoding", - NULL +static gchar *content_names[] = { + "Content-Type", + "Content-Disposition", + "Content-Transfer-Encoding", + NULL }; -static char *mime_version_name[] = { - "Mime-Version", - NULL +static gchar *mime_version_name[] = { + "Mime-Version", + NULL }; #if 0 -static void dump_mimeinfo (const char *text, MimeInfo *x) +static void dump_mimeinfo(const gchar *text, MimeInfo *x) { - debug_print ("MimeInfo[%s] %p level=%d\n", - text, x, x? x->level:0 ); - if (!x) - return; - - debug_print (" enc=`%s' enc_type=%d mime_type=%d\n", - x->encoding, x->encoding_type, x->mime_type ); - debug_print (" cont_type=`%s' cs=`%s' name=`%s' bnd=`%s'\n", - x->content_type, x->charset, x->name, x->boundary ); - debug_print (" cont_disp=`%s' fname=`%s' fpos=%ld size=%u, lvl=%d\n", - x->content_disposition, x->filename, x->fpos, x->size, - x->level ); - dump_mimeinfo (".main", x->main ); - dump_mimeinfo (".sub", x->sub ); - dump_mimeinfo (".next", x->next ); - debug_print ("MimeInfo[.parent] %p\n", x ); - dump_mimeinfo (".children", x->children ); - dump_mimeinfo (".plaintext", x->plaintext ); + debug_print("MimeInfo[%s] %p level=%d\n", text, x, x ? x->level : 0); + if (!x) + return; + + debug_print(" enc=`%s' enc_type=%d mime_type=%d\n", + x->encoding, x->encoding_type, x->mime_type); + debug_print(" cont_type=`%s' cs=`%s' name=`%s' bnd=`%s'\n", + x->content_type, x->charset, x->name, x->boundary ); + debug_print(" cont_disp=`%s' fname=`%s' fpos=%ld size=%u, lvl=%d\n", + x->content_disposition, x->filename, x->fpos, x->size, + x->level ); + dump_mimeinfo(".main", x->main ); + dump_mimeinfo(".sub", x->sub ); + dump_mimeinfo(".next", x->next ); + debug_print("MimeInfo[.parent] %p\n", x ); + dump_mimeinfo(".children", x->children ); + dump_mimeinfo(".plaintext", x->plaintext ); } -static void dump_part ( MimeInfo *mimeinfo, FILE *fp ) +static void dump_part(MimeInfo *mimeinfo, FILE *fp) { - unsigned int size = mimeinfo->size; - int c; - - if (fseek (fp, mimeinfo->fpos, SEEK_SET)) { - debug_print ("dump_part: fseek error\n"); - return; - } - - debug_print ("--- begin dump_part ----\n"); - while (size-- && (c = getc (fp)) != EOF) - putc (c, stderr); - if (ferror (fp)) - debug_print ("dump_part: read error\n"); - debug_print ("--- end dump_part ----\n"); + guint size = mimeinfo->size; + gint c; + + if (fseek(fp, mimeinfo->fpos, SEEK_SET)) { + debug_print("dump_part: fseek error\n"); + return; + } + + debug_print("--- begin dump_part ----\n"); + while (size-- && (c = getc (fp)) != EOF) + putc(c, stderr); + if (ferror(fp)) + debug_print("dump_part: read error\n"); + debug_print("--- end dump_part ----\n"); } #endif -void -rfc2015_disable_all (void) +void rfc2015_disable_all(void) { - /* FIXME: set a flag, so that we don't bother the user with failed - * gpgme messages */ + /* FIXME: set a flag, so that we don't bother the user with failed + * gpgme messages */ } - -void -rfc2015_secure_remove (const char *fname) +void rfc2015_secure_remove(const gchar *fname) { - if (!fname) - return; - /* fixme: overwrite the file first */ - remove (fname); + if (!fname) + return; + /* fixme: overwrite the file first */ + remove(fname); } -static void -sig_status_for_key(GString *str, gpgme_ctx_t ctx, gpgme_signature_t sig) +static void sig_status_for_key(GString *str, gpgme_ctx_t ctx, + gpgme_signature_t sig) { gpgme_key_t key; gpgme_user_id_t user; gpgme_get_key(ctx, sig->fpr, &key, 0); if (key == NULL || key->uids->uid == NULL) { - g_string_sprintfa (str, "%s\n", - gpgmegtk_sig_status_to_string (sig, FALSE)); + g_string_sprintfa(str, "%s\n", + gpgmegtk_sig_status_to_string (sig, FALSE)); if ((sig->fpr != NULL) && (*(sig->fpr) != '\0')) g_string_sprintfa (str, "Key fingerprint: %s\n", sig->fpr); - g_string_append (str, _("Cannot find user ID for this key.")); + g_string_append(str, _("Cannot find user ID for this key.")); return; } user = key->uids; @@ -150,8 +146,7 @@ sig_status_for_key(GString *str, gpgme_ctx_t ctx, gpgme_signature_t sig) } } -static gchar * -sig_status_full (gpgme_ctx_t ctx, gpgme_verify_result_t result) +static gchar *sig_status_full(gpgme_ctx_t ctx, gpgme_verify_result_t result) { GString *str; gpgme_signature_t sig; @@ -161,134 +156,136 @@ sig_status_full (gpgme_ctx_t ctx, gpgme_verify_result_t result) gchar *ctime_str_utf8; gchar *retval; - str = g_string_new (""); + str = g_string_new(""); sig = result->signatures; while (sig != NULL) { if (sig->timestamp != 0) { created = sig->timestamp; - ctime_val = localtime (&created); - my_strftime (ctime_str, sizeof (ctime_str), "%c", - ctime_val); - ctime_str_utf8 = conv_localetodisp (ctime_str, NULL); - g_string_sprintfa (str, - _("Signature made at %s\n"), - ctime_str_utf8); - g_free (ctime_str_utf8); + ctime_val = localtime(&created); + my_strftime(ctime_str, sizeof (ctime_str), "%c", + ctime_val); + ctime_str_utf8 = conv_localetodisp(ctime_str, NULL); + g_string_sprintfa(str, _("Signature made at %s\n"), + ctime_str_utf8); + g_free(ctime_str_utf8); } sig_status_for_key(str, ctx, sig); if (sig->next) - g_string_append (str, "\n\n"); + g_string_append(str, "\n\n"); sig = sig->next; } retval = str->str; - g_string_free (str, FALSE); + g_string_free(str, FALSE); return retval; } -static void check_signature (MimeInfo *mimeinfo, MimeInfo *partinfo, FILE *fp) +static void check_signature(MimeInfo *mimeinfo, MimeInfo *partinfo, FILE *fp) { - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_data_t sig = NULL, text = NULL; - gpgme_verify_result_t verifyresult = NULL; - GpgmegtkSigStatus statuswindow = NULL; - const char *result = NULL; - gchar *tmp_file; - gint n_exclude_chars = 0; - - if (prefs_common.gpg_signature_popup) - statuswindow = gpgmegtk_sig_status_create (); - - err = gpgme_new (&ctx); - if (err) { - debug_print ("gpgme_new failed: %s\n", gpgme_strerror (err)); - goto leave; - } - - /* don't include the last empty line. - It does not belong to the signed text */ - if (mimeinfo->children->size > 0) { - if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 1, - SEEK_SET) < 0) { - perror("fseek"); - goto leave; - } - if (fgetc(fp) == '\n') { - n_exclude_chars++; - if (mimeinfo->children->size > 1) { - if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 2, - SEEK_SET) < 0) { - perror("fseek"); - goto leave; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_data_t sig = NULL, text = NULL; + gpgme_verify_result_t verifyresult = NULL; + GpgmegtkSigStatus statuswindow = NULL; + const gchar *result = NULL; + gchar *tmp_file; + gint n_exclude_chars = 0; + + if (prefs_common.gpg_signature_popup) + statuswindow = gpgmegtk_sig_status_create(); + + err = gpgme_new(&ctx); + if (err) { + debug_print("gpgme_new failed: %s\n", gpgme_strerror(err)); + goto leave; + } + + /* don't include the last empty line. + It does not belong to the signed text */ + if (mimeinfo->children->size > 0) { + if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 1, + SEEK_SET) < 0) { + perror("fseek"); + goto leave; + } + if (fgetc(fp) == '\n') { + n_exclude_chars++; + if (mimeinfo->children->size > 1) { + if (fseek(fp, mimeinfo->children->fpos + mimeinfo->children->size - 2, + SEEK_SET) < 0) { + perror("fseek"); + goto leave; + } + if (fgetc(fp) == '\r') + n_exclude_chars++; + } } - if (fgetc(fp) == '\r') - n_exclude_chars++; - } } - } - /* canonicalize the file part. */ - tmp_file = get_tmp_file(); - if (copy_file_part(fp, mimeinfo->children->fpos, - mimeinfo->children->size - n_exclude_chars, - tmp_file) < 0) { - g_free(tmp_file); - goto leave; - } - if (canonicalize_file_replace(tmp_file) < 0) { + /* canonicalize the file part. */ + tmp_file = get_tmp_file(); + if (copy_file_part(fp, mimeinfo->children->fpos, + mimeinfo->children->size - n_exclude_chars, + tmp_file) < 0) { + g_free(tmp_file); + goto leave; + } + if (canonicalize_file_replace(tmp_file) < 0) { + unlink(tmp_file); + g_free(tmp_file); + goto leave; + } + + err = gpgme_data_new_from_file(&text, tmp_file, 1); + unlink(tmp_file); g_free(tmp_file); - goto leave; - } - - err = gpgme_data_new_from_file(&text, tmp_file, 1); - - unlink(tmp_file); - g_free(tmp_file); - - if (!err) - err = gpgme_data_new_from_filepart (&sig, NULL, fp, - partinfo->fpos, partinfo->size); - if (err) { - debug_print ("gpgme_data_new_from_filepart failed: %s\n", - gpgme_strerror (err)); - goto leave; - } - - err = gpgme_op_verify (ctx, sig, text, NULL); - if (err) { - debug_print ("gpgme_op_verify failed: %s\n", gpgme_strerror (err)); - goto leave; - } - verifyresult = gpgme_op_verify_result(ctx); - - /* FIXME: check what the heck this sig_status_full stuff is. - * Maybe it belongs in sigstatus.c - * - * I think it belongs here as it is interfacing with gmime (Toshio). */ - g_free (partinfo->sigstatus_full); - partinfo->sigstatus_full = sig_status_full (ctx, verifyresult); + + if (!err) + err = gpgme_data_new_from_filepart(&sig, NULL, fp, + partinfo->fpos, + partinfo->size); + if (err) { + debug_print("gpgme_data_new_from_filepart failed: %s\n", + gpgme_strerror (err)); + goto leave; + } + + err = gpgme_op_verify(ctx, sig, text, NULL); + if (err) { + debug_print("gpgme_op_verify failed: %s\n", + gpgme_strerror (err)); + goto leave; + } + verifyresult = gpgme_op_verify_result(ctx); + + /* FIXME: check what the heck this sig_status_full stuff is. + * Maybe it belongs in sigstatus.c + * + * I think it belongs here as it is interfacing with gmime (Toshio). */ + g_free (partinfo->sigstatus_full); + partinfo->sigstatus_full = sig_status_full(ctx, verifyresult); leave: - if (verifyresult) { - result = gpgmegtk_sig_status_to_string(verifyresult->signatures, FALSE); - } else { - result = _("Error verifying the signature"); - } - debug_print("verification status: %s\n", result); - if (prefs_common.gpg_signature_popup) - gpgmegtk_sig_status_update (statuswindow, ctx); - - g_free (partinfo->sigstatus); - partinfo->sigstatus = g_strdup (result); - - gpgme_data_release (sig); - gpgme_data_release (text); - gpgme_release (ctx); - if (prefs_common.gpg_signature_popup) - gpgmegtk_sig_status_destroy (statuswindow); + if (verifyresult) { + result = gpgmegtk_sig_status_to_string + (verifyresult->signatures, FALSE); + } else { + result = _("Error verifying the signature"); + } + debug_print("verification status: %s\n", result); + if (prefs_common.gpg_signature_popup) + gpgmegtk_sig_status_update(statuswindow, ctx); + + g_free (partinfo->sigstatus); + partinfo->sigstatus = g_strdup (result); + + gpgme_data_release(sig); + gpgme_data_release(text); + gpgme_release(ctx); + if (prefs_common.gpg_signature_popup) + gpgmegtk_sig_status_destroy(statuswindow); } /* @@ -296,178 +293,178 @@ leave: * return this filename */ #if 0 -static char * -copy_gpgmedata_to_temp (GpgmeData data, guint *length) +static gchar *copy_gpgmedata_to_temp(GpgmeData data, guint *length) { - static int id; - char *tmp; - FILE *fp; - char buf[100]; - size_t nread; - GpgmeError err; - - tmp = g_strdup_printf("%s%cgpgtmp.%08x", - get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id ); - - if ((fp = fopen(tmp, "wb")) == NULL) { - FILE_OP_ERROR(tmp, "fopen"); - g_free(tmp); - return NULL; - } - - err = gpgme_data_rewind ( data ); - if (err) - debug_print ("gpgme_data_rewind failed: %s\n", gpgme_strerror (err)); - - while (!(err = gpgme_data_read (data, buf, 100, &nread))) { - fwrite ( buf, nread, 1, fp ); - } - - if (err != GPGME_EOF) - debug_print ("gpgme_data_read failed: %s\n", gpgme_strerror (err)); - - fclose (fp); - *length = nread; - - return tmp; + static gint id; + gchar *tmp; + FILE *fp; + gchar buf[100]; + size_t nread; + GpgmeError err; + + tmp = g_strdup_printf("%s%cgpgtmp.%08x", + get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); + + if ((fp = fopen(tmp, "wb")) == NULL) { + FILE_OP_ERROR(tmp, "fopen"); + g_free(tmp); + return NULL; + } + + err = gpgme_data_rewind(data); + if (err) + debug_print("gpgme_data_rewind failed: %s\n", + gpgme_strerror(err)); + + while (!(err = gpgme_data_read(data, buf, 100, &nread))) { + fwrite(buf, nread, 1, fp); + } + + if (err != GPGME_EOF) + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(err)); + + fclose (fp); + *length = nread; + + return tmp; } #endif -static gpgme_data_t -pgp_decrypt (MimeInfo *partinfo, FILE *fp) + +static gpgme_data_t pgp_decrypt(MimeInfo *partinfo, FILE *fp) { - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_data_t cipher = NULL, plain = NULL; - struct passphrase_cb_info_s info; - - memset (&info, 0, sizeof info); - - err = gpgme_new (&ctx); - if (err) { - debug_print ("gpgme_new failed: %s\n", gpgme_strerror (err)); - goto leave; - } - - err = gpgme_data_new_from_filepart (&cipher, NULL, fp, - partinfo->fpos, partinfo->size); - if (err) { - debug_print ("gpgme_data_new_from_filepart failed: %s\n", - gpgme_strerror (err)); - goto leave; - } - - err = gpgme_data_new (&plain); - if (err) { - debug_print ("gpgme_new failed: %s\n", gpgme_strerror (err)); - goto leave; - } - - if (!getenv("GPG_AGENT_INFO")) { - info.c = ctx; - gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); - } - - err = gpgme_op_decrypt (ctx, cipher, plain); + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_data_t cipher = NULL, plain = NULL; + struct passphrase_cb_info_s info; + + memset(&info, 0, sizeof info); + + err = gpgme_new(&ctx); + if (err) { + debug_print("gpgme_new failed: %s\n", gpgme_strerror(err)); + goto leave; + } + + err = gpgme_data_new_from_filepart(&cipher, NULL, fp, + partinfo->fpos, partinfo->size); + if (err) { + debug_print("gpgme_data_new_from_filepart failed: %s\n", + gpgme_strerror(err)); + goto leave; + } + + err = gpgme_data_new(&plain); + if (err) { + debug_print("gpgme_new failed: %s\n", gpgme_strerror(err)); + goto leave; + } + + if (!g_getenv("GPG_AGENT_INFO")) { + info.c = ctx; + gpgme_set_passphrase_cb(ctx, gpgmegtk_passphrase_cb, &info); + } + + err = gpgme_op_decrypt(ctx, cipher, plain); leave: - gpgme_data_release (cipher); - if (err) { - gpgmegtk_free_passphrase(); - debug_print ("decryption failed: %s\n", gpgme_strerror (err)); - gpgme_data_release (plain); - plain = NULL; - } - else - debug_print ("** decryption succeeded\n"); - - gpgme_release (ctx); - return plain; + gpgme_data_release(cipher); + if (err) { + gpgmegtk_free_passphrase(); + debug_print("decryption failed: %s\n", gpgme_strerror(err)); + gpgme_data_release(plain); + plain = NULL; + } else + debug_print("** decryption succeeded\n"); + + gpgme_release(ctx); + return plain; } -MimeInfo ** rfc2015_find_signature (MimeInfo *mimeinfo) +MimeInfo **rfc2015_find_signature(MimeInfo *mimeinfo) { - MimeInfo *partinfo; - MimeInfo **signedinfo = NULL; - int n = 0; - - if (!mimeinfo) - return NULL; - - /* We could have a signature nested within multipart/mixed so - * recurse to find it. - */ - if (!g_ascii_strcasecmp (mimeinfo->content_type, "multipart/mixed")) { - for (partinfo = mimeinfo->children; partinfo != NULL; - partinfo = partinfo->next) { - signedinfo = rfc2015_find_signature (partinfo); - if (signedinfo) { - return signedinfo; - } - } - return NULL; - } - if (g_ascii_strcasecmp (mimeinfo->content_type, "multipart/signed")) - return NULL; - - debug_print ("** multipart/signed encountered\n"); - - /* check that we have at least 2 parts of the correct type */ - for (partinfo = mimeinfo->children; - partinfo != NULL; partinfo = partinfo->next) { - if (++n > 1 && !g_ascii_strcasecmp (partinfo->content_type, - "application/pgp-signature")) - break; - } - - if (partinfo) { - signedinfo = g_malloc(sizeof(MimeInfo *) * 2); - signedinfo[0] = mimeinfo; - signedinfo[1] = partinfo; - } - /* This is NULL if partinfo was not set */ - return signedinfo; + MimeInfo *partinfo; + MimeInfo **signedinfo = NULL; + gint n = 0; + + if (!mimeinfo) + return NULL; + + /* We could have a signature nested within multipart/mixed so + * recurse to find it. + */ + if (!g_ascii_strcasecmp(mimeinfo->content_type, "multipart/mixed")) { + for (partinfo = mimeinfo->children; partinfo != NULL; + partinfo = partinfo->next) { + signedinfo = rfc2015_find_signature(partinfo); + if (signedinfo) { + return signedinfo; + } + } + return NULL; + } + if (g_ascii_strcasecmp(mimeinfo->content_type, "multipart/signed")) + return NULL; + + debug_print("** multipart/signed encountered\n"); + + /* check that we have at least 2 parts of the correct type */ + for (partinfo = mimeinfo->children; + partinfo != NULL; partinfo = partinfo->next) { + if (++n > 1 && !g_ascii_strcasecmp(partinfo->content_type, + "application/pgp-signature")) + break; + } + + if (partinfo) { + signedinfo = g_malloc(sizeof(MimeInfo *) * 2); + signedinfo[0] = mimeinfo; + signedinfo[1] = partinfo; + } + /* This is NULL if partinfo was not set */ + return signedinfo; } -gboolean rfc2015_has_signature (MimeInfo *mimeinfo) +gboolean rfc2015_has_signature(MimeInfo *mimeinfo) { - return rfc2015_find_signature (mimeinfo) != NULL; + return rfc2015_find_signature(mimeinfo) != NULL; } -void rfc2015_check_signature (MimeInfo *mimeinfo, FILE *fp) +void rfc2015_check_signature(MimeInfo *mimeinfo, FILE *fp) { - MimeInfo **signedinfo; + MimeInfo **signedinfo; - signedinfo = rfc2015_find_signature (mimeinfo); - if (!signedinfo) - return; + signedinfo = rfc2015_find_signature(mimeinfo); + if (!signedinfo) + return; #if 0 - g_message ("** yep, it is a pgp signature"); - dump_mimeinfo ("gpg-signature", partinfo ); - dump_part (partinfo, fp ); - dump_mimeinfo ("signed text", mimeinfo->children ); - dump_part (mimeinfo->children, fp); + g_message("** yep, it is a pgp signature"); + dump_mimeinfo("gpg-signature", partinfo ); + dump_part(partinfo, fp ); + dump_mimeinfo("signed text", mimeinfo->children ); + dump_part(mimeinfo->children, fp); #endif - check_signature (signedinfo[0], signedinfo[1], fp); - g_free(signedinfo); + check_signature(signedinfo[0], signedinfo[1], fp); + g_free(signedinfo); } -int rfc2015_is_encrypted (MimeInfo *mimeinfo) +gint rfc2015_is_encrypted(MimeInfo *mimeinfo) { - if (!mimeinfo || mimeinfo->mime_type != MIME_MULTIPART) - return 0; - if (g_ascii_strcasecmp (mimeinfo->content_type, "multipart/encrypted")) - return 0; - /* fixme: we should check the protocol parameter */ - return 1; + if (!mimeinfo || mimeinfo->mime_type != MIME_MULTIPART) + return 0; + if (g_ascii_strcasecmp(mimeinfo->content_type, "multipart/encrypted")) + return 0; + /* fixme: we should check the protocol parameter */ + return 1; } -gboolean rfc2015_msg_is_encrypted (const gchar *file) +gboolean rfc2015_msg_is_encrypted(const gchar *file) { FILE *fp; MimeInfo *mimeinfo; - int ret; + gint ret; if ((fp = fopen(file, "rb")) == NULL) return FALSE; @@ -483,162 +480,159 @@ gboolean rfc2015_msg_is_encrypted (const gchar *file) return ret != 0 ? TRUE : FALSE; } -static int -name_cmp(const char *a, const char *b) +static gint name_cmp(const gchar *a, const gchar *b) { - for( ; *a && *b; a++, b++) { - if(*a != *b - && toupper(*(unsigned char *)a) != toupper(*(unsigned char *)b)) - return 1; - } + for( ; *a && *b; a++, b++) { + if (*a != *b && + g_ascii_toupper(*(guchar *)a) != g_ascii_toupper(*(guchar *)b)) + return 1; + } - return *a != *b; + return *a != *b; } -static int -headerp(char *p, char **names) +static gint headerp(gchar *p, gchar **names) { - int i, c; - char *p2; - - p2 = strchr(p, ':'); - if(!p2 || p == p2) { - return 0; - } - if(p2[-1] == ' ' || p2[-1] == '\t') { - return 0; - } - - if(!names[0]) - return 1; - - c = *p2; - *p2 = 0; - for(i = 0 ; names[i] != NULL; i++) { - if(!name_cmp (names[i], p)) - break; - } - *p2 = c; - - return names[i] != NULL; + gint i, c; + gchar *p2; + + p2 = strchr(p, ':'); + if (!p2 || p == p2) { + return 0; + } + if (p2[-1] == ' ' || p2[-1] == '\t') { + return 0; + } + + if (!names[0]) + return 1; + + c = *p2; + *p2 = 0; + for(i = 0 ; names[i] != NULL; i++) { + if (!name_cmp(names[i], p)) + break; + } + *p2 = c; + + return names[i] != NULL; } #define DECRYPTION_ABORT() \ { \ - procmime_mimeinfo_free_all(tmpinfo); \ - msginfo->decryption_failed = 1; \ - return; \ + procmime_mimeinfo_free_all(tmpinfo); \ + msginfo->decryption_failed = 1; \ + return; \ } -void rfc2015_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp) +void rfc2015_decrypt_message(MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp) { - static int id; - MimeInfo *tmpinfo, *partinfo; - int ver_ok = 0; - char *fname; - gpgme_data_t plain; - FILE *dstfp; - ssize_t nread; - char buf[BUFFSIZE]; - int in_cline; - gpgme_error_t err; - - g_return_if_fail (msginfo != NULL); - g_return_if_fail (mimeinfo != NULL); - g_return_if_fail (fp != NULL); - g_return_if_fail (mimeinfo->mime_type == MIME_MULTIPART); - - debug_print ("** decrypting multipart/encrypted message\n"); - - /* skip headers */ - if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0) - perror("fseek"); - tmpinfo = procmime_scan_mime_header(fp); - if (!tmpinfo || tmpinfo->mime_type != MIME_MULTIPART) { - DECRYPTION_ABORT(); - } - - procmime_scan_multipart_message(tmpinfo, fp); - - /* check that we have the 2 parts */ - partinfo = tmpinfo->children; - if (!partinfo || !partinfo->next) { - DECRYPTION_ABORT(); - } - if (!g_ascii_strcasecmp (partinfo->content_type, - "application/pgp-encrypted")) { - /* Fixme: check that the version is 1 */ - ver_ok = 1; - } - partinfo = partinfo->next; - if (ver_ok && - !g_ascii_strcasecmp (partinfo->content_type, - "application/octet-stream")) { - if (partinfo->next) - g_warning ("oops: pgp_encrypted with more than 2 parts"); - } - else { - DECRYPTION_ABORT(); - } - - debug_print ("** yep, it is pgp encrypted\n"); - - plain = pgp_decrypt (partinfo, fp); - if (!plain) { - DECRYPTION_ABORT(); - } - - fname = g_strdup_printf("%s%cplaintext.%08x", - get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); - - if ((dstfp = fopen(fname, "wb")) == NULL) { - FILE_OP_ERROR(fname, "fopen"); - g_free(fname); - DECRYPTION_ABORT(); - } - - /* write the orginal header to the new file */ - if (fseek(fp, tmpinfo->fpos, SEEK_SET) < 0) - perror("fseek"); - - in_cline = 0; - while (fgets(buf, sizeof(buf), fp)) { - if (headerp (buf, content_names)) { - in_cline = 1; - continue; - } - if (in_cline) { - if (buf[0] == ' ' || buf[0] == '\t') - continue; - in_cline = 0; - } - if (buf[0] == '\r' || buf[0] == '\n') - break; - fputs (buf, dstfp); - } - - err = (gpgme_data_seek (plain, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) - debug_print ("gpgme_data_seek failed: %s\n", gpgme_strerror (err)); - - nread = gpgme_data_read(plain, buf, sizeof(buf)); - while (nread > 0) { - fwrite (buf, nread, 1, dstfp); + static gint id; + MimeInfo *tmpinfo, *partinfo; + gint ver_ok = 0; + gchar *fname; + gpgme_data_t plain; + FILE *dstfp; + ssize_t nread; + gchar buf[BUFFSIZE]; + gint in_cline; + gpgme_error_t err; + + g_return_if_fail(msginfo != NULL); + g_return_if_fail(mimeinfo != NULL); + g_return_if_fail(fp != NULL); + g_return_if_fail(mimeinfo->mime_type == MIME_MULTIPART); + + debug_print("** decrypting multipart/encrypted message\n"); + + /* skip headers */ + if (fseek(fp, mimeinfo->fpos, SEEK_SET) < 0) + perror("fseek"); + tmpinfo = procmime_scan_mime_header(fp); + if (!tmpinfo || tmpinfo->mime_type != MIME_MULTIPART) { + DECRYPTION_ABORT(); + } + + procmime_scan_multipart_message(tmpinfo, fp); + + /* check that we have the 2 parts */ + partinfo = tmpinfo->children; + if (!partinfo || !partinfo->next) { + DECRYPTION_ABORT(); + } + if (!g_ascii_strcasecmp(partinfo->content_type, + "application/pgp-encrypted")) { + /* Fixme: check that the version is 1 */ + ver_ok = 1; + } + partinfo = partinfo->next; + if (ver_ok && + !g_ascii_strcasecmp(partinfo->content_type, + "application/octet-stream")) { + if (partinfo->next) + g_warning("oops: pgp_encrypted with more than 2 parts"); + } else { + DECRYPTION_ABORT(); + } + + debug_print("** yep, it is pgp encrypted\n"); + + plain = pgp_decrypt(partinfo, fp); + if (!plain) { + DECRYPTION_ABORT(); + } + + fname = g_strdup_printf("%s%cplaintext.%08x", + get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); + + if ((dstfp = fopen(fname, "wb")) == NULL) { + FILE_OP_ERROR(fname, "fopen"); + g_free(fname); + DECRYPTION_ABORT(); + } + + /* write the orginal header to the new file */ + if (fseek(fp, tmpinfo->fpos, SEEK_SET) < 0) + perror("fseek"); + + in_cline = 0; + while (fgets(buf, sizeof(buf), fp)) { + if (headerp(buf, content_names)) { + in_cline = 1; + continue; + } + if (in_cline) { + if (buf[0] == ' ' || buf[0] == '\t') + continue; + in_cline = 0; + } + if (buf[0] == '\r' || buf[0] == '\n') + break; + fputs(buf, dstfp); + } + + err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) + debug_print("gpgme_data_seek failed: %s\n", gpgme_strerror(err)); + nread = gpgme_data_read(plain, buf, sizeof(buf)); - } + while (nread > 0) { + fwrite (buf, nread, 1, dstfp); + nread = gpgme_data_read(plain, buf, sizeof(buf)); + } - if (nread != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - } + if (nread != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + } - fclose (dstfp); - procmime_mimeinfo_free_all(tmpinfo); + fclose(dstfp); + procmime_mimeinfo_free_all(tmpinfo); - msginfo->plaintext_file = fname; - msginfo->decryption_failed = 0; + msginfo->plaintext_file = fname; + msginfo->decryption_failed = 0; } #undef DECRYPTION_ABORT @@ -649,50 +643,49 @@ void rfc2015_decrypt_message (MsgInfo *msginfo, MimeInfo *mimeinfo, FILE *fp) * Encrypt it and return an GpgmeData object with the encrypted version of * the file or NULL in case of error. */ -static gpgme_data_t -pgp_encrypt ( gpgme_data_t plain, gpgme_key_t kset[] ) +static gpgme_data_t pgp_encrypt(gpgme_data_t plain, gpgme_key_t kset[]) { - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_data_t cipher = NULL; - - err = gpgme_new (&ctx); - if (!err) - err = gpgme_data_new (&cipher); - if (!err) { - gpgme_set_armor (ctx, 1); - err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (!err) { - /* - * Note -- it is currently the responsibility of select-keys.c:: - * gpgmegtk_recipient_selection() to prompt the user whether to - * encrypt to recipients whose key is not trusted. - */ - err = gpgme_op_encrypt (ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, - plain, cipher); - } - } - - if (err) { - g_warning ("pgp_encrypt(): encryption failed: %s\n", - gpgme_strerror (err)); - gpgme_data_release (cipher); - cipher = NULL; - } - else { - debug_print ("** encryption succeeded\n"); - } - - gpgme_release (ctx); - return cipher; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_data_t cipher = NULL; + + err = gpgme_new(&ctx); + if (!err) + err = gpgme_data_new(&cipher); + if (!err) { + gpgme_set_armor(ctx, 1); + err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (!err) { + /* + * Note -- it is currently the responsibility of select-keys.c:: + * gpgmegtk_recipient_selection() to prompt the user whether to + * encrypt to recipients whose key is not trusted. + */ + err = gpgme_op_encrypt(ctx, kset, + GPGME_ENCRYPT_ALWAYS_TRUST, + plain, cipher); + } + } + + if (err) { + g_warning("pgp_encrypt(): encryption failed: %s\n", + gpgme_strerror(err)); + gpgme_data_release(cipher); + cipher = NULL; + } else { + debug_print("** encryption succeeded\n"); + } + + gpgme_release(ctx); + return cipher; } /* * Create and return a list of keys matching a key id */ -GSList *rfc2015_create_signers_list (const char *keyid) +GSList *rfc2015_create_signers_list(const gchar *keyid) { GSList *key_list = NULL; gpgme_ctx_t list_ctx = NULL; @@ -700,31 +693,32 @@ GSList *rfc2015_create_signers_list (const char *keyid) gpgme_error_t err; gpgme_key_t key; - err = gpgme_new (&list_ctx); + err = gpgme_new(&list_ctx); if (err) goto leave; - err = gpgme_op_keylist_start (list_ctx, keyid, 1); + err = gpgme_op_keylist_start(list_ctx, keyid, 1); if (err) goto leave; - while ( !(err = gpgme_op_keylist_next (list_ctx, &key)) ) { - key_list = g_slist_append (key_list, key); + while (!(err = gpgme_op_keylist_next(list_ctx, &key))) { + key_list = g_slist_append(key_list, key); } if (gpgme_err_code(err) != GPG_ERR_EOF) goto leave; err = 0; if (key_list == NULL) { - debug_print ("no keys found for keyid \"%s\"\n", keyid); + debug_print("no keys found for keyid \"%s\"\n", keyid); } leave: if (err) { - debug_print ("rfc2015_create_signers_list failed: %s\n", gpgme_strerror (err)); + debug_print("rfc2015_create_signers_list failed: %s\n", + gpgme_strerror(err)); for (p = key_list; p != NULL; p = p->next) - gpgme_key_unref ((gpgme_key_t) p->data); - g_slist_free (key_list); + gpgme_key_unref((gpgme_key_t)p->data); + g_slist_free(key_list); } if (list_ctx) - gpgme_release (list_ctx); + gpgme_release(list_ctx); return err ? NULL : key_list; } @@ -732,622 +726,623 @@ leave: * Encrypt the file by extracting all recipients and finding the * encryption keys for all of them. The file content is then replaced * by the encrypted one. */ -int -rfc2015_encrypt (const char *file, GSList *recp_list, gboolean ascii_armored) +gint rfc2015_encrypt(const gchar *file, GSList *recp_list, + gboolean ascii_armored) { - FILE *fp = NULL; - char buf[BUFFSIZE]; - int i, clineidx, saved_last; - char *clines[3] = {NULL}; - gpgme_error_t err; - gpgme_data_t header = NULL; - gpgme_data_t plain = NULL; - gpgme_data_t cipher = NULL; - gpgme_key_t *kset = NULL; - ssize_t bytesRW = 0; - int mime_version_seen = 0; - char *boundary; - - boundary = generate_mime_boundary ("Encrypt"); - - /* Create the list of recipients */ - kset = gpgmegtk_recipient_selection (recp_list); - if (!kset) { - debug_print ("error creating recipient list\n" ); - goto failure; - } - - /* Open the source file */ - if ((fp = fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - err = gpgme_data_new (&header); - if (!err) - err = gpgme_data_new (&plain); - if (err) { - debug_print ("gpgme_data_new failed: %s\n", gpgme_strerror (err)); - goto failure; - } - - /* get the content header lines from the source */ - clineidx = 0; - saved_last = 0; - while (!err && fgets(buf, sizeof(buf), fp)) { - /* fixme: check for overlong lines */ - if (headerp (buf, content_names)) { - if (clineidx >= DIM (clines)) { - debug_print ("rfc2015_encrypt: too many content lines\n"); - goto failure; - } - clines[clineidx++] = g_strdup (buf); - saved_last = 1; - continue; - } - if (saved_last) { - if (*buf == ' ' || *buf == '\t') { - char *last = clines[clineidx - 1]; - clines[clineidx - 1] = g_strconcat (last, buf, NULL); - g_free (last); - continue; - } - saved_last = 0; - } - - if (headerp (buf, mime_version_name)) - mime_version_seen = 1; - - if (buf[0] == '\r' || buf[0] == '\n') - break; - bytesRW = gpgme_data_write (header, buf, strlen (buf)); - } - if (ferror (fp)) { - FILE_OP_ERROR (file, "fgets"); - goto failure; - } - - /* write them to the temp data and add the rest of the message */ - for (i = 0; (bytesRW != -1) && i < clineidx; i++) { - debug_print ("%% %s:%d: cline=`%s'", __FILE__ ,__LINE__, clines[i]); - bytesRW = gpgme_data_write (plain, clines[i], strlen (clines[i])); - } - if (bytesRW != -1) - bytesRW = gpgme_data_write (plain, "\r\n", 2); - while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { - bytesRW = gpgme_data_write (plain, buf, strlen (buf)); - } - if (ferror (fp)) { - FILE_OP_ERROR (file, "fgets"); - goto failure; - } - if (bytesRW == -1) { - debug_print ("gpgme_data_write failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - cipher = pgp_encrypt (plain, kset); - gpgme_data_release (plain); plain = NULL; - i = 0; - while (kset[i] != NULL) { - gpgme_key_unref(kset[i]); - i++; - } - g_free(kset); - kset = NULL; - if (!cipher) - goto failure; - - /* we have the encrypted message available in cipher and now we - * are going to rewrite the source file. To be sure that file has - * been truncated we use an approach which should work everywhere: - * close the file and then reopen it for writing. It is important - * that this works, otherwise it may happen that parts of the - * plaintext are still in the file (The encrypted stuff is, due to - * compression, usually shorter than the plaintext). - * - * Yes, there is a race condition here, but everyone, who is so - * stupid to store the temp file with the plaintext in a public - * directory has to live with this anyway. */ - if (fclose (fp)) { - FILE_OP_ERROR(file, "fclose"); - goto failure; - } - if ((fp = fopen(file, "wb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - /* Write the header, append new content lines, part 1 and part 2 header */ - err = (gpgme_data_seek(header, 0 , SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) { - debug_print ("gpgme_data_seek failed: %s\n", gpgme_strerror (err)); - goto failure; - } - bytesRW = gpgme_data_read(header, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read(header, buf, BUFFSIZE); - } - - if (bytesRW != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - if (ferror (fp)) { - FILE_OP_ERROR (file, "fwrite"); - goto failure; - } - gpgme_data_release (header); header = NULL; - - if (!mime_version_seen) - fputs ("MIME-Version: 1\r\n", fp); - - if (ascii_armored) { - fprintf(fp, - "Content-Type: text/plain; charset=US-ASCII\r\n" - "Content-Transfer-Encoding: 7bit\r\n" - "\r\n"); - } else { - fprintf (fp, - "Content-Type: multipart/encrypted;" - " protocol=\"application/pgp-encrypted\";\r\n" - " boundary=\"%s\"\r\n" - "\r\n" - "--%s\r\n" - "Content-Type: application/pgp-encrypted\r\n" - "\r\n" - "Version: 1\r\n" - "\r\n" - "--%s\r\n" - "Content-Type: application/octet-stream\r\n" - "\r\n", - boundary, boundary, boundary); - } - - /* append the encrypted stuff */ - err = (gpgme_data_seek(cipher, 0 , SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) { - debug_print ("** gpgme_data_seek on cipher failed: %s\n", - gpgme_strerror (err)); - debug_print ("gpgme_data_seek failed: %s\n", gpgme_strerror (err)); - goto failure; - } - - bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE); - } - - if (bytesRW != 0) { - debug_print ("** gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - /* and the final boundary */ - if (!ascii_armored) { - fprintf (fp, - "\r\n" - "--%s--\r\n", - boundary); - } - fflush (fp); - if (ferror (fp)) { - FILE_OP_ERROR (file, "fwrite"); - goto failure; - } - fclose (fp); - gpgme_data_release (cipher); - return 0; + FILE *fp = NULL; + gchar buf[BUFFSIZE]; + gint i, clineidx, saved_last; + gchar *clines[3] = {NULL}; + gpgme_error_t err; + gpgme_data_t header = NULL; + gpgme_data_t plain = NULL; + gpgme_data_t cipher = NULL; + gpgme_key_t *kset = NULL; + ssize_t bytesRW = 0; + gint mime_version_seen = 0; + gchar *boundary; + + boundary = generate_mime_boundary("Encrypt"); + + /* Create the list of recipients */ + kset = gpgmegtk_recipient_selection(recp_list); + if (!kset) { + debug_print("error creating recipient list\n"); + goto failure; + } -failure: - if (fp) - fclose (fp); - gpgme_data_release (header); - gpgme_data_release (plain); - gpgme_data_release (cipher); + /* Open the source file */ + if ((fp = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + err = gpgme_data_new(&header); + if (!err) + err = gpgme_data_new(&plain); + if (err) { + debug_print("gpgme_data_new failed: %s\n", gpgme_strerror(err)); + goto failure; + } + + /* get the content header lines from the source */ + clineidx = 0; + saved_last = 0; + while (!err && fgets(buf, sizeof(buf), fp)) { + /* fixme: check for overlong lines */ + if (headerp(buf, content_names)) { + if (clineidx >= DIM(clines)) { + debug_print("rfc2015_encrypt: too many content lines\n"); + goto failure; + } + clines[clineidx++] = g_strdup(buf); + saved_last = 1; + continue; + } + if (saved_last) { + if (*buf == ' ' || *buf == '\t') { + gchar *last = clines[clineidx - 1]; + clines[clineidx - 1] = g_strconcat(last, buf, NULL); + g_free(last); + continue; + } + saved_last = 0; + } + + if (headerp(buf, mime_version_name)) + mime_version_seen = 1; - if (kset != NULL) { + if (buf[0] == '\r' || buf[0] == '\n') + break; + bytesRW = gpgme_data_write(header, buf, strlen(buf)); + } + if (ferror(fp)) { + FILE_OP_ERROR(file, "fgets"); + goto failure; + } + + /* write them to the temp data and add the rest of the message */ + for (i = 0; (bytesRW != -1) && i < clineidx; i++) { + debug_print("%% %s:%d: cline=`%s'", __FILE__ ,__LINE__, clines[i]); + bytesRW = gpgme_data_write(plain, clines[i], strlen(clines[i])); + } + if (bytesRW != -1) + bytesRW = gpgme_data_write (plain, "\r\n", 2); + while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { + bytesRW = gpgme_data_write(plain, buf, strlen(buf)); + } + if (ferror(fp)) { + FILE_OP_ERROR(file, "fgets"); + goto failure; + } + if (bytesRW == -1) { + debug_print("gpgme_data_write failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + cipher = pgp_encrypt(plain, kset); + gpgme_data_release(plain); + plain = NULL; i = 0; while (kset[i] != NULL) { - gpgme_key_unref(kset[i]); - i++; + gpgme_key_unref(kset[i]); + i++; } g_free(kset); - } - g_free (boundary); - return -1; /* error */ + kset = NULL; + if (!cipher) + goto failure; + + /* we have the encrypted message available in cipher and now we + * are going to rewrite the source file. To be sure that file has + * been truncated we use an approach which should work everywhere: + * close the file and then reopen it for writing. It is important + * that this works, otherwise it may happen that parts of the + * plaintext are still in the file (The encrypted stuff is, due to + * compression, usually shorter than the plaintext). + * + * Yes, there is a race condition here, but everyone, who is so + * stupid to store the temp file with the plaintext in a public + * directory has to live with this anyway. */ + if (fclose (fp)) { + FILE_OP_ERROR(file, "fclose"); + goto failure; + } + if ((fp = fopen(file, "wb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + /* Write the header, append new content lines, part 1 and part 2 header */ + err = (gpgme_data_seek(header, 0 , SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) { + debug_print("gpgme_data_seek failed: %s\n", + gpgme_strerror(err)); + goto failure; + } + bytesRW = gpgme_data_read(header, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite (buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(header, buf, BUFFSIZE); + } + + if (bytesRW != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + if (ferror (fp)) { + FILE_OP_ERROR(file, "fwrite"); + goto failure; + } + gpgme_data_release(header); + header = NULL; + + if (!mime_version_seen) + fputs("MIME-Version: 1\r\n", fp); + + if (ascii_armored) { + fprintf(fp, + "Content-Type: text/plain; charset=US-ASCII\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n"); + } else { + fprintf(fp, + "Content-Type: multipart/encrypted;" + " protocol=\"application/pgp-encrypted\";\r\n" + " boundary=\"%s\"\r\n" + "\r\n" + "--%s\r\n" + "Content-Type: application/pgp-encrypted\r\n" + "\r\n" + "Version: 1\r\n" + "\r\n" + "--%s\r\n" + "Content-Type: application/octet-stream\r\n" + "\r\n", + boundary, boundary, boundary); + } + + /* append the encrypted stuff */ + err = (gpgme_data_seek(cipher, 0 , SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) { + debug_print("** gpgme_data_seek on cipher failed: %s\n", + gpgme_strerror(err)); + debug_print("gpgme_data_seek failed: %s\n", + gpgme_strerror(err)); + goto failure; + } + + bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite(buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(cipher, buf, BUFFSIZE); + } + + if (bytesRW != 0) { + debug_print("** gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + /* and the final boundary */ + if (!ascii_armored) { + fprintf(fp, + "\r\n" + "--%s--\r\n", + boundary); + } + fflush(fp); + if (ferror(fp)) { + FILE_OP_ERROR(file, "fwrite"); + goto failure; + } + fclose(fp); + gpgme_data_release(cipher); + return 0; + +failure: + if (fp) + fclose (fp); + gpgme_data_release(header); + gpgme_data_release(plain); + gpgme_data_release(cipher); + + if (kset != NULL) { + i = 0; + while (kset[i] != NULL) { + gpgme_key_unref(kset[i]); + i++; + } + g_free(kset); + } + g_free(boundary); + return -1; /* error */ } -/* +/* * plain contains an entire mime object. Sign it and return an * GpgmeData object with the signature of it or NULL in case of error. * micalg returns the micalg information about the signature. */ -static gpgme_data_t -pgp_sign (gpgme_data_t plain, GSList *key_list, gboolean clearsign, - char **micalg) +static gpgme_data_t pgp_sign(gpgme_data_t plain, GSList *key_list, + gboolean clearsign, gchar **micalg) { - GSList *p; - gpgme_ctx_t ctx = NULL; - gpgme_error_t err; - gpgme_data_t sig = NULL; - gpgme_sign_result_t result = NULL; - struct passphrase_cb_info_s info; - - *micalg = NULL; - memset (&info, 0, sizeof info); - - err = gpgme_new (&ctx); - if (err) - goto leave; - err = gpgme_data_new (&sig); - if (err) - goto leave; - - if (!getenv("GPG_AGENT_INFO")) { - info.c = ctx; - gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); - } - gpgme_set_textmode (ctx, 1); - gpgme_set_armor (ctx, 1); - gpgme_signers_clear (ctx); - for (p = key_list; p != NULL; p = p->next) { - err = gpgme_signers_add (ctx, (gpgme_key_t) p->data); + GSList *p; + gpgme_ctx_t ctx = NULL; + gpgme_error_t err; + gpgme_data_t sig = NULL; + gpgme_sign_result_t result = NULL; + struct passphrase_cb_info_s info; + + *micalg = NULL; + memset(&info, 0, sizeof info); + + err = gpgme_new(&ctx); if (err) - goto leave; - } - for (p = key_list; p != NULL; p = p->next) - gpgme_key_unref ((gpgme_key_t) p->data); - g_slist_free (key_list); - - err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (!err) { - err = gpgme_op_sign (ctx, plain, sig, - clearsign ? GPGME_SIG_MODE_CLEAR : GPGME_SIG_MODE_DETACH); - } - if (!err) { - result = gpgme_op_sign_result(ctx); - if (result && result->signatures) { - if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { - *micalg = g_strdup_printf("PGP-%s", gpgme_hash_algo_name( - result->signatures->hash_algo)); - } else { - *micalg = g_strdup(gpgme_hash_algo_name( - result->signatures->hash_algo)); - } - } else { - /* can't get result (maybe no signing key?) */ - err = GPG_ERR_USER_1; + goto leave; + err = gpgme_data_new(&sig); + if (err) + goto leave; + + if (!g_getenv("GPG_AGENT_INFO")) { + info.c = ctx; + gpgme_set_passphrase_cb(ctx, gpgmegtk_passphrase_cb, &info); + } + gpgme_set_textmode(ctx, 1); + gpgme_set_armor(ctx, 1); + gpgme_signers_clear(ctx); + for (p = key_list; p != NULL; p = p->next) { + err = gpgme_signers_add(ctx, (gpgme_key_t) p->data); + if (err) + goto leave; + } + for (p = key_list; p != NULL; p = p->next) + gpgme_key_unref((gpgme_key_t) p->data); + g_slist_free(key_list); + + err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (!err) { + err = gpgme_op_sign(ctx, plain, sig, + clearsign ? GPGME_SIG_MODE_CLEAR : GPGME_SIG_MODE_DETACH); + } + if (!err) { + result = gpgme_op_sign_result(ctx); + if (result && result->signatures) { + if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { + *micalg = g_strdup_printf + ("PGP-%s", gpgme_hash_algo_name(result->signatures->hash_algo)); + } else { + *micalg = g_strdup(gpgme_hash_algo_name(result->signatures->hash_algo)); + } + } else { + /* can't get result (maybe no signing key?) */ + err = GPG_ERR_USER_1; + } } - } leave: - if (err) { - gpgmegtk_free_passphrase(); - g_warning ("pgp_sign(): signing failed: %s\n", gpgme_strerror (err)); - gpgme_data_release (sig); - sig = NULL; - } else { - debug_print ("signing succeeded\n"); - } - - gpgme_release (ctx); - return sig; + if (err) { + gpgmegtk_free_passphrase(); + g_warning("pgp_sign(): signing failed: %s\n", gpgme_strerror(err)); + gpgme_data_release(sig); + sig = NULL; + } else { + debug_print("signing succeeded\n"); + } + + gpgme_release(ctx); + return sig; } /* * Sign the file and replace its content with the signed one. */ -int -rfc2015_sign (const char *file, GSList *key_list) +gint rfc2015_sign(const gchar *file, GSList *key_list) { - FILE *fp = NULL; - char buf[BUFFSIZE]; - int i, clineidx, saved_last; - char *clines[3] = {NULL}; - gpgme_error_t err; - gpgme_data_t header = NULL; - gpgme_data_t plain = NULL; - gpgme_data_t sigdata = NULL; - ssize_t bytesRW = -1; - int mime_version_seen = 0; - char *boundary; - char *micalg = NULL; - - boundary = generate_mime_boundary ("Signature"); - - /* Open the source file */ - if ((fp = fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - err = gpgme_data_new (&header); - if (!err) - err = gpgme_data_new (&plain); - if (err) { - debug_print ("gpgme_data_new failed: %s\n", gpgme_strerror (err)); - goto failure; - } - - /* get the content header lines from the source */ - clineidx = 0; - saved_last = 0; - while (!err && fgets(buf, sizeof(buf), fp)) { - /* fixme: check for overlong lines */ - if (headerp (buf, content_names)) { - if (clineidx >= DIM (clines)) { - debug_print ("rfc2015_sign: too many content lines\n"); - goto failure; - } - clines[clineidx++] = g_strdup (buf); - saved_last = 1; - continue; - } - if (saved_last) { - if (*buf == ' ' || *buf == '\t') { - char *last = clines[clineidx - 1]; - clines[clineidx - 1] = g_strconcat (last, buf, NULL); - g_free (last); - continue; - } - saved_last = 0; - } - - if (headerp (buf, mime_version_name)) - mime_version_seen = 1; - - if (buf[0] == '\r' || buf[0] == '\n') - break; - bytesRW = gpgme_data_write (header, buf, strlen (buf)); - } - if (ferror (fp)) { - FILE_OP_ERROR (file, "fgets"); - goto failure; - } - - /* write them to the temp data and add the rest of the message */ - for (i = 0; (bytesRW != -1) && i < clineidx; i++) { - bytesRW = gpgme_data_write (plain, clines[i], strlen (clines[i])); - } - if (bytesRW != -1) - bytesRW = gpgme_data_write (plain, "\r\n", 2 ); - while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { - bytesRW = gpgme_data_write (plain, buf, strlen (buf)); - } - if (ferror (fp)) { - FILE_OP_ERROR (file, "fgets"); - goto failure; - } - if (bytesRW == -1) { - debug_print ("gpgme_data_write failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - sigdata = pgp_sign (plain, key_list, FALSE, &micalg); - if (!sigdata) - goto failure; - - /* we have the signed message available in sigdata and now we are - * going to rewrite the original file. To be sure that file has - * been truncated we use an approach which should work everywhere: - * close the file and then reopen it for writing. */ - if (fclose (fp)) { - FILE_OP_ERROR(file, "fclose"); - goto failure; - } - if ((fp = fopen(file, "wb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - /* Write the rfc822 header and add new content lines */ - err = (gpgme_data_seek (header, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) - debug_print ("gpgme_data_seek failed: %s\n", gpgme_strerror (err)); - bytesRW = gpgme_data_read (header, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read (header, buf, BUFFSIZE); - } - if (bytesRW != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - if (ferror (fp)) { - FILE_OP_ERROR (file, "fwrite"); - goto failure; - } - gpgme_data_release (header); - header = NULL; - - if (!mime_version_seen) - fputs ("MIME-Version: 1.0\r\n", fp); - fprintf (fp, "Content-Type: multipart/signed; " - "protocol=\"application/pgp-signature\";\r\n"); - if (micalg) - fprintf (fp, " micalg=\"%s\";\r\n", micalg); - fprintf (fp, " boundary=\"%s\"\r\n", boundary); - - /* Part 1: signed material */ - fprintf (fp, "\r\n" - "--%s\r\n", - boundary); - err = (gpgme_data_seek (plain, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) { - debug_print ("gpgme_data_seek on plain failed: %s\n", - gpgme_strerror (err)); - goto failure; - } - bytesRW = gpgme_data_read (plain, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read (plain, buf, BUFFSIZE); - } - if (bytesRW != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - /* Part 2: signature */ - fprintf (fp, "\r\n" - "--%s\r\n", - boundary); - fputs ("Content-Type: application/pgp-signature\r\n" - "\r\n", fp); - - err = (gpgme_data_seek (sigdata, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) { - debug_print ("gpgme_data_seek on sigdata failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - bytesRW = gpgme_data_read (sigdata, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read (sigdata, buf, BUFFSIZE); - } - if (bytesRW != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - /* Final boundary */ - fprintf (fp, "\r\n" - "--%s--\r\n", - boundary); - fflush (fp); - if (ferror (fp)) { - FILE_OP_ERROR (file, "fwrite"); - goto failure; - } - fclose (fp); - gpgme_data_release (header); - gpgme_data_release (plain); - gpgme_data_release (sigdata); - g_free (boundary); - g_free (micalg); - return 0; + FILE *fp = NULL; + gchar buf[BUFFSIZE]; + gint i, clineidx, saved_last; + gchar *clines[3] = {NULL}; + gpgme_error_t err; + gpgme_data_t header = NULL; + gpgme_data_t plain = NULL; + gpgme_data_t sigdata = NULL; + ssize_t bytesRW = -1; + gint mime_version_seen = 0; + gchar *boundary; + gchar *micalg = NULL; + + boundary = generate_mime_boundary("Signature"); + + /* Open the source file */ + if ((fp = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + err = gpgme_data_new(&header); + if (!err) + err = gpgme_data_new(&plain); + if (err) { + debug_print("gpgme_data_new failed: %s\n", gpgme_strerror(err)); + goto failure; + } + + /* get the content header lines from the source */ + clineidx = 0; + saved_last = 0; + while (!err && fgets(buf, sizeof(buf), fp)) { + /* fixme: check for overlong lines */ + if (headerp(buf, content_names)) { + if (clineidx >= DIM(clines)) { + debug_print("rfc2015_sign: too many content lines\n"); + goto failure; + } + clines[clineidx++] = g_strdup(buf); + saved_last = 1; + continue; + } + if (saved_last) { + if (*buf == ' ' || *buf == '\t') { + gchar *last = clines[clineidx - 1]; + clines[clineidx - 1] = g_strconcat(last, buf, NULL); + g_free(last); + continue; + } + saved_last = 0; + } + + if (headerp(buf, mime_version_name)) + mime_version_seen = 1; + + if (buf[0] == '\r' || buf[0] == '\n') + break; + bytesRW = gpgme_data_write(header, buf, strlen (buf)); + } + if (ferror (fp)) { + FILE_OP_ERROR(file, "fgets"); + goto failure; + } + + /* write them to the temp data and add the rest of the message */ + for (i = 0; (bytesRW != -1) && i < clineidx; i++) { + bytesRW = gpgme_data_write(plain, clines[i], strlen(clines[i])); + } + if (bytesRW != -1) + bytesRW = gpgme_data_write(plain, "\r\n", 2 ); + while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { + bytesRW = gpgme_data_write(plain, buf, strlen(buf)); + } + if (ferror(fp)) { + FILE_OP_ERROR(file, "fgets"); + goto failure; + } + if (bytesRW == -1) { + debug_print("gpgme_data_write failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + sigdata = pgp_sign(plain, key_list, FALSE, &micalg); + if (!sigdata) + goto failure; + + /* we have the signed message available in sigdata and now we are + * going to rewrite the original file. To be sure that file has + * been truncated we use an approach which should work everywhere: + * close the file and then reopen it for writing. */ + if (fclose(fp)) { + FILE_OP_ERROR(file, "fclose"); + goto failure; + } + if ((fp = fopen(file, "wb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + /* Write the rfc822 header and add new content lines */ + err = (gpgme_data_seek(header, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) + debug_print("gpgme_data_seek failed: %s\n", + gpgme_strerror(err)); + bytesRW = gpgme_data_read(header, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite(buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(header, buf, BUFFSIZE); + } + if (bytesRW != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + if (ferror(fp)) { + FILE_OP_ERROR(file, "fwrite"); + goto failure; + } + gpgme_data_release(header); + header = NULL; + + if (!mime_version_seen) + fputs("MIME-Version: 1.0\r\n", fp); + fprintf(fp, "Content-Type: multipart/signed; " + "protocol=\"application/pgp-signature\";\r\n"); + if (micalg) + fprintf(fp, " micalg=\"%s\";\r\n", micalg); + fprintf(fp, " boundary=\"%s\"\r\n", boundary); + + /* Part 1: signed material */ + fprintf(fp, "\r\n" + "--%s\r\n", + boundary); + err = (gpgme_data_seek(plain, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) { + debug_print("gpgme_data_seek on plain failed: %s\n", + gpgme_strerror(err)); + goto failure; + } + bytesRW = gpgme_data_read(plain, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite(buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(plain, buf, BUFFSIZE); + } + if (bytesRW != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + /* Part 2: signature */ + fprintf(fp, "\r\n" + "--%s\r\n", + boundary); + fputs("Content-Type: application/pgp-signature\r\n" + "\r\n", fp); + + err = (gpgme_data_seek(sigdata, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) { + debug_print("gpgme_data_seek on sigdata failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + bytesRW = gpgme_data_read(sigdata, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite(buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(sigdata, buf, BUFFSIZE); + } + if (bytesRW != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + /* Final boundary */ + fprintf(fp, "\r\n" + "--%s--\r\n", + boundary); + fflush(fp); + if (ferror(fp)) { + FILE_OP_ERROR(file, "fwrite"); + goto failure; + } + fclose(fp); + gpgme_data_release(header); + gpgme_data_release(plain); + gpgme_data_release(sigdata); + g_free(boundary); + g_free(micalg); + return 0; failure: - if (fp) - fclose (fp); - gpgme_data_release (header); - gpgme_data_release (plain); - gpgme_data_release (sigdata); - g_free (boundary); - g_free (micalg); - return -1; /* error */ + if (fp) + fclose(fp); + gpgme_data_release(header); + gpgme_data_release(plain); + gpgme_data_release(sigdata); + g_free(boundary); + g_free(micalg); + return -1; /* error */ } /* * Sign the file with clear text and replace its content with the signed one. */ -gint -rfc2015_clearsign (const gchar *file, GSList *key_list) +gint rfc2015_clearsign(const gchar *file, GSList *key_list) { - FILE *fp; - gchar buf[BUFFSIZE]; - gpgme_error_t err; - gpgme_data_t text = NULL; - gpgme_data_t sigdata = NULL; - ssize_t bytesRW = 0; - gchar *micalg = NULL; - - if ((fp = fopen(file, "rb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - err = gpgme_data_new(&text); - if (err) { - debug_print("gpgme_data_new failed: %s\n", gpgme_strerror(err)); - goto failure; - } - - while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { - bytesRW = gpgme_data_write(text, buf, strlen(buf)); - } - if (ferror(fp)) { - FILE_OP_ERROR(file, "fgets"); - goto failure; - } - if (bytesRW == -1) { - debug_print("gpgme_data_write failed: %s\n", - gpgme_strerror(gpgme_error_from_errno(errno))); - goto failure; - } - - sigdata = pgp_sign(text, key_list, TRUE, &micalg); - if (micalg) { - g_free(micalg); - } - if (!sigdata) - goto failure; - - if (fclose(fp) == EOF) { - FILE_OP_ERROR(file, "fclose"); - fp = NULL; - goto failure; - } - if ((fp = fopen(file, "wb")) == NULL) { - FILE_OP_ERROR(file, "fopen"); - goto failure; - } - - err = (gpgme_data_seek (sigdata, 0, SEEK_SET) == -1) ? - gpgme_error_from_errno(errno) : 0; - if (err) { - debug_print("gpgme_data_seek on sigdata failed: %s\n", - gpgme_strerror(err)); - goto failure; - } - - bytesRW = gpgme_data_read (sigdata, buf, BUFFSIZE); - while (bytesRW > 0) { - fwrite (buf, bytesRW, 1, fp); - bytesRW = gpgme_data_read (sigdata, buf, BUFFSIZE); - } - if (bytesRW != 0) { - debug_print ("gpgme_data_read failed: %s\n", - gpgme_strerror (gpgme_error_from_errno(errno))); - goto failure; - } - - if (fclose(fp) == EOF) { - FILE_OP_ERROR(file, "fclose"); - fp = NULL; - goto failure; - } - gpgme_data_release(text); - gpgme_data_release(sigdata); - return 0; + FILE *fp; + gchar buf[BUFFSIZE]; + gpgme_error_t err; + gpgme_data_t text = NULL; + gpgme_data_t sigdata = NULL; + ssize_t bytesRW = 0; + gchar *micalg = NULL; + + if ((fp = fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + err = gpgme_data_new(&text); + if (err) { + debug_print("gpgme_data_new failed: %s\n", gpgme_strerror(err)); + goto failure; + } + + while ((bytesRW != -1) && fgets(buf, sizeof(buf), fp)) { + bytesRW = gpgme_data_write(text, buf, strlen(buf)); + } + if (ferror(fp)) { + FILE_OP_ERROR(file, "fgets"); + goto failure; + } + if (bytesRW == -1) { + debug_print("gpgme_data_write failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + sigdata = pgp_sign(text, key_list, TRUE, &micalg); + if (micalg) { + g_free(micalg); + } + if (!sigdata) + goto failure; + + if (fclose(fp) == EOF) { + FILE_OP_ERROR(file, "fclose"); + fp = NULL; + goto failure; + } + if ((fp = fopen(file, "wb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + goto failure; + } + + err = (gpgme_data_seek(sigdata, 0, SEEK_SET) == -1) ? + gpgme_error_from_errno(errno) : 0; + if (err) { + debug_print("gpgme_data_seek on sigdata failed: %s\n", + gpgme_strerror(err)); + goto failure; + } + + bytesRW = gpgme_data_read(sigdata, buf, BUFFSIZE); + while (bytesRW > 0) { + fwrite(buf, bytesRW, 1, fp); + bytesRW = gpgme_data_read(sigdata, buf, BUFFSIZE); + } + if (bytesRW != 0) { + debug_print("gpgme_data_read failed: %s\n", + gpgme_strerror(gpgme_error_from_errno(errno))); + goto failure; + } + + if (fclose(fp) == EOF) { + FILE_OP_ERROR(file, "fclose"); + fp = NULL; + goto failure; + } + gpgme_data_release(text); + gpgme_data_release(sigdata); + return 0; failure: - if (fp) - fclose(fp); - gpgme_data_release(text); - gpgme_data_release(sigdata); - return -1; + if (fp) + fclose(fp); + gpgme_data_release(text); + gpgme_data_release(sigdata); + return -1; } #endif /* USE_GPGME */ -- cgit v1.2.3