Browse Source

ENGINE-633: we don't remove keys for the time being with election, so we have to expect different behaviour in the tests.

doxygen_doc
parent
commit
be2ebdf804
102 changed files with 2100 additions and 1155 deletions
  1. +1
    -0
      Makefile
  2. +13
    -0
      build-android/Makefile
  3. +4
    -8
      build-windows/libpEpasn1/libpEpasn1.vcxproj
  4. +1
    -1
      src/Makefile
  5. +3
    -3
      src/aux_mime_msg.c
  6. +6
    -0
      src/etpan_mime.c
  7. +253
    -60
      src/key_reset.c
  8. +3
    -0
      src/key_reset.h
  9. +182
    -89
      src/keymanagement.c
  10. +4
    -2
      src/keymanagement.h
  11. +242
    -206
      src/message_api.c
  12. +2
    -0
      src/message_api.h
  13. +49
    -361
      src/pEpEngine.c
  14. +27
    -23
      src/pEpEngine.h
  15. +6
    -4
      src/pEp_internal.h
  16. +1
    -1
      src/pgp_sequoia.c
  17. +2
    -1
      src/platform_windows.cpp
  18. +2
    -0
      src/platform_windows.h
  19. +22
    -5
      src/timestamp.c
  20. +11
    -0
      src/timestamp.h
  21. +3
    -1
      sync/gen_statemachine.ysl2
  22. +2
    -5
      test/Makefile
  23. +1
    -1
      test/src/AppleMailTest.cc
  24. +1
    -1
      test/src/BCCTest.cc
  25. +1
    -1
      test/src/BlacklistAcceptNewKeyTest.cc
  26. +1
    -1
      test/src/BlacklistTest.cc
  27. +1
    -1
      test/src/CaseAndDotAddressTest.cc
  28. +1
    -1
      test/src/CheckRenewedExpiredKeyTrustStatusTest.cc
  29. +1
    -1
      test/src/CleanInvalidOwnKeysTest.cc
  30. +1
    -1
      test/src/CrashdumpTest.cc
  31. +1
    -1
      test/src/DecorateTest.cc
  32. +1
    -1
      test/src/DecryptAttachPrivateKeyTrustedTest.cc
  33. +1
    -1
      test/src/DecryptAttachPrivateKeyUntrustedTest.cc
  34. +1
    -1
      test/src/DeleteKeyTest.cc
  35. +1
    -1
      test/src/ElevatedAttachmentsTest.cc
  36. +1
    -1
      test/src/EmptyLongmsgFullHtmlTest.cc
  37. +1
    -1
      test/src/EncryptAttachPrivateKeyTest.cc
  38. +1
    -1
      test/src/EncryptForIdentityTest.cc
  39. +1
    -1
      test/src/EncryptMissingPrivateKeyTest.cc
  40. +4
    -9
      test/src/Engine.cc
  41. +2
    -1
      test/src/Engine.h
  42. +1
    -1
      test/src/Engine358Test.cc
  43. +1
    -1
      test/src/Engine463Test.cc
  44. +1
    -1
      test/src/Engine514Test.cc
  45. +1
    -1
      test/src/Engine655Test.cc
  46. +1
    -1
      test/src/Engine703Test.cc
  47. +1
    -1
      test/src/Engine704Test.cc
  48. +1
    -1
      test/src/Engine715Test.cc
  49. +1
    -1
      test/src/Engine736Test.cc
  50. +1
    -1
      test/src/ExpiredSubkeyTest.cc
  51. +1
    -1
      test/src/ExportKeyTest.cc
  52. +1
    -1
      test/src/ExternalRevokeTest.cc
  53. +1
    -1
      test/src/GetKeyRatingForUserTest.cc
  54. +1
    -1
      test/src/HeaderKeyImportTest.cc
  55. +1
    -1
      test/src/I18nTest.cc
  56. +1
    -1
      test/src/IdentEncFormatTest.cc
  57. +1
    -1
      test/src/ImportKeyTest.cc
  58. +143
    -5
      test/src/KeyAttachmentTest.cc
  59. +1
    -1
      test/src/KeyManipulationTest.cc
  60. +492
    -1
      test/src/KeyResetMessageTest.cc
  61. +69
    -1
      test/src/KeyeditTest.cc
  62. +1
    -1
      test/src/KeyringImportTest.cc
  63. +1
    -1
      test/src/LeastColorGroupTest.cc
  64. +1
    -1
      test/src/LeastCommonDenomColorTest.cc
  65. +1
    -1
      test/src/LiteralFilenameTest.cc
  66. +1
    -1
      test/src/LookupTest.cc
  67. +1
    -1
      test/src/LotsOfKeysTest.cc
  68. +1
    -1
      test/src/MapAsn1Test.cc
  69. +1
    -1
      test/src/Message2_1Test.cc
  70. +1
    -1
      test/src/MessageApiTest.cc
  71. +1
    -1
      test/src/MessageNullFromTest.cc
  72. +1
    -1
      test/src/MessageTwoPointOhTest.cc
  73. +1
    -1
      test/src/MimeTest.cc
  74. +3
    -3
      test/src/NoOwnIdentWritesOnDecryptTest.cc
  75. +119
    -1
      test/src/OwnIdentitiesRetrieveTest.cc
  76. +1
    -1
      test/src/OwnKeysRetrieveTest.cc
  77. +1
    -1
      test/src/PassphraseTest.cc
  78. +1
    -1
      test/src/PepSubjectReceivedTest.cc
  79. +1
    -1
      test/src/PgpBinaryTest.cc
  80. +1
    -1
      test/src/PgpListKeysTest.cc
  81. +1
    -1
      test/src/Quick11to12Test.cc
  82. +1
    -1
      test/src/ReencryptPlusExtraKeysTest.cc
  83. +60
    -1
      test/src/RevocationTest.cc
  84. +1
    -1
      test/src/RevokeRegenAttachTest.cc
  85. +1
    -1
      test/src/SenderFPRTest.cc
  86. +1
    -1
      test/src/SequenceTest.cc
  87. +1
    -1
      test/src/SignOnlyTest.cc
  88. +1
    -1
      test/src/SimpleBodyNotAltTest.cc
  89. +1
    -1
      test/src/SubkeyRatingEvalTest.cc
  90. +0
    -294
      test/src/SyncTest.cc
  91. +1
    -1
      test/src/TrustManipulationTest.cc
  92. +1
    -1
      test/src/TrustwordsTest.cc
  93. +1
    -1
      test/src/URIAddressTest.cc
  94. +1
    -1
      test/src/UnencryptedPepMailTest.cc
  95. +217
    -1
      test/src/UpdateIdAndMyselfTest.cc
  96. +1
    -1
      test/src/UserIDAliasTest.cc
  97. +1
    -1
      test/src/UserIdCollisionTest.cc
  98. +1
    -1
      test/src/VerifyTest.cc
  99. +18
    -2
      test/src/test_util.cc
  100. +8
    -0
      test/src/test_util.h

