...
1 #include "pEp_internal.h"
2 #include "dynamic_api.h"
3 #include "cryptotech.h"
8 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
10 PEP_STATUS status = PEP_STATUS_OK;
12 static const char *sql_log;
13 static const char *sql_safeword;
14 static const char *sql_get_identity;
15 static const char *sql_set_person;
16 static const char *sql_set_pgp_keypair;
17 static const char *sql_set_identity;
18 static const char *sql_set_trust;
19 static const char *sql_get_trust;
20 bool in_first = false;
22 assert(sqlite3_threadsafe());
23 if (!sqlite3_threadsafe())
24 return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
26 // a little race condition - but still a race condition
27 // mitigated by calling caveat (see documentation)
35 return PEP_ILLEGAL_VALUE;
39 pEpSession *_session = calloc(1, sizeof(pEpSession));
44 _session->version = PEP_ENGINE_VERSION;
47 if (LOCAL_DB == NULL) {
48 status = PEP_INIT_CANNOT_OPEN_DB;
52 int_result = sqlite3_open_v2(
57 | SQLITE_OPEN_FULLMUTEX
58 | SQLITE_OPEN_PRIVATECACHE,
62 if (int_result != SQLITE_OK) {
63 status = PEP_INIT_CANNOT_OPEN_DB;
67 sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
70 if (SYSTEM_DB == NULL) {
71 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
75 int_result = sqlite3_open_v2(
76 SYSTEM_DB, &_session->system_db,
78 | SQLITE_OPEN_FULLMUTEX
79 | SQLITE_OPEN_SHAREDCACHE,
83 if (int_result != SQLITE_OK) {
84 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
88 sqlite3_busy_timeout(_session->system_db, 1000);
91 int_result = sqlite3_exec(
93 "create table if not exists version_info ("
94 " id integer primary key,"
95 " timestamp integer default (datetime('now')) ,"
99 "create table if not exists log ("
100 " timestamp integer default (datetime('now')) ,"
101 " title text not null,"
102 " entity text not null,"
106 "create index if not exists log_timestamp on log ("
109 "create table if not exists pgp_keypair ("
110 " fpr text primary key,"
111 " public_id text unique,"
117 "create index if not exists pgp_keypair_expires on pgp_keypair ("
120 "create table if not exists person ("
121 " id text primary key,"
122 " username text not null,"
124 " references pgp_keypair (fpr)"
125 " on delete set null,"
129 "create table if not exists identity ("
130 " address text primary key,"
132 " references person (id)"
133 " on delete cascade,"
135 " references pgp_keypair (fpr)"
136 " on delete set null,"
139 "create table if not exists trust ("
140 " user_id text not null"
141 " references person (id)"
142 " on delete cascade,"
143 " pgp_keypair_fpr text not null"
144 " references pgp_keypair (fpr)"
145 " on delete cascade,"
146 " comm_type integer not null,"
149 "create unique index if not exists trust_index on trust ("
157 assert(int_result == SQLITE_OK);
159 int_result = sqlite3_exec(
161 "insert or replace into version_info (id, version) values (1, '1.0');",
166 assert(int_result == SQLITE_OK);
168 sql_log = "insert into log (title, entity, description, comment)"
169 "values (?1, ?2, ?3, ?4);";
171 sql_get_identity = "select fpr, identity.user_id, username, comm_type, lang"
173 " join person on id = identity.user_id"
174 " join pgp_keypair on fpr = identity.main_key_id"
175 " join trust on id = trust.user_id"
176 " and pgp_keypair_fpr = identity.main_key_id"
177 " where address = ?1 ;";
179 sql_safeword = "select id, word from wordlist where lang = lower(?1) "
182 sql_set_person = "insert or replace into person (id, username, lang) "
183 "values (?1, ?2, ?3) ;";
185 sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
188 sql_set_identity = "insert or replace into identity (address, main_key_id, "
189 "user_id) values (?1, ?2, ?3) ;";
191 sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
192 "values (?1, ?2, ?3) ;";
194 sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
195 "and pgp_keypair_fpr = ?2 ;";
198 int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
199 &_session->log, NULL);
200 assert(int_result == SQLITE_OK);
202 int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
203 strlen(sql_safeword), &_session->safeword, NULL);
204 assert(int_result == SQLITE_OK);
206 int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
207 strlen(sql_get_identity), &_session->get_identity, NULL);
208 assert(int_result == SQLITE_OK);
210 int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
211 strlen(sql_set_person), &_session->set_person, NULL);
212 assert(int_result == SQLITE_OK);
214 int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
215 strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
216 assert(int_result == SQLITE_OK);
218 int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
219 strlen(sql_set_identity), &_session->set_identity, NULL);
220 assert(int_result == SQLITE_OK);
222 int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
223 strlen(sql_set_trust), &_session->set_trust, NULL);
224 assert(int_result == SQLITE_OK);
226 int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
227 strlen(sql_get_trust), &_session->get_trust, NULL);
228 assert(int_result == SQLITE_OK);
230 status = init_cryptotech(_session, in_first);
231 if (status != PEP_STATUS_OK)
234 status = init_transport_system(_session, in_first);
235 if (status != PEP_STATUS_OK)
238 status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
239 if (status != PEP_STATUS_OK)
243 return PEP_STATUS_OK;
246 status = PEP_OUT_OF_MEMORY;
253 DYNAMIC_API void release(PEP_SESSION session)
255 bool out_last = false;
257 assert(init_count >= 0);
260 if (!(init_count && session))
263 // a small race condition but still a race condition
264 // mitigated by calling caveat (see documentation)
272 if (session->safeword)
273 sqlite3_finalize(session->safeword);
275 sqlite3_finalize(session->log);
276 if (session->get_identity)
277 sqlite3_finalize(session->get_identity);
278 if (session->set_identity)
279 sqlite3_finalize(session->set_identity);
280 if (session->set_person)
281 sqlite3_finalize(session->set_person);
282 if (session->set_pgp_keypair)
283 sqlite3_finalize(session->set_pgp_keypair);
284 if (session->set_trust)
285 sqlite3_finalize(session->set_trust);
286 if (session->get_trust)
287 sqlite3_finalize(session->get_trust);
290 sqlite3_close_v2(session->db);
291 if (session->system_db)
292 sqlite3_close_v2(session->system_db);
295 release_transport_system(session, out_last);
296 release_cryptotech(session, out_last);
302 DYNAMIC_API PEP_STATUS log_event(
303 PEP_SESSION session, const char *title, const char *entity,
304 const char *description, const char *comment
307 PEP_STATUS status = PEP_STATUS_OK;
314 if (!(session && title && entity))
315 return PEP_ILLEGAL_VALUE;
317 sqlite3_reset(session->log);
318 sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
319 sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
321 sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
323 sqlite3_bind_null(session->log, 3);
325 sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
327 sqlite3_bind_null(session->log, 4);
329 result = sqlite3_step(session->log);
330 assert(result == SQLITE_DONE || result == SQLITE_BUSY);
331 if (result != SQLITE_DONE && result != SQLITE_BUSY)
332 status = PEP_UNKNOWN_ERROR;
333 } while (result == SQLITE_BUSY);
334 sqlite3_reset(session->log);
339 DYNAMIC_API PEP_STATUS safeword(
340 PEP_SESSION session, uint16_t value, const char *lang,
341 char **word, size_t *wsize
344 PEP_STATUS status = PEP_STATUS_OK;
351 if (!(session && word && wsize))
352 return PEP_ILLEGAL_VALUE;
360 assert((lang[0] >= 'A' && lang[0] <= 'Z')
361 || (lang[0] >= 'a' && lang[0] <= 'z'));
362 assert((lang[1] >= 'A' && lang[1] <= 'Z')
363 || (lang[1] >= 'a' && lang[1] <= 'z'));
364 assert(lang[2] == 0);
366 sqlite3_reset(session->safeword);
367 sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
368 sqlite3_bind_int(session->safeword, 2, value);
370 result = sqlite3_step(session->safeword);
371 if (result == SQLITE_ROW) {
372 *word = strdup((const char *) sqlite3_column_text(session->safeword,
375 *wsize = sqlite3_column_bytes(session->safeword, 1);
377 status = PEP_SAFEWORD_NOT_FOUND;
379 status = PEP_SAFEWORD_NOT_FOUND;
381 sqlite3_reset(session->safeword);
385 DYNAMIC_API PEP_STATUS safewords(
386 PEP_SESSION session, const char *fingerprint, const char *lang,
387 char **words, size_t *wsize, int max_words
390 const char *source = fingerprint;
400 assert(max_words >= 0);
402 if (!(session && fingerprint && words && wsize && max_words >= 0))
403 return PEP_ILLEGAL_VALUE;
408 buffer = calloc(1, MAX_SAFEWORDS_SPACE);
411 return PEP_OUT_OF_MEMORY;
414 fsize = strlen(fingerprint);
419 assert((lang[0] >= 'A' && lang[0] <= 'Z')
420 || (lang[0] >= 'a' && lang[0] <= 'z'));
421 assert((lang[1] >= 'A' && lang[1] <= 'Z')
422 || (lang[1] >= 'a' && lang[1] <= 'z'));
423 assert(lang[2] == 0);
426 while (source < fingerprint + fsize) {
432 for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
433 if (*source >= 'a' && *source <= 'f')
434 value += (*source - 'a' + 10) << (3 - j++) * 4;
435 else if (*source >= 'A' && *source <= 'F')
436 value += (*source - 'A' + 10) << (3 - j++) * 4;
437 else if (*source >= '0' && *source <= '9')
438 value += (*source - '0') << (3 - j++) * 4;
443 _status = safeword(session, value, lang, &word, &_wsize);
444 if (_status == PEP_OUT_OF_MEMORY) {
446 return PEP_OUT_OF_MEMORY;
450 return PEP_SAFEWORD_NOT_FOUND;
453 if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
454 strncpy(dest, word, _wsize);
460 break; // buffer full
463 if (source < fingerprint + fsize
464 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
468 if (max_words && n_words >= max_words)
473 *wsize = dest - buffer;
474 return PEP_STATUS_OK;
477 pEp_identity *new_identity(
478 const char *address, const char *fpr, const char *user_id,
482 pEp_identity *result = calloc(1, sizeof(pEp_identity));
486 result->address = strdup(address);
487 assert(result->address);
488 if (result->address == NULL) {
492 result->address_size = strlen(address);
495 result->fpr = strdup(fpr);
497 if (result->fpr == NULL) {
498 free_identity(result);
501 result->fpr_size = strlen(fpr);
504 result->user_id = strdup(user_id);
505 assert(result->user_id);
506 if (result->user_id == NULL) {
507 free_identity(result);
510 result->user_id_size = strlen(user_id);
513 result->username = strdup(username);
514 assert(result->username);
515 if (result->username == NULL) {
516 free_identity(result);
519 result->username_size = strlen(username);
521 result->struct_size = sizeof(pEp_identity);
526 pEp_identity *identity_dup(const pEp_identity *src)
530 pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
535 dup->comm_type = src->comm_type;
536 dup->lang[0] = src->lang[0];
537 dup->lang[1] = src->lang[1];
544 void free_identity(pEp_identity *identity)
547 free(identity->address);
549 free(identity->user_id);
550 free(identity->username);
555 DYNAMIC_API PEP_STATUS get_identity(
556 PEP_SESSION session, const char *address,
557 pEp_identity **identity
560 PEP_STATUS status = PEP_STATUS_OK;
561 static pEp_identity *_identity;
569 if (!(session && address && address[0]))
570 return PEP_ILLEGAL_VALUE;
572 sqlite3_reset(session->get_identity);
573 sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
575 result = sqlite3_step(session->get_identity);
578 _identity = new_identity(
580 (const char *) sqlite3_column_text(session->get_identity, 0),
581 (const char *) sqlite3_column_text(session->get_identity, 1),
582 (const char *) sqlite3_column_text(session->get_identity, 2)
585 if (_identity == NULL)
586 return PEP_OUT_OF_MEMORY;
588 _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 3);
589 _lang = (const char *) sqlite3_column_text(session->get_identity, 4);
590 if (_lang && _lang[0]) {
591 assert(_lang[0] >= 'a' && _lang[0] <= 'z');
592 assert(_lang[1] >= 'a' && _lang[1] <= 'z');
593 assert(_lang[2] == 0);
594 _identity->lang[0] = _lang[0];
595 _identity->lang[1] = _lang[1];
596 _identity->lang[2] = 0;
598 *identity = _identity;
601 status = PEP_CANNOT_FIND_IDENTITY;
605 sqlite3_reset(session->get_identity);
609 DYNAMIC_API PEP_STATUS set_identity(
610 PEP_SESSION session, const pEp_identity *identity
617 assert(identity->address);
618 assert(identity->fpr);
619 assert(identity->user_id);
620 assert(identity->username);
622 if (!(session && identity && identity->address && identity->fpr &&
623 identity->user_id && identity->username))
624 return PEP_ILLEGAL_VALUE;
626 sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
628 sqlite3_reset(session->set_person);
629 sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
631 sqlite3_bind_text(session->set_person, 2, identity->username, -1,
633 if (identity->lang[0])
634 sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
637 sqlite3_bind_null(session->set_person, 3);
638 result = sqlite3_step(session->set_person);
639 sqlite3_reset(session->set_person);
640 if (result != SQLITE_DONE) {
641 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
642 return PEP_CANNOT_SET_PERSON;
645 sqlite3_reset(session->set_pgp_keypair);
646 sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
648 result = sqlite3_step(session->set_pgp_keypair);
649 sqlite3_reset(session->set_pgp_keypair);
650 if (result != SQLITE_DONE) {
651 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
652 return PEP_CANNOT_SET_PGP_KEYPAIR;
655 sqlite3_reset(session->set_identity);
656 sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
658 sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
660 sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
662 result = sqlite3_step(session->set_identity);
663 sqlite3_reset(session->set_identity);
664 if (result != SQLITE_DONE) {
665 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
666 return PEP_CANNOT_SET_IDENTITY;
669 sqlite3_reset(session->set_trust);
670 sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
672 sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
674 sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
675 result = sqlite3_step(session->set_trust);
676 sqlite3_reset(session->set_trust);
677 if (result != SQLITE_DONE) {
678 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
679 return PEP_CANNOT_SET_IDENTITY;
682 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
683 if (result == SQLITE_OK)
684 return PEP_STATUS_OK;
686 return PEP_COMMIT_FAILED;
689 void pEp_free(void *p)
694 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
696 PEP_STATUS status = PEP_STATUS_OK;
701 assert(identity->user_id);
702 assert(identity->user_id[0]);
703 assert(identity->fpr);
704 assert(identity->fpr[0]);
706 if (!(session && identity && identity->user_id && identity->user_id[0] &&
707 identity->fpr && identity->fpr[0]))
708 return PEP_ILLEGAL_VALUE;
710 identity->comm_type = PEP_ct_unknown;
712 sqlite3_reset(session->get_trust);
713 sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
714 sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
716 result = sqlite3_step(session->get_trust);
719 const char * user_id = (const char *) sqlite3_column_text(session->get_trust, 1);
720 int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 2);
722 if (strcmp(user_id, identity->user_id) != 0) {
723 free(identity->user_id);
724 identity->user_id = strdup(user_id);
725 assert(identity->user_id);
726 if (identity->user_id == NULL)
727 return PEP_OUT_OF_MEMORY;
729 identity->comm_type = comm_type;
734 status = PEP_CANNOT_FIND_IDENTITY;
737 sqlite3_reset(session->get_trust);
741 DYNAMIC_API PEP_STATUS decrypt_and_verify(
742 PEP_SESSION session, const char *ctext, size_t csize,
743 char **ptext, size_t *psize, stringlist_t **keylist
753 if (!(session && ctext && csize && ptext && psize && keylist && keylist))
754 return PEP_ILLEGAL_VALUE;
756 return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
759 DYNAMIC_API PEP_STATUS encrypt_and_sign(
760 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
761 size_t psize, char **ctext, size_t *csize
771 if (!(session && keylist && ptext && psize && ctext && csize))
772 return PEP_ILLEGAL_VALUE;
774 return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
777 DYNAMIC_API PEP_STATUS verify_text(
778 PEP_SESSION session, const char *text, size_t size,
779 const char *signature, size_t sig_size, stringlist_t **keylist
789 if (!(session && text && size && signature && sig_size && keylist))
790 return PEP_ILLEGAL_VALUE;
792 return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
795 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
800 if (!(session && fpr))
801 return PEP_ILLEGAL_VALUE;
803 return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
806 DYNAMIC_API PEP_STATUS export_key(
807 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
815 if (!(session && fpr && key_data && size))
816 return PEP_ILLEGAL_VALUE;
818 return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
821 DYNAMIC_API PEP_STATUS find_keys(
822 PEP_SESSION session, const char *pattern, stringlist_t **keylist
829 if (!(session && pattern && keylist))
830 return PEP_ILLEGAL_VALUE;
832 return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
835 DYNAMIC_API PEP_STATUS generate_keypair(
836 PEP_SESSION session, pEp_identity *identity
841 assert(identity->address);
842 assert(identity->fpr == NULL);
843 assert(identity->username);
845 if (!(session && identity && identity->address && identity->fpr == NULL &&
847 return PEP_ILLEGAL_VALUE;
849 return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
852 DYNAMIC_API PEP_STATUS get_key_rating(
855 PEP_comm_type *comm_type
862 if (!(session && fpr && comm_type))
863 return PEP_ILLEGAL_VALUE;
865 return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
868 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
873 if (!(session && key_data))
874 return PEP_ILLEGAL_VALUE;
876 return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
879 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
884 if (!(session && pattern))
885 return PEP_ILLEGAL_VALUE;
887 return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
890 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
895 if (!(session && pattern))
896 return PEP_ILLEGAL_VALUE;
898 return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
901 DYNAMIC_API PEP_STATUS renew_key(
910 if (!(session && fpr))
911 return PEP_ILLEGAL_VALUE;
913 return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
916 DYNAMIC_API PEP_STATUS revoke_key(PEP_SESSION session, const char *fpr)
921 if (!(session && fpr))
922 return PEP_ILLEGAL_VALUE;
924 return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr);