You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2126 lines
72 KiB

8 years ago
8 years ago
7 years ago
8 years ago
8 years ago
8 years ago
4 years ago
4 years ago
4 years ago
8 years ago
7 years ago
5 years ago
5 years ago
8 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
1 year ago
1 year ago
1 year ago
1 year ago
4 years ago
4 years ago
8 years ago
8 years ago
8 years ago
7 years ago
3 years ago
3 years ago
8 years ago
8 years ago
4 years ago
3 years ago
8 years ago
8 years ago
4 years ago
7 years ago
8 years ago
8 years ago
8 years ago
4 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
3 years ago
2 years ago
2 years ago
  1. // This file is under GNU General Public License 3.0
  2. // see LICENSE.txt
  3. #include "platform.h"
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include "pEp_internal.h"
  10. #include "keymanagement.h"
  11. #include "KeySync_fsm.h"
  12. #include "blacklist.h"
  13. static bool key_matches_address(PEP_SESSION session, const char* address,
  14. const char* fpr) {
  15. if (!session || !address || !fpr)
  16. return false;
  17. bool retval = false;
  18. stringlist_t *keylist = NULL;
  19. PEP_STATUS status = find_keys(session, address, &keylist);
  20. if (status == PEP_STATUS_OK && keylist) {
  21. stringlist_t* curr = keylist;
  22. while (curr) {
  23. if (curr->value) {
  24. if (strcasecmp(curr->value, fpr)) {
  25. retval = true;
  26. break;
  27. }
  28. }
  29. curr = curr->next;
  30. }
  31. }
  32. free_stringlist(keylist);
  33. return retval;
  34. }
  35. // Does not return PASSPHRASE errors
  36. PEP_STATUS elect_pubkey(
  37. PEP_SESSION session, pEp_identity * identity, bool check_blacklist
  38. )
  39. {
  40. PEP_STATUS status;
  41. stringlist_t *keylist = NULL;
  42. char *_fpr = "";
  43. identity->comm_type = PEP_ct_unknown;
  44. status = find_keys(session, identity->address, &keylist);
  45. assert(status != PEP_OUT_OF_MEMORY);
  46. if (status == PEP_OUT_OF_MEMORY)
  47. return PEP_OUT_OF_MEMORY;
  48. if (!keylist || !keylist->value)
  49. identity->comm_type = PEP_ct_key_not_found;
  50. else {
  51. stringlist_t *_keylist;
  52. for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
  53. PEP_comm_type _comm_type_key;
  54. status = get_key_rating(session, _keylist->value, &_comm_type_key);
  55. assert(status != PEP_OUT_OF_MEMORY);
  56. if (status == PEP_OUT_OF_MEMORY) {
  57. free_stringlist(keylist);
  58. return PEP_OUT_OF_MEMORY;
  59. }
  60. if (_comm_type_key != PEP_ct_compromised &&
  61. _comm_type_key != PEP_ct_unknown)
  62. {
  63. if (identity->comm_type == PEP_ct_unknown ||
  64. _comm_type_key > identity->comm_type)
  65. {
  66. bool blacklisted = false;
  67. bool mistrusted = false;
  68. status = is_mistrusted_key(session, _keylist->value, &mistrusted);
  69. if (status == PEP_STATUS_OK && check_blacklist)
  70. status = blacklist_is_listed(session, _keylist->value, &blacklisted);
  71. if (status == PEP_STATUS_OK && !mistrusted && !blacklisted) {
  72. identity->comm_type = _comm_type_key;
  73. _fpr = _keylist->value;
  74. }
  75. }
  76. }
  77. }
  78. }
  79. free(identity->fpr);
  80. if (!_fpr || _fpr[0] == '\0')
  81. identity->fpr = NULL;
  82. else {
  83. identity->fpr = strdup(_fpr);
  84. if (identity->fpr == NULL) {
  85. free_stringlist(keylist);
  86. return PEP_OUT_OF_MEMORY;
  87. }
  88. }
  89. free_stringlist(keylist);
  90. return PEP_STATUS_OK;
  91. }
  92. // own_must_contain_private is usually true when calling;
  93. // we only set it to false when we have the idea of
  94. // possibly having an own pubkey that we need to check on its own
  95. // N.B. Checked for PASSPHRASE errors - will now return them always
  96. // False value of "renew_private" prevents their possibility, though.
  97. PEP_STATUS validate_fpr(PEP_SESSION session,
  98. pEp_identity* ident,
  99. bool check_blacklist,
  100. bool own_must_contain_private,
  101. bool renew_private) {
  102. PEP_STATUS status = PEP_STATUS_OK;
  103. if (!session || !ident || !ident->fpr || !ident->fpr[0])
  104. return PEP_ILLEGAL_VALUE;
  105. char* fpr = ident->fpr;
  106. bool has_private = false;
  107. status = contains_priv_key(session, fpr, &has_private);
  108. // N.B. Will not contain PEP_PASSPHRASE related returns here
  109. if (ident->me && own_must_contain_private) {
  110. if (status != PEP_STATUS_OK || !has_private)
  111. return PEP_KEY_UNSUITABLE;
  112. }
  113. else if (status != PEP_STATUS_OK && has_private) // should never happen
  114. has_private = false;
  115. ident->comm_type = PEP_ct_unknown;
  116. status = get_trust(session, ident);
  117. if (status != PEP_STATUS_OK)
  118. ident->comm_type = PEP_ct_unknown;
  119. PEP_comm_type ct = ident->comm_type;
  120. if (ct == PEP_ct_unknown) {
  121. // If status is bad, it's ok, we get the rating
  122. // we should use then (PEP_ct_unknown)
  123. get_key_rating(session, fpr, &ct);
  124. ident->comm_type = ct;
  125. }
  126. else if (ct == PEP_ct_key_expired || ct == PEP_ct_key_expired_but_confirmed) {
  127. PEP_comm_type ct_expire_check = PEP_ct_unknown;
  128. get_key_rating(session, fpr, &ct_expire_check);
  129. if (ct_expire_check >= PEP_ct_strong_but_unconfirmed) {
  130. ident->comm_type = ct_expire_check;
  131. if (ct == PEP_ct_key_expired_but_confirmed)
  132. ident->comm_type |= PEP_ct_confirmed;
  133. ct = ident->comm_type;
  134. // We need to fix this trust in the DB.
  135. status = set_trust(session, ident);
  136. }
  137. }
  138. bool pEp_user = false;
  139. is_pEp_user(session, ident, &pEp_user);
  140. if (pEp_user) {
  141. switch (ct) {
  142. case PEP_ct_OpenPGP:
  143. case PEP_ct_OpenPGP_unconfirmed:
  144. ct += 0x47; // difference between PEP and OpenPGP values;
  145. ident->comm_type = ct;
  146. break;
  147. default:
  148. break;
  149. }
  150. }
  151. bool revoked, expired;
  152. bool blacklisted = false;
  153. // Should not need to decrypt key material
  154. status = key_revoked(session, fpr, &revoked);
  155. if (status != PEP_STATUS_OK) {
  156. return status;
  157. }
  158. if (!revoked) {
  159. time_t exp_time = (ident->me ?
  160. time(NULL) + (7*24*3600) : time(NULL));
  161. // Should not need to decrypt key material
  162. status = key_expired(session, fpr,
  163. exp_time,
  164. &expired);
  165. assert(status == PEP_STATUS_OK);
  166. if (status != PEP_STATUS_OK)
  167. return status;
  168. if (check_blacklist && IS_PGP_CT(ct) &&
  169. !ident->me) {
  170. status = blacklist_is_listed(session,
  171. fpr,
  172. &blacklisted);
  173. if (status != PEP_STATUS_OK)
  174. return status;
  175. }
  176. }
  177. // Renew key if it's expired, our own, has a private part,
  178. // isn't too weak, and we didn't say "DON'T DO THIS"
  179. if (renew_private && ident->me && has_private &&
  180. (ct >= PEP_ct_strong_but_unconfirmed) &&
  181. !revoked && expired) {
  182. // extend key
  183. timestamp *ts = new_timestamp(time(NULL) + KEY_EXPIRE_DELTA);
  184. status = renew_key(session, fpr, ts);
  185. free_timestamp(ts);
  186. if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE)
  187. return status;
  188. if (status == PEP_STATUS_OK) {
  189. // if key is valid (second check because pEp key might be extended above)
  190. // Return fpr
  191. status = key_expired(session, fpr, time(NULL), &expired);
  192. if (status != PEP_STATUS_OK)
  193. return status;
  194. if (expired) {
  195. if (ident->comm_type & PEP_ct_confirmed || (ident->comm_type == PEP_ct_key_expired_but_confirmed))
  196. ident->comm_type = PEP_ct_key_expired_but_confirmed;
  197. else
  198. ident->comm_type = PEP_ct_key_expired;
  199. return status;
  200. }
  201. // communicate key(?)
  202. }
  203. }
  204. if (revoked)
  205. ct = PEP_ct_key_revoked;
  206. else if (expired) {
  207. if (ident->comm_type & PEP_ct_confirmed || (ident->comm_type == PEP_ct_key_expired_but_confirmed))
  208. ct = PEP_ct_key_expired_but_confirmed;
  209. else
  210. ct = PEP_ct_key_expired;
  211. }
  212. else if (blacklisted) { // never true for .me
  213. ident->comm_type = ct = PEP_ct_key_not_found;
  214. free(ident->fpr);
  215. ident->fpr = strdup("");
  216. status = PEP_KEY_BLACKLISTED;
  217. }
  218. switch (ct) {
  219. case PEP_ct_key_expired:
  220. case PEP_ct_key_expired_but_confirmed:
  221. case PEP_ct_key_revoked:
  222. case PEP_ct_key_b0rken:
  223. // delete key from being default key for all users/identities
  224. status = remove_fpr_as_default(session, fpr);
  225. status = update_trust_for_fpr(session,
  226. fpr,
  227. ct);
  228. case PEP_ct_mistrusted:
  229. free(ident->fpr);
  230. ident->fpr = NULL;
  231. ident->comm_type = ct;
  232. status = PEP_KEY_UNSUITABLE;
  233. default:
  234. break;
  235. }
  236. return status;
  237. }
  238. PEP_STATUS get_all_keys_for_user(PEP_SESSION session,
  239. const char* user_id,
  240. stringlist_t** keys) {
  241. if (!session || EMPTYSTR(user_id) || !keys)
  242. return PEP_ILLEGAL_VALUE;
  243. PEP_STATUS status = PEP_STATUS_OK;
  244. *keys = NULL;
  245. stringlist_t* _kl = NULL;
  246. sqlite3_reset(session->get_all_keys_for_user);
  247. sqlite3_bind_text(session->get_all_keys_for_user, 1, user_id, -1, SQLITE_STATIC);
  248. int result = -1;
  249. while ((result = sqlite3_step(session->get_all_keys_for_user)) == SQLITE_ROW) {
  250. const char* keyres = (const char *) sqlite3_column_text(session->get_all_keys_for_user, 0);
  251. if (keyres) {
  252. if (_kl)
  253. stringlist_add(_kl, keyres);
  254. else
  255. _kl = new_stringlist(keyres);
  256. }
  257. }
  258. if (!_kl)
  259. return PEP_KEY_NOT_FOUND;
  260. *keys = _kl;
  261. sqlite3_reset(session->get_all_keys_for_user);
  262. return status;
  263. }
  264. PEP_STATUS get_user_default_key(PEP_SESSION session, const char* user_id,
  265. char** default_key) {
  266. assert(session);
  267. assert(user_id);
  268. if (!session || !user_id)
  269. return PEP_ILLEGAL_VALUE;
  270. PEP_STATUS status = PEP_STATUS_OK;
  271. // try to get default key for user_data
  272. sqlite3_reset(session->get_user_default_key);
  273. sqlite3_bind_text(session->get_user_default_key, 1, user_id,
  274. -1, SQLITE_STATIC);
  275. const int result = sqlite3_step(session->get_user_default_key);
  276. char* user_fpr = NULL;
  277. if (result == SQLITE_ROW) {
  278. const char* u_fpr =
  279. (char *) sqlite3_column_text(session->get_user_default_key, 0);
  280. if (u_fpr)
  281. user_fpr = strdup(u_fpr);
  282. }
  283. else
  284. status = PEP_GET_KEY_FAILED;
  285. sqlite3_reset(session->get_user_default_key);
  286. *default_key = user_fpr;
  287. return status;
  288. }
  289. // Only call on retrieval of previously stored identity!
  290. // Also, we presume that if the stored_identity was sent in
  291. // without an fpr, there wasn't one in the trust DB for this
  292. // identity.
  293. //
  294. // Will now NOT return passphrase errors, as we tell
  295. // validate_fpr NOT to renew it. And we specifically suppress them
  296. // with "PEP_KEY_UNSUITABLE"
  297. //
  298. PEP_STATUS get_valid_pubkey(PEP_SESSION session,
  299. pEp_identity* stored_identity,
  300. bool* is_identity_default,
  301. bool* is_user_default,
  302. bool* is_address_default,
  303. bool check_blacklist) {
  304. PEP_STATUS status = PEP_STATUS_OK;
  305. if (!stored_identity || EMPTYSTR(stored_identity->user_id)
  306. || !is_identity_default || !is_user_default || !is_address_default)
  307. return PEP_ILLEGAL_VALUE;
  308. *is_identity_default = *is_user_default = *is_address_default = false;
  309. PEP_comm_type first_reject_comm_type = PEP_ct_key_not_found;
  310. PEP_STATUS first_reject_status = PEP_KEY_NOT_FOUND;
  311. char* stored_fpr = stored_identity->fpr;
  312. // Input: stored identity retrieved from database
  313. // if stored identity contains a default key; if so, we return from here
  314. if (!EMPTYSTR(stored_fpr)) {
  315. // Won't ask for passphrase, won't return PASSPHRASE status
  316. // Because of non-renewal
  317. status = validate_fpr(session, stored_identity, check_blacklist, true, false);
  318. switch (status) {
  319. case PEP_STATUS_OK:
  320. if (!EMPTYSTR(stored_identity->fpr)) {
  321. *is_identity_default = *is_address_default = true;
  322. return status;
  323. }
  324. break;
  325. case PEP_KEY_NOT_FOUND:
  326. break;
  327. default:
  328. first_reject_status = status;
  329. first_reject_comm_type = stored_identity->comm_type;
  330. }
  331. }
  332. // if no valid default stored identity key found
  333. free(stored_identity->fpr);
  334. stored_identity->fpr = NULL;
  335. char* user_fpr = NULL;
  336. status = get_user_default_key(session, stored_identity->user_id, &user_fpr);
  337. if (!EMPTYSTR(user_fpr)) {
  338. // There exists a default key for user, so validate
  339. stored_identity->fpr = user_fpr;
  340. // Won't ask for passphrase, won't return PASSPHRASE status
  341. // Because of non-renewal
  342. status = validate_fpr(session, stored_identity, check_blacklist, true, false);
  343. switch (status) {
  344. case PEP_STATUS_OK:
  345. if (!EMPTYSTR(stored_identity->fpr)) {
  346. *is_user_default = true;
  347. *is_address_default = key_matches_address(session,
  348. stored_identity->address,
  349. stored_identity->fpr);
  350. return status;
  351. }
  352. break;
  353. case PEP_KEY_NOT_FOUND:
  354. break;
  355. default:
  356. if (first_reject_status != PEP_KEY_NOT_FOUND) {
  357. first_reject_status = status;
  358. first_reject_comm_type = stored_identity->comm_type;
  359. }
  360. }
  361. }
  362. // If we got here, there's no usable default.
  363. // status = elect_pubkey(session, stored_identity, check_blacklist);
  364. // if (status == PEP_STATUS_OK) {
  365. // if (!EMPTYSTR(stored_identity->fpr)) {
  366. // // Won't ask for passphrase, won't return PASSPHRASE status
  367. // // Because of non-renewal
  368. // status = validate_fpr(session, stored_identity, false, true, false); // blacklist already filtered of needed
  369. // }
  370. // }
  371. // else if (status != PEP_KEY_NOT_FOUND && first_reject_status != PEP_KEY_NOT_FOUND) {
  372. // first_reject_status = status;
  373. // first_reject_comm_type = stored_identity->comm_type;
  374. // }
  375. switch (first_reject_comm_type) {
  376. case PEP_ct_key_revoked:
  377. case PEP_ct_key_b0rken:
  378. case PEP_ct_key_expired:
  379. case PEP_ct_key_expired_but_confirmed:
  380. case PEP_ct_compromised:
  381. case PEP_ct_mistrusted:
  382. // this only happens when it's all there is
  383. status = first_reject_status;
  384. free(stored_identity->fpr);
  385. stored_identity->fpr = NULL;
  386. stored_identity->comm_type = first_reject_comm_type;
  387. break;
  388. default:
  389. if (check_blacklist && status == PEP_KEY_BLACKLISTED) {
  390. free(stored_identity->fpr);
  391. stored_identity->fpr = NULL;
  392. stored_identity->comm_type = PEP_ct_key_not_found;
  393. }
  394. break;
  395. }
  396. // should never happen, but we will MAKE sure
  397. if (PASS_ERROR(status))
  398. status = PEP_KEY_UNSUITABLE; // renew it on your own time, baby
  399. return status;
  400. }
  401. static void transfer_ident_lang_and_flags(pEp_identity* new_ident,
  402. pEp_identity* stored_ident) {
  403. if (new_ident->lang[0] == 0) {
  404. new_ident->lang[0] = stored_ident->lang[0];
  405. new_ident->lang[1] = stored_ident->lang[1];
  406. new_ident->lang[2] = 0;
  407. }
  408. new_ident->flags = stored_ident->flags;
  409. new_ident->me = new_ident->me || stored_ident->me;
  410. }
  411. static void adjust_pEp_trust_status(PEP_SESSION session, pEp_identity* identity) {
  412. assert(session);
  413. assert(identity);
  414. if (identity->comm_type < PEP_ct_strong_but_unconfirmed ||
  415. (identity->comm_type | PEP_ct_confirmed) == PEP_ct_pEp)
  416. return;
  417. bool pEp_user;
  418. is_pEp_user(session, identity, &pEp_user);
  419. if (pEp_user) {
  420. PEP_comm_type confirmation_status = identity->comm_type & PEP_ct_confirmed;
  421. identity->comm_type = PEP_ct_pEp_unconfirmed | confirmation_status;
  422. if (identity->major_ver == 0) {
  423. identity->major_ver = 2;
  424. identity->minor_ver = 0;
  425. }
  426. }
  427. }
  428. // NEVER called on an own identity.
  429. // But we also make sure get_valid_pubkey
  430. // and friends NEVER return with a password error.
  431. // (get_valid_pubkey tells validate_fpr not to try renewal)
  432. // Will not return PASSPHRASE errors.
  433. static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
  434. pEp_identity* return_id,
  435. pEp_identity* stored_ident,
  436. bool store) {
  437. if (!session || !return_id || !stored_ident)
  438. return PEP_ILLEGAL_VALUE;
  439. PEP_STATUS status;
  440. bool is_identity_default, is_user_default, is_address_default;
  441. bool no_stored_default = EMPTYSTR(stored_ident->fpr);
  442. status = get_valid_pubkey(session, stored_ident,
  443. &is_identity_default,
  444. &is_user_default,
  445. &is_address_default,
  446. false);
  447. bool is_pEp = false;
  448. switch (status) {
  449. case PEP_STATUS_OK:
  450. if (!EMPTYSTR(stored_ident->fpr)) {
  451. // set identity comm_type from trust db (user_id, FPR)
  452. status = get_trust(session, stored_ident);
  453. if (status == PEP_CANNOT_FIND_IDENTITY || stored_ident->comm_type == PEP_ct_unknown) {
  454. // This is OK - there is no trust DB entry, but we
  455. // found a key. We won't store this, but we'll
  456. // use it.
  457. PEP_comm_type ct = PEP_ct_unknown;
  458. status = get_key_rating(session, stored_ident->fpr, &ct);
  459. stored_ident->comm_type = ct;
  460. }
  461. }
  462. else if (stored_ident->comm_type == PEP_ct_unknown)
  463. stored_ident->comm_type = PEP_ct_key_not_found;
  464. break;
  465. default:
  466. is_pEp_user(session, stored_ident, &is_pEp);
  467. if (is_pEp) {
  468. switch (stored_ident->comm_type) {
  469. case PEP_ct_key_expired:
  470. case PEP_ct_key_expired_but_confirmed:
  471. store = false;
  472. break;
  473. default:
  474. break;
  475. }
  476. }
  477. free(stored_ident->fpr);
  478. stored_ident->fpr = NULL;
  479. stored_ident->comm_type = PEP_ct_key_not_found;
  480. }
  481. free(return_id->fpr);
  482. return_id->fpr = NULL;
  483. if (status == PEP_STATUS_OK && !EMPTYSTR(stored_ident->fpr))
  484. return_id->fpr = strdup(stored_ident->fpr);
  485. return_id->comm_type = stored_ident->comm_type;
  486. // We patch the DB with the input username, but if we didn't have
  487. // one, we pull it out of storage if available.
  488. if (!EMPTYSTR(stored_ident->username)) {
  489. if (!EMPTYSTR(return_id->username) &&
  490. (strcasecmp(return_id->username, return_id->address) == 0)) {
  491. free(return_id->username);
  492. return_id->username = NULL;
  493. }
  494. if (EMPTYSTR(return_id->username)) {
  495. free(return_id->username);
  496. return_id->username = strdup(stored_ident->username);
  497. }
  498. }
  499. else {
  500. if (EMPTYSTR(return_id->username))
  501. return_id->username = strdup(return_id->address);
  502. }
  503. return_id->me = stored_ident->me;
  504. return_id->major_ver = stored_ident->major_ver;
  505. return_id->minor_ver = stored_ident->minor_ver;
  506. // FIXME: Do we ALWAYS do this? We probably should...
  507. if (EMPTYSTR(return_id->user_id)) {
  508. free(return_id->user_id);
  509. return_id->user_id = strdup(stored_ident->user_id);
  510. }
  511. adjust_pEp_trust_status(session, return_id);
  512. // Call set_identity() to store
  513. if (store && (is_identity_default || is_user_default) &&
  514. is_address_default) {
  515. // if we got an fpr which is default for either user
  516. // or identity AND is valid for this address, set in DB
  517. // as default
  518. status = set_identity(session, return_id);
  519. }
  520. else if (store && no_stored_default && !EMPTYSTR(return_id->fpr)
  521. && return_id->comm_type != PEP_ct_key_revoked
  522. && return_id->comm_type != PEP_ct_key_expired
  523. && return_id->comm_type != PEP_ct_key_expired_but_confirmed
  524. && return_id->comm_type != PEP_ct_mistrusted
  525. && return_id->comm_type != PEP_ct_key_b0rken) {
  526. // We would have stored this anyway for a first-time elected key. We just have an ident w/ no default already.
  527. status = set_identity(session, return_id);
  528. }
  529. else { // this is a key other than the default, but there IS a default (FIXME: fdik, do we really want behaviour below?)
  530. // Store without default fpr/ct, but return the fpr and ct
  531. // for current use
  532. char* save_fpr = return_id->fpr;
  533. PEP_comm_type save_ct = return_id->comm_type;
  534. return_id->fpr = NULL;
  535. return_id->comm_type = PEP_ct_unknown;
  536. if (store) {
  537. PEP_STATUS save_status = status;
  538. status = set_identity(session, return_id);
  539. if (save_status != PEP_STATUS_OK)
  540. status = save_status;
  541. }
  542. return_id->fpr = save_fpr;
  543. return_id->comm_type = save_ct;
  544. }
  545. transfer_ident_lang_and_flags(return_id, stored_ident);
  546. return_id->enc_format = stored_ident->enc_format;
  547. if (return_id->comm_type == PEP_ct_unknown)
  548. return_id->comm_type = PEP_ct_key_not_found;
  549. return status;
  550. }
  551. // Should not return PASSPHRASE errors because we force
  552. // calls that can cause key renewal not to.
  553. DYNAMIC_API PEP_STATUS update_identity(
  554. PEP_SESSION session, pEp_identity * identity
  555. )
  556. {
  557. PEP_STATUS status = PEP_STATUS_OK;
  558. assert(session);
  559. assert(identity);
  560. assert(!EMPTYSTR(identity->address));
  561. if (!(session && identity && !EMPTYSTR(identity->address)))
  562. return PEP_ILLEGAL_VALUE;
  563. //
  564. // Record some information about the input identity so that we don't keep
  565. // evaluating it
  566. //
  567. bool is_own_user = identity->me;
  568. bool input_has_user_id = !EMPTYSTR(identity->user_id);
  569. bool input_has_username = !EMPTYSTR(identity->username);
  570. bool input_has_real_id = input_has_user_id ? (strstr(identity->user_id, "TOFU_") != identity->user_id) : false;
  571. bool input_name_is_addr = input_has_username ? strcmp(identity->username, identity->address) == 0 : false;
  572. bool weak_input_name = input_name_is_addr || !input_has_username;
  573. char* default_own_id = NULL;
  574. pEp_identity* stored_ident = NULL;
  575. status = get_default_own_userid(session, &default_own_id);
  576. if (status == PEP_STATUS_OK || status == PEP_CANNOT_FIND_IDENTITY)
  577. status = PEP_STATUS_OK;
  578. else
  579. goto pEp_free;
  580. // To be clear, if an own identity comes in here, the only way we will accept
  581. // it is if the caller did not KNOW this, as indicated by the lack of a known
  582. // own user_id and identity->me being false.
  583. //
  584. // IF either of these are set, then the call will fail. If, however, we get
  585. // an identity which simply has the own address on it, we'll kindly call a read-only
  586. // version of myself.
  587. if (!is_own_user) {
  588. if (default_own_id) {
  589. if (input_has_user_id) {
  590. if (strcmp(default_own_id, identity->user_id) == 0) {
  591. is_own_user = true;
  592. }
  593. else {
  594. char* alias = NULL;
  595. if (get_userid_alias_default(session, identity->user_id, &alias) == PEP_STATUS_OK) {
  596. if (alias && strcmp(default_own_id, alias) == 0)
  597. is_own_user = true;
  598. free(alias);
  599. }
  600. }
  601. }
  602. else {
  603. // Check if own address. For now, this is a special case;
  604. // we try to require apps to send in user_ids, but must prevent
  605. // writes to an own identity from within THIS function
  606. // NOTE: These semantics MAY CHANGE.
  607. bool _own_addr = false;
  608. is_own_address(session, identity->address, &_own_addr);
  609. if (_own_addr) {
  610. free(identity->user_id);
  611. identity->user_id = strdup(default_own_id);
  612. // Do not renew, do not generate
  613. return _myself(session, identity, false, false, false, true);
  614. }
  615. }
  616. }
  617. // Otherwise, we don't even HAVE an own user yet, so we're ok.
  618. }
  619. if (is_own_user) {
  620. free(default_own_id);
  621. return PEP_ILLEGAL_VALUE;
  622. }
  623. // We have, at least, an address.
  624. // Retrieve stored identity information!
  625. //////////////////////////////////////////////////////////////////////////////////////////////////////
  626. // If we can get a starting identity from the database, do it. If we have a user_id (thank you, users),
  627. // this is pretty simple.
  628. //
  629. // Otherwise, we double-check that someone didn't pass in an own address (hey, if you don't give us a
  630. // user_id, we're have to guess somehow, and treating own identities like partner identities is dangerous).
  631. //////////////////////////////////////////////////////////////////////////////////////////////////////
  632. if (input_has_user_id) {
  633. // (we're gonna update the trust/fpr anyway, so we use the no-fpr-from-trust-db variant)
  634. // * do get_identity() to retrieve stored identity information
  635. status = get_identity_without_trust_check(session, identity->address, identity->user_id, &stored_ident);
  636. }
  637. else { // see if we perhaps own this user
  638. if (default_own_id) {
  639. status = get_identity(session,
  640. identity->address,
  641. default_own_id,
  642. &stored_ident);
  643. }
  644. }
  645. //////////////////////////////////////////////////////////////////////////////////////////////////////
  646. // If we're unable to get a starting stored ID, we now need to try to get IDs which match the address.
  647. // Should we find them, we go through the list and try to find an acceptable one by evaluating the
  648. // following properties (not in order of priority, and not for every case - the logic here is a mess):
  649. //
  650. // 1. Did the input have a user_id?
  651. // 2. Did the input hava a username?
  652. // 3. Is the input user_id a real id?
  653. // 4. Is the stored user_id a real id?
  654. // 5. Does the stored user_id have a username?
  655. // 6. Do the names match?
  656. //
  657. // Based on this, if we find an acceptable candidate, we do one:
  658. //
  659. // 1. Replace the global DB user_id with the input user_id and patch the stored identity's user_id
  660. // (this may be different than 1, though in practice it seems we always do both)
  661. // 2. Patch the output identity's user_id from the stored identity
  662. //
  663. // If we find none, in the case if the has-username-but-no-user_id input case, we'll try a TOFU id
  664. // fetch before giving up on stored identity candidates.
  665. //
  666. // Acceptable candidates are then passed to prepare_update_identity which will patch usernames and
  667. // find any applicable keys.
  668. //
  669. // Unacceptable candidates will then have minimal record information entered depending on how much
  670. // came in in the input, TOFU user_ids created when needed, and a new record placed in the DB
  671. // accordingly.
  672. //
  673. if (!stored_ident) {
  674. identity_list* id_list = NULL;
  675. status = get_identities_by_address(session, identity->address, &id_list);
  676. if (id_list) {
  677. identity_list* stored_curr = id_list;
  678. // Ok, here's where we search for stored identities and try to find a candidate.
  679. while (stored_curr) {
  680. // Ok, this is where the above code fun begins. Let's get some information about the identity.
  681. pEp_identity* candidate = stored_curr->ident;
  682. if (candidate) {
  683. char* candidate_id = candidate->user_id;
  684. // this_uid should never be NULL, as this is half of the ident
  685. // DB primary key
  686. assert(!EMPTYSTR(candidate_id));
  687. // grab some information about the stored identity
  688. bool candidate_has_real_id = strstr(candidate_id, "TOFU_") != candidate_id;
  689. bool candidate_has_username = !EMPTYSTR(candidate->username);
  690. bool candidate_name_is_addr = candidate_has_username ? strcmp(candidate->address, candidate->username) == 0 : false;
  691. bool weak_candidate_name = !candidate_has_username || candidate_name_is_addr;
  692. bool names_match = (weak_candidate_name && weak_input_name) ||
  693. ((input_has_username && candidate_has_username) &&
  694. (strcmp(identity->username, candidate->username) == 0));
  695. // This is where the optimisation gets a little weird:
  696. //
  697. // Decide whether to accept and patch the database and stored id from the input,
  698. // Accept and patch the input id from the database, or reject and go to the next
  699. // one in the list
  700. //
  701. // This is unnecessary, but I think the terms need to be descriptive where possible
  702. bool input_addr_only = !input_has_username && !input_has_user_id;
  703. bool candidate_id_best = candidate_has_real_id && !input_has_real_id;
  704. bool input_id_best = input_has_real_id && !candidate_has_real_id;
  705. bool patch_input_id_conditions = input_has_user_id || names_match || weak_candidate_name;
  706. if (input_addr_only || (candidate_id_best && patch_input_id_conditions)) {
  707. identity->user_id = strdup(candidate_id);
  708. assert(identity->user_id);
  709. if (!identity->user_id)
  710. goto enomem;
  711. stored_ident = identity_dup(candidate);
  712. break;
  713. }
  714. else if (input_id_best && (names_match || (input_has_username && weak_candidate_name))) {
  715. // Replace the TOFU db in the database with the input ID globally
  716. status = replace_userid(session,
  717. candidate_id,
  718. identity->user_id);
  719. if (status != PEP_STATUS_OK) {
  720. free_identity_list(id_list);
  721. free(default_own_id);
  722. return status;
  723. }
  724. // Reflect the change we just made to the DB
  725. free(candidate->user_id);
  726. candidate->user_id = strdup(identity->user_id);
  727. stored_ident = identity_dup(candidate);
  728. break;
  729. } // End else if
  730. // Else, we reject this candidate and try the next one, if there is one.
  731. stored_curr = stored_curr->next;
  732. }
  733. // Ok, we've checked all of the candidates, and if there's a stored identity, there's a duplicate.
  734. // Freeeeeeee...
  735. free_identity_list(id_list);
  736. }
  737. }
  738. // If, by here, there is no user id on the identity, we put one on there.
  739. // We've found any non-TOFU one we're going to find, so if this is empty,
  740. // We don't have a stored ident.
  741. if (EMPTYSTR(identity->user_id)) {
  742. identity->user_id = calloc(1, strlen(identity->address) + 6);
  743. if (!identity->user_id)
  744. goto enomem;
  745. snprintf(identity->user_id, strlen(identity->address) + 6,
  746. "TOFU_%s", identity->address);
  747. // Try one last time to see if there is an ident for us with a TOFU id, if there was no ID but there
  748. // was a usernames
  749. if (input_has_username) {
  750. status = get_identity(session,
  751. identity->address,
  752. identity->user_id,
  753. &stored_ident);
  754. }
  755. }
  756. }
  757. //
  758. // Either update the identity (and possibly DB to reflect stored ident information, or
  759. // create a new identity and store it.
  760. //
  761. if (status == PEP_STATUS_OK && stored_ident) {
  762. // An identity was available.
  763. // Call will patch the username where needed and
  764. // get a valid default key (for ident or user)
  765. status = prepare_updated_identity(session,
  766. identity,
  767. stored_ident, true);
  768. }
  769. else { // No stored ident. We're done.
  770. // If we needed TOFU, we've taken care of the ID above.
  771. if (EMPTYSTR(identity->username)) { // currently, not after messing around
  772. free(identity->username);
  773. identity->username = strdup(identity->address);
  774. if (!identity->username)
  775. goto enomem;
  776. }
  777. free(identity->fpr);
  778. identity->fpr = NULL;
  779. identity->comm_type = PEP_ct_unknown;
  780. adjust_pEp_trust_status(session, identity);
  781. status = set_identity(session, identity);
  782. }
  783. // VB says, and I quote, "that is not implemented and no one is using it right now"
  784. // about this bit. So, um, you're forewarned.
  785. if (identity->comm_type != PEP_ct_compromised &&
  786. identity->comm_type < PEP_ct_strong_but_unconfirmed)
  787. if (session->examine_identity)
  788. session->examine_identity(identity, session->examine_management);
  789. goto pEp_free;
  790. enomem:
  791. status = PEP_OUT_OF_MEMORY;
  792. pEp_free:
  793. free(default_own_id);
  794. free_identity(stored_ident);
  795. return status;
  796. }
  797. PEP_STATUS elect_ownkey(
  798. PEP_SESSION session, pEp_identity * identity
  799. )
  800. {
  801. PEP_STATUS status;
  802. stringlist_t *keylist = NULL;
  803. free(identity->fpr);
  804. identity->fpr = NULL;
  805. status = find_private_keys(session, identity->address, &keylist);
  806. assert(status != PEP_OUT_OF_MEMORY);
  807. if (status == PEP_OUT_OF_MEMORY)
  808. return PEP_OUT_OF_MEMORY;
  809. if (keylist != NULL && keylist->value != NULL)
  810. {
  811. char *_fpr = NULL;
  812. identity->comm_type = PEP_ct_unknown;
  813. stringlist_t *_keylist;
  814. for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
  815. bool is_own = false;
  816. status = own_key_is_listed(session, _keylist->value, &is_own);
  817. assert(status == PEP_STATUS_OK);
  818. if (status != PEP_STATUS_OK) {
  819. free_stringlist(keylist);
  820. return status;
  821. }
  822. if (is_own)
  823. {
  824. PEP_comm_type _comm_type_key;
  825. status = get_key_rating(session, _keylist->value, &_comm_type_key);
  826. assert(status != PEP_OUT_OF_MEMORY);
  827. if (status == PEP_OUT_OF_MEMORY) {
  828. free_stringlist(keylist);
  829. return PEP_OUT_OF_MEMORY;
  830. }
  831. if (_comm_type_key != PEP_ct_compromised &&
  832. _comm_type_key != PEP_ct_unknown)
  833. {
  834. if (identity->comm_type == PEP_ct_unknown ||
  835. _comm_type_key > identity->comm_type)
  836. {
  837. identity->comm_type = _comm_type_key;
  838. _fpr = _keylist->value;
  839. }
  840. }
  841. }
  842. }
  843. if (_fpr)
  844. {
  845. identity->fpr = strdup(_fpr);
  846. assert(identity->fpr);
  847. if (identity->fpr == NULL)
  848. {
  849. free_stringlist(keylist);
  850. return PEP_OUT_OF_MEMORY;
  851. }
  852. }
  853. free_stringlist(keylist);
  854. }
  855. return PEP_STATUS_OK;
  856. }
  857. PEP_STATUS _has_usable_priv_key(PEP_SESSION session, char* fpr,
  858. bool* is_usable) {
  859. bool has_private = false;
  860. PEP_STATUS status = contains_priv_key(session, fpr, &has_private);
  861. *is_usable = has_private;
  862. return status;
  863. }
  864. PEP_STATUS _myself(PEP_SESSION session,
  865. pEp_identity * identity,
  866. bool do_keygen,
  867. bool do_renew,
  868. bool ignore_flags,
  869. bool read_only)
  870. {
  871. PEP_STATUS status;
  872. assert(session);
  873. assert(identity);
  874. assert(!EMPTYSTR(identity->address));
  875. if (!session || EMPTYSTR(identity->address))
  876. return PEP_ILLEGAL_VALUE;
  877. // this is leading to crashes otherwise
  878. if (!(identity->user_id && identity->user_id[0])) {
  879. free(identity->user_id);
  880. identity->user_id = strdup(PEP_OWN_USERID);
  881. assert(identity->user_id);
  882. if (!identity->user_id)
  883. return PEP_OUT_OF_MEMORY;
  884. }
  885. pEp_identity *stored_identity = NULL;
  886. char* revoked_fpr = NULL;
  887. bool valid_key_found = false;
  888. char* default_own_id = NULL;
  889. status = get_default_own_userid(session, &default_own_id);
  890. // Deal with non-default user_ids.
  891. // FIXME: if non-default and read-only, reject totally?
  892. if (default_own_id && strcmp(default_own_id, identity->user_id) != 0) {
  893. if (read_only) {
  894. free(identity->user_id);
  895. identity->user_id = strdup(default_own_id);
  896. assert(identity->user_id);
  897. if (!identity->user_id)
  898. return PEP_OUT_OF_MEMORY;
  899. }
  900. else {
  901. status = set_userid_alias(session, default_own_id, identity->user_id);
  902. // Do we want this to be fatal? For now, we'll do it...
  903. if (status != PEP_STATUS_OK)
  904. goto pEp_free;
  905. free(identity->user_id);
  906. identity->user_id = strdup(default_own_id);
  907. assert(identity->user_id);
  908. if (identity->user_id == NULL) {
  909. status = PEP_OUT_OF_MEMORY;
  910. goto pEp_free;
  911. }
  912. }
  913. }
  914. // NOTE: IF WE DON'T YET HAVE AN OWN_ID, WE IGNORE REFERENCES TO THIS ADDRESS IN THE
  915. // DB (WHICH MAY HAVE BEEN SET BEFORE MYSELF WAS CALLED BY RECEIVING AN EMAIL FROM
  916. // THIS ADDRESS), AS IT IS NOT AN OWN_IDENTITY AND HAS NO INFORMATION WE NEED OR WHAT TO
  917. // SET FOR MYSELF
  918. // Ok, so now, set up the own_identity:
  919. identity->comm_type = PEP_ct_pEp;
  920. identity->me = true;
  921. if(ignore_flags)
  922. identity->flags = 0;
  923. // Let's see if we have an identity record in the DB for
  924. // this user_id + address
  925. // DEBUG_LOG("myself", "debug", identity->address);
  926. // This will grab the actual flags from the db
  927. status = get_identity(session,
  928. identity->address,
  929. identity->user_id,
  930. &stored_identity);
  931. assert(status != PEP_OUT_OF_MEMORY);
  932. if (status == PEP_OUT_OF_MEMORY) {
  933. status = PEP_OUT_OF_MEMORY;
  934. goto pEp_free;
  935. }
  936. // Set usernames - priority is input username > stored name > address
  937. // If there's an input username, we always patch the username with that
  938. // input.
  939. // N.B. there was an || read_only here, but why? read_only ONLY means
  940. // we don't write to the DB! So... removed. But how this managed to work
  941. // before I don't know.
  942. if (EMPTYSTR(identity->username)) {
  943. bool stored_uname = (stored_identity && !EMPTYSTR(stored_identity->username));
  944. char* uname = (stored_uname ? stored_identity->username : identity->address);
  945. if (uname) {
  946. free(identity->username);
  947. identity->username = strdup(uname);
  948. assert(identity->username);
  949. if (identity->username == NULL) {
  950. status = PEP_OUT_OF_MEMORY;
  951. goto pEp_free;
  952. }
  953. }
  954. }
  955. // ignore input fpr
  956. if (identity->fpr) {
  957. free(identity->fpr);
  958. identity->fpr = NULL;
  959. }
  960. // check stored identity
  961. if (stored_identity) {
  962. if (!EMPTYSTR(stored_identity->fpr)) {
  963. // Fall back / retrieve
  964. status = validate_fpr(session, stored_identity, false, true, do_renew);
  965. switch (status) {
  966. // Only possible if we called this with do_renew = true
  967. case PEP_OUT_OF_MEMORY:
  968. case PEP_PASSPHRASE_REQUIRED:
  969. case PEP_WRONG_PASSPHRASE:
  970. goto pEp_free;
  971. case PEP_STATUS_OK:
  972. if (stored_identity->comm_type >= PEP_ct_strong_but_unconfirmed) {
  973. identity->fpr = strdup(stored_identity->fpr);
  974. assert(identity->fpr);
  975. if (!identity->fpr) {
  976. status = PEP_OUT_OF_MEMORY;
  977. goto pEp_free;
  978. }
  979. valid_key_found = true;
  980. }
  981. else {
  982. bool revoked = false;
  983. status = key_revoked(session, stored_identity->fpr, &revoked);
  984. if (status)
  985. goto pEp_free;
  986. if (revoked) {
  987. revoked_fpr = strdup(stored_identity->fpr);
  988. assert(revoked_fpr);
  989. if (!revoked_fpr) {
  990. status = PEP_OUT_OF_MEMORY;
  991. goto pEp_free;
  992. }
  993. }
  994. }
  995. break;
  996. default:
  997. break;
  998. }
  999. }
  1000. // reconcile language, flags
  1001. transfer_ident_lang_and_flags(identity, stored_identity);
  1002. }
  1003. // Nothing left to do but generate a key
  1004. if (!valid_key_found) {
  1005. if (!do_keygen || read_only)
  1006. status = PEP_GET_KEY_FAILED;
  1007. else {
  1008. // / DEBUG_LOG("Generating key pair", "debug", identity->address);
  1009. free(identity->fpr);
  1010. identity->fpr = NULL;
  1011. status = generate_keypair(session, identity);
  1012. assert(status != PEP_OUT_OF_MEMORY);
  1013. if (status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
  1014. goto pEp_free;
  1015. if (status != PEP_STATUS_OK) {
  1016. char buf[11];
  1017. snprintf(buf, 11, "%d", status); // uh, this is kludgey. FIXME
  1018. // DEBUG_LOG("Generating key pair failed", "debug", buf);
  1019. }
  1020. else {
  1021. valid_key_found = true;
  1022. if (revoked_fpr) {
  1023. status = set_revoked(session, revoked_fpr,
  1024. stored_identity->fpr, time(NULL));
  1025. assert(status == PEP_STATUS_OK);
  1026. }
  1027. }
  1028. }
  1029. }
  1030. if (valid_key_found) {
  1031. identity->comm_type = PEP_ct_pEp;
  1032. status = PEP_STATUS_OK;
  1033. }
  1034. else {
  1035. free(identity->fpr);
  1036. identity->fpr = NULL;
  1037. identity->comm_type = PEP_ct_unknown;
  1038. }
  1039. unsigned int major_ver = 0;
  1040. unsigned int minor_ver = 0;
  1041. pEp_version_major_minor(PEP_VERSION, &major_ver, &minor_ver);
  1042. identity->major_ver = major_ver;
  1043. identity->minor_ver = minor_ver;
  1044. // We want to set an identity in the DB even if a key isn't found, but we have to preserve the status if
  1045. // it's NOT ok
  1046. if (!read_only) {
  1047. PEP_STATUS set_id_status = set_identity(session, identity);
  1048. if (set_id_status == PEP_STATUS_OK)
  1049. set_id_status = set_as_pEp_user(session, identity);
  1050. status = (status == PEP_STATUS_OK ? set_id_status : status);
  1051. }
  1052. pEp_free:
  1053. free(default_own_id);
  1054. free(revoked_fpr);
  1055. free_identity(stored_identity);
  1056. return status;
  1057. }
  1058. DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
  1059. {
  1060. return _myself(session, identity, true, true, false, false);
  1061. }
  1062. DYNAMIC_API PEP_STATUS register_examine_function(
  1063. PEP_SESSION session,
  1064. examine_identity_t examine_identity,
  1065. void *management
  1066. )
  1067. {
  1068. assert(session);
  1069. if (!session)
  1070. return PEP_ILLEGAL_VALUE;
  1071. session->examine_management = management;
  1072. session->examine_identity = examine_identity;
  1073. return PEP_STATUS_OK;
  1074. }
  1075. DYNAMIC_API PEP_STATUS do_keymanagement(
  1076. retrieve_next_identity_t retrieve_next_identity,
  1077. void *management
  1078. )
  1079. {
  1080. PEP_SESSION session;
  1081. pEp_identity *identity;
  1082. // FIXME_NOW: ensure_decrypt callback???
  1083. PEP_STATUS status = init(&session, NULL, NULL, NULL);
  1084. assert(!status);
  1085. if (status)
  1086. return status;
  1087. assert(session && retrieve_next_identity);
  1088. if (!(session && retrieve_next_identity))
  1089. return PEP_ILLEGAL_VALUE;
  1090. log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
  1091. while ((identity = retrieve_next_identity(management)))
  1092. {
  1093. assert(identity->address);
  1094. if(identity->address)
  1095. {
  1096. DEBUG_LOG("do_keymanagement", "retrieve_next_identity", identity->address);
  1097. if (identity->me) {
  1098. status = myself(session, identity);
  1099. } else {
  1100. status = recv_key(session, identity->address);
  1101. }
  1102. assert(status != PEP_OUT_OF_MEMORY);
  1103. if(status == PEP_OUT_OF_MEMORY)
  1104. return PEP_OUT_OF_MEMORY;
  1105. }
  1106. free_identity(identity);
  1107. }
  1108. log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
  1109. release(session);
  1110. return PEP_STATUS_OK;
  1111. }
  1112. DYNAMIC_API PEP_STATUS key_mistrusted(
  1113. PEP_SESSION session,
  1114. pEp_identity *ident
  1115. )
  1116. {
  1117. PEP_STATUS status = PEP_STATUS_OK;
  1118. assert(session);
  1119. assert(ident);
  1120. assert(!EMPTYSTR(ident->fpr));
  1121. if (!(session && ident && ident->fpr))
  1122. return PEP_ILLEGAL_VALUE;
  1123. bool has_private = false;
  1124. status = contains_priv_key(session, ident->fpr, &has_private);
  1125. if (status != PEP_STATUS_OK && status != PEP_KEY_NOT_FOUND)
  1126. return status;
  1127. // See if key is revoked already
  1128. if (has_private) {
  1129. bool revoked = false;
  1130. status = key_revoked(session, ident->fpr, &revoked);
  1131. if (!revoked)
  1132. revoke_key(session, ident->fpr, NULL);
  1133. }
  1134. else {
  1135. if (ident->fpr) {
  1136. // Make sure there was a default in the DB for this identity;
  1137. // if not, set one, even though we're going to mistrust this. Otherwise,
  1138. // cannot reset.
  1139. pEp_identity* stored_ident = NULL;
  1140. get_identity(session, ident->address, ident->user_id, &stored_ident);
  1141. bool set_in_db = true;
  1142. if (!stored_ident)
  1143. stored_ident = identity_dup(ident);
  1144. else if (!stored_ident->fpr)
  1145. stored_ident->fpr = strdup(ident->fpr);
  1146. else
  1147. set_in_db = false;
  1148. if (set_in_db)
  1149. status = set_identity(session, stored_ident);
  1150. free_identity(stored_ident);
  1151. if (status != PEP_STATUS_OK)
  1152. return status;
  1153. }
  1154. }
  1155. // double-check to be sure key is even in the DB
  1156. if (ident->fpr)
  1157. status = set_pgp_keypair(session, ident->fpr);
  1158. // We set this temporarily but will grab it back from the cache afterwards
  1159. ident->comm_type = PEP_ct_mistrusted;
  1160. status = set_trust(session, ident);
  1161. if (status == PEP_STATUS_OK)
  1162. // cascade that mistrust for anyone using this key
  1163. status = mark_as_compromised(session, ident->fpr);
  1164. if (status == PEP_STATUS_OK)
  1165. status = add_mistrusted_key(session, ident->fpr);
  1166. return status;
  1167. }
  1168. DYNAMIC_API PEP_STATUS key_reset_trust(
  1169. PEP_SESSION session,
  1170. pEp_identity *ident
  1171. )
  1172. {
  1173. PEP_STATUS status = PEP_STATUS_OK;
  1174. assert(session);
  1175. assert(ident);
  1176. assert(!EMPTYSTR(ident->fpr));
  1177. assert(!EMPTYSTR(ident->address));
  1178. assert(!EMPTYSTR(ident->user_id));
  1179. if (!(session && ident && ident->fpr && ident->fpr[0] != '\0' && ident->address &&
  1180. ident->user_id))
  1181. return PEP_ILLEGAL_VALUE;
  1182. // we do not change the input struct at ALL.
  1183. pEp_identity* input_copy = identity_dup(ident);
  1184. pEp_identity* tmp_ident = NULL;
  1185. status = get_trust(session, input_copy);
  1186. if (status != PEP_STATUS_OK)
  1187. goto pEp_free;
  1188. PEP_comm_type new_trust = PEP_ct_unknown;
  1189. status = get_key_rating(session, ident->fpr, &new_trust);
  1190. if (status != PEP_STATUS_OK)
  1191. goto pEp_free;
  1192. bool pEp_user = false;
  1193. status = is_pEp_user(session, ident, &pEp_user);
  1194. if (pEp_user && new_trust >= PEP_ct_unconfirmed_encryption)
  1195. input_copy->comm_type = PEP_ct_pEp_unconfirmed;
  1196. else
  1197. input_copy->comm_type = new_trust;
  1198. status = set_trust(session, input_copy);
  1199. if (status != PEP_STATUS_OK)
  1200. goto pEp_free;
  1201. bool mistrusted_key = false;
  1202. status = is_mistrusted_key(session, ident->fpr, &mistrusted_key);
  1203. if (status != PEP_STATUS_OK)
  1204. goto pEp_free;
  1205. if (mistrusted_key)
  1206. status = delete_mistrusted_key(session, ident->fpr);
  1207. if (status != PEP_STATUS_OK)
  1208. goto pEp_free;
  1209. tmp_ident = new_identity(ident->address, NULL, ident->user_id, NULL);
  1210. if (!tmp_ident)
  1211. return PEP_OUT_OF_MEMORY;
  1212. if (is_me(session, tmp_ident))
  1213. status = myself(session, tmp_ident);
  1214. else
  1215. status = update_identity(session, tmp_ident);
  1216. if (status != PEP_STATUS_OK)
  1217. goto pEp_free;
  1218. // remove as default if necessary
  1219. if (!EMPTYSTR(tmp_ident->fpr) && strcmp(tmp_ident->fpr, ident->fpr) == 0) {
  1220. free(tmp_ident->fpr);
  1221. tmp_ident->fpr = NULL;
  1222. tmp_ident->comm_type = PEP_ct_unknown;
  1223. status = set_identity(session, tmp_ident);
  1224. if (status != PEP_STATUS_OK)
  1225. goto pEp_free;
  1226. }
  1227. char* user_default = NULL;
  1228. get_main_user_fpr(session, tmp_ident->user_id, &user_default);
  1229. if (!EMPTYSTR(user_default)) {
  1230. if (strcmp(user_default, ident->fpr) == 0)
  1231. status = refresh_userid_default_key(session, ident->user_id);
  1232. if (status != PEP_STATUS_OK)
  1233. goto pEp_free;
  1234. }
  1235. pEp_free:
  1236. free_identity(tmp_ident);
  1237. free_identity(input_copy);
  1238. return status;
  1239. }
  1240. // Technically speaking, this should not EVER
  1241. // return PASSPHRASE errors, because
  1242. // this is never for an own identity (enforced), and thus
  1243. // validate_fpr will not call renew_key.
  1244. // If it ever does, the status gets propagated, but
  1245. // it is distinctly not OK.
  1246. DYNAMIC_API PEP_STATUS trust_personal_key(
  1247. PEP_SESSION session,
  1248. pEp_identity *ident
  1249. )
  1250. {
  1251. PEP_STATUS status = PEP_STATUS_OK;
  1252. assert(session);
  1253. assert(ident);
  1254. assert(!EMPTYSTR(ident->address));
  1255. assert(!EMPTYSTR(ident->user_id));
  1256. assert(!EMPTYSTR(ident->fpr));
  1257. if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
  1258. EMPTYSTR(ident->fpr))
  1259. return PEP_ILLEGAL_VALUE;
  1260. if (is_me(session, ident))
  1261. return PEP_ILLEGAL_VALUE;
  1262. char* ident_default_fpr = NULL;
  1263. // Before we do anything, be sure the input fpr is even eligible to be trusted
  1264. PEP_comm_type input_default_ct = PEP_ct_unknown;
  1265. status = get_key_rating(session, ident->fpr, &input_default_ct);
  1266. if (input_default_ct < PEP_ct_strong_but_unconfirmed)
  1267. return PEP_KEY_UNSUITABLE;
  1268. status = set_pgp_keypair(session, ident->fpr);
  1269. if (status != PEP_STATUS_OK)
  1270. return status;
  1271. pEp_identity* ident_copy = identity_dup(ident);
  1272. char* cached_fpr = NULL;
  1273. // for setting up a temp trusted identity for the input fpr
  1274. pEp_identity* tmp_id = NULL;
  1275. // For later, in case we need to check the user default key
  1276. pEp_identity* tmp_user_ident = NULL;
  1277. // Save the input fpr, which we already tested as non-NULL
  1278. cached_fpr = strdup(ident->fpr);
  1279. // Set up a temp trusted identity for the input fpr without a comm type;
  1280. tmp_id = new_identity(ident->address, ident->fpr, ident->user_id, NULL);
  1281. status = validate_fpr(session, tmp_id, false, true, false);
  1282. if (status == PEP_STATUS_OK) {
  1283. // Validate fpr gets trust DB or, when that fails, key comm type. we checked
  1284. // above that the key was ok. (not revoked or expired), but we want the max.
  1285. tmp_id->comm_type = _MAX(tmp_id->comm_type, input_default_ct) | PEP_ct_confirmed;
  1286. // Get the default identity without setting the fpr
  1287. status = update_identity(session, ident_copy);
  1288. ident_default_fpr = (EMPTYSTR(ident_copy->fpr) ? NULL : strdup(ident_copy->fpr));
  1289. if (status == PEP_STATUS_OK) {
  1290. bool trusted_default = false;
  1291. // If there's no default, or the default is different from the input...
  1292. if (EMPTYSTR(ident_default_fpr) || strcmp(cached_fpr, ident_default_fpr) != 0) {
  1293. // If the default fpr (if there is one) is trusted and key is strong enough,
  1294. // don't replace, we just set the trusted bit on this key for this user_id...
  1295. // (If there's no default fpr, this won't be true anyway.)
  1296. if ((ident_copy->comm_type >= PEP_ct_strong_but_unconfirmed &&
  1297. (ident_copy->comm_type & PEP_ct_confirmed))) {
  1298. trusted_default = true;
  1299. status = set_trust(session, tmp_id);
  1300. input_default_ct = tmp_id->comm_type;
  1301. }
  1302. else {
  1303. free(ident_copy->fpr);
  1304. ident_copy->fpr = strdup(cached_fpr);
  1305. ident_copy->comm_type = tmp_id->comm_type;
  1306. status = set_identity(session, ident_copy); // replace identity default
  1307. if (status == PEP_STATUS_OK) {
  1308. if ((ident_copy->comm_type | PEP_ct_confirmed) == PEP_ct_pEp)
  1309. status = set_as_pEp_user(session, ident_copy);
  1310. }
  1311. }
  1312. }
  1313. else { // we're setting this on the default fpr
  1314. ident->comm_type = tmp_id->comm_type;
  1315. status = set_identity(session, ident);
  1316. trusted_default = true;
  1317. }
  1318. if (status == PEP_STATUS_OK && !trusted_default) {
  1319. // Ok, there wasn't a trusted default, so we replaced. Thus, we also
  1320. // make sure there's a trusted default on the user_id. If there
  1321. // is not, we make this the default.
  1322. char* user_default = NULL;
  1323. status = get_main_user_fpr(session, ident->user_id, &user_default);
  1324. if (status == PEP_STATUS_OK && user_default) {
  1325. tmp_user_ident = new_identity(ident->address,
  1326. user_default,
  1327. ident->user_id,
  1328. NULL);
  1329. if (!tmp_user_ident)
  1330. status = PEP_OUT_OF_MEMORY;
  1331. else {
  1332. status = validate_fpr(session, tmp_user_ident, false, true, false);
  1333. if (status != PEP_STATUS_OK ||
  1334. tmp_user_ident->comm_type < PEP_ct_strong_but_unconfirmed ||
  1335. !(tmp_user_ident->comm_type & PEP_ct_confirmed))
  1336. {
  1337. char* trusted_fpr = (trusted_default ? ident_default_fpr : cached_fpr);
  1338. status = replace_main_user_fpr(session, ident->user_id, trusted_fpr);
  1339. }
  1340. }
  1341. }
  1342. }
  1343. }
  1344. }
  1345. free(ident_default_fpr);
  1346. free(cached_fpr);
  1347. free_identity(tmp_id);
  1348. free_identity(ident_copy);
  1349. free_identity(tmp_user_ident);
  1350. return status;
  1351. }
  1352. DYNAMIC_API PEP_STATUS trust_own_key(
  1353. PEP_SESSION session,
  1354. pEp_identity* ident
  1355. )
  1356. {
  1357. assert(session);
  1358. assert(ident);
  1359. assert(!EMPTYSTR(ident->address));
  1360. assert(!EMPTYSTR(ident->user_id));
  1361. assert(!EMPTYSTR(ident->fpr));
  1362. if (!ident || EMPTYSTR(ident->address) || EMPTYSTR(ident->user_id) ||
  1363. EMPTYSTR(ident->fpr))
  1364. return PEP_ILLEGAL_VALUE;
  1365. if (!is_me(session, ident))
  1366. return PEP_ILLEGAL_VALUE;
  1367. // don't check blacklist or require a private key
  1368. PEP_STATUS status = validate_fpr(session, ident, false, false, true);
  1369. if (status != PEP_STATUS_OK)
  1370. return status;
  1371. status = set_pgp_keypair(session, ident->fpr);
  1372. if (status != PEP_STATUS_OK)
  1373. return status;
  1374. if (ident->comm_type < PEP_ct_strong_but_unconfirmed)
  1375. return PEP_KEY_UNSUITABLE;
  1376. ident->comm_type |= PEP_ct_confirmed;
  1377. status = set_trust(session, ident);
  1378. return status;
  1379. }
  1380. DYNAMIC_API PEP_STATUS own_key_is_listed(
  1381. PEP_SESSION session,
  1382. const char *fpr,
  1383. bool *listed
  1384. )
  1385. {
  1386. PEP_STATUS status = PEP_STATUS_OK;
  1387. int count;
  1388. assert(session && fpr && fpr[0] && listed);
  1389. if (!(session && fpr && fpr[0] && listed))
  1390. return PEP_ILLEGAL_VALUE;
  1391. *listed = false;
  1392. sqlite3_reset(session->own_key_is_listed);
  1393. sqlite3_bind_text(session->own_key_is_listed, 1, fpr, -1, SQLITE_STATIC);
  1394. int result;
  1395. result = sqlite3_step(session->own_key_is_listed);
  1396. switch (result) {
  1397. case SQLITE_ROW:
  1398. count = sqlite3_column_int(session->own_key_is_listed, 0);
  1399. *listed = count > 0;
  1400. status = PEP_STATUS_OK;
  1401. break;
  1402. default:
  1403. status = PEP_UNKNOWN_ERROR;
  1404. }
  1405. sqlite3_reset(session->own_key_is_listed);
  1406. return status;
  1407. }
  1408. PEP_STATUS _own_identities_retrieve(
  1409. PEP_SESSION session,
  1410. identity_list **own_identities,
  1411. identity_flags_t excluded_flags
  1412. )
  1413. {
  1414. PEP_STATUS status = PEP_STATUS_OK;
  1415. assert(session && own_identities);
  1416. if (!(session && own_identities))
  1417. return PEP_ILLEGAL_VALUE;
  1418. *own_identities = NULL;
  1419. identity_list *_own_identities = new_identity_list(NULL);
  1420. if (_own_identities == NULL)
  1421. goto enomem;
  1422. sqlite3_reset(session->own_identities_retrieve);
  1423. int result;
  1424. // address, fpr, username, user_id, comm_type, lang, flags
  1425. const char *address = NULL;
  1426. const char *fpr = NULL;
  1427. const char *username = NULL;
  1428. const char *user_id = NULL;
  1429. PEP_comm_type comm_type = PEP_ct_unknown;
  1430. const char *lang = NULL;
  1431. unsigned int flags = 0;
  1432. identity_list *_bl = _own_identities;
  1433. sqlite3_bind_int(session->own_identities_retrieve, 1, excluded_flags);
  1434. do {
  1435. result = sqlite3_step(session->own_identities_retrieve);
  1436. switch (result) {
  1437. case SQLITE_ROW:
  1438. address = (const char *)
  1439. sqlite3_column_text(session->own_identities_retrieve, 0);
  1440. fpr = (const char *)
  1441. sqlite3_column_text(session->own_identities_retrieve, 1);
  1442. user_id = (const char *)
  1443. sqlite3_column_text(session->own_identities_retrieve, 2);
  1444. username = (const char *)
  1445. sqlite3_column_text(session->own_identities_retrieve, 3);
  1446. comm_type = PEP_ct_pEp;
  1447. lang = (const char *)
  1448. sqlite3_column_text(session->own_identities_retrieve, 4);
  1449. flags = (unsigned int)
  1450. sqlite3_column_int(session->own_identities_retrieve, 5);
  1451. pEp_identity *ident = new_identity(address, fpr, user_id, username);
  1452. if (!ident)
  1453. goto enomem;
  1454. ident->comm_type = comm_type;
  1455. if (lang && lang[0]) {
  1456. ident->lang[0] = lang[0];
  1457. ident->lang[1] = lang[1];
  1458. ident->lang[2] = 0;
  1459. }
  1460. ident->me = true;
  1461. ident->flags = flags;
  1462. _bl = identity_list_add(_bl, ident);
  1463. if (_bl == NULL) {
  1464. free_identity(ident);
  1465. goto enomem;
  1466. }
  1467. break;
  1468. case SQLITE_DONE:
  1469. break;
  1470. default:
  1471. status = PEP_UNKNOWN_ERROR;
  1472. result = SQLITE_DONE;
  1473. }
  1474. } while (result != SQLITE_DONE);
  1475. sqlite3_reset(session->own_identities_retrieve);
  1476. if (status == PEP_STATUS_OK)
  1477. *own_identities = _own_identities;
  1478. else
  1479. free_identity_list(_own_identities);
  1480. goto the_end;
  1481. enomem:
  1482. free_identity_list(_own_identities);
  1483. status = PEP_OUT_OF_MEMORY;
  1484. the_end:
  1485. return status;
  1486. }
  1487. DYNAMIC_API PEP_STATUS own_identities_retrieve(
  1488. PEP_SESSION session,
  1489. identity_list **own_identities
  1490. )
  1491. {
  1492. return _own_identities_retrieve(session, own_identities, 0);
  1493. }
  1494. PEP_STATUS _own_keys_retrieve(
  1495. PEP_SESSION session,
  1496. stringlist_t **keylist,
  1497. identity_flags_t excluded_flags,
  1498. bool private_only
  1499. )
  1500. {
  1501. PEP_STATUS status = PEP_STATUS_OK;
  1502. assert(session && keylist);
  1503. if (!(session && keylist))
  1504. return PEP_ILLEGAL_VALUE;
  1505. *keylist = NULL;
  1506. stringlist_t *_keylist = NULL;
  1507. sqlite3_reset(session->own_keys_retrieve);
  1508. int result;
  1509. stringlist_t *_bl = _keylist;
  1510. sqlite3_bind_int(session->own_keys_retrieve, 1, excluded_flags);
  1511. do {
  1512. result = sqlite3_step(session->own_keys_retrieve);
  1513. switch (result) {
  1514. case SQLITE_ROW:
  1515. _bl = stringlist_add(_bl, (const char *)
  1516. sqlite3_column_text(session->own_keys_retrieve, 0));
  1517. if (_bl == NULL)
  1518. goto enomem;
  1519. if (_keylist == NULL)
  1520. _keylist = _bl;
  1521. break;
  1522. case SQLITE_DONE:
  1523. break;
  1524. default:
  1525. status = PEP_UNKNOWN_ERROR;
  1526. result = SQLITE_DONE;
  1527. }
  1528. } while (result != SQLITE_DONE);
  1529. sqlite3_reset(session->own_keys_retrieve);
  1530. if (status == PEP_STATUS_OK) {
  1531. dedup_stringlist(_keylist);
  1532. if (private_only) {
  1533. stringlist_t* _kl = _keylist;
  1534. stringlist_t* _kl_prev = NULL;
  1535. while (_kl) {
  1536. bool has_private = false;
  1537. contains_priv_key(session, _kl->value, &has_private);
  1538. if (!has_private) {
  1539. stringlist_t* _kl_tmp = _kl;
  1540. if (_kl_prev)
  1541. _kl_prev->next = _kl->next;
  1542. else
  1543. _keylist = _kl->next;
  1544. _kl = _kl->next;
  1545. _kl_tmp->next = NULL;
  1546. free_stringlist(_kl_tmp);
  1547. continue;
  1548. }
  1549. _kl_prev = _kl;
  1550. _kl = _kl->next;
  1551. }
  1552. }
  1553. *keylist = _keylist;
  1554. }
  1555. else
  1556. free_stringlist(_keylist);
  1557. goto the_end;
  1558. enomem:
  1559. free_stringlist(_keylist);
  1560. status = PEP_OUT_OF_MEMORY;
  1561. the_end:
  1562. return status;
  1563. }
  1564. DYNAMIC_API PEP_STATUS own_keys_retrieve(PEP_SESSION session, stringlist_t **keylist)
  1565. {
  1566. return _own_keys_retrieve(session, keylist, 0, true);
  1567. }
  1568. // Returns PASSPHRASE errors when necessary
  1569. DYNAMIC_API PEP_STATUS set_own_key(
  1570. PEP_SESSION session,
  1571. pEp_identity *me,
  1572. const char *fpr
  1573. )
  1574. {
  1575. PEP_STATUS status = PEP_STATUS_OK;
  1576. assert(session && me);
  1577. assert(!EMPTYSTR(fpr));
  1578. assert(!EMPTYSTR(me->address));
  1579. assert(!EMPTYSTR(me->user_id));
  1580. assert(!EMPTYSTR(me->username));
  1581. if (!session || !me || EMPTYSTR(fpr) || EMPTYSTR(me->address) ||
  1582. EMPTYSTR(me->user_id) || EMPTYSTR(me->username))
  1583. return PEP_ILLEGAL_VALUE;
  1584. if (me->fpr == fpr)
  1585. me->fpr = NULL;
  1586. // renew if needed, but do not generate
  1587. status = _myself(session, me, false, true, true, false);
  1588. // we do not need a valid key but dislike other errors
  1589. if (status != PEP_STATUS_OK && status != PEP_GET_KEY_FAILED && status != PEP_KEY_UNSUITABLE)
  1590. return status;
  1591. status = PEP_STATUS_OK;
  1592. bool private = false;
  1593. status = contains_priv_key(session, fpr, &private);
  1594. if (status != PEP_STATUS_OK)
  1595. return status;
  1596. if (!private)
  1597. return PEP_KEY_UNSUITABLE;
  1598. if (me->fpr)
  1599. free(me->fpr);
  1600. me->fpr = strdup(fpr);
  1601. assert(me->fpr);
  1602. if (!me->fpr)
  1603. return PEP_OUT_OF_MEMORY;
  1604. status = validate_fpr(session, me, false, true, true);
  1605. if (status)
  1606. return status;
  1607. me->comm_type = PEP_ct_pEp;
  1608. status = set_identity(session, me);
  1609. if (status == PEP_STATUS_OK)
  1610. signal_Sync_event(session, Sync_PR_keysync, SynchronizeGroupKeys, NULL);
  1611. return status;
  1612. }
  1613. PEP_STATUS contains_priv_key(PEP_SESSION session, const char *fpr,
  1614. bool *has_private) {
  1615. assert(session);
  1616. assert(fpr);
  1617. assert(has_private);
  1618. if (!(session && fpr && has_private))
  1619. return PEP_ILLEGAL_VALUE;
  1620. return session->cryptotech[PEP_crypt_OpenPGP].contains_priv_key(session, fpr, has_private);
  1621. }
  1622. PEP_STATUS add_mistrusted_key(PEP_SESSION session, const char* fpr)
  1623. {
  1624. int result;
  1625. assert(!EMPTYSTR(fpr));
  1626. if (!(session) || EMPTYSTR(fpr))
  1627. return PEP_ILLEGAL_VALUE;
  1628. sqlite3_reset(session->add_mistrusted_key);
  1629. sqlite3_bind_text(session->add_mistrusted_key, 1, fpr, -1,
  1630. SQLITE_STATIC);
  1631. result = sqlite3_step(session->add_mistrusted_key);
  1632. sqlite3_reset(session->add_mistrusted_key);
  1633. if (result != SQLITE_DONE)
  1634. return PEP_CANNOT_SET_PGP_KEYPAIR; // FIXME: Better status?
  1635. return PEP_STATUS_OK;
  1636. }
  1637. PEP_STATUS delete_mistrusted_key(PEP_SESSION session, const char* fpr)
  1638. {
  1639. int result;
  1640. assert(!EMPTYSTR(fpr));
  1641. if (!(session) || EMPTYSTR(fpr))
  1642. return PEP_ILLEGAL_VALUE;
  1643. sqlite3_reset(session->delete_mistrusted_key);
  1644. sqlite3_bind_text(session->delete_mistrusted_key, 1, fpr, -1,
  1645. SQLITE_STATIC);
  1646. result = sqlite3_step(session->delete_mistrusted_key);
  1647. sqlite3_reset(session->delete_mistrusted_key);
  1648. if (result != SQLITE_DONE)
  1649. return PEP_UNKNOWN_ERROR; // FIXME: Better status?
  1650. return PEP_STATUS_OK;
  1651. }
  1652. PEP_STATUS is_mistrusted_key(PEP_SESSION session, const char* fpr,
  1653. bool* mistrusted)
  1654. {
  1655. PEP_STATUS status = PEP_STATUS_OK;
  1656. assert(session);
  1657. assert(!EMPTYSTR(fpr));
  1658. if (!(session && fpr))
  1659. return PEP_ILLEGAL_VALUE;
  1660. *mistrusted = false;
  1661. sqlite3_reset(session->is_mistrusted_key);
  1662. sqlite3_bind_text(session->is_mistrusted_key, 1, fpr, -1, SQLITE_STATIC);
  1663. int result;
  1664. result = sqlite3_step(session->is_mistrusted_key);
  1665. switch (result) {
  1666. case SQLITE_ROW:
  1667. *mistrusted = sqlite3_column_int(session->is_mistrusted_key, 0);
  1668. status = PEP_STATUS_OK;
  1669. break;
  1670. default:
  1671. status = PEP_UNKNOWN_ERROR;
  1672. }
  1673. sqlite3_reset(session->is_mistrusted_key);
  1674. return status;
  1675. }
  1676. static PEP_STATUS _wipe_default_key_if_invalid(PEP_SESSION session,
  1677. pEp_identity* ident) {
  1678. PEP_STATUS status = PEP_STATUS_OK;
  1679. if (!ident->user_id)
  1680. return PEP_ILLEGAL_VALUE;
  1681. if (!ident->fpr)
  1682. return status;
  1683. char* cached_fpr = strdup(ident->fpr);
  1684. if (!ident->fpr)
  1685. return PEP_OUT_OF_MEMORY;
  1686. PEP_STATUS keystatus = validate_fpr(session, ident, true, false, true);
  1687. if (PASS_ERROR(status))
  1688. return status;
  1689. switch (keystatus) {
  1690. case PEP_STATUS_OK:
  1691. // Check for non-renewable expiry and
  1692. // if so, fallthrough
  1693. if (ident->comm_type != PEP_ct_key_expired_but_confirmed &&
  1694. ident->comm_type != PEP_ct_key_expired) {
  1695. break;
  1696. }
  1697. case PEP_KEY_UNSUITABLE:
  1698. case PEP_KEY_BLACKLISTED:
  1699. // Remove key as default for all identities and users
  1700. status = remove_fpr_as_default(session, cached_fpr);
  1701. break;
  1702. default:
  1703. break;
  1704. }
  1705. free(cached_fpr);
  1706. // This may have been for a user default, not an identity default.
  1707. if (status == PEP_STATUS_OK && !(EMPTYSTR(ident->address)))
  1708. status = <