+ 1
- 0
Makefile View File

@ -54,6 +54,7 @@ clean:
$(MAKE) -C db clean
$(MAKE) -C asn.1 clean
$(MAKE) -C sync clean
$(MAKE) -C build-android clean
tags:
$(MAKE) -C asn.1 tags


+ 13
- 0
build-android/Makefile View File

@ -0,0 +1,13 @@
# Copyright 2020, pEp Foundation
# This file is part of pEpEngine - Android Build
# This file may be used under the terms of the GNU General Public License version 3
# see LICENSE.txt
include ../Makefile.conf
all:
echo "Placeholder command, this is meant to be cleaned by JNIAdapter Android build"
.PHONY: clean
clean:
rm -rf include/

+ 4
- 8
build-windows/libpEpasn1/libpEpasn1.vcxproj View File

@ -60,10 +60,6 @@
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<PreBuildEvent>
<Command>cd "$(ProjectDir)..\.." &amp;&amp; "$(ProjectDir)..\generate_code.cmd"</Command>
<Message>Generating Code for pEp Sync</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -81,10 +77,6 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>cd "$(ProjectDir)..\.." &amp;&amp; "$(ProjectDir)..\generate_code.cmd"</Command>
<Message>Generating Code for pEp Sync</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
@ -227,4 +219,8 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<Target Name="BeforeRebuild">
<Message Text="Generating Code for pEp Sync" />
<Exec Command="CD &quot;$(ProjectDir)..\..&quot; &amp;&amp; &quot;$(ProjectDir)..\generate_code.cmd&quot;" />
</Target>
</Project>

+ 1
- 1
src/Makefile View File

@ -28,7 +28,7 @@ endif
ifeq ($(BUILD_ON),Darwin)
ifeq ($(BUILD_FOR),Darwin)
CFLAGS+= -DSQLITE_THREADSAFE=1
LDLIBS+= -lz -liconv
LDLIBS+= -lz -liconv -mmacosx-version-min=10.10
else
$(error I do not know how to make for $(BUILD_FOR) on $(BUILD_ON))
endif


+ 3
- 3
src/aux_mime_msg.c View File

@ -38,7 +38,7 @@ static PEP_STATUS update_identity_recip_list(PEP_SESSION session,
}
}
else
status = _myself(session, curr_identity, false, false, true);
status = _myself(session, curr_identity, false, false, false, true);
if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
return status;
}
@ -83,9 +83,9 @@ DYNAMIC_API PEP_STATUS MIME_decrypt_message(
if (!is_me(session, tmp_msg->from))
status = update_identity(session, (tmp_msg->from));
else
status = _myself(session, tmp_msg->from, false, false, true);
status = _myself(session, tmp_msg->from, false, true, false, true);
if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY)
if (status == PEP_ILLEGAL_VALUE || status == PEP_OUT_OF_MEMORY || PASS_ERROR(status))
goto pEp_error;
}


+ 6
- 0
src/etpan_mime.c View File

@ -548,6 +548,12 @@ timestamp * etpantime_to_timestamp(const struct mailimf_date_time *et)
result->tm_mon = et->dt_month - 1;
result->tm_year = et->dt_year - 1900;
result->tm_gmtoff = 36L * (long) et->dt_zone;
// Normalize to UTC and then forget the offset.
time_t t = timegm_with_gmtoff(result);
gmtime_r(&t, result);
result->tm_gmtoff = 0;
return result;
}


+ 253
- 60
src/key_reset.c View File

