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 -```
     5.1 --- a/src/cryptotech.h	Thu Jun 02 13:46:38 2016 +0200
     5.2 +++ b/src/cryptotech.h	Sat Jun 04 17:33:52 2016 +0200
     5.3 @@ -61,7 +61,7 @@
     5.4          const char *reason);
     5.5  
     5.6  typedef PEP_STATUS (*key_expired_t)(PEP_SESSION session, const char *fpr,
     5.7 -        bool *expired);
     5.8 +        const time_t when, bool *expired);
     5.9  
    5.10  typedef PEP_STATUS (*key_revoked_t)(PEP_SESSION session, const char *fpr,
    5.11                                      bool *revoked);
     6.1 --- a/src/keymanagement.c	Thu Jun 02 13:46:38 2016 +0200
     6.2 +++ b/src/keymanagement.c	Sat Jun 04 17:33:52 2016 +0200
     6.3 @@ -367,12 +367,25 @@
     6.4              free_stringlist(keylist);
     6.5          }
     6.6      }
     6.7 -    
     6.8 -    // TODO : Check key for revoked state
     6.9 +
    6.10 +    bool revoked = false;
    6.11 +    char *r_fpr = NULL;
    6.12 +    if (!EMPTYSTR(identity->fpr))
    6.13 +    {
    6.14 +        status = key_revoked(session, identity->fpr, &revoked);
    6.15 +        assert(status == PEP_STATUS_OK);
    6.16 +        if (status != PEP_STATUS_OK) {
    6.17 +            return status;
    6.18 +        }
    6.19 +    }
    6.20      
    6.21 -    if (EMPTYSTR(identity->fpr) /* or revoked */)
    6.22 -    {
    6.23 -        stringlist_t *keylist = NULL;
    6.24 +    if (EMPTYSTR(identity->fpr) || revoked)
    6.25 +    {        
    6.26 +        if(revoked)
    6.27 +        {
    6.28 +            r_fpr = identity->fpr;
    6.29 +            identity->fpr = NULL;
    6.30 +        }
    6.31          
    6.32          DEBUG_LOG("generating key pair", "debug", identity->address);
    6.33          status = generate_keypair(session, identity);
    6.34 @@ -381,26 +394,28 @@
    6.35              char buf[11];
    6.36              snprintf(buf, 11, "%d", status);
    6.37              DEBUG_LOG("generating key pair failed", "debug", buf);
    6.38 +            if(revoked && r_fpr)
    6.39 +                free(r_fpr);
    6.40              return status;
    6.41          }
    6.42          
    6.43 -        status = find_keys(session, identity->address, &keylist);
    6.44 -        assert(status != PEP_OUT_OF_MEMORY);
    6.45 -        if (status == PEP_OUT_OF_MEMORY)
    6.46 -            return PEP_OUT_OF_MEMORY;
    6.47 -        
    6.48 -        assert(keylist && keylist->value);
    6.49 -        if (keylist == NULL) {
    6.50 -            return PEP_UNKNOWN_ERROR;
    6.51 -        }else if (keylist->value == NULL) {
    6.52 -            free_stringlist(keylist);
    6.53 -            return PEP_UNKNOWN_ERROR;
    6.54 +        if(revoked)
    6.55 +        {
    6.56 +            status = set_revoked(session, r_fpr,
    6.57 +                                 identity->fpr, time(NULL));
    6.58 +            free(r_fpr);
    6.59 +            if (status != PEP_STATUS_OK) {
    6.60 +                return status;
    6.61 +            }
    6.62          }
    6.63      }
    6.64      else
    6.65      {
    6.66          bool expired;
    6.67 -        status = key_expired(session, identity->fpr, &expired);
    6.68 +        status = key_expired(session, identity->fpr, 
    6.69 +                             time(NULL) + (7*24*3600), // In a week
    6.70 +                             &expired);
    6.71 +
    6.72          assert(status == PEP_STATUS_OK);
    6.73          if (status != PEP_STATUS_OK) {
    6.74              return status;
    6.75 @@ -502,8 +517,14 @@
    6.76          return PEP_ILLEGAL_VALUE;
    6.77  
    6.78      if (ident->me)
    6.79 +    {
    6.80          revoke_key(session, ident->fpr, NULL);
    6.81 -    status = mark_as_compromized(session, ident->fpr);
    6.82 +        myself(session, ident);
    6.83 +    }
    6.84 +    else
    6.85 +    {
    6.86 +        status = mark_as_compromized(session, ident->fpr);
    6.87 +    }
    6.88  
    6.89      return status;
    6.90  }
     7.1 --- a/src/message_api.c	Thu Jun 02 13:46:38 2016 +0200
     7.2 +++ b/src/message_api.c	Sat Jun 04 17:33:52 2016 +0200
     7.3 @@ -863,12 +863,32 @@
     7.4          update_identity(session, msg->from);
     7.5  }
     7.6  
     7.7 -void attach_own_key(PEP_SESSION session, message *msg)
     7.8 +
     7.9 +PEP_STATUS _attach_key(PEP_SESSION session, const char* fpr, message *msg)
    7.10  {
    7.11      char *keydata;
    7.12      size_t size;
    7.13      bloblist_t *bl;
    7.14  
    7.15 +    PEP_STATUS status = export_key(session, fpr, &keydata, &size);
    7.16 +    assert(status == PEP_STATUS_OK);
    7.17 +    if (status != PEP_STATUS_OK)
    7.18 +        return status;
    7.19 +    assert(size);
    7.20 +    
    7.21 +    bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
    7.22 +                      "pEpkey.asc");
    7.23 +    
    7.24 +    if (msg->attachments == NULL && bl)
    7.25 +        msg->attachments = bl;
    7.26 +
    7.27 +    return PEP_STATUS_OK;
    7.28 +}
    7.29 +
    7.30 +#define ONE_WEEK (7*24*3600)
    7.31 +
    7.32 +void attach_own_key(PEP_SESSION session, message *msg)
    7.33 +{
    7.34      assert(session);
    7.35      assert(msg);
    7.36  
    7.37 @@ -879,16 +899,24 @@
    7.38      if (msg->from == NULL || msg->from->fpr == NULL)
    7.39          return;
    7.40  
    7.41 -    PEP_STATUS status = export_key(session, msg->from->fpr, &keydata, &size);
    7.42 -    assert(status == PEP_STATUS_OK);
    7.43 -    if (status != PEP_STATUS_OK)
    7.44 +    if(_attach_key(session, msg->from->fpr, msg) != PEP_STATUS_OK)
    7.45          return;
    7.46 -    assert(size);
    7.47 -
    7.48 -    bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
    7.49 -            "pEpkey.asc");
    7.50 -    if (msg->attachments == NULL && bl)
    7.51 -        msg->attachments = bl;
    7.52 +    
    7.53 +    char *revoked_fpr = NULL;
    7.54 +    uint64_t revocation_date = 0;
    7.55 +    
    7.56 +    if(get_revoked(session, msg->from->fpr,
    7.57 +                   &revoked_fpr, &revocation_date) == PEP_STATUS_OK &&
    7.58 +       revoked_fpr != NULL)
    7.59 +    {
    7.60 +        time_t now = time(NULL);
    7.61 +        
    7.62 +        if (now < (time_t)revocation_date + ONE_WEEK)
    7.63 +        {
    7.64 +            _attach_key(session, revoked_fpr, msg);
    7.65 +        }
    7.66 +    }
    7.67 +    free(revoked_fpr);
    7.68  }
    7.69  
    7.70  PEP_cryptotech determine_encryption_format(message *msg)
     8.1 --- a/src/pEpEngine.c	Thu Jun 02 13:46:38 2016 +0200
     8.2 +++ b/src/pEpEngine.c	Sat Jun 04 17:33:52 2016 +0200
     8.3 @@ -34,9 +34,14 @@
     8.4      static const char *sql_own_key_is_listed;
     8.5      static const char *sql_own_key_retrieve;
     8.6  
     8.7 +    // Sequence
     8.8      static const char *sql_sequence_value1;
     8.9      static const char *sql_sequence_value2;
    8.10  
    8.11 +    // Revocation tracking
    8.12 +    static const char *sql_set_revoked;
    8.13 +    static const char *sql_get_revoked;
    8.14 +    
    8.15      bool in_first = false;
    8.16  
    8.17      assert(sqlite3_threadsafe());
    8.18 @@ -177,6 +182,13 @@
    8.19                  "   name text primary key,\n"
    8.20                  "   value integer default 0\n"
    8.21                  ");\n"
    8.22 +                "create table if not exists revoked_keys (\n"
    8.23 +                "   revoked_fpr text primary key,\n"
    8.24 +                "   replacement_fpr text not null\n"
    8.25 +                "       references pgp_keypair (fpr)\n"
    8.26 +                "       on delete cascade,\n"
    8.27 +                "   revocation_date integer\n"
    8.28 +                ");\n"
    8.29                  ,
    8.30              NULL,
    8.31              NULL,
    8.32 @@ -275,6 +287,15 @@
    8.33                                "(select coalesce((select value + 1 from sequences "
    8.34                                "where name = ?1), 1 ))) ; ";
    8.35          sql_sequence_value2 = "select value from sequences where name = ?1 ;";
    8.36 +        
    8.37 +        sql_set_revoked =     "insert or replace into revoked_keys ("
    8.38 +                              "    revoked_fpr, replacement_fpr, revocation_date) "
    8.39 +                              "values (upper(replace(?1,' ','')),"
    8.40 +                              "        upper(replace(?2,' ','')),"
    8.41 +                              "        ?3) ;";
    8.42 +        
    8.43 +        sql_get_revoked =     "select revoked_fpr, revocation_date from revoked_keys"
    8.44 +                              "    where replacement_fpr = upper(replace(?1,' ','')) ;";
    8.45      }
    8.46  
    8.47      int_result = sqlite3_prepare_v2(_session->db, sql_log, (int)strlen(sql_log),
    8.48 @@ -367,6 +388,16 @@
    8.49              (int)strlen(sql_sequence_value2), &_session->sequence_value2, NULL);
    8.50      assert(int_result == SQLITE_OK);
    8.51  
    8.52 +    // Revocation tracking
    8.53 +    
    8.54 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
    8.55 +                                    (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
    8.56 +    assert(int_result == SQLITE_OK);
    8.57 +    
    8.58 +    int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
    8.59 +                                    (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
    8.60 +    assert(int_result == SQLITE_OK);
    8.61 +    
    8.62      status = init_cryptotech(_session, in_first);
    8.63      if (status != PEP_STATUS_OK)
    8.64          goto pep_error;
    8.65 @@ -552,7 +583,7 @@
    8.66          if (*word)
    8.67              *wsize = sqlite3_column_bytes(session->trustword, 1);
    8.68          else
    8.69 -            status = PEP_TRUSTWORD_NOT_FOUND;
    8.70 +            status = PEP_OUT_OF_MEMORY;
    8.71      } else
    8.72          status = PEP_TRUSTWORD_NOT_FOUND;
    8.73  
    8.74 @@ -1174,6 +1205,7 @@
    8.75  DYNAMIC_API PEP_STATUS key_expired(
    8.76          PEP_SESSION session,
    8.77          const char *fpr,
    8.78 +        const time_t when,
    8.79          bool *expired
    8.80      )
    8.81  {
    8.82 @@ -1185,7 +1217,24 @@
    8.83          return PEP_ILLEGAL_VALUE;
    8.84  
    8.85      return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
    8.86 -            expired);
    8.87 +            when, expired);
    8.88 +}
    8.89 +
    8.90 +DYNAMIC_API PEP_STATUS key_revoked(
    8.91 +                                   PEP_SESSION session,
    8.92 +                                   const char *fpr,
    8.93 +                                   bool *revoked
    8.94 +                                   )
    8.95 +{
    8.96 +    assert(session);
    8.97 +    assert(fpr);
    8.98 +    assert(revoked);
    8.99 +    
   8.100 +    if (!(session && fpr && revoked))
   8.101 +        return PEP_ILLEGAL_VALUE;
   8.102 +    
   8.103 +    return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
   8.104 +                                                              revoked);
   8.105  }
   8.106  
   8.107  static void _clean_log_value(char *text)
   8.108 @@ -1473,6 +1522,95 @@
   8.109      return status;
   8.110  }
   8.111  
   8.112 +DYNAMIC_API PEP_STATUS set_revoked(
   8.113 +       PEP_SESSION session,
   8.114 +       const char *revoked_fpr,
   8.115 +       const char *replacement_fpr,
   8.116 +       const uint64_t revocation_date
   8.117 +    )
   8.118 +{
   8.119 +    PEP_STATUS status = PEP_STATUS_OK;
   8.120 +    
   8.121 +    assert(session &&
   8.122 +           revoked_fpr && revoked_fpr[0] &&
   8.123 +           replacement_fpr && replacement_fpr[0]
   8.124 +          );
   8.125 +    
   8.126 +    if (!(session &&
   8.127 +          revoked_fpr && revoked_fpr[0] &&
   8.128 +          replacement_fpr && replacement_fpr[0]
   8.129 +         ))
   8.130 +        return PEP_ILLEGAL_VALUE;
   8.131 +    
   8.132 +    sqlite3_reset(session->set_revoked);
   8.133 +    sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
   8.134 +    sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1, SQLITE_STATIC);
   8.135 +    sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
   8.136 +
   8.137 +    int result;
   8.138 +    
   8.139 +    result = sqlite3_step(session->set_revoked);
   8.140 +    switch (result) {
   8.141 +        case SQLITE_DONE:
   8.142 +            status = PEP_STATUS_OK;
   8.143 +            break;
   8.144 +            
   8.145 +        default:
   8.146 +            status = PEP_UNKNOWN_ERROR;
   8.147 +    }
   8.148 +    
   8.149 +    sqlite3_reset(session->set_revoked);
   8.150 +    return status;
   8.151 +}
   8.152 +
   8.153 +DYNAMIC_API PEP_STATUS get_revoked(
   8.154 +        PEP_SESSION session,
   8.155 +        const char *fpr,
   8.156 +        char **revoked_fpr,
   8.157 +        uint64_t *revocation_date
   8.158 +    )
   8.159 +{
   8.160 +    PEP_STATUS status = PEP_STATUS_OK;
   8.161 +
   8.162 +    assert(session &&
   8.163 +           revoked_fpr &&
   8.164 +           fpr && fpr[0]
   8.165 +          );
   8.166 +    
   8.167 +    if (!(session &&
   8.168 +           revoked_fpr &&
   8.169 +           fpr && fpr[0]
   8.170 +          ))
   8.171 +        return PEP_ILLEGAL_VALUE;
   8.172 +
   8.173 +    *revoked_fpr = NULL;
   8.174 +    *revocation_date = 0;
   8.175 +
   8.176 +    sqlite3_reset(session->get_revoked);
   8.177 +    sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
   8.178 +
   8.179 +    int result;
   8.180 +    
   8.181 +    result = sqlite3_step(session->get_revoked);
   8.182 +    switch (result) {
   8.183 +        case SQLITE_ROW: {
   8.184 +            *revoked_fpr = strdup((const char *) sqlite3_column_text(session->get_revoked, 0));
   8.185 +            if(*revoked_fpr)
   8.186 +                *revocation_date = sqlite3_column_int64(session->get_revoked, 1);
   8.187 +            else
   8.188 +                status = PEP_OUT_OF_MEMORY;
   8.189 +
   8.190 +            break;
   8.191 +        }
   8.192 +        default:
   8.193 +            status = PEP_CANNOT_FIND_IDENTITY;
   8.194 +    }
   8.195 +
   8.196 +    sqlite3_reset(session->get_revoked);
   8.197 +
   8.198 +    return status;
   8.199 +}
   8.200 +
   8.201  DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
   8.202  {
   8.203      assert(session);
     9.1 --- a/src/pEpEngine.h	Thu Jun 02 13:46:38 2016 +0200
     9.2 +++ b/src/pEpEngine.h	Sat Jun 04 17:33:52 2016 +0200
     9.3 @@ -344,7 +344,7 @@
     9.4      // range 0x40 to 0x7f: unconfirmed encryption and anonymization
     9.5  
     9.6      PEP_ct_unconfirmed_enc_anon = 0x40,         // generic
     9.7 -    PEP_ct_PEP_unconfirmed = 0x7f,
     9.8 +    PEP_ct_pEp_unconfirmed = 0x7f,
     9.9  
    9.10      PEP_ct_confirmed = 0x80,                    // this bit decides if trust is confirmed
    9.11  
    9.12 @@ -706,14 +706,30 @@
    9.13  //  parameters:
    9.14  //      session (in)            session handle
    9.15  //      fpr (in)                ID of key to check as UTF-8 string
    9.16 +//      when (in)               UTC time of when should expiry be considered
    9.17  //      expired (out)           flag if key expired
    9.18  
    9.19  DYNAMIC_API PEP_STATUS key_expired(
    9.20          PEP_SESSION session,
    9.21          const char *fpr,
    9.22 +        const time_t when,
    9.23          bool *expired
    9.24      );
    9.25  
    9.26 +    
    9.27 +// key_revoked() - flags if a key is already revoked
    9.28 +//
    9.29 +//  parameters:
    9.30 +//      session (in)            session handle
    9.31 +//      fpr (in)                ID of key to check as UTF-8 string
    9.32 +//      revoked (out)           flag if key revoked
    9.33 +
    9.34 +DYNAMIC_API PEP_STATUS key_revoked(
    9.35 +        PEP_SESSION session,
    9.36 +        const char *fpr,
    9.37 +        bool *revoked
    9.38 +    );
    9.39 +
    9.40  
    9.41  // get_crashdump_log() - get the last log messages out
    9.42  //
    9.43 @@ -785,6 +801,37 @@
    9.44          int32_t *value
    9.45      );
    9.46  
    9.47 +    
    9.48 +// set_revoked() - records relation between a revoked key and its replacement
    9.49 +//
    9.50 +//  parameters:
    9.51 +//      session (in)            session handle
    9.52 +//      revoked_fpr (in)        revoked fingerprint
    9.53 +//      replacement_fpr (in)    replacement key fingerprint
    9.54 +//      revocation_date (in)    revocation date
    9.55 +
    9.56 +DYNAMIC_API PEP_STATUS set_revoked(
    9.57 +       PEP_SESSION session,
    9.58 +       const char *revoked_fpr,
    9.59 +       const char *replacement_fpr,
    9.60 +       const uint64_t revocation_date
    9.61 +    );
    9.62 +
    9.63 +// get_revoked() - find revoked key that may have been replaced by given key, if any
    9.64 +//
    9.65 +//  parameters:
    9.66 +//      session (in)            session handle
    9.67 +//      fpr (in)                given fingerprint
    9.68 +//      revoked_fpr (out)       revoked fingerprint
    9.69 +//      revocation_date (out)   revocation date
    9.70 +    
    9.71 +DYNAMIC_API PEP_STATUS get_revoked(
    9.72 +        PEP_SESSION session,
    9.73 +        const char *fpr,
    9.74 +        char **revoked_fpr,
    9.75 +        uint64_t *revocation_date
    9.76 +    );
    9.77 +
    9.78  
    9.79  DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session);
    9.80  
    10.1 --- a/src/pEp_internal.h	Thu Jun 02 13:46:38 2016 +0200
    10.2 +++ b/src/pEp_internal.h	Sat Jun 04 17:33:52 2016 +0200
    10.3 @@ -115,7 +115,11 @@
    10.4      sqlite3_stmt *sequence_value1;
    10.5      sqlite3_stmt *sequence_value2;
    10.6  
    10.7 -    // callbacks   
    10.8 +    // sequence value
    10.9 +    sqlite3_stmt *set_revoked;
   10.10 +    sqlite3_stmt *get_revoked;
   10.11 +
   10.12 +    // callbacks
   10.13      examine_identity_t examine_identity;
   10.14      void *examine_management;
   10.15      void *sync_obj;
    11.1 --- a/src/pgp_gpg.c	Thu Jun 02 13:46:38 2016 +0200
    11.2 +++ b/src/pgp_gpg.c	Sat Jun 04 17:33:52 2016 +0200
    11.3 @@ -1783,6 +1783,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  {
   11.11 @@ -1799,9 +1800,34 @@
   11.12      if (status != PEP_STATUS_OK)
   11.13          return status;
   11.14  
   11.15 -    if (key && key->subkeys)
   11.16 +    if ((key && key->expired) ||
   11.17 +        (key && key->subkeys && key->subkeys->expired))
   11.18 +    {
   11.19 +        // Already marked expired
   11.20 +        *expired = 1;
   11.21 +    }
   11.22 +    else if (key)
   11.23      {
   11.24 -        *expired = key->subkeys->expired;
   11.25 +        // Detect if will be expired
   11.26 +        // i.e. Check that keys capabilities will
   11.27 +        // not be expired at given time.
   11.28 +        gpgme_subkey_t _sk;
   11.29 +        bool crt_available = false;
   11.30 +        bool sgn_available = false;
   11.31 +        bool enc_available = false;
   11.32 +        for (_sk = key->subkeys; _sk; _sk = _sk->next) {
   11.33 +            if (_sk->expires > when) // not expired at that date ?
   11.34 +            {
   11.35 +                if (_sk->can_certify) crt_available = true;
   11.36 +                if (_sk->can_sign) sgn_available = true;
   11.37 +                if (_sk->can_encrypt) enc_available = true;
   11.38 +                // Authenticate is not used here.
   11.39 +            }
   11.40 +        }
   11.41 +        if(!(crt_available && sgn_available && enc_available))
   11.42 +        {
   11.43 +            *expired = 1;
   11.44 +        }
   11.45      }
   11.46      else
   11.47      {
    12.1 --- a/src/pgp_gpg.h	Thu Jun 02 13:46:38 2016 +0200
    12.2 +++ b/src/pgp_gpg.h	Sat Jun 04 17:33:52 2016 +0200
    12.3 @@ -61,6 +61,7 @@
    12.4  PEP_STATUS pgp_key_expired(
    12.5          PEP_SESSION session,
    12.6          const char *fpr,
    12.7 +        const time_t when,
    12.8          bool *expired
    12.9      );
   12.10  
    13.1 --- a/src/pgp_netpgp.c	Thu Jun 02 13:46:38 2016 +0200
    13.2 +++ b/src/pgp_netpgp.c	Sat Jun 04 17:33:52 2016 +0200
    13.3 @@ -1597,6 +1597,7 @@
    13.4  PEP_STATUS pgp_key_expired(
    13.5          PEP_SESSION session,
    13.6          const char *fprstr,
    13.7 +        const time_t when,
    13.8          bool *expired
    13.9      )
   13.10  {
   13.11 @@ -1610,6 +1611,7 @@
   13.12      if (!session || !fprstr || !expired)
   13.13          return PEP_UNKNOWN_ERROR;
   13.14  
   13.15 +    // TODO : take "when" in account 
   13.16  
   13.17      *expired = false;
   13.18  
    14.1 --- a/src/pgp_netpgp.h	Thu Jun 02 13:46:38 2016 +0200
    14.2 +++ b/src/pgp_netpgp.h	Sat Jun 04 17:33:52 2016 +0200
    14.3 @@ -61,6 +61,7 @@
    14.4  PEP_STATUS pgp_key_expired(
    14.5          PEP_SESSION session,
    14.6          const char *fpr,
    14.7 +        const time_t when,
    14.8          bool *expired
    14.9      );
   14.10  
    15.1 --- a/test/Makefile	Thu Jun 02 13:46:38 2016 +0200
    15.2 +++ b/test/Makefile	Sat Jun 04 17:33:52 2016 +0200
    15.3 @@ -16,6 +16,7 @@
    15.4  
    15.5  UNIT_TESTS_SOURCE=$(wildcard *_test.cc)
    15.6  UNIT_TESTS=$(subst .cc,,$(UNIT_TESTS_SOURCE))
    15.7 +UNIT_TESTS_RUN=$(subst .cc,_run,$(UNIT_TESTS_SOURCE))
    15.8  
    15.9  all: $(TARGET) $(UNIT_TESTS)
   15.10  
   15.11 @@ -28,10 +29,10 @@
   15.12  test: pEpEngineTest
   15.13  	LD_LIBRARY_PATH=~/lib:../src ./pEpEngineTest
   15.14  
   15.15 -unit_tests: $(UNIT_TESTS)
   15.16 -	for t in ./*_test ; do \
   15.17 -		if LD_LIBRARY_PATH=~/lib:../src $$t ; then true; else break; fi \
   15.18 -	done
   15.19 +%_test_run : %_test
   15.20 +	LD_LIBRARY_PATH=~/lib:../src ./$<
   15.21 +
   15.22 +unit_tests: $(UNIT_TESTS) $(UNIT_TESTS_RUN)
   15.23  
   15.24  install:
   15.25  	make -C .. install
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/revoke_regen_attach_test.cc	Sat Jun 04 17:33:52 2016 +0200
    16.3 @@ -0,0 +1,82 @@
    16.4 +#include <stdlib.h>
    16.5 +#include <string.h>
    16.6 +#include <time.h>
    16.7 +#include "platform.h"
    16.8 +#include <iostream>
    16.9 +#include <fstream>
   16.10 +#include <assert.h>
   16.11 +#include "mime.h"
   16.12 +#include "message_api.h"
   16.13 +
   16.14 +using namespace std;
   16.15 +
   16.16 +int main() {
   16.17 +    cout << "\n*** revoke_regen_attach_test ***\n\n";
   16.18 +
   16.19 +    PEP_SESSION session;
   16.20 +    
   16.21 +    cout << "calling init()\n";
   16.22 +    PEP_STATUS status = init(&session);   
   16.23 +    assert(status == PEP_STATUS_OK);
   16.24 +    assert(session);
   16.25 +    cout << "init() completed.\n";
   16.26 +
   16.27 +    cout << "creating own id for : ";
   16.28 +    char *uniqname = strdup("AAAAtestuser@testdomain.org");
   16.29 +    srandom(time(NULL));
   16.30 +    for(int i=0; i < 4;i++)
   16.31 +        uniqname[i] += random() & 0xf;
   16.32 +    
   16.33 +    cout << uniqname << "\n";
   16.34 +    pEp_identity * me = new_identity(uniqname, NULL, PEP_OWN_USERID, "Test User");
   16.35 +    free(uniqname);
   16.36 +    myself(session, me);
   16.37 +
   16.38 +    cout << "generated fingerprint \n";
   16.39 +    cout << me->fpr << "\n";
   16.40 +
   16.41 +    const char *prev_fpr = strdup(me->fpr);
   16.42 +    
   16.43 +    cout << "revoke \n";
   16.44 +    
   16.45 +    key_compromized(session, me);
   16.46 +
   16.47 +    cout << "re-generated fingerprint \n";
   16.48 +    cout << me->fpr << "\n";
   16.49 +    
   16.50 +    assert(strcmp(me->fpr, prev_fpr));
   16.51 +
   16.52 +    identity_list *to = new_identity_list(new_identity("vb@dingens.org", NULL, "42", "Volker Birk"));
   16.53 +    message *msg = new_message(PEP_dir_outgoing);
   16.54 +    assert(msg);
   16.55 +    msg->from = me;
   16.56 +    msg->to = to;
   16.57 +    msg->shortmsg = strdup("hello, world");
   16.58 +    cout << "message created.\n";
   16.59 +
   16.60 +    cout << "encrypting message as MIME multipart…\n";
   16.61 +    message *enc_msg;
   16.62 +    cout << "calling encrypt_message()\n";
   16.63 +    status = encrypt_message(session, msg, NULL, &enc_msg, PEP_enc_PGP_MIME);
   16.64 +    cout << status;
   16.65 +    assert(status == PEP_STATUS_OK);
   16.66 +    assert(enc_msg);
   16.67 +    cout << "message encrypted.\n";
   16.68 +
   16.69 +    cout << msg->attachments->filename;
   16.70 +    assert(bloblist_length(msg->attachments) == 2);
   16.71 +    assert(strcmp(msg->attachments->filename, "pEpkey.asc") == 0);
   16.72 +    assert(strcmp(msg->attachments->next->filename, "pEpkey.asc") == 0);
   16.73 +
   16.74 +    cout << "message contains 2 key attachements.\n";
   16.75 +
   16.76 +    free_message(msg);
   16.77 +    free_message(enc_msg);
   16.78 +   
   16.79 +    // TODO: check that revoked key isn't sent after some time.
   16.80 +
   16.81 +    release(session);
   16.82 +
   16.83 +    return 0;
   16.84 +}
   16.85 +