reverted df0ef2b26196 : 'Attach own key on unencrypted message with encrypt_message() when given enc_format is PEP_enc_none'. Kept code enforcing src->dir != PEP_dir_incoming in encrypt_message, though.
1 #include "pEp_internal.h"
2 #include "message_api.h"
12 #define MIN(A, B) ((B) > (A) ? (A) : (B))
15 #define MAX(A, B) ((B) > (A) ? (B) : (A))
19 static bool string_equality(const char *s1, const char *s2)
21 if (s1 == NULL || s2 == NULL)
26 return strcmp(s1, s2) == 0;
29 static bool is_mime_type(const bloblist_t *bl, const char *mt)
33 return bl && string_equality(bl->mime_type, mt);
36 static bool is_fileending(const bloblist_t *bl, const char *fe)
40 if (bl == NULL || bl->filename == NULL)
43 assert(bl && bl->filename);
45 size_t fe_len = strlen(fe);
46 size_t fn_len = strlen(bl->filename);
51 assert(fn_len > fe_len);
53 return strcmp(bl->filename + (fn_len - fe_len), fe) == 0;
56 static void add_opt_field(message *msg, const char *name, const char *value)
60 if (msg && name && value) {
61 stringpair_t *pair = new_stringpair(name, value);
65 stringpair_list_t *field = stringpair_list_add(msg->opt_fields, pair);
69 if (msg->opt_fields == NULL)
70 msg->opt_fields = field;
74 static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
79 assert(strcmp(shortmsg, "pEp") != 0);
84 ptext = calloc(1, strlen(shortmsg) + strlen(longmsg) + 12);
89 strcpy(ptext, "Subject: ");
90 strcat(ptext, shortmsg);
91 strcat(ptext, "\n\n");
92 strcat(ptext, longmsg);
97 static int seperate_short_and_long(const char *src, char **shortmsg, char **longmsg)
99 char *_shortmsg = NULL;
100 char *_longmsg = NULL;
109 if (strncasecmp(src, "subject: ", 9) == 0) {
110 char *line_end = strchr(src, '\n');
112 if (line_end == NULL) {
113 _shortmsg = strdup(src + 9);
115 if (_shortmsg == NULL)
120 size_t n = line_end - src;
122 if (*(line_end - 1) == '\r')
123 _shortmsg = strndup(src + 9, n - 10);
125 _shortmsg = strndup(src + 9, n - 9);
127 if (_shortmsg == NULL)
130 while (*(src + n) && (*(src + n) == '\n' || *(src + n) == '\r'))
134 _longmsg = strdup(src + n);
136 if (_longmsg == NULL)
142 _shortmsg = strdup("");
144 if (_shortmsg == NULL)
146 _longmsg = strdup(src);
148 if (_longmsg == NULL)
152 *shortmsg = _shortmsg;
164 static PEP_STATUS copy_fields(message *dst, const message *src)
169 free_timestamp(dst->sent);
172 dst->sent = timestamp_dup(src->sent);
173 if (dst->sent == NULL)
174 return PEP_OUT_OF_MEMORY;
177 free_timestamp(dst->recv);
180 dst->recv = timestamp_dup(src->recv);
181 if (dst->recv == NULL)
182 return PEP_OUT_OF_MEMORY;
185 free_identity(dst->from);
188 dst->from = identity_dup(src->from);
189 if (dst->from == NULL)
190 return PEP_OUT_OF_MEMORY;
193 free_identity_list(dst->to);
195 if (src->to && src->to->ident) {
196 dst->to = identity_list_dup(src->to);
198 return PEP_OUT_OF_MEMORY;
201 free_identity(dst->recv_by);
204 dst->recv_by = identity_dup(src->recv_by);
205 if (dst->recv_by == NULL)
206 return PEP_OUT_OF_MEMORY;
209 free_identity_list(dst->cc);
211 if (src->cc && src->cc->ident) {
212 dst->cc = identity_list_dup(src->cc);
214 return PEP_OUT_OF_MEMORY;
217 free_identity_list(dst->bcc);
219 if (src->bcc && src->bcc->ident) {
220 dst->bcc = identity_list_dup(src->bcc);
221 if (dst->bcc == NULL)
222 return PEP_OUT_OF_MEMORY;
225 free_identity_list(dst->reply_to);
226 dst->reply_to = NULL;
227 if (src->reply_to && src->reply_to->ident) {
228 dst->reply_to = identity_list_dup(src->reply_to);
229 if (dst->reply_to == NULL)
230 return PEP_OUT_OF_MEMORY;
233 free_stringlist(dst->in_reply_to);
234 dst->in_reply_to = NULL;
235 if (src->in_reply_to && src->in_reply_to->value) {
236 dst->in_reply_to = stringlist_dup(src->in_reply_to);
237 if (dst->in_reply_to == NULL)
238 return PEP_OUT_OF_MEMORY;
241 free_stringlist(dst->references);
242 dst->references = NULL;
243 if (src->references) {
244 dst->references = stringlist_dup(src->references);
245 if (dst->references == NULL)
246 return PEP_OUT_OF_MEMORY;
249 free_stringlist(dst->keywords);
250 dst->keywords = NULL;
251 if (src->keywords && src->keywords->value) {
252 dst->keywords = stringlist_dup(src->keywords);
253 if (dst->keywords == NULL)
254 return PEP_OUT_OF_MEMORY;
258 dst->comments = NULL;
260 dst->comments = strdup(src->comments);
261 assert(dst->comments);
262 if (dst->comments == NULL)
263 return PEP_OUT_OF_MEMORY;
266 return PEP_STATUS_OK;
269 static message * clone_to_empty_message(const message * src)
272 message * msg = NULL;
276 msg = calloc(1, sizeof(message));
283 status = copy_fields(msg, src);
284 if (status != PEP_STATUS_OK)
294 static PEP_STATUS encrypt_PGP_MIME(
301 PEP_STATUS status = PEP_STATUS_OK;
302 bool free_ptext = false;
306 char *mimetext = NULL;
308 assert(dst->longmsg == NULL);
309 dst->enc_format = PEP_enc_PGP_MIME;
311 if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0) {
312 if (session->unencrypted_subject) {
313 dst->shortmsg = strdup(src->shortmsg);
314 assert(dst->shortmsg);
315 if (dst->shortmsg == NULL)
317 ptext = src->longmsg;
320 ptext = combine_short_and_long(src->shortmsg, src->longmsg);
326 else if (src->longmsg) {
327 ptext = src->longmsg;
333 message *_src = calloc(1, sizeof(message));
337 _src->longmsg = ptext;
338 _src->longmsg_formatted = src->longmsg_formatted;
339 _src->attachments = src->attachments;
340 _src->enc_format = PEP_enc_none;
341 status = mime_encode_message(_src, true, &mimetext);
342 assert(status == PEP_STATUS_OK);
349 if (mimetext == NULL)
352 status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
358 dst->longmsg = strdup("this message was encrypted with p≡p "
359 "https://pEp-project.org");
360 assert(dst->longmsg);
361 if (dst->longmsg == NULL)
364 char *v = strdup("Version: 1");
369 bloblist_t *_a = new_bloblist(v, 11, "application/pgp-encrypted", NULL);
372 dst->attachments = _a;
374 _ctext = malloc(csize);
378 memcpy(_ctext, ctext, csize);
380 _a = bloblist_add(_a, _ctext, csize, "application/octet-stream",
385 return PEP_STATUS_OK;
388 status = PEP_OUT_OF_MEMORY;
397 static PEP_STATUS encrypt_PGP_in_pieces(
404 PEP_STATUS status = PEP_STATUS_OK;
408 bool free_ptext = false;
410 assert(dst->longmsg == NULL);
411 assert(dst->attachments == NULL);
413 dst->enc_format = PEP_enc_pieces;
415 if (src->shortmsg && src->shortmsg[0] && strcmp(src->shortmsg, "pEp") != 0) {
416 if (session->unencrypted_subject) {
417 dst->shortmsg = strdup(src->shortmsg);
418 assert(dst->shortmsg);
419 if (dst->shortmsg == NULL)
421 ptext = src->longmsg;
424 ptext = combine_short_and_long(src->shortmsg, src->longmsg);
430 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
436 dst->longmsg = strndup(ctext, csize);
437 assert(dst->longmsg);
438 if (dst->longmsg == NULL)
445 else if (src->longmsg && src->longmsg[0]) {
446 ptext = src->longmsg;
447 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
450 dst->longmsg = strndup(ctext, csize);
451 assert(dst->longmsg);
452 if (dst->longmsg == NULL)
460 dst->longmsg = strdup("");
461 assert(dst->longmsg);
462 if (dst->longmsg == NULL)
466 if (src->longmsg_formatted && src->longmsg_formatted[0]) {
467 ptext = src->longmsg_formatted;
468 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
471 char *_ctext = malloc(csize);
475 memcpy(_ctext, ctext, csize);
477 bloblist_t *_a = bloblist_add(dst->attachments, _ctext, csize,
478 "application/octet-stream", "PGPexch.htm.pgp");
481 if (dst->attachments == NULL)
482 dst->attachments = _a;
489 if (src->attachments) {
490 if (dst->attachments == NULL) {
491 dst->attachments = new_bloblist(NULL, 0, NULL, NULL);
492 if (dst->attachments == NULL)
496 bloblist_t *_s = src->attachments;
497 bloblist_t *_d = dst->attachments;
499 for (int n = 0; _s && _s->value; _s = _s->next) {
500 size_t psize = _s->size;
502 status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
505 char *filename = NULL;
508 size_t len = strlen(_s->filename);
509 filename = calloc(1, len + 5);
510 if (filename == NULL)
513 strcpy(filename, _s->filename);
514 strcpy(filename + len, ".pgp");
517 filename = calloc(1, 20);
518 if (filename == NULL)
523 snprintf(filename, 20, "Attachment%d.pgp", n);
526 char *_ctext = malloc(csize);
530 memcpy(_ctext, ctext, csize);
532 _d = bloblist_add(_d, _ctext, csize, "application/octet-stream",
543 return PEP_STATUS_OK;
546 status = PEP_OUT_OF_MEMORY;
554 static char * keylist_to_string(const stringlist_t *keylist)
557 size_t size = stringlist_length(keylist);
559 const stringlist_t *_kl;
560 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
561 size += strlen(_kl->value);
564 char *result = calloc(1, size);
569 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
570 _r = stpcpy(_r, _kl->value);
571 if (_kl->next && _kl->next->value)
572 _r = stpcpy(_r, ",");
582 static const char * color_to_string(PEP_color color)
585 case PEP_rating_cannot_decrypt:
586 return "cannot_decrypt";
587 case PEP_rating_have_no_key:
588 return "have_no_key";
589 case PEP_rating_unencrypted:
590 return "unencrypted";
591 case PEP_rating_unencrypted_for_some:
592 return "unencrypted_for_some";
593 case PEP_rating_unreliable:
595 case PEP_rating_reliable:
597 case PEP_rating_trusted:
599 case PEP_rating_trusted_and_anonymized:
600 return "trusted_and_anonymized";
601 case PEP_rating_fully_anonymous:
602 return "fully_anonymous";
603 case PEP_rating_mistrust:
605 case PEP_rating_b0rken:
607 case PEP_rating_under_attack:
608 return "unter_attack";
614 static void decorate_message(
617 stringlist_t *keylist
622 add_opt_field(msg, "X-pEp-Version", "1.0");
624 if (color != PEP_rating_undefined)
625 add_opt_field(msg, "X-EncStatus", color_to_string(color));
628 char *_keylist = keylist_to_string(keylist);
629 add_opt_field(msg, "X-KeyList", _keylist);
634 static PEP_color _rating(PEP_comm_type ct, PEP_color color)
636 if (ct == PEP_ct_unknown)
637 return PEP_rating_undefined;
639 else if (ct == PEP_ct_compromized)
640 return PEP_rating_under_attack;
642 else if (ct == PEP_ct_mistrusted)
643 return PEP_rating_mistrust;
645 if (color == PEP_rating_unencrypted_for_some)
646 return PEP_rating_unencrypted_for_some;
648 if (ct == PEP_ct_no_encryption || ct == PEP_ct_no_encrypted_channel ||
649 ct == PEP_ct_my_key_not_included) {
650 if (color > PEP_rating_unencrypted_for_some)
651 return PEP_rating_unencrypted_for_some;
653 return PEP_rating_unencrypted;
656 if (color == PEP_rating_unencrypted)
657 return PEP_rating_unencrypted_for_some;
659 if (ct >= PEP_ct_confirmed_enc_anon)
660 return PEP_rating_trusted_and_anonymized;
662 else if (ct >= PEP_ct_strong_encryption)
663 return PEP_rating_trusted;
665 else if (ct >= PEP_ct_strong_but_unconfirmed && ct < PEP_ct_confirmed)
666 return PEP_rating_reliable;
669 return PEP_rating_unreliable;
672 static bool is_encrypted_attachment(const bloblist_t *blob)
678 if (blob->filename == NULL)
681 ext = strrchr(blob->filename, '.');
685 if (strcmp(blob->mime_type, "application/octet-stream") == 0) {
686 if (strcmp(ext, ".pgp") == 0 || strcmp(ext, ".gpg") == 0 ||
687 strcmp(ext, ".asc") == 0)
690 else if (strcmp(blob->mime_type, "text/plain") == 0) {
691 if (strcmp(ext, ".asc") == 0)
698 static bool is_encrypted_html_attachment(const bloblist_t *blob)
701 assert(blob->filename);
703 if (strncmp(blob->filename, "PGPexch.htm.", 12) == 0) {
704 if (strcmp(blob->filename + 11, ".pgp") == 0 ||
705 strcmp(blob->filename + 11, ".asc") == 0)
712 static char * without_double_ending(const char *filename)
718 ext = strrchr(filename, '.');
722 char *result = strndup(filename, ext - filename);
727 static PEP_color decrypt_color(PEP_STATUS status)
730 case PEP_UNENCRYPTED:
732 case PEP_VERIFY_NO_KEY:
733 case PEP_VERIFIED_AND_TRUSTED:
734 return PEP_rating_unencrypted;
737 return PEP_rating_unreliable;
739 case PEP_DECRYPTED_AND_VERIFIED:
740 return PEP_rating_reliable;
742 case PEP_DECRYPT_NO_KEY:
743 return PEP_rating_have_no_key;
745 case PEP_DECRYPT_WRONG_FORMAT:
746 case PEP_CANNOT_DECRYPT_UNKNOWN:
747 return PEP_rating_cannot_decrypt;
750 return PEP_rating_undefined;
754 static PEP_color key_color(PEP_SESSION session, const char *fpr)
756 PEP_comm_type comm_type = PEP_ct_unknown;
761 PEP_STATUS status = get_key_rating(session, fpr, &comm_type);
762 if (status != PEP_STATUS_OK)
763 return PEP_rating_undefined;
765 return _rating(comm_type, PEP_rating_undefined);
768 static PEP_color keylist_color(PEP_SESSION session, stringlist_t *keylist)
770 PEP_color color = PEP_rating_reliable;
772 assert(keylist && keylist->value);
773 if (keylist == NULL || keylist->value == NULL)
774 return PEP_rating_undefined;
777 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
781 PEP_color _color = key_color(session, _kl->value);
782 if (_color <= PEP_rating_mistrust)
785 if (color == PEP_rating_undefined)
788 if (_color >= PEP_rating_reliable) {
789 status = least_trust(session, _kl->value, &ct);
790 if (status != PEP_STATUS_OK)
791 return PEP_rating_undefined;
792 if (ct == PEP_ct_unknown)
793 color = PEP_rating_unencrypted_for_some;
795 color = _rating(ct, color);
797 else if (_color == PEP_rating_unencrypted) {
798 if (color > PEP_rating_unencrypted_for_some)
799 color = PEP_rating_unencrypted_for_some;
806 static PEP_comm_type _get_comm_type(
808 PEP_comm_type max_comm_type,
812 PEP_STATUS status = update_identity(session, ident);
814 if (max_comm_type == PEP_ct_compromized)
815 return PEP_ct_compromized;
817 if (max_comm_type == PEP_ct_mistrusted)
818 return PEP_ct_mistrusted;
820 if (status == PEP_STATUS_OK) {
821 if (ident->comm_type == PEP_ct_compromized)
822 return PEP_ct_compromized;
823 else if (ident->comm_type == PEP_ct_mistrusted)
824 return PEP_ct_mistrusted;
826 return MIN(max_comm_type, ident->comm_type);
829 return PEP_ct_unknown;
833 void import_attached_keys(PEP_SESSION session, const message *msg)
839 for (bl = msg->attachments; bl && bl->value; bl = bl->next) {
840 assert(bl && bl->value && bl->size);
842 // workaround for Apple Mail bugs
843 if (is_mime_type(bl, "application/x-apple-msg-attachment")) {
844 if (is_fileending(bl, ".asc")) {
845 if (strlen(bl->filename) == 14 &&
846 bl->filename[0] == '0' && bl->filename[1] == 'x')
847 import_key(session, bl->value, bl->size);
848 else if (strlen(bl->filename) == 12)
849 import_key(session, bl->value, bl->size);
852 else if (bl->mime_type == NULL ||
853 is_mime_type(bl, "application/octet-stream")) {
854 if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
855 is_fileending(bl, ".key") || is_fileending(bl, ".asc"))
856 import_key(session, bl->value, bl->size);
858 else if (is_mime_type(bl, "application/pgp-keys")) {
859 import_key(session, bl->value, bl->size);
861 else if (is_mime_type(bl, "text/plain")) {
862 if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
863 is_fileending(bl, ".key") || is_fileending(bl, ".asc"))
864 import_key(session, bl->value, bl->size);
867 if(msg->from && msg->from->user_id && msg->from->address)
868 update_identity(session, msg->from);
871 void attach_own_key(PEP_SESSION session, message *msg)
880 if (msg->dir == PEP_dir_incoming)
883 assert(msg->from && msg->from->fpr);
884 if (msg->from == NULL || msg->from->fpr == NULL)
887 PEP_STATUS status = export_key(session, msg->from->fpr, &keydata, &size);
888 assert(status == PEP_STATUS_OK);
889 if (status != PEP_STATUS_OK)
893 bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
895 if (msg->attachments == NULL && bl)
896 msg->attachments = bl;
899 PEP_cryptotech determine_encryption_format(message *msg)
903 if (is_PGP_message_text(msg->longmsg)) {
904 msg->enc_format = PEP_enc_pieces;
905 return PEP_crypt_OpenPGP;
907 else if (msg->attachments && msg->attachments->next &&
908 is_mime_type(msg->attachments, "application/pgp-encrypted") &&
909 is_PGP_message_text(msg->attachments->next->value)
911 msg->enc_format = PEP_enc_PGP_MIME;
912 return PEP_crypt_OpenPGP;
915 msg->enc_format = PEP_enc_none;
916 return PEP_crypt_none;
920 DYNAMIC_API PEP_STATUS encrypt_message(
923 stringlist_t * extra,
925 PEP_enc_format enc_format
928 PEP_STATUS status = PEP_STATUS_OK;
929 message * msg = NULL;
930 stringlist_t * keys = NULL;
935 assert(enc_format != PEP_enc_none);
937 if (!(session && src && dst && enc_format != PEP_enc_none))
938 return PEP_ILLEGAL_VALUE;
940 if (src->dir == PEP_dir_incoming)
941 return PEP_ILLEGAL_VALUE;
943 determine_encryption_format(src);
944 if (src->enc_format != PEP_enc_none)
945 return PEP_ILLEGAL_VALUE;
949 status = myself(session, src->from);
950 if (status != PEP_STATUS_OK)
953 keys = new_stringlist(src->from->fpr);
957 stringlist_t *_k = keys;
960 _k = stringlist_append(_k, extra);
965 bool dest_keys_found = true;
966 PEP_comm_type max_comm_type = PEP_ct_pEp;
970 if ((_il = src->bcc) && _il->ident)
972 // BCC limited support:
973 // - App splits mails with BCC in multiple mails.
974 // - Each email is encrypted separately
976 if(_il->next || src->to || src->cc)
978 // Only one Bcc with no other recipient allowed for now
979 return PEP_ILLEGAL_VALUE;
982 PEP_STATUS _status = update_identity(session, _il->ident);
983 if (_status != PEP_STATUS_OK) {
988 if (_il->ident->fpr && _il->ident->fpr[0]) {
989 _k = stringlist_add(_k, _il->ident->fpr);
992 max_comm_type = _get_comm_type(session, max_comm_type,
996 dest_keys_found = false;
997 status = PEP_KEY_NOT_FOUND;
1002 for (_il = src->to; _il && _il->ident; _il = _il->next) {
1003 PEP_STATUS _status = update_identity(session, _il->ident);
1004 if (_status != PEP_STATUS_OK) {
1009 if (_il->ident->fpr && _il->ident->fpr[0]) {
1010 _k = stringlist_add(_k, _il->ident->fpr);
1013 max_comm_type = _get_comm_type(session, max_comm_type,
1017 dest_keys_found = false;
1018 status = PEP_KEY_NOT_FOUND;
1022 for (_il = src->cc; _il && _il->ident; _il = _il->next) {
1023 PEP_STATUS _status = update_identity(session, _il->ident);
1024 if (_status != PEP_STATUS_OK)
1030 if (_il->ident->fpr && _il->ident->fpr[0]) {
1031 _k = stringlist_add(_k, _il->ident->fpr);
1034 max_comm_type = _get_comm_type(session, max_comm_type,
1038 dest_keys_found = false;
1039 status = PEP_KEY_NOT_FOUND;
1044 if (!dest_keys_found ||
1045 stringlist_length(keys) == 0 ||
1046 _rating(max_comm_type,
1047 PEP_rating_undefined) < PEP_rating_reliable)
1049 free_stringlist(keys);
1050 if (!session->passive_mode)
1051 attach_own_key(session, src);
1052 return PEP_UNENCRYPTED;
1055 msg = clone_to_empty_message(src);
1059 attach_own_key(session, src);
1061 switch (enc_format) {
1062 case PEP_enc_PGP_MIME:
1063 case PEP_enc_PEP: // BUG: should be implemented extra
1064 status = encrypt_PGP_MIME(session, src, keys, msg);
1067 case PEP_enc_pieces:
1068 status = encrypt_PGP_in_pieces(session, src, keys, msg);
1071 /* case PEP_enc_PEP:
1077 status = PEP_ILLEGAL_VALUE;
1081 if (status == PEP_OUT_OF_MEMORY)
1084 if (status != PEP_STATUS_OK)
1088 free_stringlist(keys);
1090 if (msg && msg->shortmsg == NULL) {
1091 msg->shortmsg = strdup("pEp");
1092 assert(msg->shortmsg);
1096 decorate_message(msg, PEP_rating_undefined, NULL);
1102 status = PEP_OUT_OF_MEMORY;
1105 free_stringlist(keys);
1111 DYNAMIC_API PEP_STATUS decrypt_message(
1112 PEP_SESSION session,
1115 stringlist_t **keylist,
1119 PEP_STATUS status = PEP_STATUS_OK;
1120 PEP_STATUS decrypt_status = PEP_CANNOT_DECRYPT_UNKNOWN;
1121 message *msg = NULL;
1126 stringlist_t *_keylist = NULL;
1134 if (!(session && src && dst && keylist && color))
1135 return PEP_ILLEGAL_VALUE;
1137 import_attached_keys(session, src);
1138 PEP_cryptotech crypto = determine_encryption_format(src);
1142 *color = PEP_rating_undefined;
1144 switch (src->enc_format) {
1146 *color = PEP_rating_unencrypted;
1147 return PEP_UNENCRYPTED;
1149 case PEP_enc_PGP_MIME:
1150 ctext = src->attachments->next->value;
1151 csize = src->attachments->next->size;
1154 case PEP_enc_pieces:
1155 ctext = src->longmsg;
1156 csize = strlen(ctext);
1162 status = cryptotech[crypto].decrypt_and_verify(session, ctext,
1163 csize, &ptext, &psize, &_keylist);
1164 if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
1167 decrypt_status = status;
1170 switch (src->enc_format) {
1171 case PEP_enc_PGP_MIME:
1172 status = mime_decode_message(ptext, psize, &msg);
1173 if (status != PEP_STATUS_OK)
1177 case PEP_enc_pieces:
1178 msg = clone_to_empty_message(src);
1182 msg->longmsg = strdup(ptext);
1183 assert(msg->longmsg);
1184 if (msg->longmsg == NULL)
1187 bloblist_t *_m = msg->attachments;
1188 if (_m == NULL && src->attachments && src->attachments->value) {
1189 msg->attachments = new_bloblist(NULL, 0, NULL, NULL);
1190 _m = msg->attachments;
1194 for (_s = src->attachments; _s && _s->value; _s = _s->next) {
1195 if (is_encrypted_attachment(_s)) {
1196 stringlist_t *_keylist = NULL;
1200 attctext = _s->value;
1201 attcsize = _s->size;
1203 status = decrypt_and_verify(session, attctext, attcsize,
1204 &ptext, &psize, &_keylist);
1205 free_stringlist(_keylist);
1208 if (is_encrypted_html_attachment(_s)) {
1209 msg->longmsg_formatted = strdup(ptext);
1210 assert(msg->longmsg_formatted);
1211 if (msg->longmsg_formatted == NULL)
1215 char * mime_type = "application/octet-stream";
1217 without_double_ending(_s->filename);
1218 if (filename == NULL)
1221 char *_ptext = malloc(psize);
1225 memcpy(_ptext, ptext, psize);
1227 _m = bloblist_add(_m, _ptext, psize, mime_type,
1232 if (msg->attachments == NULL)
1233 msg->attachments = _m;
1237 char *copy = malloc(_s->size);
1241 memcpy(copy, _s->value, _s->size);
1242 _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
1248 char *copy = malloc(_s->size);
1252 memcpy(copy, _s->value, _s->size);
1253 _m = bloblist_add(_m, copy, _s->size, _s->mime_type, _s->filename);
1262 // BUG: must implement more
1266 switch (src->enc_format) {
1267 case PEP_enc_PGP_MIME:
1268 case PEP_enc_pieces:
1269 status = copy_fields(msg, src);
1270 if (status != PEP_STATUS_OK)
1273 if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0)
1278 int r = seperate_short_and_long(msg->longmsg, &shortmsg,
1283 free(msg->shortmsg);
1286 msg->shortmsg = shortmsg;
1287 msg->longmsg = longmsg;
1290 msg->shortmsg = strdup(src->shortmsg);
1291 assert(msg->shortmsg);
1292 if (msg->shortmsg == NULL)
1298 // BUG: must implement more
1302 import_attached_keys(session, msg);
1304 if(decrypt_status == PEP_DECRYPTED){
1306 // In case message did decrypt, but no valid signature could be found
1307 // then retry decrypt+verify after importing key.
1308 // TODO optimize if import_attached_keys didn't import any key
1310 char *re_ptext = NULL;
1313 free_stringlist(_keylist);
1316 status = cryptotech[crypto].decrypt_and_verify(session, ctext,
1317 csize, &re_ptext, &re_psize, &_keylist);
1322 if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
1325 decrypt_status = status;
1328 *color = decrypt_color(decrypt_status);
1330 if (*color > PEP_rating_mistrust) {
1331 PEP_color kl_color = PEP_rating_undefined;
1334 kl_color = keylist_color(session, _keylist);
1336 if (kl_color <= PEP_rating_mistrust) {
1339 else if (*color >= PEP_rating_reliable &&
1340 kl_color < PEP_rating_reliable) {
1341 *color = PEP_rating_unreliable;
1343 else if (*color >= PEP_rating_reliable &&
1344 kl_color >= PEP_rating_reliable) {
1345 if (!(src->from && src->from->user_id && src->from->user_id[0])) {
1346 *color = PEP_rating_unreliable;
1349 char *fpr = _keylist->value;
1350 pEp_identity *_from = new_identity(src->from->address, fpr,
1351 src->from->user_id, src->from->username);
1354 status = update_identity(session, _from);
1355 if (_from->comm_type != PEP_ct_unknown)
1356 *color = _rating(_from->comm_type, PEP_rating_undefined);
1357 free_identity(_from);
1358 if (status != PEP_STATUS_OK)
1366 decorate_message(msg, *color, _keylist);
1369 *keylist = _keylist;
1371 return PEP_STATUS_OK;
1374 status = PEP_OUT_OF_MEMORY;
1378 free_stringlist(_keylist);
1383 DYNAMIC_API PEP_STATUS outgoing_message_color(
1384 PEP_SESSION session,
1389 PEP_STATUS status = PEP_STATUS_OK;
1390 PEP_comm_type max_comm_type = PEP_ct_pEp;
1391 bool comm_type_determined = false;
1397 assert(msg->dir == PEP_dir_outgoing);
1400 if (!(session && msg && color))
1401 return PEP_ILLEGAL_VALUE;
1403 if (msg->from == NULL || msg->dir != PEP_dir_outgoing)
1404 return PEP_ILLEGAL_VALUE;
1406 *color = PEP_rating_undefined;
1408 status = myself(session, msg->from);
1409 if (status != PEP_STATUS_OK)
1412 for (il = msg->to; il != NULL; il = il->next)
1416 update_identity(session, il->ident);
1417 max_comm_type = _get_comm_type(session, max_comm_type,
1419 comm_type_determined = true;
1423 for (il = msg->cc; il != NULL; il = il->next)
1427 update_identity(session, il->ident);
1428 max_comm_type = _get_comm_type(session, max_comm_type,
1430 comm_type_determined = true;
1434 for (il = msg->bcc; il != NULL; il = il->next)
1438 update_identity(session, il->ident);
1439 max_comm_type = _get_comm_type(session, max_comm_type,
1441 comm_type_determined = true;
1445 if (comm_type_determined == false)
1446 *color = PEP_rating_undefined;
1448 *color = MAX(_rating(max_comm_type, PEP_rating_undefined),
1449 PEP_rating_unencrypted);
1451 return PEP_STATUS_OK;
1454 DYNAMIC_API PEP_STATUS identity_color(
1455 PEP_SESSION session,
1456 pEp_identity *ident,
1460 PEP_STATUS status = PEP_STATUS_OK;
1466 if (!(session && ident && color))
1467 return PEP_ILLEGAL_VALUE;
1470 status = myself(session, ident);
1472 status = update_identity(session, ident);
1474 if (status == PEP_STATUS_OK)
1475 *color = _rating(ident->comm_type, PEP_rating_undefined);
1480 DYNAMIC_API PEP_STATUS get_binary_path(PEP_cryptotech tech, const char **path)
1482 PEP_STATUS status = PEP_STATUS_OK;
1486 return PEP_ILLEGAL_VALUE;
1488 if (cryptotech[tech].binary_path == NULL)
1491 status = cryptotech[tech].binary_path(path);