@ -67,9 +67,14 @@ static PEP_STATUS _generate_reset_structs(PEP_SESSION session,
if (!include_secret) { // This isn't to own recips, so shipping the rev'd key is OK. Own keys are revoked on each device.
status = export_key(session, old_fpr, &key_material_old, &datasize);
// Shouldn't happen, but we can't make presumptions about crypto engine
if (PASS_ERROR(status))
goto pEp_error;
if (datasize > 0 && key_material_old) {
if (status != PEP_STATUS_OK)
return status;
goto pEp_error;
if (!keys)
keys = new_bloblist(key_material_old, datasize,
@ -82,10 +87,13 @@ static PEP_STATUS _generate_reset_structs(PEP_SESSION session,
datasize = 0;
}
status = export_key(session, new_fpr, &key_material_new, &datasize);
// Shouldn't happen, but we can't make presumptions about crypto engine
if (PASS_ERROR(status))
goto pEp_error;
if (datasize > 0 && key_material_new) {
if (status != PEP_STATUS_OK)
return status;
goto pEp_error;
if (!keys)
keys = new_bloblist(key_material_new, datasize,
@ -97,8 +105,8 @@ static PEP_STATUS _generate_reset_structs(PEP_SESSION session,
datasize = 0;
if (include_secret) {
status = export_secret_key(session, new_fpr, &key_material_priv, &datasize);
if (status != PEP_STATUS_OK)
return status;
if (status != PEP_STATUS_OK) // includes PASS_ERROR
goto pEp_error;
if (datasize > 0 && key_material_priv) {
bloblist_add(keys, key_material_priv, datasize, "application/pgp-keys",
"file://pEpkey_priv.asc");
@ -112,6 +120,13 @@ static PEP_STATUS _generate_reset_structs(PEP_SESSION session,
*key_attachments = keys;
}
return status;
pEp_error:
free(key_material_old);
free(key_material_new);
free(key_material_priv);
free_bloblist(keys);
return status;
}
// For multiple idents under a single key
@ -139,9 +154,11 @@ static PEP_STATUS _generate_own_commandlist_msg(PEP_SESSION session,
&kr_commands,
true);
if (status != PEP_STATUS_OK)
return status; // FIXME
if (!key_attachments || !kr_commands)
return PEP_UNKNOWN_ERROR;
goto pEp_error;
if (!key_attachments || !kr_commands) {
status = PEP_UNKNOWN_ERROR;
goto pEp_error;
}
}
}
@ -154,7 +171,7 @@ static PEP_STATUS _generate_own_commandlist_msg(PEP_SESSION session,
size_t size = 0;
status = key_reset_commands_to_PER(kr_commands, &payload, &size);
if (status != PEP_STATUS_OK)
return status;
goto pEp_error;
// From and to our first ident - this only goes to us.
pEp_identity* from = identity_dup(from_idents->ident);
@ -163,17 +180,22 @@ static PEP_STATUS _generate_own_commandlist_msg(PEP_SESSION session,
BASE_KEYRESET, payload, size, NULL,
&msg);
if (status != PEP_STATUS_OK) {
free(msg);
return status;
if (status != PEP_STATUS_OK)
goto pEp_error;
if (!msg) {
status = PEP_OUT_OF_MEMORY;
goto pEp_error;
}
if (!msg->attachments) {
status = PEP_UNKNOWN_ERROR;
goto pEp_error;
}
if (!msg)
return PEP_OUT_OF_MEMORY;
if (!msg->attachments)
return PEP_UNKNOWN_ERROR;
if (!bloblist_join(msg->attachments, key_attachments))
return PEP_UNKNOWN_ERROR;
if (!bloblist_join(msg->attachments, key_attachments)) {
status = PEP_UNKNOWN_ERROR;
goto pEp_error;
}
if (msg)
*dst = msg;
@ -181,7 +203,16 @@ static PEP_STATUS _generate_own_commandlist_msg(PEP_SESSION session,
free_keyreset_command_list(kr_commands);
return status;
pEp_error:
if (!msg)
free_bloblist(key_attachments);
else
free(msg);
free_keyreset_command_list(kr_commands);
return status;
}
static PEP_STATUS _generate_keyreset_command_message(PEP_SESSION session,
@ -195,8 +226,7 @@ static PEP_STATUS _generate_keyreset_command_message(PEP_SESSION session,
if (!session || !from_ident || !old_fpr || !new_fpr || !dst)
return PEP_ILLEGAL_VALUE;
// safe cast
if (!is_me(session, (pEp_identity*)from_ident))
if (!is_me(session, from_ident))
return PEP_ILLEGAL_VALUE;
PEP_STATUS status = PEP_STATUS_OK;
@ -225,29 +255,41 @@ static PEP_STATUS _generate_keyreset_command_message(PEP_SESSION session,
&key_attachments,
&kr_list,
is_private);
// N.B. command list and key attachments are freed by
// _generate_reset_structs when status is not OK
if (status != PEP_STATUS_OK)
return status; // FIXME
return status;
if (!key_attachments || !kr_list)
return PEP_UNKNOWN_ERROR;
char* payload = NULL;
size_t size = 0;
status = key_reset_commands_to_PER(kr_list, &payload, &size);
if (status != PEP_STATUS_OK)
return status;
status = base_prepare_message(session, outgoing_ident, to_ident,
BASE_KEYRESET, payload, size, NULL,
&msg);
if (status) {
if (status != PEP_STATUS_OK) {
free(msg);
return status;
}
if (!msg)
return PEP_OUT_OF_MEMORY;
if (!msg->attachments)
if (!msg->attachments) {
free(msg);
return PEP_UNKNOWN_ERROR;
}
if (msg)
*dst = msg;
return status;
}
PEP_STATUS has_key_reset_been_sent(
@ -398,6 +440,8 @@ PEP_STATUS receive_key_reset(PEP_SESSION session,
if (!sender_id->user_id)
return PEP_UNKNOWN_ERROR;
}
if (status != PEP_STATUS_OK) // Do we need to be more specific??
return status;
bool sender_own_key = false;
bool from_me = is_me(session, sender_id);
@ -503,7 +547,9 @@ PEP_STATUS receive_key_reset(PEP_SESSION session,
free(curr_ident->user_id);
curr_ident->user_id = NULL;
status = update_identity(session, curr_ident);
if (status != PEP_STATUS_OK)
return status;
// Ok, now check the old fpr to see if we have an entry for it
// temp fpr set for function call
curr_ident->fpr = old_fpr;
@ -577,6 +623,9 @@ PEP_STATUS receive_key_reset(PEP_SESSION session,
status = replace_main_user_fpr_if_equal(session, curr_ident->user_id,
new_fpr, old_fpr);
if (status != PEP_STATUS_OK)
return status;
// This only sets as the default, does NOT TRUST IN ANY WAY
PEP_comm_type new_key_rating = PEP_ct_unknown;
@ -722,8 +771,10 @@ PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
if (!reset_msg)
return PEP_ILLEGAL_VALUE;
if (!reset_msg->attachments)
return PEP_UNKNOWN_ERROR;
if (!reset_msg->attachments) {
status = PEP_UNKNOWN_ERROR;
goto pEp_free;
}
message* output_msg = NULL;
@ -733,6 +784,8 @@ PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
if (status == PEP_STATUS_OK)
*dst = output_msg;
else if (output_msg) // shouldn't happen, but...
free_message(output_msg);
pEp_free:
@ -919,6 +972,67 @@ static PEP_STATUS _dup_grouped_only(identity_list* idents, identity_list** filte
return PEP_STATUS_OK;
}
static PEP_STATUS _check_own_reset_passphrase_readiness(PEP_SESSION session,
const char* key) {
// Check generation setup
// Because of the above, we can support a signing passphrase
// that differs from the generation passphrase. We'll
// just check to make sure everything is in order for
// later use, however
if (session->new_key_pass_enable) {
if (EMPTYSTR(session->generation_passphrase))
return PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED;
}
stringlist_t* test_key = NULL;
// Be sure we HAVE this key
PEP_STATUS status = find_keys(session, key, &test_key);
bool exists_key = test_key != NULL;
free_stringlist(test_key);
if (!exists_key || status == PEP_KEY_NOT_FOUND) {
remove_fpr_as_default(session, key);
return PEP_KEY_NOT_FOUND;
}
if (status != PEP_STATUS_OK)
return status;
ensure_passphrase_t ensure_key_cb = session->ensure_passphrase;
// Check to see that this key has its passphrase set as the configured
// passphrase, IF it has one. If not, bail early.
status = probe_encrypt(session, key);
if (PASS_ERROR(status)) {
if (ensure_key_cb)
status = ensure_key_cb(session, key);
}
if (status != PEP_STATUS_OK)
return status;
if (EMPTYSTR(session->curr_passphrase) && !EMPTYSTR(session->generation_passphrase)) {
// We'll need it as the current passphrase to sign
// messages with the generated keys
config_passphrase(session, session->generation_passphrase);
}
return PEP_STATUS_OK;
}
// This is for ONE specific key, but possibly many identities
// We could have ONE return for PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED
// and another for PEP_PASSPHRASE_REQUIRED/PEP_WRONG_PASSPHRASE
// State would advance though, it just might need to be called
// twice with correct passwords, and more without.
// (In other words, with multiple passwords, this is not the end of all things)
//
// N.B. This function presumes that ALL idents in this group have the
// key in question as their main key. That's what this function
// was created for.
// FIXME:
// I am not sure this is safe with already-revoked keys.
//
static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
identity_list* key_idents,
const char* old_key,
@ -929,19 +1043,33 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
if (!session || !key_idents || EMPTYSTR(old_key))
return PEP_ILLEGAL_VALUE;
messageToSend_t send_cb = session->messageToSend;
if (!send_cb)
return PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
PEP_STATUS status = PEP_STATUS_OK;
message* enc_msg = NULL;
message* outmsg = NULL;
stringlist_t* test_key = NULL;
// Make sure the signing password is set correctly and that
// we are also ready for keygen
status = _check_own_reset_passphrase_readiness(session, old_key);
if (status != PEP_STATUS_OK)
return status;
char* cached_passphrase = EMPTYSTR(session->curr_passphrase) ? NULL : strdup(session->curr_passphrase);
// if we only want grouped identities, we do this:
if (grouped_only) {
identity_list* new_list = NULL;
status = _dup_grouped_only(key_idents, &new_list);
if (status != PEP_STATUS_OK)
return status;
goto pEp_error;
key_idents = new_list; // local var change, won't impact caller
}
@ -956,47 +1084,70 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
ident->fpr = NULL;
status = _generate_keypair(session, ident, true);
if (status != PEP_STATUS_OK)
return status;
goto pEp_error;
}
// Ok, everyone's got a new keypair. Hoorah!
// generate, sign, and push messages into queue
message* outmsg = NULL;
//
// Because we have to export the NEW secret keys,
// we have to switch in the passgen key
// as the configured key. We'll switch it back
// afterward (no revocation, decrypt, or signing
// with the old key happens in here)
config_passphrase(session, session->generation_passphrase);
status = _generate_own_commandlist_msg(session,
key_idents,
old_key,
&outmsg);
config_passphrase(session, cached_passphrase);
// Key-based errors here shouldn't happen.
if (status != PEP_STATUS_OK)
goto pEp_error;
// Following will only be true if some idents were grouped,
// and will only include grouped idents!
// and will only include grouped idents!
// Will be signed with old signing key.
// (Again, see the FIXME - we need to figure oout what
// happens if it got revoked externally)
if (outmsg) {
message* enc_msg = NULL;
// encrypt this baby and get out
// extra keys???
status = encrypt_message(session, outmsg, NULL, &enc_msg, PEP_enc_auto, PEP_encrypt_flag_key_reset_only);
if (status != PEP_STATUS_OK) {
goto pEp_free;
}
if (status != PEP_STATUS_OK)
goto pEp_error;
_add_auto_consume(enc_msg);
// insert into queue
status = send_cb(enc_msg);
if (status != PEP_STATUS_OK) {
free(enc_msg);
goto pEp_free;
}
if (status != PEP_STATUS_OK)
goto pEp_error;
}
// Ok, we've signed everything we need to with the old key,
// Revoke that baby.
status = revoke_key(session, old_key, NULL);
// again, we should not have key-related issues here,
// as we ensured the correct password earlier
if (status != PEP_STATUS_OK)
goto pEp_free;
goto pEp_error;
// Ok, NOW - the current password needs to be swapped out
// because we're going to sign with keys using it.
//
// All new keys have the same passphrase, if any
//
config_passphrase(session, session->generation_passphrase);
for (curr_ident = key_idents; curr_ident && curr_ident->ident; curr_ident = curr_ident->next) {
if (curr_ident->ident->flags & PEP_idf_devicegroup) {
pEp_identity* ident = curr_ident->ident;
@ -1006,10 +1157,10 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
char* new_key = ident->fpr;
ident->fpr = NULL;
status = set_own_key(session, ident, new_key);
if (status != PEP_STATUS_OK) {
if (status != PEP_STATUS_OK)
// scream loudly and cry, then hang head in shame
return status;
}
goto pEp_error;
free(ident->fpr);
// release ownership to the struct again
@ -1021,7 +1172,7 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
status = set_revoked(session, old_key, new_key, time(NULL));
if (status != PEP_STATUS_OK)
goto pEp_free;
goto pEp_error;
// Whether new_key is NULL or not, if this key is equal to the current user default, we
// replace it.
@ -1031,12 +1182,12 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
old_key);
if (status != PEP_STATUS_OK)
goto pEp_free;
goto pEp_error;
pEp_identity* tmp_ident = identity_dup(ident);
if (!tmp_ident) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
goto pEp_error;
}
free(tmp_ident->fpr);
@ -1045,24 +1196,36 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
tmp_ident->fpr = strdup(old_key); // freed in free_identity
if (status == PEP_STATUS_OK)
status = send_key_reset_to_recents(session, tmp_ident, old_key, ident->fpr);
if (status != PEP_STATUS_OK)
goto pEp_error;
free_identity(tmp_ident);
}
}
config_passphrase(session, cached_passphrase);
if (status == PEP_STATUS_OK)
// cascade that mistrust for anyone using this key
status = mark_as_compromised(session, old_key);
status = mark_as_compromised(session, old_key);
if (status == PEP_STATUS_OK)
status = remove_fpr_as_default(session, old_key);
if (status == PEP_STATUS_OK)
status = add_mistrusted_key(session, old_key);
pEp_free:
return status;
pEp_error:
// Just in case
config_passphrase(session, cached_passphrase);
free_stringlist(test_key);
free_message(outmsg);
free_message(enc_msg);
free(cached_passphrase);
return status;
}
DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session) {
assert(session);
@ -1080,7 +1243,7 @@ DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session) {
status = get_all_keys_for_user(session, user_id, &keys);
// TODO: free
if (status == PEP_STATUS_OK) {
if (status == PEP_STATUS_OK) {
stringlist_t* curr_key;
for (curr_key = keys; curr_key && curr_key->value; curr_key = curr_key->next) {
@ -1097,6 +1260,16 @@ DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session) {
else
goto pEp_free;
// This is in a switch because our return statuses COULD get more
// complicated
switch (status) {
case PEP_STATUS_OK:
case PEP_KEY_NOT_FOUND: // call removed it as a default
break;
default:
goto pEp_free;
}
free_identity_list(key_idents);
}
}
@ -1108,8 +1281,6 @@ pEp_free:
return status;
}
// Notes to integrate into header:
// IF there is an ident, it must have a user_id.
PEP_STATUS key_reset(
PEP_SESSION session,
const char* key_id,
@ -1129,6 +1300,8 @@ PEP_STATUS key_reset(
identity_list* key_idents = NULL;
stringlist_t* keys = NULL;
char* cached_passphrase = EMPTYSTR(session->curr_passphrase) ? NULL : strdup(session->curr_passphrase);
if (!EMPTYSTR(key_id)) {
fpr_copy = strdup(key_id);
if (!fpr_copy)
@ -1228,7 +1401,7 @@ PEP_STATUS key_reset(
// case of own identities with private keys.
if (is_own_private) {
// This is now the "is_own" base case - we don't do this
// per-identity, because all identities using this key will
// need new ones. That said, this is really only a problem
@ -1250,6 +1423,14 @@ PEP_STATUS key_reset(
if (is_grouped)
status = _key_reset_device_group_for_shared_key(session, key_idents, fpr_copy, false);
else if (status == PEP_STATUS_OK) {
// KB: FIXME_NOW - revoked?
// Make sure we can even progress - if there are passphrase issues,
// bounce back to the caller now, because our attempts to make it work failed,
// even possibly with callback.
status = _check_own_reset_passphrase_readiness(session, fpr_copy);
if (status != PEP_STATUS_OK)
return status;
// now have ident list, or should
identity_list* curr_ident;
@ -1260,10 +1441,14 @@ PEP_STATUS key_reset(
// Do the full reset on this identity
// Base case for is_own_private starts here
// Note that we reset this key for ANY own ident that has it. And if
// tmp_ident did NOT have this key, it won't matter. We will reset the
// tmp_ident did NOT have this key, it won't matter. We will reset this
// key for all idents for this user.
status = revoke_key(session, fpr_copy, NULL);
// Should never happen, we checked this, but STILL.
if (PASS_ERROR(status))
goto pEp_free;
// If we have a full identity, we have some cleanup and generation tasks here
if (!EMPTYSTR(this_ident->address)) {
// generate new key
@ -1308,10 +1493,14 @@ PEP_STATUS key_reset(
// for all active communication partners:
// active_send revocation
config_passphrase(session, session->generation_passphrase);
tmp_ident->fpr = fpr_copy;
if (status == PEP_STATUS_OK)
status = send_key_reset_to_recents(session, this_ident, fpr_copy, new_key);
config_passphrase(session, cached_passphrase);
tmp_ident->fpr = NULL;
if (PASS_ERROR(status))
goto pEp_free; // should NOT happen
}
// Whether new_key is NULL or not, if this key is equal to the current user default, we
@ -1323,8 +1512,10 @@ PEP_STATUS key_reset(
// we got an error and want to bail anyway.
goto pEp_free;
}
else
return PEP_CANNOT_FIND_IDENTITY;
else {
status = PEP_CANNOT_FIND_IDENTITY;
goto pEp_free;
}
} // end is_own_private
else {
// if it's mistrusted, make it not be so.
@ -1366,7 +1557,9 @@ pEp_free:
free(own_id);
free_identity_list(key_idents);
free_stringlist(keys);
free(new_key);
free(new_key);
config_passphrase(session, cached_passphrase);
free(cached_passphrase);
return status;
}


+ 3
- 0
src/key_reset.h View File

@ -90,6 +90,8 @@ DYNAMIC_API PEP_STATUS key_reset_user(
DYNAMIC_API PEP_STATUS key_reset_all_own_keys(PEP_SESSION session);
// FIXME: Doc
// This is simply NOT SAFE for multiple passwords on the extant
// keys. Cannot be called with multiple passwords for that purpose.
DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session);
// key_reset() - reset the database status for a key, removing all trust information
@ -116,6 +118,7 @@ DYNAMIC_API PEP_STATUS key_reset_own_grouped_keys(PEP_SESSION session);
// if NULL and fpr is non-NULL, we'll reset the key for all
// associated identities. If both ident and fpr are NULL, see
// the fpr arg documentation.
// ***IF there is an ident, it must have a user_id.***
//
// Note: ident->fpr is always ignored
//


+ 182
- 89
src/keymanagement.c View File

@ -11,6 +11,7 @@
#include "pEp_internal.h"
#include "keymanagement.h"
#include "KeySync_fsm.h"
#include "blacklist.h"
@ -39,6 +40,7 @@ static bool key_matches_address(PEP_SESSION session, const char* address,
return retval;
}
// Does not return PASSPHRASE errors
PEP_STATUS elect_pubkey(
PEP_SESSION session, pEp_identity * identity, bool check_blacklist
)
@ -106,10 +108,13 @@ PEP_STATUS elect_pubkey(
// own_must_contain_private is usually true when calling;
// we only set it to false when we have the idea of
// possibly having an own pubkey that we need to check on its own
// N.B. Checked for PASSPHRASE errors - will now return them always
// False value of "renew_private" prevents their possibility, though.
PEP_STATUS validate_fpr(PEP_SESSION session,
pEp_identity* ident,
bool check_blacklist,
bool own_must_contain_private) {
bool own_must_contain_private,
bool renew_private) {
PEP_STATUS status = PEP_STATUS_OK;
@ -121,6 +126,7 @@ PEP_STATUS validate_fpr(PEP_SESSION session,
bool has_private = false;
status = contains_priv_key(session, fpr, &has_private);
// N.B. Will not contain PEP_PASSPHRASE related returns here
if (ident->me && own_must_contain_private) {
if (status != PEP_STATUS_OK || !has_private)
return PEP_KEY_UNSUITABLE;
@ -173,6 +179,7 @@ PEP_STATUS validate_fpr(PEP_SESSION session,
bool revoked, expired;
bool blacklisted = false;
// Should not need to decrypt key material
status = key_revoked(session, fpr, &revoked);
if (status != PEP_STATUS_OK) {
@ -182,11 +189,12 @@ PEP_STATUS validate_fpr(PEP_SESSION session,
if (!revoked) {
time_t exp_time = (ident->me ?
time(NULL) + (7*24*3600) : time(NULL));
// Should not need to decrypt key material
status = key_expired(session, fpr,
exp_time,
&expired);
assert(status == PEP_STATUS_OK);
if (status != PEP_STATUS_OK)
return status;
@ -202,7 +210,9 @@ PEP_STATUS validate_fpr(PEP_SESSION session,
}
}
if (ident->me && has_private &&
// Renew key if it's expired, our own, has a private part,
// isn't too weak, and we didn't say "DON'T DO THIS"
if (renew_private && ident->me && has_private &&
(ct >= PEP_ct_strong_but_unconfirmed) &&
!revoked && expired) {
// extend key
@ -210,6 +220,9 @@ PEP_STATUS validate_fpr(PEP_SESSION session,
status = renew_key(session, fpr, ts);
free_timestamp(ts);
if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE)
return status;
if (status == PEP_STATUS_OK) {
// if key is valid (second check because pEp key might be extended above)
// Return fpr
@ -338,6 +351,11 @@ PEP_STATUS get_user_default_key(PEP_SESSION session, const char* user_id,
// Also, we presume that if the stored_identity was sent in
// without an fpr, there wasn't one in the trust DB for this
// identity.
//
// Will now NOT return passphrase errors, as we tell
// validate_fpr NOT to renew it. And we specifically suppress them
// with "PEP_KEY_UNSUITABLE"
//
PEP_STATUS get_valid_pubkey(PEP_SESSION session,
pEp_identity* stored_identity,
bool* is_identity_default,
@ -357,19 +375,28 @@ PEP_STATUS get_valid_pubkey(PEP_SESSION session,
PEP_STATUS first_reject_status = PEP_KEY_NOT_FOUND;
char* stored_fpr = stored_identity->fpr;
// Input: stored identity retrieved from database
// if stored identity contains a default key
if (!EMPTYSTR(stored_fpr)) {
status = validate_fpr(session, stored_identity, check_blacklist, true);
if (status == PEP_STATUS_OK && !EMPTYSTR(stored_identity->fpr)) {
*is_identity_default = *is_address_default = true;
return status;
}
else if (status != PEP_KEY_NOT_FOUND) {
first_reject_status = status;
first_reject_comm_type = stored_identity->comm_type;
}
}
// Won't ask for passphrase, won't return PASSPHRASE status
// Because of non-renewal
status = validate_fpr(session, stored_identity, check_blacklist, true, false);
switch (status) {
case PEP_STATUS_OK:
if (!EMPTYSTR(stored_identity->fpr)) {
*is_identity_default = *is_address_default = true;
return status;
}
break;
case PEP_KEY_NOT_FOUND:
break;
default:
first_reject_status = status;
first_reject_comm_type = stored_identity->comm_type;
}
}
// if no valid default stored identity key found
free(stored_identity->fpr);
stored_identity->fpr = NULL;
@ -380,24 +407,38 @@ PEP_STATUS get_valid_pubkey(PEP_SESSION session,
if (!EMPTYSTR(user_fpr)) {
// There exists a default key for user, so validate
stored_identity->fpr = user_fpr;
status = validate_fpr(session, stored_identity, check_blacklist, true);
if (status == PEP_STATUS_OK && stored_identity->fpr) {
*is_user_default = true;
*is_address_default = key_matches_address(session,
stored_identity->address,
stored_identity->fpr);
return status;
}
else if (status != PEP_KEY_NOT_FOUND && first_reject_status != PEP_KEY_NOT_FOUND) {
first_reject_status = status;
first_reject_comm_type = stored_identity->comm_type;
}
// Won't ask for passphrase, won't return PASSPHRASE status
// Because of non-renewal
status = validate_fpr(session, stored_identity, check_blacklist, true, false);
switch (status) {
case PEP_STATUS_OK:
if (!EMPTYSTR(stored_identity->fpr)) {
*is_user_default = true;
*is_address_default = key_matches_address(session,
stored_identity->address,
stored_identity->fpr);
return status;
}
break;
case PEP_KEY_NOT_FOUND:
break;
default:
if (first_reject_status != PEP_KEY_NOT_FOUND) {
first_reject_status = status;
first_reject_comm_type = stored_identity->comm_type;
}
}
}
status = elect_pubkey(session, stored_identity, check_blacklist);
if (status == PEP_STATUS_OK) {
if (!EMPTYSTR(stored_identity->fpr))
validate_fpr(session, stored_identity, false, true); // blacklist already filtered of needed
if (!EMPTYSTR(stored_identity->fpr)) {
// Won't ask for passphrase, won't return PASSPHRASE status
// Because of non-renewal
status = validate_fpr(session, stored_identity, false, true, false); // blacklist already filtered of needed
}
}
else if (status != PEP_KEY_NOT_FOUND && first_reject_status != PEP_KEY_NOT_FOUND) {
first_reject_status = status;
@ -425,6 +466,11 @@ PEP_STATUS get_valid_pubkey(PEP_SESSION session,
}
break;
}
// should never happen, but we will MAKE sure
if (PASS_ERROR(status))
status = PEP_KEY_UNSUITABLE; // renew it on your own time, baby
return status;
}
@ -463,6 +509,11 @@ static void adjust_pEp_trust_status(PEP_SESSION session, pEp_identity* identity)
}
// NEVER called on an own identity.
// But we also make sure get_valid_pubkey
// and friends NEVER return with a password error.
// (get_valid_pubkey tells validate_fpr not to try renewal)
// Will not return PASSPHRASE errors.
static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
pEp_identity* return_id,
pEp_identity* stored_ident,
@ -480,29 +531,31 @@ static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
&is_identity_default,
&is_user_default,
&is_address_default,
false);
if (status == PEP_STATUS_OK && stored_ident->fpr && *(stored_ident->fpr) != '\0') {
// set identity comm_type from trust db (user_id, FPR)
status = get_trust(session, stored_ident);
if (status == PEP_CANNOT_FIND_IDENTITY || stored_ident->comm_type == PEP_ct_unknown) {
// This is OK - there is no trust DB entry, but we
// found a key. We won't store this, but we'll
// use it.
PEP_comm_type ct = PEP_ct_unknown;
status = get_key_rating(session, stored_ident->fpr, &ct);
stored_ident->comm_type = ct;
}
}
else if (status != PEP_STATUS_OK) {
free(stored_ident->fpr);
stored_ident->fpr = NULL;
stored_ident->comm_type = PEP_ct_key_not_found;
}
else { // no key returned, but status ok?
if (stored_ident->comm_type == PEP_ct_unknown)
stored_ident->comm_type = PEP_ct_key_not_found;
false);
switch (status) {
case PEP_STATUS_OK:
if (!EMPTYSTR(stored_ident->fpr)) {
// set identity comm_type from trust db (user_id, FPR)
status = get_trust(session, stored_ident);
if (status == PEP_CANNOT_FIND_IDENTITY || stored_ident->comm_type == PEP_ct_unknown) {
// This is OK - there is no trust DB entry, but we
// found a key. We won't store this, but we'll
// use it.
PEP_comm_type ct = PEP_ct_unknown;
status = get_key_rating(session, stored_ident->fpr, &ct);
stored_ident->comm_type = ct;
}
}
else if (stored_ident->comm_type == PEP_ct_unknown)
stored_ident->comm_type = PEP_ct_key_not_found;
break;
default:
free(stored_ident->fpr);
stored_ident->fpr = NULL;
stored_ident->comm_type = PEP_ct_key_not_found;
}
free(return_id->fpr);
return_id->fpr = NULL;
if (status == PEP_STATUS_OK && !EMPTYSTR(stored_ident->fpr))
@ -582,6 +635,8 @@ static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
return status;
}
// Should not return PASSPHRASE errors because we force
// calls that can cause key renewal not to.
DYNAMIC_API PEP_STATUS update_identity(
PEP_SESSION session, pEp_identity * identity
)
@ -629,7 +684,8 @@ DYNAMIC_API PEP_STATUS update_identity(
if (_own_addr) {
free(identity->user_id);
identity->user_id = strdup(default_own_id);
return _myself(session, identity, false, false, true);
// Do not renew, do not generate
return _myself(session, identity, false, false, false, true);
}
}
}
@ -1052,7 +1108,8 @@ PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
PEP_STATUS _myself(PEP_SESSION session,
pEp_identity * identity,
bool do_keygen,
bool do_keygen,
bool do_renew,
bool ignore_flags,
bool read_only)
{
@ -1139,7 +1196,10 @@ PEP_STATUS _myself(PEP_SESSION session,
// Set usernames - priority is input username > stored name > address
// If there's an input username, we always patch the username with that
// input.
if (EMPTYSTR(identity->username) || read_only) {
// N.B. there was an || read_only here, but why? read_only ONLY means
// we don't write to the DB! So... removed. But how this managed to work
// before I don't know.
if (EMPTYSTR(identity->username)) {
bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
char* uname = (stored_uname ? stored_identity->username : identity->address);
if (uname) {
@ -1164,34 +1224,43 @@ PEP_STATUS _myself(PEP_SESSION session,
if (stored_identity) {
if (!EMPTYSTR(stored_identity->fpr)) {
// Fall back / retrieve
status = validate_fpr(session, stored_identity, false, true);
if (status == PEP_OUT_OF_MEMORY)
goto pEp_free;
if (status == PEP_STATUS_OK) {
if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
identity->fpr = strdup(stored_identity->fpr);
assert(identity->fpr);
if (!identity->fpr) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
valid_key_found = true;
}
else {
bool revoked = false;
status = key_revoked(session, stored_identity->fpr, &revoked);
if (status)
goto pEp_free;
if (revoked) {
revoked_fpr = strdup(stored_identity->fpr);
assert(revoked_fpr);
if (!revoked_fpr) {
status = validate_fpr(session, stored_identity, false, true, do_renew);
switch (status) {
// Only possible if we called this with do_renew = true
case PEP_OUT_OF_MEMORY:
case PEP_PASSPHRASE_REQUIRED:
case PEP_WRONG_PASSPHRASE:
goto pEp_free;
case PEP_STATUS_OK:
if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
identity->fpr = strdup(stored_identity->fpr);
assert(identity->fpr);
if (!identity->fpr) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
valid_key_found = true;
}
}
}
else {
bool revoked = false;
status = key_revoked(session, stored_identity->fpr, &revoked);
if (status)
goto pEp_free;
if (revoked) {
revoked_fpr = strdup(stored_identity->fpr);
assert(revoked_fpr);
if (!revoked_fpr) {
status = PEP_OUT_OF_MEMORY;
goto pEp_free;
}
}
}
break;
default:
break;
}
}
// reconcile language, flags
transfer_ident_lang_and_flags(identity, stored_identity);
@ -1209,6 +1278,9 @@ PEP_STATUS _myself(PEP_SESSION session,
status = generate_keypair(session, identity);
assert(status != PEP_OUT_OF_MEMORY);
if (status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
goto pEp_free;
if (status != PEP_STATUS_OK) {
char buf[11];
snprintf(buf, 11, "%d", status); // uh, this is kludgey. FIXME
@ -1260,7 +1332,7 @@ pEp_free:
DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
{
return _myself(session, identity, true, false, false);
return _myself(session, identity, true, true, false, false);
}
DYNAMIC_API PEP_STATUS register_examine_function(
@ -1286,7 +1358,8 @@ DYNAMIC_API PEP_STATUS do_keymanagement(
{
PEP_SESSION session;
pEp_identity *identity;
PEP_STATUS status = init(&session, NULL, NULL);
// FIXME_NOW: ensure_decrypt callback???
PEP_STATUS status = init(&session, NULL, NULL, NULL);
assert(!status);
if (status)
return status;
@ -1490,6 +1563,12 @@ pEp_free:
return status;
}
// Technically speaking, this should not EVER
// return PASSPHRASE errors, because
// this is never for an own identity (enforced), and thus
// validate_fpr will not call renew_key.
// If it ever does, the status gets propagated, but
// it is distinctly not OK.
DYNAMIC_API PEP_STATUS trust_personal_key(
PEP_SESSION session,
pEp_identity *ident
@ -1537,7 +1616,7 @@ DYNAMIC_API PEP_STATUS trust_personal_key(
// Set up a temp trusted identity for the input fpr without a comm type;
tmp_id = new_identity(ident->address, ident->fpr, ident->user_id, NULL);
status = validate_fpr(session, tmp_id, false, true);
status = validate_fpr(session, tmp_id, false, true, false);
if (status == PEP_STATUS_OK) {
// Validate fpr gets trust DB or, when that fails, key comm type. we checked
@ -1597,7 +1676,7 @@ DYNAMIC_API PEP_STATUS trust_personal_key(
if (!tmp_user_ident)
status = PEP_OUT_OF_MEMORY;
else {
status = validate_fpr(session, tmp_user_ident, false, true);
status = validate_fpr(session, tmp_user_ident, false, true, false);
if (status != PEP_STATUS_OK ||
tmp_user_ident->comm_type < PEP_ct_strong_but_unconfirmed ||
@ -1639,7 +1718,7 @@ DYNAMIC_API PEP_STATUS trust_own_key(
return PEP_ILLEGAL_VALUE;
// don't check blacklist or require a private key
PEP_STATUS status = validate_fpr(session, ident, false, false);
PEP_STATUS status = validate_fpr(session, ident, false, false, true);
if (status != PEP_STATUS_OK)
return status;
@ -1890,6 +1969,7 @@ DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **key
return _own_keys_retrieve(session, keylist, 0, true);
}
// Returns PASSPHRASE errors when necessary
DYNAMIC_API PEP_STATUS set_own_key(
PEP_SESSION session,
pEp_identity *me,
@ -1911,7 +1991,8 @@ DYNAMIC_API PEP_STATUS set_own_key(
if (me->fpr == fpr)
me->fpr = NULL;
status = _myself(session, me, false, true, false);
// renew if needed, but do not generate
status = _myself(session, me, false, true, true, false);
// we do not need a valid key but dislike other errors
if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE)
return status;
@ -1933,12 +2014,15 @@ DYNAMIC_API PEP_STATUS set_own_key(
if (!me->fpr)
return PEP_OUT_OF_MEMORY;
status = validate_fpr(session, me, false, true);
status = validate_fpr(session, me, false, true, true);
if (status)
return status;
me->comm_type = PEP_ct_pEp;
status = set_identity(session, me);
if (status == PEP_STATUS_OK)
signal_Sync_event(session, Sync_PR_keysync, SynchronizeGroupKeys, NULL);
return status;
}
@ -2047,7 +2131,10 @@ static PEP_STATUS _wipe_default_key_if_invalid(PEP_SESSION session,
if (!ident->fpr)
return PEP_OUT_OF_MEMORY;
PEP_STATUS keystatus = validate_fpr(session, ident, true, false);
PEP_STATUS keystatus = validate_fpr(session, ident, true, false, true);
if (PASS_ERROR(status))
return status;
switch (keystatus) {
case PEP_STATUS_OK:
// Check for non-renewable expiry and
@ -2066,7 +2153,8 @@ static PEP_STATUS _wipe_default_key_if_invalid(PEP_SESSION session,
}
free(cached_fpr);
if (status == PEP_STATUS_OK)
// This may have been for a user default, not an identity default.
if (status == PEP_STATUS_OK && !(EMPTYSTR(ident->address)))
status = myself(session, ident);
return status;
@ -2093,7 +2181,9 @@ DYNAMIC_API PEP_STATUS clean_own_key_defaults(PEP_SESSION session) {
if (!ident)
continue;
_wipe_default_key_if_invalid(session, ident);
status = _wipe_default_key_if_invalid(session, ident);
if (PASS_ERROR(status))
return status;
}
free_identity_list(idents);
@ -2117,8 +2207,11 @@ DYNAMIC_API PEP_STATUS clean_own_key_defaults(PEP_SESSION session) {
return status;
}
else if (user_default_key) {
pEp_identity* empty_user = new_identity(NULL, user_default_key, NULL, own_id);
_wipe_default_key_if_invalid(session, empty_user);
pEp_identity* empty_user = new_identity(NULL, user_default_key, own_id, NULL);
status = _wipe_default_key_if_invalid(session, empty_user);
if (PASS_ERROR(status))
return status;
free(user_default_key);
}
free(own_id);


+ 4
- 2
src/keymanagement.h View File

@ -117,6 +117,7 @@ DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity);
PEP_STATUS _myself(PEP_SESSION session,
pEp_identity * identity,
bool do_keygen,
bool do_renew,
bool ignore_flags,
bool read_only);
@ -432,8 +433,9 @@ PEP_STATUS get_valid_pubkey(PEP_SESSION session,
PEP_STATUS validate_fpr(PEP_SESSION session,
pEp_identity* ident,
bool check_blacklist,
bool own_must_contain_private);
bool own_must_contain_private,
bool renew_private);
#ifdef __cplusplus
}
#endif

+ 242
- 206
src/message_api.c View File

@ -13,6 +13,7 @@
#include "base64.h"
#include "resource_id.h"
#include "internal_format.h"
#include "keymanagement.h"
#include <assert.h>
#include <string.h>
@ -1375,18 +1376,24 @@ static PEP_rating keylist_rating(PEP_SESSION session, stringlist_t *keylist, cha
return rating;
}
// KB: Fixme - the first statement below is probably unnecessary now.
// Internal function WARNING:
// Only call this on an ident that might have its FPR set from retrieval!
// Should be called on ident that might have its FPR set from retrieval!
// (or on one without an fpr)
// We do not want myself() setting the fpr here.
//
// Cannot return passphrase statuses. No keygen or renewal allowed here.
static PEP_comm_type _get_comm_type(
PEP_SESSION session,
PEP_comm_type max_comm_type,
pEp_identity *ident
)
{
if (!ident)