From: Christoph Hohmann Date: Fri, 14 Nov 2003 18:37:20 +0000 (+0000) Subject: 0.9.6claws74 X-Git-Tag: rel_0_9_7~29 X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=commitdiff_plain;h=d8417950cd50b586dd915881bb40be60af9ea4de;hp=b03fccda750b9bd0692b217248d8e96a96537549 0.9.6claws74 * src/messageview.c * src/pgpmime.c * src/privacy.[ch] prepare for message part decrypting * src/sgpgme.c add output for expired signatures * src/rfc2015.c remove some old code --- diff --git a/ChangeLog.claws b/ChangeLog.claws index 1b5f4422b..ff5e388b4 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,16 @@ +2003-11-14 [christoph] 0.9.6claws74 + + * src/messageview.c + * src/pgpmime.c + * src/privacy.[ch] + prepare for message part decrypting + + * src/sgpgme.c + add output for expired signatures + + * src/rfc2015.c + remove some old code + 2003-11-10 [christoph] 0.9.6claws73 * src/mimeview.c diff --git a/configure.ac b/configure.ac index 092111817..674088826 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=9 MICRO_VERSION=6 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=73 +EXTRA_VERSION=74 if test $EXTRA_VERSION -eq 0; then VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws else diff --git a/src/messageview.c b/src/messageview.c index c392a6ed2..200781fb0 100644 --- a/src/messageview.c +++ b/src/messageview.c @@ -617,17 +617,46 @@ GList *messageview_get_window_list(void) return messageview_list; } +static gboolean find_encrypted_func(GNode *node, gpointer data) +{ + MimeInfo *mimeinfo = (MimeInfo *) node->data; + MimeInfo **encinfo = (MimeInfo **) data; + + if (privacy_mimeinfo_is_encrypted(mimeinfo)) { + *encinfo = mimeinfo; + return TRUE; + } + + return FALSE; +} + +static MimeInfo *find_encrypted_part(MimeInfo *rootinfo) +{ + MimeInfo *encinfo = NULL; + + g_node_traverse(rootinfo->node, G_IN_ORDER, G_TRAVERSE_ALL, -1, + find_encrypted_func, &encinfo); + + return encinfo; +} + void messageview_show(MessageView *messageview, MsgInfo *msginfo, gboolean all_headers) { gchar *file; - MimeInfo *mimeinfo; + MimeInfo *mimeinfo, *encinfo; g_return_if_fail(msginfo != NULL); mimeinfo = procmime_scan_message(msginfo); g_return_if_fail(mimeinfo != NULL); + while ((encinfo = find_encrypted_part(mimeinfo)) != NULL) { + debug_print("decrypting message part\n"); + if (privacy_mimeinfo_decrypt(encinfo) < 0) + break; + } + file = procmsg_get_message_file_path(msginfo); if (!file) { g_warning("can't get message file path.\n"); diff --git a/src/pgpmime.c b/src/pgpmime.c index 55f0a8515..3719895c2 100644 --- a/src/pgpmime.c +++ b/src/pgpmime.c @@ -208,6 +208,34 @@ static gchar *pgpmime_get_sig_info_full(MimeInfo *mimeinfo) return sgpgme_sigstat_info_full(data->ctx, data->sigstatus); } +static gboolean pgpmime_is_encrypted(MimeInfo *mimeinfo) +{ + MimeInfo *tmpinfo; + + if (mimeinfo->type != MIMETYPE_MULTIPART) + return FALSE; + if (g_strcasecmp(mimeinfo->subtype, "encrypted")) + return FALSE; + if (g_strcasecmp(procmime_mimeinfo_get_parameter(mimeinfo, "protocol"), "application/pgp-encrypted")) + return FALSE; + if (g_node_n_children(mimeinfo->node) != 2) + return FALSE; + + tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 0)->data; + if (tmpinfo->type != MIMETYPE_APPLICATION) + return FALSE; + if (g_strcasecmp(tmpinfo->subtype, "pgp-encrypted")) + return FALSE; + + tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 1)->data; + if (tmpinfo->type != MIMETYPE_APPLICATION) + return FALSE; + if (g_strcasecmp(tmpinfo->subtype, "octet-stream")) + return FALSE; + + return TRUE; +} + static PrivacySystem pgpmime_system = { "PGP/Mime", /* name */ @@ -220,7 +248,7 @@ static PrivacySystem pgpmime_system = { pgpmime_get_sig_info_full, /* get_sig_info_full(MimeInfo *) */ /* NOT YET */ - NULL, /* is_encrypted(MimeInfo *) */ + pgpmime_is_encrypted, /* is_encrypted(MimeInfo *) */ NULL, /* decrypt(MimeInfo *) */ }; diff --git a/src/privacy.c b/src/privacy.c index 04ec5cacf..bc165da28 100644 --- a/src/privacy.c +++ b/src/privacy.c @@ -25,16 +25,32 @@ static GSList *systems = NULL; +/** + * Register a new Privacy System + * + * \param system The Privacy System that should be registered + */ void privacy_register_system(PrivacySystem *system) { systems = g_slist_append(systems, system); } +/** + * Unregister a new Privacy System. The system must not be in + * use anymore when it is unregistered. + * + * \param system The Privacy System that should be unregistered + */ void privacy_unregister_system(PrivacySystem *system) { systems = g_slist_remove(systems, system); } +/** + * Free a PrivacyData of a PrivacySystem + * + * \param privacydata The data to free + */ void privacy_free_privacydata(PrivacyData *privacydata) { g_return_if_fail(privacydata != NULL); @@ -42,6 +58,15 @@ void privacy_free_privacydata(PrivacyData *privacydata) privacydata->system->free_privacydata(privacydata); } +/** + * Check if a MimeInfo is signed with one of the available + * privacy system. If a privacydata is set in the MimeInfo + * it will directory return the return value by the system + * set in the privacy data or check all available privacy + * systems otherwise. + * + * \return True if the MimeInfo has a signature + */ gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo) { GSList *cur; @@ -66,6 +91,14 @@ gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo) return FALSE; } +/** + * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed + * should be called before otherwise it is done by this function. + * If the MimeInfo is not signed an error code will be returned. + * + * \return Error code indicating the result of the check, + * < 0 if an error occured + */ gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo) { PrivacySystem *system; @@ -144,7 +177,20 @@ gchar *privacy_mimeinfo_sig_info_full(MimeInfo *mimeinfo) gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo) { + GSList *cur; g_return_val_if_fail(mimeinfo != NULL, FALSE); + for(cur = systems; cur != NULL; cur = g_slist_next(cur)) { + PrivacySystem *system = (PrivacySystem *) cur->data; + + if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo)) + return TRUE; + } + return FALSE; } + +gint privacy_mimeinfo_decrypt(MimeInfo *mimeinfo) +{ + return -1; +} diff --git a/src/privacy.h b/src/privacy.h index c4bdaa1c8..53891e9b9 100644 --- a/src/privacy.h +++ b/src/privacy.h @@ -46,10 +46,8 @@ SignatureStatus privacy_mimeinfo_get_sig_status (MimeInfo *); gchar *privacy_mimeinfo_sig_info_short (MimeInfo *); gchar *privacy_mimeinfo_sig_info_full (MimeInfo *); -#if 0 /* NOT YET */ gboolean privacy_mimeinfo_is_encrypted (MimeInfo *); -gint privacy_decrypt (MimeInfo *); -#endif +gint privacy_mimeinfo_decrypt (MimeInfo *); struct _PrivacySystem { gchar *name; @@ -62,7 +60,6 @@ struct _PrivacySystem { gchar *(*get_sig_info_short) (MimeInfo *); gchar *(*get_sig_info_full) (MimeInfo *); - /* NOT YET */ gboolean (*is_encrypted) (MimeInfo *); MimeInfo *(*decrypt) (MimeInfo *); }; diff --git a/src/rfc2015.c b/src/rfc2015.c index cbe5351cb..0aa4fd2df 100644 --- a/src/rfc2015.c +++ b/src/rfc2015.c @@ -126,302 +126,6 @@ rfc2015_secure_remove (const char *fname) } -static const gchar * -sig_status_to_string (GpgmeSigStat status) -{ - const gchar *result; - - switch (status) { - case GPGME_SIG_STAT_NONE: - result = _("Oops: Signature not verified"); - break; - case GPGME_SIG_STAT_NOSIG: - result = _("No signature found"); - break; - case GPGME_SIG_STAT_GOOD: - result = _("Good signature"); - break; - case GPGME_SIG_STAT_GOOD_EXP: - result = _("Good signature but it has expired"); - break; - case GPGME_SIG_STAT_GOOD_EXPKEY: - result = _("Good signature but the key has expired"); - break; - case GPGME_SIG_STAT_BAD: - result = _("BAD signature"); - break; - case GPGME_SIG_STAT_NOKEY: - result = _("No public key to verify the signature"); - break; - case GPGME_SIG_STAT_ERROR: - result = _("Error verifying the signature"); - break; - case GPGME_SIG_STAT_DIFF: - result = _("Different results for signatures"); - break; - default: - result = _("Error: Unknown status"); - break; - } - - return result; -} - -static const gchar * -sig_status_with_name (GpgmeSigStat status) -{ - const gchar *result; - - switch (status) { - case GPGME_SIG_STAT_NONE: - result = _("Oops: Signature not verified"); - break; - case GPGME_SIG_STAT_NOSIG: - result = _("No signature found"); - break; - case GPGME_SIG_STAT_GOOD: - result = _("Good signature from \"%s\""); - break; - case GPGME_SIG_STAT_GOOD_EXP: - result = _("Good signature from \"%s\" but it has expired"); - break; - case GPGME_SIG_STAT_GOOD_EXPKEY: - result = _("Good signature from \"%s\" but the key has expired"); - break; - case GPGME_SIG_STAT_BAD: - result = _("BAD signature from \"%s\""); - break; - case GPGME_SIG_STAT_NOKEY: - result = _("No public key to verify the signature"); - break; - case GPGME_SIG_STAT_ERROR: - result = _("Error verifying the signature"); - break; - case GPGME_SIG_STAT_DIFF: - result = _("Different results for signatures"); - break; - default: - result = _("Error: Unknown status"); - break; - } - - return result; -} - -static void -sig_status_for_key(GString *str, GpgmeCtx ctx, GpgmeSigStat status, - GpgmeKey key, const gchar *fpr) -{ - gint idx = 0; - const char *uid; - - uid = gpgme_key_get_string_attr (key, GPGME_ATTR_USERID, NULL, idx); - if (uid == NULL) { - g_string_sprintfa (str, "%s\n", - sig_status_to_string (status)); - if ((fpr != NULL) && (*fpr != '\0')) - g_string_sprintfa (str, "Key fingerprint: %s\n", fpr); - g_string_append (str, _("Cannot find user ID for this key.")); - sig_expiration_check(str, ctx, key, status, 0); - return; - } - g_string_sprintfa (str, sig_status_with_name (status), uid); - g_string_append (str, "\n"); - - while (1) { - uid = gpgme_key_get_string_attr (key, GPGME_ATTR_USERID, - NULL, ++idx); - if (uid == NULL) - break; - g_string_sprintfa (str, _(" aka \"%s\"\n"), - uid); - } - sig_expiration_check(str, ctx, key, status, 0); -} - -static void -sig_expiration_check(GString *str, GpgmeCtx ctx, GpgmeKey key, - GpgmeSigStat status, int idx) -{ - if (status == GPGME_SIG_STAT_GOOD_EXP) - sig_expired(str, ctx, idx); - else if (status == GPGME_SIG_STAT_GOOD_EXPKEY) - sig_key_expired(str, key, idx); -} - -static void -sig_expired(GString *str, GpgmeCtx ctx, int idx) -{ - unsigned long exp_time; - exp_time = gpgme_get_sig_ulong_attr(ctx, idx, GPGME_ATTR_EXPIRE, 0); - g_string_sprintfa(str, _("Signature expired %s"), ctime(&exp_time)); -} - -static void -sig_key_expired(GString *str, GpgmeKey key, int idx) -{ - unsigned long exp_time; - exp_time = gpgme_key_get_ulong_attr(key, GPGME_ATTR_EXPIRE, NULL, idx); - g_string_sprintfa(str, _("Key expired %s"), ctime(&exp_time)); -} - -static gchar * -sig_status_full (GpgmeCtx ctx) -{ - GString *str; - gint sig_idx = 0; - GpgmeError err; - GpgmeSigStat status; - GpgmeKey key; - const char *fpr; - time_t created; - struct tm *ctime_val; - char ctime_str[80]; - gchar *retval; - - str = g_string_new (""); - - fpr = gpgme_get_sig_status (ctx, sig_idx, &status, &created); - while (fpr != NULL) { - if (created != 0) { - ctime_val = localtime (&created); - strftime (ctime_str, sizeof (ctime_str), "%c", - ctime_val); - g_string_sprintfa (str, - _("Signature made at %s\n"), - ctime_str); - } - err = gpgme_get_sig_key (ctx, sig_idx, &key); - if (err != 0) { - g_string_sprintfa (str, "%s\n", - sig_status_to_string (status)); - if ((fpr != NULL) && (*fpr != '\0')) - g_string_sprintfa (str, - _("Key fingerprint: %s\n"), - fpr); - } else { - const char *key_id_str; - - sig_status_for_key (str, ctx, status, key, fpr); - key_id_str = gpgme_key_get_string_attr(key, - GPGME_ATTR_KEYID, NULL, 0); - key_id_str += 8; - g_string_sprintfa (str, _("Key ID: %s\n"), key_id_str); - gpgme_key_unref (key); - } - g_string_append (str, "\n\n"); - - fpr = gpgme_get_sig_status (ctx, ++sig_idx, &status, &created); - } - - retval = str->str; - g_string_free (str, FALSE); - return retval; -} - -static void check_signature (MimeInfo *mimeinfo, MimeInfo *partinfo, FILE *fp) -{ -#if 0 /* FIXME */ - GpgmeCtx ctx = NULL; - GpgmeError err; - GpgmeData sig = NULL, text = NULL; - GpgmeSigStat status = GPGME_SIG_STAT_NONE; - 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->length > 0) { - if (fseek(fp, mimeinfo->children->offset + mimeinfo->children->length - 1, - SEEK_SET) < 0) { - perror("fseek"); - goto leave; - } - if (fgetc(fp) == '\n') { - n_exclude_chars++; - if (mimeinfo->children->length > 1) { - if (fseek(fp, mimeinfo->children->offset + mimeinfo->children->length - 2, - SEEK_SET) < 0) { - perror("fseek"); - goto leave; - } - if (fgetc(fp) == '\r') - n_exclude_chars++; - } - } - } - - /* canonicalize the file part. */ - tmp_file = get_tmp_file(); - if (copy_file_part(fp, mimeinfo->children->offset, - mimeinfo->children->length - 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); - - if (!err) - err = gpgme_data_new_from_filepart (&sig, NULL, fp, - partinfo->offset, partinfo->length); - if (err) { - debug_print ("gpgme_data_new_from_filepart failed: %s\n", - gpgme_strerror (err)); - goto leave; - } - - err = gpgme_op_verify (ctx, sig, text, &status); - if (err) { - debug_print ("gpgme_op_verify failed: %s\n", gpgme_strerror (err)); - goto leave; - } - - /* FIXME: check what the heck this sig_status_full stuff is. - * it should better go into sigstatus.c */ - g_free (partinfo->sigstatus_full); - partinfo->sigstatus_full = sig_status_full (ctx); - -leave: - result = gpgmegtk_sig_status_to_string(status); - 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); - partinfo->sig_ok = (status == GPGME_SIG_STAT_GOOD); - partinfo->sig_unknown = (status == GPGME_SIG_STAT_NOKEY); - partinfo->sig_expired = (status == GPGME_SIG_STAT_GOOD_EXP); - partinfo->key_expired = (status == GPGME_SIG_STAT_GOOD_EXPKEY); - - gpgme_data_release (sig); - gpgme_data_release (text); - gpgme_release (ctx); - if (prefs_common.gpg_signature_popup) - gpgmegtk_sig_status_destroy (statuswindow); -#endif -} - /* * Copy a gpgme data object to a temporary file and * return this filename diff --git a/src/sgpgme.c b/src/sgpgme.c index 146e65c8e..b68d3af4e 100644 --- a/src/sgpgme.c +++ b/src/sgpgme.c @@ -148,29 +148,42 @@ gchar *sgpgme_sigstat_info_full(GpgmeCtx ctx, GpgmeSigStat status) while (gpgme_get_sig_key(ctx, i, &key) != GPGME_EOF) { time_t sigtime, expiretime; GpgmeSigStat sigstatus; - gchar time[64]; - const gchar *keytype, *keyid; + gchar timestr[64]; + const gchar *keytype, *keyid, *uid; sigtime = gpgme_get_sig_ulong_attr(ctx, i, GPGME_ATTR_CREATED, 0); - strftime(time, 64, "%c", gmtime(&sigtime)); + strftime(timestr, 64, "%c", gmtime(&sigtime)); keytype = gpgme_key_get_string_attr(key, GPGME_ATTR_ALGO, NULL, 0); keyid = gpgme_key_get_string_attr(key, GPGME_ATTR_KEYID, NULL, 0); g_string_sprintfa(siginfo, _("Signature made %s using %s key ID %s\n"), - time, keytype, keyid); + timestr, keytype, keyid); sigstatus = gpgme_get_sig_ulong_attr(ctx, i, GPGME_ATTR_SIG_STATUS, 0); + uid = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, NULL, 0); switch (sigstatus) { case GPGME_SIG_STAT_GOOD: - case GPGME_SIG_STAT_GOOD_EXP: case GPGME_SIG_STAT_GOOD_EXPKEY: - { - gint j = 1; - const gchar *uid; - g_string_sprintfa(siginfo, _("Good signature from \"%s\"\n"), - gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, NULL, 0)); + uid); + break; + case GPGME_SIG_STAT_GOOD_EXP: + g_string_sprintfa(siginfo, + _("Expired signature from \"%s\"\n"), + uid); + break; + case GPGME_SIG_STAT_BAD: + g_string_sprintfa(siginfo, + _("BAD signature from \"%s\"\n"), + uid); + break; + default: + break; + } + if (sigstatus != GPGME_SIG_STAT_BAD) { + gint j = 1; + while (uid = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, NULL, j)) { g_string_sprintfa(siginfo, _(" aka \"%s\"\n"), @@ -180,23 +193,19 @@ gchar *sgpgme_sigstat_info_full(GpgmeCtx ctx, GpgmeSigStat status) g_string_sprintfa(siginfo, _("Primary key fingerprint: %s\n"), gpgme_key_get_string_attr(key, GPGME_ATTR_FPR, NULL, 0)); - break; - } - case GPGME_SIG_STAT_BAD: - g_string_sprintfa(siginfo, - _("BAD signature from \"%s\"\n"), - gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, NULL, 0)); - break; - default: - break; } + expiretime = gpgme_get_sig_ulong_attr(ctx, i, GPGME_ATTR_EXPIRE, 0); if (expiretime > 0) { - strftime(time, 64, "%c", gmtime(&expiretime)); - g_string_sprintfa(siginfo, - _("Signature expires %s\n"), - time); + const gchar *format; + + strftime(timestr, 64, "%c", gmtime(&expiretime)); + if (time(NULL) < expiretime) + format = _("Signature expires %s\n"); + else + format = _("Signature expired %s\n"); + g_string_sprintfa(siginfo, format, time); } g_string_append(siginfo, "\n");