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.

395 lines
11 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 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
3 years ago
  1. /** @file */
  2. /** @brief File description for doxygen missing. FIXME */
  3. // This file is under GNU General Public License 3.0
  4. // see LICENSE.txt
  5. #include "pEp_internal.h"
  6. #include <memory.h>
  7. #include <assert.h>
  8. #include "KeySync_fsm.h"
  9. DYNAMIC_API PEP_STATUS register_sync_callbacks(
  10. PEP_SESSION session,
  11. void *management,
  12. notifyHandshake_t notifyHandshake,
  13. retrieve_next_sync_event_t retrieve_next_sync_event
  14. )
  15. {
  16. assert(session && notifyHandshake && retrieve_next_sync_event);
  17. if (!(session && notifyHandshake && retrieve_next_sync_event))
  18. return PEP_ILLEGAL_VALUE;
  19. identity_list *own_identities = NULL;
  20. PEP_STATUS status = own_identities_retrieve(session, &own_identities);
  21. if (status)
  22. return status;
  23. bool own_identities_available = own_identities && own_identities->ident;
  24. free_identity_list(own_identities);
  25. if (!own_identities_available)
  26. return PEP_SYNC_CANNOT_START;
  27. session->sync_management = management;
  28. session->notifyHandshake = notifyHandshake;
  29. session->retrieve_next_sync_event = retrieve_next_sync_event;
  30. // start state machine
  31. return Sync_driver(session, Sync_PR_keysync, Init);
  32. }
  33. DYNAMIC_API void unregister_sync_callbacks(PEP_SESSION session) {
  34. // stop state machine
  35. free_Sync_state(session);
  36. // unregister
  37. session->sync_management = NULL;
  38. session->notifyHandshake = NULL;
  39. session->retrieve_next_sync_event = NULL;
  40. }
  41. DYNAMIC_API PEP_STATUS deliverHandshakeResult(
  42. PEP_SESSION session,
  43. sync_handshake_result result,
  44. const identity_list *identities_sharing
  45. )
  46. {
  47. assert(session);
  48. if (!session)
  49. return PEP_ILLEGAL_VALUE;
  50. for (const identity_list *_il = identities_sharing; _il && _il->ident;
  51. _il = _il->next) {
  52. if (!_il->ident->me || !_il->ident->user_id || !_il->ident->user_id[0]
  53. || !_il->ident->address || !_il->ident->address[0])
  54. return PEP_ILLEGAL_VALUE;
  55. }
  56. PEP_STATUS status = PEP_STATUS_OK;
  57. int event;
  58. switch (result) {
  59. case SYNC_HANDSHAKE_CANCEL:
  60. event = Cancel;
  61. break;
  62. case SYNC_HANDSHAKE_ACCEPTED:
  63. {
  64. event = Accept;
  65. break;
  66. }
  67. case SYNC_HANDSHAKE_REJECTED:
  68. {
  69. event = Reject;
  70. break;
  71. }
  72. default:
  73. return PEP_ILLEGAL_VALUE;
  74. }
  75. identity_list *own_identities = NULL;
  76. if (identities_sharing && identities_sharing->ident) {
  77. own_identities = identity_list_dup(identities_sharing);
  78. if (!own_identities)
  79. return PEP_OUT_OF_MEMORY;
  80. }
  81. else {
  82. status = own_identities_retrieve(session, &own_identities);
  83. }
  84. if (!status)
  85. status = signal_Sync_event(session, Sync_PR_keysync, event, own_identities);
  86. return status;
  87. }
  88. DYNAMIC_API PEP_STATUS do_sync_protocol(
  89. PEP_SESSION session,
  90. void *obj
  91. )
  92. {
  93. Sync_event_t *event= NULL;
  94. assert(session && session->retrieve_next_sync_event);
  95. if (!(session && session->retrieve_next_sync_event))
  96. return PEP_ILLEGAL_VALUE;
  97. log_event(session, "sync_protocol thread started", "pEp sync protocol",
  98. NULL, NULL);
  99. while (true)
  100. {
  101. event = session->retrieve_next_sync_event(session->sync_management,
  102. SYNC_THRESHOLD);
  103. if (!event)
  104. break;
  105. do_sync_protocol_step(session, obj, event);
  106. }
  107. session->sync_obj = NULL;
  108. log_event(session, "sync_protocol thread shutdown", "pEp sync protocol",
  109. NULL, NULL);
  110. return PEP_STATUS_OK;
  111. }
  112. DYNAMIC_API PEP_STATUS do_sync_protocol_step(
  113. PEP_SESSION session,
  114. void *obj,
  115. SYNC_EVENT event
  116. )
  117. {
  118. assert(session);
  119. if (!session)
  120. return PEP_ILLEGAL_VALUE;
  121. if (!event)
  122. return PEP_STATUS_OK;
  123. session->sync_obj = obj;
  124. PEP_STATUS status = recv_Sync_event(session, event);
  125. return status == PEP_MESSAGE_IGNORE ? PEP_STATUS_OK : status;
  126. }
  127. DYNAMIC_API bool is_sync_thread(PEP_SESSION session)
  128. {
  129. assert(session);
  130. if (!session)
  131. return false;
  132. return session->retrieve_next_sync_event != NULL;
  133. }
  134. DYNAMIC_API SYNC_EVENT new_sync_timeout_event()
  135. {
  136. return SYNC_TIMEOUT_EVENT;
  137. }
  138. DYNAMIC_API PEP_STATUS enter_device_group(
  139. PEP_SESSION session,
  140. const identity_list *identities_sharing
  141. )
  142. {
  143. assert(session);
  144. if (!session)
  145. return PEP_ILLEGAL_VALUE;
  146. for (const identity_list *_il = identities_sharing; _il && _il->ident;
  147. _il = _il->next) {
  148. if (!_il->ident->me || !_il->ident->user_id || !_il->ident->user_id[0]
  149. || !_il->ident->address || !_il->ident->address[0])
  150. return PEP_ILLEGAL_VALUE;
  151. }
  152. identity_list *own_identities = NULL;
  153. PEP_STATUS status = own_identities_retrieve(session, &own_identities);
  154. if (status)
  155. goto the_end;
  156. if (identities_sharing && identities_sharing->ident) {
  157. for (identity_list *_il = own_identities; _il && _il->ident;
  158. _il = _il->next) {
  159. bool found = false;
  160. for (const identity_list *_is = identities_sharing;
  161. _is && _is->ident; _is = _is->next) {
  162. // FIXME: "john@doe.com" and "mailto:john@doe.com" should be equal
  163. if (strcmp(_il->ident->address, _is->ident->address) == 0
  164. && strcmp(_il->ident->user_id, _is->ident->user_id) == 0) {
  165. found = true;
  166. status = set_identity_flags(session, _il->ident, PEP_idf_devicegroup);
  167. if (status)
  168. goto the_end;
  169. break;
  170. }
  171. }
  172. if (!found) {
  173. status = unset_identity_flags(session, _il->ident, PEP_idf_devicegroup);
  174. if (status)
  175. goto the_end;
  176. }
  177. }
  178. }
  179. else {
  180. for (identity_list *_il = own_identities; _il && _il->ident;
  181. _il = _il->next) {
  182. status = set_identity_flags(session, _il->ident, PEP_idf_devicegroup);
  183. if (status)
  184. goto the_end;
  185. }
  186. }
  187. the_end:
  188. free_identity_list(own_identities);
  189. return status;
  190. }
  191. PEP_STATUS disable_sync(PEP_SESSION session)
  192. {
  193. assert(session);
  194. if (!session)
  195. return PEP_ILLEGAL_VALUE;
  196. if (session->inject_sync_event)
  197. session->inject_sync_event((void *) SHUTDOWN, NULL);
  198. identity_list *il = NULL;
  199. PEP_STATUS status = own_identities_retrieve(session, &il);
  200. if (status)
  201. goto the_end;
  202. for (identity_list *_il = il; _il && _il->ident ; _il = _il->next) {
  203. status = unset_identity_flags(session, _il->ident, PEP_idf_devicegroup);
  204. if (status)
  205. goto the_end;
  206. }
  207. the_end:
  208. free_identity_list(il);
  209. return status;
  210. }
  211. DYNAMIC_API PEP_STATUS leave_device_group(PEP_SESSION session) {
  212. assert(session);
  213. if (!session)
  214. return PEP_ILLEGAL_VALUE;
  215. bool grouped = false;
  216. PEP_STATUS status = deviceGrouped(session, &grouped);
  217. if (status)
  218. return status;
  219. if (!grouped) {
  220. if (session->inject_sync_event)
  221. session->inject_sync_event((void *) SHUTDOWN, NULL);
  222. return PEP_STATUS_OK;
  223. }
  224. return signal_Sync_event(session, Sync_PR_keysync, LeaveDeviceGroup, NULL);
  225. }
  226. DYNAMIC_API PEP_STATUS enable_identity_for_sync(PEP_SESSION session,
  227. pEp_identity *ident)
  228. {
  229. assert(session && ident && ident->user_id && ident->user_id[0] && ident->address && ident->address[0]);
  230. if (!(session && ident && ident->user_id && ident->user_id[0] && ident->address && ident->address[0]))
  231. return PEP_ILLEGAL_VALUE;
  232. // safeguard: in case the delivered identity is not valid fetch flags from the database
  233. // while doing this check if this is an own identity and return an error if not
  234. pEp_identity *stored_ident = NULL;
  235. PEP_STATUS status = get_identity(session, ident->address, ident->user_id, &stored_ident);
  236. if (status)
  237. return status;
  238. assert(stored_ident);
  239. if (!stored_ident->me) {
  240. free_identity(stored_ident);
  241. return PEP_ILLEGAL_VALUE;
  242. }
  243. ident->flags = stored_ident->flags;
  244. free_identity(stored_ident);
  245. // if we're grouped and this identity is enabled already we can stop here
  246. if ((ident->flags & PEP_idf_devicegroup) && !(ident->flags & PEP_idf_not_for_sync))
  247. return PEP_STATUS_OK;
  248. // if the identity is marked not for sync unset this to enable
  249. if (ident->flags & PEP_idf_not_for_sync) {
  250. status = unset_identity_flags(session, ident, PEP_idf_not_for_sync);
  251. if (status)
  252. return status;
  253. }
  254. // if we're grouped then add the identity to the group
  255. bool grouped = false;
  256. status = deviceGrouped(session, &grouped);
  257. if (status)
  258. return status;
  259. if (grouped) {
  260. status = set_identity_flags(session, ident, PEP_idf_devicegroup);
  261. if (status)
  262. return status;
  263. // signal we have a new identity in the group
  264. signal_Sync_event(session, Sync_PR_keysync, KeyGen, NULL);
  265. }
  266. return PEP_STATUS_OK;
  267. }
  268. DYNAMIC_API PEP_STATUS disable_identity_for_sync(PEP_SESSION session,
  269. pEp_identity *ident)
  270. {
  271. assert(session && ident);
  272. if (!(session && ident))
  273. return PEP_ILLEGAL_VALUE;
  274. // safeguard: in case the delivered identity is not valid fetch flags from the database
  275. // while doing this check if this is an own identity and return an error if not
  276. pEp_identity *stored_ident = NULL;
  277. PEP_STATUS status = get_identity(session, ident->address, ident->user_id, &stored_ident);
  278. if (status)
  279. return status;
  280. assert(stored_ident);
  281. if (!stored_ident->me) {
  282. free_identity(stored_ident);
  283. return PEP_ILLEGAL_VALUE;
  284. }
  285. ident->flags = stored_ident->flags;
  286. free_identity(stored_ident);
  287. // if this identity is disabled and not part of a device group already we can end here
  288. if ((ident->flags & PEP_idf_not_for_sync) && !(ident->flags & PEP_idf_devicegroup))
  289. return PEP_STATUS_OK;
  290. // if the identity is not part of a device group just disable it to keep this
  291. if (!(ident->flags & PEP_idf_devicegroup)) {
  292. status = set_identity_flags(session, ident, PEP_idf_not_for_sync);
  293. return status;
  294. }
  295. // we are grouped and this identity is part of a device group => key reset in all cases
  296. status = unset_identity_flags(session, ident, PEP_idf_devicegroup);
  297. if (status)
  298. return status;
  299. status = set_identity_flags(session, ident, PEP_idf_not_for_sync);
  300. if (status)
  301. return status;
  302. status = key_reset_identity(session, ident, NULL);
  303. return status;
  304. }
  305. DYNAMIC_API PEP_STATUS disable_all_sync_channels(PEP_SESSION session)
  306. {
  307. assert(session);
  308. if (!session)
  309. return PEP_ILLEGAL_VALUE;
  310. identity_list *own_identities = NULL;
  311. PEP_STATUS status = own_identities_retrieve(session, &own_identities);
  312. if (status)
  313. return status;
  314. for (identity_list *oi = own_identities; oi && oi->ident; oi = oi->next) {
  315. status = set_identity_flags(session, oi->ident, PEP_idf_not_for_sync);
  316. if (status)
  317. break;
  318. }
  319. free_identity_list(own_identities);
  320. return status;
  321. }