merging
authorVolker Birk <vb@pep-project.org>
Sat, 04 Jun 2016 17:33:52 +0200
changeset 7121719c03def17
parent 711 d88dea0f5448
parent 710 9dd174f288d4
child 713 599d073e49e7
merging
build-mac/README.md
db/dic2csv.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/README-OSX.md	Sat Jun 04 17:33:52 2016 +0200
     1.3 @@ -0,0 +1,27 @@
     1.4 +# Dependencies
     1.5 +
     1.6 +You need a working [asn1c](https://lionet.info/asn1c/blog/).
     1.7 +
     1.8 +```
     1.9 +brew install asn1c
    1.10 +```
    1.11 +
    1.12 +# Building for OS X
    1.13 +
    1.14 +## Build libetpan
    1.15 +
    1.16 +```
    1.17 +cd pEpEngine
    1.18 +autoreconf -vfi
    1.19 +./configure
    1.20 +make
    1.21 +make install
    1.22 +```
    1.23 +
    1.24 +# Building for iOS
    1.25 +
    1.26 +This is done with Xcode. Simply add `pEpEngine.xcodeproj` to
    1.27 +your project and add a dependency to the target `pEpEngine`
    1.28 +(in `Target Dependencies` in your `Build Phases`.
    1.29 +
    1.30 +Usually you just integrate `pEpiOSAdapter.xcodeproj`.
     2.1 --- a/README.txt	Thu Jun 02 13:46:38 2016 +0200
     2.2 +++ b/README.txt	Sat Jun 04 17:33:52 2016 +0200
     2.3 @@ -43,13 +43,23 @@
     2.4  
     2.5  p≡p engine is depending on the following FOSS libraries:
     2.6  
     2.7 -libetpan, see https://github.com/fdik/libetpan
     2.8 -zlib, see http://zlib.net/
     2.9 -OpenSSL, see http://openssl.org/
    2.10 -iconv, see http://www.gnu.org/software/libiconv/
    2.11 -Cyrus SASL, see http://cyrusimap.org/
    2.12 -GnuPG via GPGME, see https://gnupg.org/
    2.13 -NetPGP/p≡p, see https://cacert.pep.foundation/dev/repos/netpgp-et/
    2.14 +* libetpan, see https://github.com/fdik/libetpan
    2.15 +       git clone https://github.com/fdik/libetpan
    2.16 +
    2.17 +* zlib, see http://zlib.net/
    2.18 +
    2.19 +* OpenSSL, see http://openssl.org/
    2.20 +
    2.21 +* iconv, see http://www.gnu.org/software/libiconv/
    2.22 +
    2.23 +* Cyrus SASL, see http://cyrusimap.org/
    2.24 +
    2.25 +* GnuPG via GPGME, see https://gnupg.org/
    2.26 +
    2.27 +* NetPGP/p≡p, see https://cacert.pep.foundation/dev/repos/netpgp-et/
    2.28 +
    2.29 +* Asn1c, download from https://lionet.info/soft/asn1c-0.9.27.tar.gz
    2.30 +       (Debian's version 0.9.24 does not work)
    2.31  
    2.32  
    2.33  2. Building p≡p engine
     3.1 --- a/build-mac/README.md	Thu Jun 02 13:46:38 2016 +0200
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,15 +0,0 @@
     3.4 -# Building for iOS
     3.5 -
     3.6 -This is done with Xcode. Simply add `pEpEngine.xcodeproj` to
     3.7 -your project and add a dependency to the target `pEpEngine`
     3.8 -(in `Target Dependencies` in your `Build Phases`.
     3.9 -
    3.10 -Usually you just integrate `pEpiOSAdapter.xcodeproj`.
    3.11 -
    3.12 -## Dependencies
    3.13 -
    3.14 -You need a working [asn1c](https://lionet.info/asn1c/blog/).
    3.15 -
    3.16 -```
    3.17 -brew install asn1c
    3.18 -```
     4.1 --- a/src/cryptotech.h	Thu Jun 02 13:46:38 2016 +0200
     4.2 +++ b/src/cryptotech.h	Sat Jun 04 17:33:52 2016 +0200
     4.3 @@ -61,7 +61,7 @@
     4.4          const char *reason);
     4.5  
     4.6  typedef PEP_STATUS (*key_expired_t)(PEP_SESSION session, const char *fpr,
     4.7 -        bool *expired);
     4.8 +        const time_t when, bool *expired);
     4.9  
    4.10  typedef PEP_STATUS (*key_revoked_t)(PEP_SESSION session, const char *fpr,
    4.11                                      bool *revoked);
     5.1 --- a/src/keymanagement.c	Thu Jun 02 13:46:38 2016 +0200
     5.2 +++ b/src/keymanagement.c	Sat Jun 04 17:33:52 2016 +0200
     5.3 @@ -367,12 +367,25 @@
     5.4              free_stringlist(keylist);
     5.5          }
     5.6      }
     5.7 +
     5.8 +    bool revoked = false;
     5.9 +    char *r_fpr = NULL;
    5.10 +    if (!EMPTYSTR(identity->fpr))
    5.11 +    {
    5.12 +        status = key_revoked(session, identity->fpr, &revoked);
    5.13 +        assert(status == PEP_STATUS_OK);
    5.14 +        if (status != PEP_STATUS_OK) {
    5.15 +            return status;
    5.16 +        }
    5.17 +    }
    5.18      
    5.19 -    // TODO : Check key for revoked state
    5.20 -    
    5.21 -    if (EMPTYSTR(identity->fpr) /* or revoked */)
    5.22 -    {
    5.23 -        stringlist_t *keylist = NULL;
    5.24 +    if (EMPTYSTR(identity->fpr) || revoked)
    5.25 +    {        
    5.26 +        if(revoked)
    5.27 +        {
    5.28 +            r_fpr = identity->fpr;
    5.29 +            identity->fpr = NULL;
    5.30 +        }
    5.31          
    5.32          DEBUG_LOG("generating key pair", "debug", identity->address);
    5.33          status = generate_keypair(session, identity);
    5.34 @@ -381,26 +394,28 @@
    5.35              char buf[11];
    5.36              snprintf(buf, 11, "%d", status);
    5.37              DEBUG_LOG("generating key pair failed", "debug", buf);
    5.38 +            if(revoked && r_fpr)
    5.39 +                free(r_fpr);
    5.40              return status;
    5.41          }
    5.42          
    5.43 -        status = find_keys(session, identity->address, &keylist);
    5.44 -        assert(status != PEP_OUT_OF_MEMORY);
    5.45 -        if (status == PEP_OUT_OF_MEMORY)
    5.46 -            return PEP_OUT_OF_MEMORY;
    5.47 -        
    5.48 -        assert(keylist && keylist->value);
    5.49 -        if (keylist == NULL) {
    5.50 -            return PEP_UNKNOWN_ERROR;
    5.51 -        }else if (keylist->value == NULL) {
    5.52 -            free_stringlist(keylist);
    5.53 -            return PEP_UNKNOWN_ERROR;
    5.54 +        if(revoked)
    5.55 +        {
    5.56 +            status = set_revoked(session, r_fpr,
    5.57 +                                 identity->fpr, time(NULL));
    5.58 +            free(r_fpr);
    5.59 +            if (status != PEP_STATUS_OK) {
    5.60 +                return status;
    5.61 +            }
    5.62          }
    5.63      }
    5.64      else
    5.65      {
    5.66          bool expired;
    5.67 -        status = key_expired(session, identity->fpr, &expired);
    5.68 +        status = key_expired(session, identity->fpr, 
    5.69 +                             time(NULL) + (7*24*3600), // In a week
    5.70 +                             &expired);
    5.71 +
    5.72          assert(status == PEP_STATUS_OK);
    5.73          if (status != PEP_STATUS_OK) {
    5.74              return status;
    5.75 @@ -502,8 +517,14 @@
    5.76          return PEP_ILLEGAL_VALUE;
    5.77  
    5.78      if (ident->me)
    5.79 +    {
    5.80          revoke_key(session, ident->fpr, NULL);
    5.81 -    status = mark_as_compromized(session, ident->fpr);
    5.82 +        myself(session, ident);
    5.83 +    }
    5.84 +    else
    5.85 +    {
    5.86 +        status = mark_as_compromized(session, ident->fpr);
    5.87 +    }
    5.88  
    5.89      return status;
    5.90  }
     6.1 --- a/src/message_api.c	Thu Jun 02 13:46:38 2016 +0200
     6.2 +++ b/src/message_api.c	Sat Jun 04 17:33:52 2016 +0200
     6.3 @@ -863,12 +863,32 @@
     6.4          update_identity(session, msg->from);
     6.5  }
     6.6  
     6.7 -void attach_own_key(PEP_SESSION session, message *msg)
     6.8 +
     6.9 +PEP_STATUS _attach_key(PEP_SESSION session, const char* fpr, message *msg)
    6.10  {
    6.11      char *keydata;
    6.12      size_t size;
    6.13      bloblist_t *bl;
    6.14  
    6.15 +    PEP_STATUS status = export_key(session, fpr, &keydata, &size);
    6.16 +    assert(status == PEP_STATUS_OK);
    6.17 +    if (status != PEP_STATUS_OK)
    6.18 +        return status;
    6.19 +    assert(size);
    6.20 +    
    6.21 +    bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
    6.22 +                      "pEpkey.asc");
    6.23 +    
    6.24 +    if (msg->attachments == NULL && bl)
    6.25 +        msg->attachments = bl;
    6.26 +
    6.27 +    return PEP_STATUS_OK;
    6.28 +}
    6.29 +
    6.30 +#define ONE_WEEK (7*24*3600)
    6.31 +
    6.32 +void attach_own_key(PEP_SESSION session, message *msg)
    6.33 +{
    6.34      assert(session);
    6.35      assert(msg);
    6.36  
    6.37 @@ -879,16 +899,24 @@
    6.38      if (msg->from == NULL || msg->from->fpr == NULL)
    6.39          return;
    6.40  
    6.41 -    PEP_STATUS status = export_key(session, msg->from->fpr, &keydata, &size);
    6.42 -    assert(status == PEP_STATUS_OK);
    6.43 -    if (status != PEP_STATUS_OK)
    6.44 +    if(_attach_key(session, msg->from->fpr, msg) != PEP_STATUS_OK)
    6.45          return;
    6.46 -    assert(size);
    6.47 -
    6.48 -    bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
    6.49 -            "pEpkey.asc");
    6.50 -    if (msg->attachments == NULL && bl)
    6.51 -        msg->attachments = bl;
    6.52 +    
    6.53 +    char *revoked_fpr = NULL;
    6.54 +    uint64_t revocation_date = 0;
    6.55 +    
    6.56 +    if(get_revoked(session, msg->from->fpr,
    6.57 +                   &revoked_fpr, &revocation_date) == PEP_STATUS_OK &&
    6.58 +       revoked_fpr != NULL)
    6.59 +    {
    6.60 +        time_t now = time(NULL);
    6.61 +        
    6.62 +        if (now < (time_t)revocation_date + ONE_WEEK)
    6.63 +        {
    6.64 +            _attach_key(session, revoked_fpr, msg);
    6.65 +        }
    6.66 +    }
    6.67 +    free(revoked_fpr);
    6.68  }
    6.69  
    6.70  PEP_cryptotech determine_encryption_format(message *msg)
     7.1 --- a/src/pEpEngine.c	Thu Jun 02 13:46:38 2016 +0200
     7.2 +++ b/src/pEpEngine.c	Sat Jun 04 17:33:52 2016 +0200
     7.3 @@ -34,9 +34,14 @@
     7.4      static const char *sql_own_key_is_listed;
     7.5      static const char *sql_own_key_retrieve;
     7.6  
     7.7 +    // Sequence
     7.8      static const char *sql_sequence_value1;
     7.9      static const char *sql_sequence_value2;
    7.10  
    7.11 +    // Revocation tracking
    7.12 +    static const char *sql_set_revoked;
    7.13 +    static const char *sql_get_revoked;
    7.14 +    
    7.15      bool in_first = false;
    7.16  
    7.17      assert(sqlite3_threadsafe());
    7.18 @@ -177,6 +182,13 @@
    7.19                  "   name text primary key,\n"
    7.20                  "   value integer default 0\n"
    7.21                  ");\n"
    7.22 +                "create table if not exists revoked_keys (\n"
    7.23 +                "   revoked_fpr text primary key,\n"
    7.24 +                "   replacement_fpr text not null\n"
    7.25 +                "       references pgp_keypair (fpr)\n"
    7.26 +                "       on delete cascade,\n"
    7.27 +                "   revocation_date integer\n"
    7.28 +                ");\n"
    7.29                  ,
    7.30              NULL,
    7.31              NULL,
    7.32 @@ -275,6 +287,15 @@
    7.33                                "(select coalesce((select value + 1 from sequences "
    7.34                                "where name = ?1), 1 ))) ; ";
    7.35          sql_sequence_value2 = "select value from sequences where name = ?1 ;";
    7.36 +        
    7.37 +        sql_set_revoked =     "insert or replace into revoked_keys ("
    7.38 +                              "    revoked_fpr, replacement_fpr, revocation_date) "
    7.39 +                              "values (upper(replace(?1,' ','')),"
    7.40 +                              "        upper(replace(?2,' ','')),"
    7.41 +                              "        ?3) ;";
    7.42 +        
    7.43 +        sql_get_revoked =     "select revoked_fpr, revocation_date from revoked_keys"
    7.44 +                              "    where replacement_fpr = upper(replace(?1,' ','')) ;";
    7.45      }
    7.46  
    7.47      int_result = sqlite3_prepare_v2(_session->db, sql_log, (int)strlen(sql_log),
    7.48 @@ -367,6 +388,16 @@
    7.49              (int)strlen(sql_sequence_value2), &_session->sequence_value2, NULL);
    7.50      assert(int_result == SQLITE_OK);
    7.51  
    7.52 +    // Revocation tracking
    7.53 +    
    7.54 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
    7.55 +                                    (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
    7.56 +    assert(int_result == SQLITE_OK);
    7.57 +    
    7.58 +    int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
    7.59 +                                    (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
    7.60 +    assert(int_result == SQLITE_OK);
    7.61 +    
    7.62      status = init_cryptotech(_session, in_first);
    7.63      if (status != PEP_STATUS_OK)
    7.64          goto pep_error;
    7.65 @@ -552,7 +583,7 @@
    7.66          if (*word)
    7.67              *wsize = sqlite3_column_bytes(session->trustword, 1);
    7.68          else
    7.69 -            status = PEP_TRUSTWORD_NOT_FOUND;
    7.70 +            status = PEP_OUT_OF_MEMORY;
    7.71      } else
    7.72          status = PEP_TRUSTWORD_NOT_FOUND;
    7.73  
    7.74 @@ -1174,6 +1205,7 @@
    7.75  DYNAMIC_API PEP_STATUS key_expired(
    7.76          PEP_SESSION session,
    7.77          const char *fpr,
    7.78 +        const time_t when,
    7.79          bool *expired
    7.80      )
    7.81  {
    7.82 @@ -1185,7 +1217,24 @@
    7.83          return PEP_ILLEGAL_VALUE;
    7.84  
    7.85      return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
    7.86 -            expired);
    7.87 +            when, expired);
    7.88 +}
    7.89 +
    7.90 +DYNAMIC_API PEP_STATUS key_revoked(
    7.91 +                                   PEP_SESSION session,
    7.92 +                                   const char *fpr,
    7.93 +                                   bool *revoked
    7.94 +                                   )
    7.95 +{
    7.96 +    assert(session);
    7.97 +    assert(fpr);
    7.98 +    assert(revoked);
    7.99 +    
   7.100 +    if (!(session && fpr && revoked))
   7.101 +        return PEP_ILLEGAL_VALUE;
   7.102 +    
   7.103 +    return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
   7.104 +                                                              revoked);
   7.105  }
   7.106  
   7.107  static void _clean_log_value(char *text)
   7.108 @@ -1473,6 +1522,95 @@
   7.109      return status;
   7.110  }
   7.111  
   7.112 +DYNAMIC_API PEP_STATUS set_revoked(
   7.113 +       PEP_SESSION session,
   7.114 +       const char *revoked_fpr,
   7.115 +       const char *replacement_fpr,
   7.116 +       const uint64_t revocation_date
   7.117 +    )
   7.118 +{
   7.119 +    PEP_STATUS status = PEP_STATUS_OK;
   7.120 +    
   7.121 +    assert(session &&
   7.122 +           revoked_fpr && revoked_fpr[0] &&
   7.123 +           replacement_fpr && replacement_fpr[0]
   7.124 +          );
   7.125 +    
   7.126 +    if (!(session &&
   7.127 +          revoked_fpr && revoked_fpr[0] &&
   7.128 +          replacement_fpr && replacement_fpr[0]
   7.129 +         ))
   7.130 +        return PEP_ILLEGAL_VALUE;
   7.131 +    
   7.132 +    sqlite3_reset(session->set_revoked);
   7.133 +    sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
   7.134 +    sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1, SQLITE_STATIC);
   7.135 +    sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
   7.136 +
   7.137 +    int result;
   7.138 +    
   7.139 +    result = sqlite3_step(session->set_revoked);
   7.140 +    switch (result) {
   7.141 +        case SQLITE_DONE:
   7.142 +            status = PEP_STATUS_OK;
   7.143 +            break;
   7.144 +            
   7.145 +        default:
   7.146 +            status = PEP_UNKNOWN_ERROR;
   7.147 +    }
   7.148 +    
   7.149 +    sqlite3_reset(session->set_revoked);
   7.150 +    return status;
   7.151 +}
   7.152 +
   7.153 +DYNAMIC_API PEP_STATUS get_revoked(
   7.154 +        PEP_SESSION session,
   7.155 +        const char *fpr,
   7.156 +        char **revoked_fpr,
   7.157 +        uint64_t *revocation_date
   7.158 +    )
   7.159 +{
   7.160 +    PEP_STATUS status = PEP_STATUS_OK;
   7.161 +
   7.162 +    assert(session &&
   7.163 +           revoked_fpr &&
   7.164 +           fpr && fpr[0]
   7.165 +          );
   7.166 +    
   7.167 +    if (!(session &&
   7.168 +           revoked_fpr &&
   7.169 +           fpr && fpr[0]
   7.170 +          ))
   7.171 +        return PEP_ILLEGAL_VALUE;
   7.172 +
   7.173 +    *revoked_fpr = NULL;
   7.174 +    *revocation_date = 0;
   7.175 +
   7.176 +    sqlite3_reset(session->get_revoked);
   7.177 +    sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
   7.178 +
   7.179 +    int result;
   7.180 +    
   7.181 +    result = sqlite3_step(session->get_revoked);
   7.182 +    switch (result) {
   7.183 +        case SQLITE_ROW: {
   7.184 +            *revoked_fpr = strdup((const char *) sqlite3_column_text(session->get_revoked, 0));
   7.185 +            if(*revoked_fpr)
   7.186 +                *revocation_date = sqlite3_column_int64(session->get_revoked, 1);
   7.187 +            else
   7.188 +                status = PEP_OUT_OF_MEMORY;
   7.189 +
   7.190 +            break;
   7.191 +        }
   7.192 +        default:
   7.193 +            status = PEP_CANNOT_FIND_IDENTITY;
   7.194 +    }
   7.195 +
   7.196 +    sqlite3_reset(session->get_revoked);
   7.197 +
   7.198 +    return status;
   7.199 +}
   7.200 +
   7.201  DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
   7.202  {
   7.203      assert(session);
     8.1 --- a/src/pEpEngine.h	Thu Jun 02 13:46:38 2016 +0200
     8.2 +++ b/src/pEpEngine.h	Sat Jun 04 17:33:52 2016 +0200
     8.3 @@ -344,7 +344,7 @@
     8.4      // range 0x40 to 0x7f: unconfirmed encryption and anonymization
     8.5  
     8.6      PEP_ct_unconfirmed_enc_anon = 0x40,         // generic
     8.7 -    PEP_ct_PEP_unconfirmed = 0x7f,
     8.8 +    PEP_ct_pEp_unconfirmed = 0x7f,
     8.9  
    8.10      PEP_ct_confirmed = 0x80,                    // this bit decides if trust is confirmed
    8.11  
    8.12 @@ -706,14 +706,30 @@
    8.13  //  parameters:
    8.14  //      session (in)            session handle
    8.15  //      fpr (in)                ID of key to check as UTF-8 string
    8.16 +//      when (in)               UTC time of when should expiry be considered
    8.17  //      expired (out)           flag if key expired
    8.18  
    8.19  DYNAMIC_API PEP_STATUS key_expired(
    8.20          PEP_SESSION session,
    8.21          const char *fpr,
    8.22 +        const time_t when,
    8.23          bool *expired
    8.24      );
    8.25  
    8.26 +    
    8.27 +// key_revoked() - flags if a key is already revoked
    8.28 +//
    8.29 +//  parameters:
    8.30 +//      session (in)            session handle
    8.31 +//      fpr (in)                ID of key to check as UTF-8 string
    8.32 +//      revoked (out)           flag if key revoked
    8.33 +
    8.34 +DYNAMIC_API PEP_STATUS key_revoked(
    8.35 +        PEP_SESSION session,
    8.36 +        const char *fpr,
    8.37 +        bool *revoked
    8.38 +    );
    8.39 +
    8.40  
    8.41  // get_crashdump_log() - get the last log messages out
    8.42  //
    8.43 @@ -785,6 +801,37 @@
    8.44          int32_t *value
    8.45      );
    8.46  
    8.47 +    
    8.48 +// set_revoked() - records relation between a revoked key and its replacement
    8.49 +//
    8.50 +//  parameters:
    8.51 +//      session (in)            session handle
    8.52 +//      revoked_fpr (in)        revoked fingerprint
    8.53 +//      replacement_fpr (in)    replacement key fingerprint
    8.54 +//      revocation_date (in)    revocation date
    8.55 +
    8.56 +DYNAMIC_API PEP_STATUS set_revoked(
    8.57 +       PEP_SESSION session,
    8.58 +       const char *revoked_fpr,
    8.59 +       const char *replacement_fpr,
    8.60 +       const uint64_t revocation_date
    8.61 +    );
    8.62 +
    8.63 +// get_revoked() - find revoked key that may have been replaced by given key, if any
    8.64 +//
    8.65 +//  parameters:
    8.66 +//      session (in)            session handle
    8.67 +//      fpr (in)                given fingerprint
    8.68 +//      revoked_fpr (out)       revoked fingerprint
    8.69 +//      revocation_date (out)   revocation date
    8.70 +    
    8.71 +DYNAMIC_API PEP_STATUS get_revoked(
    8.72 +        PEP_SESSION session,
    8.73 +        const char *fpr,
    8.74 +        char **revoked_fpr,
    8.75 +        uint64_t *revocation_date
    8.76 +    );
    8.77 +
    8.78  
    8.79  DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session);
    8.80  
     9.1 --- a/src/pEp_internal.h	Thu Jun 02 13:46:38 2016 +0200
     9.2 +++ b/src/pEp_internal.h	Sat Jun 04 17:33:52 2016 +0200
     9.3 @@ -115,7 +115,11 @@
     9.4      sqlite3_stmt *sequence_value1;
     9.5      sqlite3_stmt *sequence_value2;
     9.6  
     9.7 -    // callbacks   
     9.8 +    // sequence value
     9.9 +    sqlite3_stmt *set_revoked;
    9.10 +    sqlite3_stmt *get_revoked;
    9.11 +
    9.12 +    // callbacks
    9.13      examine_identity_t examine_identity;
    9.14      void *examine_management;
    9.15      void *sync_obj;
    10.1 --- a/src/pgp_gpg.c	Thu Jun 02 13:46:38 2016 +0200
    10.2 +++ b/src/pgp_gpg.c	Sat Jun 04 17:33:52 2016 +0200
    10.3 @@ -1783,6 +1783,7 @@
    10.4  PEP_STATUS pgp_key_expired(
    10.5          PEP_SESSION session,
    10.6          const char *fpr,
    10.7 +        const time_t when,
    10.8          bool *expired
    10.9      )
   10.10  {
   10.11 @@ -1799,9 +1800,34 @@
   10.12      if (status != PEP_STATUS_OK)
   10.13          return status;
   10.14  
   10.15 -    if (key && key->subkeys)
   10.16 +    if ((key && key->expired) ||
   10.17 +        (key && key->subkeys && key->subkeys->expired))
   10.18      {
   10.19 -        *expired = key->subkeys->expired;
   10.20 +        // Already marked expired
   10.21 +        *expired = 1;
   10.22 +    }
   10.23 +    else if (key)
   10.24 +    {
   10.25 +        // Detect if will be expired
   10.26 +        // i.e. Check that keys capabilities will
   10.27 +        // not be expired at given time.
   10.28 +        gpgme_subkey_t _sk;
   10.29 +        bool crt_available = false;
   10.30 +        bool sgn_available = false;
   10.31 +        bool enc_available = false;
   10.32 +        for (_sk = key->subkeys; _sk; _sk = _sk->next) {
   10.33 +            if (_sk->expires > when) // not expired at that date ?
   10.34 +            {
   10.35 +                if (_sk->can_certify) crt_available = true;
   10.36 +                if (_sk->can_sign) sgn_available = true;
   10.37 +                if (_sk->can_encrypt) enc_available = true;
   10.38 +                // Authenticate is not used here.
   10.39 +            }
   10.40 +        }
   10.41 +        if(!(crt_available && sgn_available && enc_available))
   10.42 +        {
   10.43 +            *expired = 1;
   10.44 +        }
   10.45      }
   10.46      else
   10.47      {
    11.1 --- a/src/pgp_gpg.h	Thu Jun 02 13:46:38 2016 +0200
    11.2 +++ b/src/pgp_gpg.h	Sat Jun 04 17:33:52 2016 +0200
    11.3 @@ -61,6 +61,7 @@
    11.4  PEP_STATUS pgp_key_expired(
    11.5          PEP_SESSION session,
    11.6          const char *fpr,
    11.7 +        const time_t when,
    11.8          bool *expired
    11.9      );
   11.10  
    12.1 --- a/src/pgp_netpgp.c	Thu Jun 02 13:46:38 2016 +0200
    12.2 +++ b/src/pgp_netpgp.c	Sat Jun 04 17:33:52 2016 +0200
    12.3 @@ -1597,6 +1597,7 @@
    12.4  PEP_STATUS pgp_key_expired(
    12.5          PEP_SESSION session,
    12.6          const char *fprstr,
    12.7 +        const time_t when,
    12.8          bool *expired
    12.9      )
   12.10  {
   12.11 @@ -1610,6 +1611,7 @@
   12.12      if (!session || !fprstr || !expired)
   12.13          return PEP_UNKNOWN_ERROR;
   12.14  
   12.15 +    // TODO : take "when" in account 
   12.16  
   12.17      *expired = false;
   12.18  
    13.1 --- a/src/pgp_netpgp.h	Thu Jun 02 13:46:38 2016 +0200
    13.2 +++ b/src/pgp_netpgp.h	Sat Jun 04 17:33:52 2016 +0200
    13.3 @@ -61,6 +61,7 @@
    13.4  PEP_STATUS pgp_key_expired(
    13.5          PEP_SESSION session,
    13.6          const char *fpr,
    13.7 +        const time_t when,
    13.8          bool *expired
    13.9      );
   13.10  
    14.1 --- a/test/Makefile	Thu Jun 02 13:46:38 2016 +0200
    14.2 +++ b/test/Makefile	Sat Jun 04 17:33:52 2016 +0200
    14.3 @@ -16,6 +16,7 @@
    14.4  
    14.5  UNIT_TESTS_SOURCE=$(wildcard *_test.cc)
    14.6  UNIT_TESTS=$(subst .cc,,$(UNIT_TESTS_SOURCE))
    14.7 +UNIT_TESTS_RUN=$(subst .cc,_run,$(UNIT_TESTS_SOURCE))
    14.8  
    14.9  all: $(TARGET) $(UNIT_TESTS)
   14.10  
   14.11 @@ -28,10 +29,10 @@
   14.12  test: pEpEngineTest
   14.13  	LD_LIBRARY_PATH=~/lib:../src ./pEpEngineTest
   14.14  
   14.15 -unit_tests: $(UNIT_TESTS)
   14.16 -	for t in ./*_test ; do \
   14.17 -		if LD_LIBRARY_PATH=~/lib:../src $$t ; then true; else break; fi \
   14.18 -	done
   14.19 +%_test_run : %_test
   14.20 +	LD_LIBRARY_PATH=~/lib:../src ./$<
   14.21 +
   14.22 +unit_tests: $(UNIT_TESTS) $(UNIT_TESTS_RUN)
   14.23  
   14.24  install:
   14.25  	make -C .. install
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/revoke_regen_attach_test.cc	Sat Jun 04 17:33:52 2016 +0200
    15.3 @@ -0,0 +1,82 @@
    15.4 +#include <stdlib.h>
    15.5 +#include <string.h>
    15.6 +#include <time.h>
    15.7 +#include "platform.h"
    15.8 +#include <iostream>
    15.9 +#include <fstream>
   15.10 +#include <assert.h>
   15.11 +#include "mime.h"
   15.12 +#include "message_api.h"
   15.13 +
   15.14 +using namespace std;
   15.15 +
   15.16 +int main() {
   15.17 +    cout << "\n*** revoke_regen_attach_test ***\n\n";
   15.18 +
   15.19 +    PEP_SESSION session;
   15.20 +    
   15.21 +    cout << "calling init()\n";
   15.22 +    PEP_STATUS status = init(&session);   
   15.23 +    assert(status == PEP_STATUS_OK);
   15.24 +    assert(session);
   15.25 +    cout << "init() completed.\n";
   15.26 +
   15.27 +    cout << "creating own id for : ";
   15.28 +    char *uniqname = strdup("AAAAtestuser@testdomain.org");
   15.29 +    srandom(time(NULL));
   15.30 +    for(int i=0; i < 4;i++)
   15.31 +        uniqname[i] += random() & 0xf;
   15.32 +    
   15.33 +    cout << uniqname << "\n";
   15.34 +    pEp_identity * me = new_identity(uniqname, NULL, PEP_OWN_USERID, "Test User");
   15.35 +    free(uniqname);
   15.36 +    myself(session, me);
   15.37 +
   15.38 +    cout << "generated fingerprint \n";
   15.39 +    cout << me->fpr << "\n";
   15.40 +
   15.41 +    const char *prev_fpr = strdup(me->fpr);
   15.42 +    
   15.43 +    cout << "revoke \n";
   15.44 +    
   15.45 +    key_compromized(session, me);
   15.46 +
   15.47 +    cout << "re-generated fingerprint \n";
   15.48 +    cout << me->fpr << "\n";
   15.49 +    
   15.50 +    assert(strcmp(me->fpr, prev_fpr));
   15.51 +
   15.52 +    identity_list *to = new_identity_list(new_identity("vb@dingens.org", NULL, "42", "Volker Birk"));
   15.53 +    message *msg = new_message(PEP_dir_outgoing);
   15.54 +    assert(msg);
   15.55 +    msg->from = me;
   15.56 +    msg->to = to;
   15.57 +    msg->shortmsg = strdup("hello, world");
   15.58 +    cout << "message created.\n";
   15.59 +
   15.60 +    cout << "encrypting message as MIME multipart…\n";
   15.61 +    message *enc_msg;
   15.62 +    cout << "calling encrypt_message()\n";
   15.63 +    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME);
   15.64 +    cout << status;
   15.65 +    assert(status == PEP_STATUS_OK);
   15.66 +    assert(enc_msg);
   15.67 +    cout << "message encrypted.\n";
   15.68 +
   15.69 +    cout << msg->attachments->filename;
   15.70 +    assert(bloblist_length(msg->attachments) == 2);
   15.71 +    assert(strcmp(msg->attachments->filename, "pEpkey.asc") == 0);
   15.72 +    assert(strcmp(msg->attachments->next->filename, "pEpkey.asc") == 0);
   15.73 +
   15.74 +    cout << "message contains 2 key attachements.\n";
   15.75 +
   15.76 +    free_message(msg);
   15.77 +    free_message(enc_msg);
   15.78 +   
   15.79 +    // TODO: check that revoked key isn't sent after some time.
   15.80 +
   15.81 +    release(session);
   15.82 +
   15.83 +    return 0;
   15.84 +}
   15.85 +