merge "default" into "ENGINE-320" and solved one merge conflict. :-)
1.1 --- a/.hgignore Fri Dec 15 15:05:41 2017 +0100
1.2 +++ b/.hgignore Mon Jan 15 17:07:05 2018 +0100
1.3 @@ -57,3 +57,7 @@
1.4 secring.gpg
1.5 trustdb.gpg
1.6 .pEp_management.db
1.7 +.cache
1.8 +__pycache__
1.9 +*.pyc
1.10 +test/python_tests/test?
2.1 --- a/.hgtags Fri Dec 15 15:05:41 2017 +0100
2.2 +++ b/.hgtags Mon Jan 15 17:07:05 2018 +0100
2.3 @@ -4,3 +4,4 @@
2.4 a1ba15c1ac041c780e52e759db6b77d116f29c72 0.8.0
2.5 3efe9ded2561d3f6d406acbcbcee01b823cb4de8 for_Outlook-1.1.10
2.6 fa00137505b8528c77efe8df40963f5fef452cad 0.9.0 release
2.7 +b70a6082836b89f8718b23dcba0624d6db318033 ENGINE-323 fixed
3.1 --- a/build-android/jni/Android.mk Fri Dec 15 15:05:41 2017 +0100
3.2 +++ b/build-android/jni/Android.mk Mon Jan 15 17:07:05 2018 +0100
3.3 @@ -29,13 +29,13 @@
3.4 #
3.5 LOCAL_CFLAGS += -DSQLITE_TEMP_STORE=3
3.6
3.7 -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../src \
3.8 - $(LOCAL_PATH)/../../asn.1 \
3.9 +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../asn.1 \
3.10 $(GPGME_INCLUDE_PATH) \
3.11 $(LIBETPAN_PATH)/include
3.12 LOCAL_C_INCLUDES += $(GPGBUILD)/include
3.13
3.14 -LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/../../src
3.15 +$(shell sh $(LOCAL_PATH)/../takeOutHeaderFiles.sh $(LOCAL_PATH)../../)
3.16 +LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)../include
3.17
3.18 ENGINE_SRC_FILES := $(shell find $(LOCAL_PATH)/../../src/ ! -name "*netpgp*" -name "*.c")
3.19 #ENGINE_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../src/*.c)
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/build-android/takeOutHeaderFiles.sh Mon Jan 15 17:07:05 2018 +0100
4.3 @@ -0,0 +1,9 @@
4.4 +#!/bin/sh
4.5 +
4.6 +set -e
4.7 +engine_dir="$1"
4.8 +
4.9 +mkdir -p "$engine_dir/build-android/include/pEp"
4.10 +cd "$engine_dir/src"
4.11 +cp *.h "$engine_dir/build-android/include/pEp"
4.12 +
5.1 --- a/src/Makefile Fri Dec 15 15:05:41 2017 +0100
5.2 +++ b/src/Makefile Mon Jan 15 17:07:05 2018 +0100
5.3 @@ -80,6 +80,7 @@
5.4 .PHONY: clean
5.5 clean:
5.6 rm -f *.d *.o *.a $(TARGET) *.dll *.so *.zip *.d.* *.def *~
5.7 + rm -Rf $(TARGET).dSYM
5.8
5.9 .PHONY: install
5.10 install: $(TARGET)
6.1 --- a/src/message_api.c Fri Dec 15 15:05:41 2017 +0100
6.2 +++ b/src/message_api.c Mon Jan 15 17:07:05 2018 +0100
6.3 @@ -29,7 +29,8 @@
6.4 return false;
6.5 }
6.6
6.7 -static bool is_wrapper(message* src) {
6.8 +static bool is_wrapper(message* src)
6.9 +{
6.10 bool retval = false;
6.11
6.12 if (src) {
6.13 @@ -62,20 +63,23 @@
6.14 }
6.15
6.16
6.17 -static stringpair_t* search_optfields(const message* msg, const char* key) {
6.18 - stringpair_list_t* opt_fields = msg->opt_fields;
6.19 -
6.20 - const stringpair_list_t* curr;
6.21 -
6.22 - for (curr = opt_fields; curr && curr->value; curr = curr->next) {
6.23 - if (curr->value->key) {
6.24 - if (strcasecmp(curr->value->key, key) == 0)
6.25 - return curr->value;
6.26 - }
6.27 - }
6.28 -
6.29 - return NULL;
6.30 -}
6.31 +/*
6.32 + * static stringpair_t* search_optfields(const message* msg, const char* key) {
6.33 + * if (msg && key) {
6.34 + * stringpair_list_t* opt_fields = msg->opt_fields;
6.35 + *
6.36 + * const stringpair_list_t* curr;
6.37 + *
6.38 + * for (curr = opt_fields; curr && curr->value; curr = curr->next) {
6.39 + * if (curr->value->key) {
6.40 + * if (strcasecmp(curr->value->key, key) == 0)
6.41 + * return curr->value;
6.42 + * }
6.43 + * }
6.44 + * }
6.45 + * return NULL;
6.46 + * }
6.47 + */
6.48
6.49 static char * keylist_to_string(const stringlist_t *keylist)
6.50 {
6.51 @@ -1415,15 +1419,15 @@
6.52 assert(session);
6.53 assert(src);
6.54 assert(dst);
6.55 - assert(enc_format != PEP_enc_none);
6.56 -
6.57 - if (!(session && src && dst && enc_format != PEP_enc_none))
6.58 +
6.59 + if (!(session && src && dst))
6.60 return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
6.61
6.62 if (src->dir == PEP_dir_incoming)
6.63 return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
6.64
6.65 determine_encryption_format(src);
6.66 + // TODO: change this for multi-encryption in message format 2.0
6.67 if (src->enc_format != PEP_enc_none)
6.68 return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
6.69
6.70 @@ -1450,7 +1454,7 @@
6.71
6.72 identity_list * _il;
6.73
6.74 - if ((_il = src->bcc) && _il->ident)
6.75 + if (enc_format != PEP_enc_none && (_il = src->bcc) && _il->ident)
6.76 {
6.77 // BCC limited support:
6.78 // - App splits mails with BCC in multiple mails.
6.79 @@ -1524,7 +1528,7 @@
6.80 }
6.81 }
6.82
6.83 - if (!dest_keys_found ||
6.84 + if (enc_format == PEP_enc_none || !dest_keys_found ||
6.85 stringlist_length(keys) == 0 ||
6.86 _rating(max_comm_type,
6.87 PEP_rating_undefined) < PEP_rating_reliable)
6.88 @@ -2194,7 +2198,7 @@
6.89 char* ptext,
6.90 size_t psize) {
6.91
6.92 - PEP_STATUS status = PEP_UNKNOWN_ERROR;
6.93 + PEP_STATUS status = PEP_STATUS_OK;
6.94
6.95 *msg_ptr = clone_to_empty_message(src);
6.96
6.97 @@ -2552,9 +2556,7 @@
6.98 now we need to update the message rating with the
6.99 sender and recipients in mind */
6.100 status = amend_rating_according_to_sender_and_recipients(session,
6.101 - rating,
6.102 - src->from,
6.103 - _keylist);
6.104 + rating, src->from, _keylist);
6.105
6.106 if (status != PEP_STATUS_OK)
6.107 GOTO(pep_error);
6.108 @@ -3191,10 +3193,7 @@
6.109 GOTO(pep_error);
6.110 }
6.111
6.112 - // Clear the encryption status, or mime_encode will ignore
6.113 - // the plaintext and do all sorts of other stupid things
6.114 - enc_msg->enc_format = PEP_enc_none;
6.115 - status = mime_encode_message(enc_msg, false, mime_ciphertext);
6.116 + status = _mime_encode_message_internal(enc_msg, false, mime_ciphertext, false);
6.117
6.118 pep_error:
6.119 free_message(tmp_msg);
6.120 @@ -3380,10 +3379,8 @@
6.121 if (status != PEP_STATUS_OK)
6.122 GOTO(pep_error);
6.123
6.124 - status = amend_rating_according_to_sender_and_recipients(session,
6.125 - &_rating,
6.126 - msg->from,
6.127 - _keylist);
6.128 + status = amend_rating_according_to_sender_and_recipients(session, &_rating,
6.129 + msg->from, _keylist);
6.130 if (status == PEP_STATUS_OK)
6.131 *rating = _rating;
6.132
7.1 --- a/src/message_api.h Fri Dec 15 15:05:41 2017 +0100
7.2 +++ b/src/message_api.h Mon Jan 15 17:07:05 2018 +0100
7.3 @@ -49,7 +49,8 @@
7.4 // session (in) session handle
7.5 // src (in) message to encrypt
7.6 // extra (in) extra keys for encryption
7.7 -// dst (out) pointer to new encrypted message or NULL on failure
7.8 +// dst (out) pointer to new encrypted message or NULL if no
7.9 +// encryption could take place
7.10 // enc_format (in) encrypted format
7.11 // flags (in) flags to set special encryption features
7.12 //
7.13 @@ -60,9 +61,9 @@
7.14 // PEP_KEY_HAS_AMBIG_NAME at least one of the receipient keys has
7.15 // an ambiguous name
7.16 // PEP_GET_KEY_FAILED cannot retrieve key
7.17 -// PEP_UNENCRYPTED no recipients with usable key,
7.18 -// message is left unencrypted,
7.19 -// and key is attached to it
7.20 +// PEP_UNENCRYPTED on demand or no recipients with usable
7.21 +// key, is left unencrypted, and key is
7.22 +// attached to it
7.23 //
7.24 // caveat:
7.25 // the ownershop of src remains with the caller
8.1 --- a/src/mime.c Fri Dec 15 15:05:41 2017 +0100
8.2 +++ b/src/mime.c Mon Jan 15 17:07:05 2018 +0100
8.3 @@ -97,6 +97,20 @@
8.4 return status;
8.5 }
8.6
8.7 +static bool known_ascii_type(const char* mime_type) {
8.8 + const char* text_types[] = {"application/pgp-keys",
8.9 + "application/pgp-encrypted"};
8.10 + const int TEXT_TYPE_ARRAY_SIZE = sizeof(text_types)/sizeof(text_types[0]);
8.11 +
8.12 + int i;
8.13 +
8.14 + for (i = 0; i < TEXT_TYPE_ARRAY_SIZE; i++) {
8.15 + if (strcmp(text_types[i], mime_type) == 0)
8.16 + return true;
8.17 + }
8.18 + return false;
8.19 +}
8.20 +
8.21
8.22 static PEP_STATUS mime_attachment(
8.23 bloblist_t *blob,
8.24 @@ -122,7 +136,9 @@
8.25 mime_type = blob->mime_type;
8.26
8.27 pEp_rid_list_t* resource = parse_uri(blob->filename);
8.28 - mime = get_file_part(resource, mime_type, blob->value_ref, blob->size, transport_encode);
8.29 + bool already_ascii = known_ascii_type(mime_type);
8.30 + mime = get_file_part(resource, mime_type, blob->value_ref, blob->size,
8.31 + (already_ascii ? false : transport_encode));
8.32 free_rid_list(resource);
8.33
8.34 assert(mime);
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/src/pEp_string.c Mon Jan 15 17:07:05 2018 +0100
9.3 @@ -0,0 +1,52 @@
9.4 +// This file is under GNU General Public License 3.0
9.5 +// see LICENSE.txt
9.6 +
9.7 +#include "pEp_string.h"
9.8 +
9.9 +#include <stdlib.h>
9.10 +#include <assert.h>
9.11 +
9.12 +DYNAMIC_API char * new_string(const char *src, size_t len)
9.13 +{
9.14 + assert(src || len);
9.15 + if (!(src || len))
9.16 + return NULL;
9.17 +
9.18 + char *s = NULL;
9.19 + if (src) {
9.20 + if (len)
9.21 + s = strndup(src, len);
9.22 + else
9.23 + s = strdup(src);
9.24 + assert(s);
9.25 + }
9.26 + else {
9.27 + s = calloc(1, len);
9.28 + assert(s);
9.29 + }
9.30 +
9.31 + return s;
9.32 +}
9.33 +
9.34 +
9.35 +DYNAMIC_API void free_string(char *s)
9.36 +{
9.37 + free(s);
9.38 +}
9.39 +
9.40 +DYNAMIC_API char * string_dup(const char *src, size_t len)
9.41 +{
9.42 + assert(src);
9.43 + if (!src)
9.44 + return NULL;
9.45 +
9.46 + char *s = NULL;
9.47 + if (len)
9.48 + s = strndup(src, len);
9.49 + else
9.50 + s = strdup(src);
9.51 + assert(s);
9.52 +
9.53 + return s;
9.54 +}
9.55 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/src/pEp_string.h Mon Jan 15 17:07:05 2018 +0100
10.3 @@ -0,0 +1,56 @@
10.4 +// This file is under GNU General Public License 3.0
10.5 +// see LICENSE.txt
10.6 +
10.7 +#pragma once
10.8 +
10.9 +#include <string.h>
10.10 +#include "dynamic_api.h"
10.11 +
10.12 +#ifdef __cplusplus
10.13 +extern "C" {
10.14 +#endif
10.15 +
10.16 +
10.17 +// new_string() - allocate a new string
10.18 +//
10.19 +// parameters:
10.20 +// src (in) string to copy or NULL
10.21 +// len (in) length of newly created string or 0 for default
10.22 +//
10.23 +// return value:
10.24 +// pointer to string object or NULL if out of memory
10.25 +//
10.26 +// caveat:
10.27 +// one of the two parameters has to be set at least
10.28 +//
10.29 +// calling with str and len is equivalent to strndup()
10.30 +// calling with str but len=0 is equivalent to strdup()
10.31 +// calling with str=NULL and len is equivalent to calloc()
10.32 +
10.33 +DYNAMIC_API char * new_string(const char *src, size_t len);
10.34 +
10.35 +
10.36 +// free_string() - free memory occupied by string
10.37 +//
10.38 +// parameters:
10.39 +// s (in) pointer to string to free
10.40 +
10.41 +DYNAMIC_API void free_string(char *s);
10.42 +
10.43 +
10.44 +// string_dup() - duplicate a string
10.45 +//
10.46 +// parameters:
10.47 +// src (in) string to duplicate
10.48 +// len (in) length of newly created string or 0 for default
10.49 +//
10.50 +// return value:
10.51 +// pointer to copy or NULL if out of memory
10.52 +
10.53 +DYNAMIC_API char * string_dup(const char *src, size_t len);
10.54 +
10.55 +
10.56 +#ifdef __cplusplus
10.57 +}
10.58 +#endif
10.59 +
11.1 --- a/test/message_api_test.cc Fri Dec 15 15:05:41 2017 +0100
11.2 +++ b/test/message_api_test.cc Mon Jan 15 17:07:05 2018 +0100
11.3 @@ -12,8 +12,160 @@
11.4
11.5 using namespace std;
11.6
11.7 +void test_MIME_decrypt_message()
11.8 +{
11.9 + static const std::string private_key =
11.10 + "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
11.11 + "\n"
11.12 + "lQOmBFpCxkEBCCC8ugYsWOsv966JOl5Ahdw6YiobbU9peFLV8aMBOG+oNIPs3BQj\n"
11.13 + "u3FUugkVqA5In93oqVgNZ2LU6Y/RWldN+Pc4IMf6qSZnTBj/1ffBjuqAow1hPEYV\n"
11.14 + "354LNYoQtJXioY0X8FjRgt+NoBPphRbo+XJ0uIQckJey6uvvtukEZkMLM1ur1aID\n"
11.15 + "9biJZ7yXtJM7KxN5792Vo2gGp/1hlFW6SfM7E0g60L5DT8C/BsYeKtMmxKNZngo6\n"
11.16 + "ZBxLDAcxMcT5UpRW79B34pTINZAEsvLeT7TLajzqP/OggUrFkkwLr3KJk09aFF+6\n"
11.17 + "TN6CI2fDdSqdoPVEgNrZE9zFqAgVWOdhLOHRpXgt7wARAQABAAgZATpqsN4xRaIk\n"
11.18 + "giMdmujkGoMqB/ypoCOW0mqcp3ThESSqWR/Dh8n//k+poHj0Atf7fzie6JNsKruM\n"
11.19 + "Yo3mdIzyuuxHsONp6xEtNnkDgEB4WTb2btQQFrNaWXNTPzGVqiBoBShcw5xI7SiG\n"
11.20 + "CKaDlCePbaAHyBHO0uzBdVFo6czqkceXSJ+hNDY7xbURbkgIA5SGJ+8cssmcKKoc\n"
11.21 + "LDY34S3Pu0gG3+K6gSedYaHAqVVQn8dmEitvDFQ96sTNIpPiMp5Tc+/8UXziF91f\n"
11.22 + "XRrXYX9o3nkCvz01qtjR4LQVDztysm3/VmDcsjqhzALiiBLigyglpE5DEp0+wMUq\n"
11.23 + "gw5TpWZ63lf6XjEEEM+c+D3HHsEnh24+DNU2OyfFZGpp9olSaTDcXtEBuBTt/Uhy\n"
11.24 + "NnqF4MswQ2me4Lfr4D4sUS5jtsKkee+2IQuwtg/bBVYsL6MfV2llJco2vrOCb6y8\n"
11.25 + "u9CnQhRbVBd6kBMiJeE50Ijk3jP78GrkPm3rGWKCWRuXVr07+U2MsEnvSkkBfpEE\n"
11.26 + "EOi2NcXCCJux9xZv0xOyWogXDVLVrrhs8/PGjJO1IeaMtmrzleo3azUbWus/BYLA\n"
11.27 + "vJkO+PElg/MCc2ub5hFs7IqSbLmteWFiSOzTcdHNWeqETsixAc8dpbq0zhkPwdzA\n"
11.28 + "otLEBS3mpaB29Bpt9lzgewHoVI/o/OvUFFaP+b1Fd4wOJH8EELZPWw+85tSB1l63\n"
11.29 + "4B+77YoBc9wDBFg7Pt4Eo0eghFZ/159YTA1bcr3fZ8bYIgiHHNLC/Fsx+sUu00PC\n"
11.30 + "ctLrOxGRbuDyNy2rsezf8Bz8xpihBPuBmSbKoaZguSazgpuC1LPkVbQQVaN1h+Ir\n"
11.31 + "9/tJufw+hT9Eggvx5xtCo7GD1trnx0xLKbQhVGVzdCBUb25pIDxlbmdpbmUtMzIy\n"
11.32 + "QHBlcHRlc3QuY2g+iQE8BBMBCAAiBQJaQsZBAhsDBgsJCAcDAgYVCAIJCgsEFgID\n"
11.33 + "AQIeAQIXgAAKCRCvYy6fx5m31NWeCCCXgm1J7Pq4ECKaMZcp7WoWguXQW+Ellgrx\n"
11.34 + "B6EjZmvy1iB0RYaDz6F0HCXd0WtC2YDlkxJ47rKBHsnmcyHbFNlY0fgc5Uhs7apI\n"
11.35 + "bBMHHRGwl8pie05DqxQ0jBxO2esk/IPJDhLXw7gZvaY/9PUS669QWoq+L/Hhph8V\n"
11.36 + "5v65jnw2937bOaf6wvEUUj2cg6cUaPTZSXv26vxUrT8RD+DxbQiNjJIeGRfVj3QY\n"
11.37 + "9GCTcp45ZaB8kLQEVayFrC3Jougcklk5DS1zlFCHiYLa4cco/68XHL7/CFdIxxsK\n"
11.38 + "Rd/3FYWX6zfQZJs5U6KmGy18cXvk0OOtTru9aNHR0YiLj4Vs8K+mWA10vZ0DpgRa\n"
11.39 + "QsZBAQggwrnOsiJ3JNB+mTm9pZbX4mUkw7OXrar1CvOVDqrnI+H+Z9/DC1FDEupw\n"
11.40 + "8mD3fFV4veO6smjb9wWAXhmU88OxXziChM8WJlWz2GrZPoM2DIYu1gLycp7wo1Md\n"
11.41 + "mzhd/5tpBWMJ4gGS9AjvQc5ffk7JVBAnmhh4ZtdoEctHMJs7+1RhXE7KUM1QWjew\n"
11.42 + "2GAVAaw+KsuXvqsF8soXvlFaHe9sTHKXKUD/MN4WWPR3SIvC4yoadlUpCMfooXf8\n"
11.43 + "ZCFLbVirkqGy5AakF7thlaTq7bxEX5BQbP/DjVuTTd311jk4x7oT+1bT7D6iIoES\n"
11.44 + "DKfYijw+059CrCbjFUn3/RRg5sx/55FA2XEAEQEAAQAIHiu228SYwSeGGM2cLUt1\n"
11.45 + "vBxKeYDnmeb2aJFfUnia/E3NZ7f4/0fUo9qkv9th0l1asMLsU1bG/I6NcR5u3sYE\n"
11.46 + "iham0IIxHTdY6QluHzwN573TB8OqoLQDo2D/ATf95PhDcsWvUKIomU1ojhG3Wy+3\n"
11.47 + "TzIseD97O9hWhjnsaRxr1QDclghnNffz589T40wAQAkdQlfDuBABberGNR0DsCZq\n"
11.48 + "w1xx1+EaEt8o7sXfRMFKoBLJzya0toJNIBGdXCXVPFPtYx6RAiD1KoufgXwVCBaL\n"
11.49 + "CHc8QvurgyMBghc9pBcdGs60fNhWn1U4qeWzPOHO95ZWVFObBiuGqkX25revf1Dg\n"
11.50 + "RTY5OsBTBBDdnMElWA+l6ctlSX8vNUQBin7aPbHu1HrmUxH9EiKwUd6jdoFmssw7\n"
11.51 + "soohAfYJCsuTQLHPI+9W6okF4rjlvl0aS2cN4HSbLjTwdNiUgIHVKJPDq8WDgCsV\n"
11.52 + "bR09wsLkohmoX/qZFEQMKdr7A2ar64zQzpx6ZFB0kS71Fr6+rFUAIzePBBDg8QXr\n"
11.53 + "J/R6iZYnMNv/mzyNunbM3B7siwbILS1kLeS6lTYeaKORa7JFRc776rkWV//P1Soc\n"
11.54 + "nW2byeBxNxOmdNXlNsA6Gg8O4rn3rxEgBZlsOYUG1ZcPZZu8kNFkLTYP+mgFIP3I\n"
11.55 + "izn858IbnNFm0HjRMGiS+zip2r/rgbniIhLQ2l7/BBCL+2x0+Ww5I/el6A7k+y2X\n"
11.56 + "3xazBVOQfpPl9BgMdsuO0BBlN5RpbTfE8TVpWneeamAuRJh7ArApbAS508Thw7Sj\n"
11.57 + "8iLKXj5yScAEC2WO9ZsHqJ/RN3VyhCCI0u3Y75wB3qfcroZUlwvQb/WfH8/vHr2O\n"
11.58 + "E72YoprbNOmRFZ7LZkRX56URRn2JASMEGAEIAAkFAlpCxkECGwwACgkQr2Mun8eZ\n"
11.59 + "t9RozQggkb/Lb08g4w99CcXq6hV28D5bOHjiEx4XNdkeLVExhfk1zgQ9lf4rjyb2\n"
11.60 + "ox+e3Dc5S590NoYg/35vd/QWPsg1JiCvAu296lzOLtIiTAI1KGUJdbsLxRIduOU7\n"
11.61 + "6n/KVxRG4w4kJqpbu+UzBY7KtDbWzapJx8v0sdsTOVxg7kFxvYtra5TRaPfce4EX\n"
11.62 + "ox2V2HPhtFNSILH8Jqh/R0PV5RRbNFHZA4cKXkBJMw3BcpbpXeLCXiD6P3FNVSKh\n"
11.63 + "Rkd3JY0XJhwbvGPCRWkobtxkieZe0bCmKu8+gw0Zqm2QNA7J6iMT4rMZWH9k7lpp\n"
11.64 + "okyt7GheXlwKEtVQSAcH/NalK9Q+ckaQttA=\n"
11.65 + "=KACn\n"
11.66 + "-----END PGP PRIVATE KEY BLOCK-----\n"
11.67 + "\n";
11.68 +
11.69 + static const std::string mimetext =
11.70 + "To: denden@peptest.ch\r\n"
11.71 + "From: Lars Rohwedder <roker@pep-project.org>\r\n"
11.72 + "Subject: Test for ENGINE-322\r\n"
11.73 + "Message-ID: <4b2d328c-b284-e359-1c2c-fe136358b8a6@pep-project.org>\r\n"
11.74 + "Date: Thu, 28 Dec 2017 22:00:47 +0100\r\n"
11.75 + "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0)\r\n"
11.76 + " Gecko/20100101 Thunderbird/52.5.0\r\n"
11.77 + "MIME-Version: 1.0\r\n"
11.78 + "Content-Type: text/plain; charset=utf-8\r\n"
11.79 + "Content-Language: en-US\r\n"
11.80 + "Content-Transfer-Encoding: 8bit\r\n"
11.81 + "\r\n"
11.82 + "-----BEGIN PGP MESSAGE-----\r\n"
11.83 + "Charset: utf-8\r\n"
11.84 + "\r\n"
11.85 + "hQEQA30SSxlFRbxRAQgggvPrko4vJ988ylqdGF7/Jtw/61VddHg7rjOTG7yZiq2J\r\n"
11.86 + "p0lXb0N9Bz8SON/m4NWWS5ij0Bj1wMdTgLowLxMz0PfCIyyiQIfqEBAXUcAOQh2f\r\n"
11.87 + "Pg2iZbynrQ1T4M/D0BlIn2bfXb790Cni+o1OmWTCx4wC6AKtGvlonLAIsH1hUfs+\r\n"
11.88 + "yKOyCCNaNSmyAPeF3F5v7iEO5Eez1R/UrtxcYj2QmCdVt5v0AuAlm5HVPJgj7wCd\r\n"
11.89 + "MeRmK4a1+sM51CcCf6Tk9uZbIVrr/XkyGVPmmHTK8E4QmvmL6PGeuIitwqKe80/L\r\n"
11.90 + "XH4ZYPXIxVU9o5HoSo3YJ3BSKLQzCoDRCD8JlCo08K6mrpuFAgwD42RJLbKIaR4B\r\n"
11.91 + "EADNgisKiIku4SrBmBkryyKMYmOTW0QKnY/wfNselpzuj5cMpKA4e60x/wEQRIvC\r\n"
11.92 + "m1ZO7LjhbVjNf6ws2FgytnTRf+8R/R8mp6/XIDeUvaBvUku5yoRjTeznFRwpj6yT\r\n"
11.93 + "WfQMlLojI2fe+y5fHKIIjTpW5HOQQv7sZ4UzE+jRpRErRVq4UI49l7yTBnG0j75w\r\n"
11.94 + "UZTt05OnJMQrCCiD7Fu9xDw5If3x884GehKpFGm6XqZ8V7NhwGk6mf62rZEouBQh\r\n"
11.95 + "AhTu/irkz30PpWY3gGj2YF0PIaQmweb9u2izox1kTfq2xRfPLg/4cOgBKy1/Xeea\r\n"
11.96 + "IVeaACAcoNdJaYuZCSe9CMbr5s7kusE22/6fB0L1itGr09EzhwGJS/+XSt0IwcJw\r\n"
11.97 + "7XDUGtmYXuTy08wUKU9McxXJ8nlUkXF9ZcswVxHKG36ZRfzx5eBPjzSnDo8EZHs2\r\n"
11.98 + "wr7wnS8s8J+AvB7kZYFChAct4KH9OwT3/2pSdhd8/sSCkj2zGtrB+8h2QkIE4csD\r\n"
11.99 + "rIHtBp4oWCJq1XOKYPvdGqWBxZ/7086kksB99Eyn+sy5C0iNTbEdUN4JkIYq1C0n\r\n"
11.100 + "DExbr+dqip65DEJRj7TPfwTJ5D28djPYutanSRfJS/niPqztWu0R1ISucw1TMdGU\r\n"
11.101 + "NcqsqQLPYzTV6xTq+bgBsi8DO4tXkcOpf7eDEP+5kDOncNLpAZGc9NUnVa/jpkYO\r\n"
11.102 + "XE+CNJ5SYQPdsGcir9JNXNTDgKAGSTI7OAU/ZxOcMCsmctJATcAZERFgvUy8YZN1\r\n"
11.103 + "3X4Ii6osc8u6shJrjL/detZs8LH8wSe6NYQdtipQo4ySAYQAO9tXdoRrfktXrYus\r\n"
11.104 + "eLh86toD19D5R9RxHnVEMQP5CdNWgvX7X4ngK94kJq18QCDa1bZXhHBKmWOnAtyL\r\n"
11.105 + "zpcUNnCWo2gml6GX2kyuL+5Ji6afwKHZg+iag8wBDLGQ+hoOMnzk1iP4DFeQ7iZN\r\n"
11.106 + "Qvd4mWWASd2BCnf9ulKiMw1wdzN2mpYRNo+nRHx0Zu50VUyj0xMm8VSyUZis5+YH\r\n"
11.107 + "I3Se7UEeS6ppLsiGcyaJDCMp/38xt5SU5NY4wAAubc6MJclECcvSkM1W/20wQ4di\r\n"
11.108 + "z5FhKHlqZaPTXN02h0P78wKDDwJr7fFvqtB8G2LgtwbXAkOUvn8vbomQLHBkQ+GH\r\n"
11.109 + "AuXqBGxKrIwyIEjLZf6hDz++0fDa/ACeFynpxNl1ehmvCl5CsEMcCiM+Ic2pZ/ML\r\n"
11.110 + "+Hle0GWEKej4WBzXi0j4pzR4WZFt9XCv5+yYAg+UHKc2Kn0Q+bC1AZYxhQDicTP9\r\n"
11.111 + "qNKTLBHRAeJoQ1y4vHXYGwRGH+penfJiKsQsyOOeoQlZar8tvRYR77K8FhxBtnYK\r\n"
11.112 + "Xrv+rb1BT/2Ey7P4jb8PiZpbic7ACu1MjFdmlPKrExe5+MY+Pr9ms+hxJrdBH736\r\n"
11.113 + "K6dojmWUQKpJRzue2lWsfESLxIVeB+vmbg2zU3PflCmMIsRNh2US7vZj2WdgqSqz\r\n"
11.114 + "wR2eTG4MgPVy4iiGOVT2JWS5t+KXm3kwUZTy9Twi6P1ebNm/B8KQwlutssdWip2q\r\n"
11.115 + "hON1aFYa4L601zrHgow592PdBkRPQZGiXNHffCvHgsxBHsj4G4JWZhmIkEK/cIWl\r\n"
11.116 + "RanlZdQG6UPHkoUomh7hauUUgcYe4FWt4NBKdiba36Y=\r\n"
11.117 + "=1lFj\r\n"
11.118 + "-----END PGP MESSAGE-----\r\n"
11.119 + "\r\n";
11.120 +
11.121 + PEP_SESSION session;
11.122 + PEP_STATUS status1 = init(&session);
11.123 + assert(status1 == PEP_STATUS_OK);
11.124 + assert(session);
11.125 +
11.126 + // import secret key
11.127 + identity_list* pk = NULL;
11.128 + status1 = import_key( session, private_key.c_str(), private_key.size(), &pk );
11.129 + assert(status1 == PEP_STATUS_OK);
11.130 + std::cout << "Imported " << identity_list_length(pk) << " private key(s)." << endl;
11.131 +
11.132 + char* plaintext = nullptr;
11.133 + stringlist_t* keys_used = nullptr;
11.134 + PEP_rating rating;
11.135 + PEP_decrypt_flags_t dec_flags;
11.136 +
11.137 + PEP_STATUS status2 = MIME_decrypt_message(session, mimetext.c_str(), mimetext.length(),
11.138 + &plaintext, &keys_used, &rating, &dec_flags);
11.139 +
11.140 + std::cout << "MIME_decrypt_message returned " << std::dec << status2 << std::hex << " (0x" << status2 << ")" << std::dec << endl;
11.141 +
11.142 + assert(status2 == PEP_DECRYPTED);
11.143 + assert(plaintext);
11.144 +
11.145 + pEp_free(plaintext);
11.146 +
11.147 + identity_list* il = pk;
11.148 + while(il)
11.149 + {
11.150 + std::cout << "Delete test key \"" << il->ident->fpr << "\"" << endl;
11.151 + delete_keypair( session, il->ident->fpr );
11.152 + il = il->next;
11.153 + }
11.154 + free_identity_list(pk);
11.155 +}
11.156 +
11.157 +
11.158 int main() {
11.159 cout << "\n*** message_api_test ***\n\n";
11.160 + test_MIME_decrypt_message();
11.161
11.162 PEP_SESSION session;
11.163
11.164 @@ -169,14 +321,35 @@
11.165
11.166 cout << dec_msg << endl;
11.167
11.168 + cout << "\nTesting encrypt_message() with enc_format = PEP_enc_none\n\n";
11.169 +
11.170 + message *msg7 = new_message(PEP_dir_outgoing);
11.171 + pEp_identity * me7 = new_identity("pep.test.alice@pep-project.org", NULL, PEP_OWN_USERID, "Alice Test");
11.172 + identity_list *to7 = new_identity_list(new_identity("pep.test.bob@pep-project.org", NULL, "42", "Bob Test"));
11.173 + msg7->from = me7;
11.174 + msg7->to = to7;
11.175 + msg7->shortmsg = strdup("My Subject");
11.176 + msg7->longmsg = strdup("This is some text.\n");
11.177 +
11.178 + message *enc7 = nullptr;
11.179 + PEP_STATUS status9 = encrypt_message(session, msg7, NULL, &enc7, PEP_enc_none, 0);
11.180 + std::cout << "encrypt_message returned " << std::dec << status9 << std::hex << " (0x" << status9 << ")" << std::dec << endl;
11.181 + assert(status9 == PEP_UNENCRYPTED);
11.182 + assert(enc7 == nullptr);
11.183 + assert(msg7->shortmsg && msg7->longmsg);
11.184 + cout << msg7->shortmsg << "\n";
11.185 + cout << msg7->longmsg << "\n";
11.186 + assert(strcmp(msg7->shortmsg, "My Subject") == 0);
11.187 + assert(strcmp(msg7->longmsg, "This is some text.\n") == 0);
11.188
11.189 - cout << "freeing messages…\n";
11.190 + cout << "\nfreeing messages…\n";
11.191 + free_message(msg7);
11.192 + free_message(msg6);
11.193 + free_message(msg5);
11.194 free_message(msg4);
11.195 free_message(msg3);
11.196 free_message(msg2);
11.197 free_message(enc_msg2);
11.198 - free_message(msg6);
11.199 - free_message(msg5);
11.200 cout << "done.\n";
11.201
11.202 free(enc_msg);
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/test/python_tests/README.md Mon Jan 15 17:07:05 2018 +0100
12.3 @@ -0,0 +1,16 @@
12.4 +# Usage
12.5 +
12.6 +To execute these tests, install p≡p Python adapter from
12.7 +<https://letsencrypt.pep.foundation/dev/repos/pEpPythonAdapter/>
12.8 +
12.9 +These tests are meant to be run using py.test <https://pytest.org> and
12.10 +pytest-xdist <https://pypi.python.org/pypi/pytest-xdist>
12.11 +
12.12 +You can run setup_test.py before running the tests if the initial setup is
12.13 +failing.
12.14 +
12.15 +To remove all generated files run setup_test.py -r
12.16 +
12.17 +# License
12.18 +
12.19 +All documentation is under CC BY-SA 3.0.
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/test/python_tests/conftest.py Mon Jan 15 17:07:05 2018 +0100
13.3 @@ -0,0 +1,14 @@
13.4 +# -*- coding: utf-8 -*-
13.5 +
13.6 +# this file is under GNU General Public License 3.0
13.7 +# Copyleft 2017, p≡p foundation
13.8 +
13.9 +
13.10 +from setup_test import create_homes
13.11 +
13.12 +
13.13 +def pytest_runtest_setup(item):
13.14 + try:
13.15 + create_homes()
13.16 + except FileExistsError: # if concurrent process is already creating things
13.17 + pass
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/test/python_tests/pytest.ini Mon Jan 15 17:07:05 2018 +0100
14.3 @@ -0,0 +1,10 @@
14.4 +# --boxed run each test in an own process
14.5 +# -v verbose output
14.6 +# -n 2 two parallel tasks
14.7 +
14.8 +# this file is under GNU General Public License 3.0
14.9 +# Copyleft 2017, p≡p foundation
14.10 +
14.11 +[pytest]
14.12 +addopts = --boxed -v -n 2 test_handshake.py
14.13 +
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/test/python_tests/setup_test.py Mon Jan 15 17:07:05 2018 +0100
15.3 @@ -0,0 +1,126 @@
15.4 +#!/usr/bin/env python3
15.5 +# -*- coding: utf-8 -*-
15.6 +
15.7 +# this file is under GNU General Public License 3.0
15.8 +# Copyleft 2017, p≡p foundation
15.9 +
15.10 +#import vimpdb; vimpdb.set_trace()
15.11 +
15.12 +
15.13 +"""
15.14 +This script is setting up the test environment by creating two home directories
15.15 +for simulation of message exchange between two p≡p parties.
15.16 +
15.17 +The directories are created in the current directory.
15.18 +"""
15.19 +
15.20 +
15.21 +import os
15.22 +import shutil
15.23 +from multiprocessing import Process
15.24 +from time import sleep
15.25 +
15.26 +
15.27 +realhome = os.path.expanduser("~")
15.28 +mydir = os.path.abspath(os.path.curdir)
15.29 +
15.30 +
15.31 +def link_if_exists(dirname, arthome):
15.32 + "link directory from home to artificial home"
15.33 +
15.34 + orig = os.path.join(realhome, dirname)
15.35 + if os.path.exists(orig):
15.36 + if not os.path.exists(dirname):
15.37 + os.symlink(orig, dirname, True)
15.38 +
15.39 +
15.40 +def create_own_identities(mydir, arthome, username):
15.41 + "create own identities as part of the test setup"
15.42 +
15.43 + os.environ["HOME"] = os.path.join(mydir, arthome)
15.44 + os.environ["GNUPGHOME"] = os.path.join(mydir, arthome, '.gnupg')
15.45 +
15.46 + import pEp
15.47 + me = pEp.Identity()
15.48 + me.address = arthome + "@peptest.ch"
15.49 + me.username = username
15.50 +
15.51 + pEp.myself(me)
15.52 + print(repr(me))
15.53 +
15.54 +
15.55 +def link_file(filename):
15.56 + "sym-link file to version in parent directory"
15.57 +
15.58 + src = os.path.join(os.pardir, filename)
15.59 + if not os.path.exists(filename):
15.60 + os.symlink(src, filename, False)
15.61 +
15.62 +
15.63 +def create_home(mydir, arthome, username):
15.64 + "create an artificial home directory for testing"
15.65 +
15.66 + os.chdir(mydir)
15.67 + os.makedirs(arthome, exist_ok=True)
15.68 +
15.69 + os.chdir(arthome)
15.70 +
15.71 + link_if_exists("bin", arthome)
15.72 + link_if_exists("include", arthome)
15.73 + link_if_exists("lib", arthome)
15.74 + link_if_exists("share", arthome)
15.75 + link_if_exists(".local", arthome)
15.76 + link_if_exists("Library", arthome) # this may exist on macOS
15.77 +
15.78 + p = Process(target=create_own_identities, args=(mydir, arthome, username))
15.79 + p.start()
15.80 + p.join()
15.81 +
15.82 + with open(".ready", "w"): pass
15.83 +
15.84 +
15.85 +def create_homes():
15.86 + "create two artificial home directories for the two parties"
15.87 +
15.88 + try:
15.89 + os.stat("test1")
15.90 + except FileNotFoundError:
15.91 + create_home(mydir, "test1", "Alice One")
15.92 + create_home(mydir, "test2", "Bob Two")
15.93 + os.chdir(mydir);
15.94 + os.makedirs("common", exist_ok=True) # common inbox for Sync tests
15.95 + else:
15.96 + while True:
15.97 + try:
15.98 + os.stat("test2/.ready")
15.99 + except:
15.100 + sleep(1)
15.101 + else:
15.102 + break
15.103 +
15.104 +
15.105 +def remove_homes():
15.106 + """remove formerly created artificial home directories including their
15.107 + contents"""
15.108 +
15.109 + os.chdir(mydir)
15.110 + shutil.rmtree("test1", ignore_errors=True)
15.111 + shutil.rmtree("test2", ignore_errors=True)
15.112 + shutil.rmtree("common", ignore_errors=True)
15.113 + shutil.rmtree("__pycache__", ignore_errors=True)
15.114 +
15.115 +
15.116 +if __name__ == "__main__":
15.117 + import argparse
15.118 +
15.119 + parser = argparse.ArgumentParser(description=__doc__)
15.120 + parser.add_argument('-r', '--remove', action="store_true",
15.121 + help=remove_homes.__doc__)
15.122 +
15.123 + args = parser.parse_args()
15.124 +
15.125 + if args.remove:
15.126 + remove_homes()
15.127 + else:
15.128 + create_homes()
15.129 +
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/test/python_tests/test_handshake.py Mon Jan 15 17:07:05 2018 +0100
16.3 @@ -0,0 +1,127 @@
16.4 +# -*- coding: utf-8 -*-
16.5 +
16.6 +# this file is under GNU General Public License 3.0
16.7 +# Copyleft 2017, p≡p foundation
16.8 +
16.9 +
16.10 +from transport import *
16.11 +
16.12 +
16.13 +def setup_gnupg():
16.14 + assert os.environ["GNUPGHOME"] != ""
16.15 +
16.16 +
16.17 +mydir = os.path.dirname(os.path.realpath(__file__))
16.18 +
16.19 +
16.20 +class Test1:
16.21 +
16.22 + def setup_method(self):
16.23 + arthome = "test1"
16.24 +
16.25 + os.environ["HOME"] = os.path.join(mydir, arthome)
16.26 + os.environ["GNUPGHOME"] = os.path.join(mydir, arthome, '.gnupg')
16.27 +
16.28 + os.chdir(os.path.join(mydir, arthome))
16.29 +
16.30 + @property
16.31 + def me(self):
16.32 + # because of flaws of py.test these two statements are necessary
16.33 + setup_gnupg() # work around a bug with initializing os.environ
16.34 + import pEp # after that import pEp module, not before
16.35 +
16.36 + i = pEp.Identity()
16.37 + i.address = "test1@peptest.ch"
16.38 + i.username = "Alice One"
16.39 + i.myself()
16.40 + return i
16.41 +
16.42 + @property
16.43 + def you(self):
16.44 + setup_gnupg() ; import pEp
16.45 +
16.46 + i = pEp.Identity()
16.47 + i.address = "test2@peptest.ch"
16.48 + i.username = "Bob Two"
16.49 + i.update()
16.50 + return i
16.51 +
16.52 + def test_handshake(self):
16.53 + setup_gnupg() ; import pEp
16.54 +
16.55 + msg = pEp.Message(1)
16.56 + msg.from_ = self.me
16.57 + msg.to = [self.you]
16.58 + msg.shortmsg = "Subject line"
16.59 + msg.longmsg = "Message Text\n"
16.60 +
16.61 + enc = msg.encrypt()
16.62 + send_message("test2", str(enc))
16.63 +
16.64 + txt = wait_for_message()
16.65 + enc = pEp.Message(txt)
16.66 + assert enc.from_.address == "test2@peptest.ch"
16.67 + inc, keys, rating, consumed, flags = enc.decrypt()
16.68 + assert rating == 6
16.69 +
16.70 + msg = pEp.Message(1)
16.71 + msg.from_ = self.me
16.72 + msg.to = [self.you]
16.73 + msg.shortmsg = "Subject line complete"
16.74 + msg.longmsg = "Message Text complete\n"
16.75 +
16.76 + enc = msg.encrypt()
16.77 + send_message("test2", str(enc))
16.78 +
16.79 +class Test2:
16.80 +
16.81 + def setup_method(self):
16.82 + arthome = "test2"
16.83 +
16.84 + os.environ["HOME"] = os.path.join(mydir, arthome)
16.85 + os.environ["GNUPGHOME"] = os.path.join(mydir, arthome, '.gnupg')
16.86 +
16.87 + os.chdir(os.path.join(mydir, arthome))
16.88 +
16.89 + @property
16.90 + def me(self):
16.91 + setup_gnupg() ; import pEp
16.92 +
16.93 + i = pEp.Identity()
16.94 + i.address = "test2@peptest.ch"
16.95 + i.username = "Bob Two"
16.96 + i.myself()
16.97 + return i
16.98 +
16.99 + @property
16.100 + def you(self):
16.101 + setup_gnupg() ; import pEp
16.102 +
16.103 + i = pEp.Identity()
16.104 + i.address = "test1@peptest.ch"
16.105 + i.username = "Alice One"
16.106 + i.update()
16.107 + return i
16.108 +
16.109 + def test_handshake(self):
16.110 + setup_gnupg() ; import pEp
16.111 +
16.112 + txt = wait_for_message()
16.113 + msg = pEp.Message(txt)
16.114 + msg.decrypt()
16.115 + assert msg.from_.address == self.you.address
16.116 +
16.117 + out = pEp.Message(1)
16.118 + out.from_ = self.me
16.119 + out.to = [self.you]
16.120 + out.shortmsg = "Subject Back"
16.121 + out.longmsg = "Text Back\n"
16.122 +
16.123 + enc = out.encrypt()
16.124 + send_message("test1", str(enc))
16.125 +
16.126 + txt = wait_for_message()
16.127 + msg = pEp.Message(txt)
16.128 + msg.decrypt()
16.129 + assert msg.from_.address == self.you.address
16.130 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/test/python_tests/transport.py Mon Jan 15 17:07:05 2018 +0100
17.3 @@ -0,0 +1,70 @@
17.4 +# -*- coding: utf-8 -*-
17.5 +
17.6 +# this file is under GNU General Public License 3.0
17.7 +# Copyleft 2017, p≡p foundation
17.8 +
17.9 +
17.10 +"""
17.11 +This module is implementing a basic message transport. Messages are written
17.12 +into the artificial home of the receiver and deleted when read.
17.13 +"""
17.14 +
17.15 +
17.16 +import os
17.17 +import time
17.18 +from glob import glob
17.19 +
17.20 +
17.21 +timeout = 5
17.22 +
17.23 +
17.24 +def send_message(to, msg):
17.25 + "send message by creating a file in recipient's artificial home"
17.26 +
17.27 + recipient_dir = os.path.join(os.pardir, to)
17.28 + filename = '{:024x}'.format(int(time.monotonic() * 10000000000)) + \
17.29 + os.extsep + "eml"
17.30 + dotpath = os.path.join(recipient_dir, "." + filename)
17.31 + path = os.path.join(recipient_dir, filename)
17.32 +
17.33 + with open(dotpath, "w") as file:
17.34 + file.write(msg)
17.35 +
17.36 + os.rename(dotpath, path)
17.37 +
17.38 +
17.39 +def recv_message(inbox=None):
17.40 + """receive message by returning the first .eml files content in artificial
17.41 + home"""
17.42 +
17.43 + if inbox:
17.44 + filename = glob(os.path.join(os.pardir, inbox, "*.eml"))[0]
17.45 + else:
17.46 + filename = glob("*.eml")[0]
17.47 +
17.48 + with open(filename, "r") as file:
17.49 + msg = file.read()
17.50 +
17.51 + os.remove(filename)
17.52 +
17.53 + return msg
17.54 +
17.55 +
17.56 +def wait_for_message():
17.57 + "wait until a message arrives and return the message"
17.58 +
17.59 + found = False
17.60 + for i in range(timeout):
17.61 + try:
17.62 + msg = recv_message()
17.63 + except IndexError:
17.64 + time.sleep(1)
17.65 + else:
17.66 + found = True
17.67 + break
17.68 +
17.69 + if not found:
17.70 + raise RuntimeError("timeout")
17.71 +
17.72 + return msg
17.73 +