1 #include "pEp_internal.h"
2 #include "dynamic_api.h"
3 #include "cryptotech.h"
9 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
11 PEP_STATUS status = PEP_STATUS_OK;
13 static const char *sql_log;
14 static const char *sql_safeword;
15 static const char *sql_get_identity;
16 static const char *sql_set_person;
17 static const char *sql_set_pgp_keypair;
18 static const char *sql_set_identity;
19 static const char *sql_set_trust;
20 static const char *sql_get_trust;
21 bool in_first = false;
23 assert(sqlite3_threadsafe());
24 if (!sqlite3_threadsafe())
25 return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
27 // a little race condition - but still a race condition
28 // mitigated by calling caveat (see documentation)
36 return PEP_ILLEGAL_VALUE;
40 pEpSession *_session = calloc(1, sizeof(pEpSession));
45 _session->version = PEP_ENGINE_VERSION;
48 if (LOCAL_DB == NULL) {
49 status = PEP_INIT_CANNOT_OPEN_DB;
53 int_result = sqlite3_open_v2(
58 | SQLITE_OPEN_FULLMUTEX
59 | SQLITE_OPEN_PRIVATECACHE,
63 if (int_result != SQLITE_OK) {
64 status = PEP_INIT_CANNOT_OPEN_DB;
68 sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
71 if (SYSTEM_DB == NULL) {
72 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
76 int_result = sqlite3_open_v2(
77 SYSTEM_DB, &_session->system_db,
79 | SQLITE_OPEN_FULLMUTEX
80 | SQLITE_OPEN_SHAREDCACHE,
84 if (int_result != SQLITE_OK) {
85 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
89 sqlite3_busy_timeout(_session->system_db, 1000);
92 int_result = sqlite3_exec(
94 "create table if not exists version_info ("
95 " id integer primary key,"
96 " timestamp integer default (datetime('now')) ,"
100 "create table if not exists log ("
101 " timestamp integer default (datetime('now')) ,"
102 " title text not null,"
103 " entity text not null,"
107 "create index if not exists log_timestamp on log ("
110 "create table if not exists pgp_keypair ("
111 " fpr text primary key,"
112 " public_id text unique,"
118 "create index if not exists pgp_keypair_expires on pgp_keypair ("
121 "create table if not exists person ("
122 " id text primary key,"
123 " username text not null,"
125 " references pgp_keypair (fpr)"
126 " on delete set null,"
130 "create table if not exists identity ("
131 " address text primary key,"
133 " references person (id)"
134 " on delete cascade,"
136 " references pgp_keypair (fpr)"
137 " on delete set null,"
140 "create table if not exists trust ("
141 " user_id text not null"
142 " references person (id)"
143 " on delete cascade,"
144 " pgp_keypair_fpr text not null"
145 " references pgp_keypair (fpr)"
146 " on delete cascade,"
147 " comm_type integer not null,"
150 "create unique index if not exists trust_index on trust ("
158 assert(int_result == SQLITE_OK);
160 int_result = sqlite3_exec(
162 "insert or replace into version_info (id, version) values (1, '1.0');",
167 assert(int_result == SQLITE_OK);
169 sql_log = "insert into log (title, entity, description, comment)"
170 "values (?1, ?2, ?3, ?4);";
172 sql_get_identity = "select fpr, identity.user_id, username, comm_type, lang"
174 " join person on id = identity.user_id"
175 " join pgp_keypair on fpr = identity.main_key_id"
176 " join trust on id = trust.user_id"
177 " and pgp_keypair_fpr = identity.main_key_id"
178 " where address = ?1 ;";
180 sql_safeword = "select id, word from wordlist where lang = lower(?1) "
183 sql_set_person = "insert or replace into person (id, username, lang) "
184 "values (?1, ?2, ?3) ;";
186 sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
189 sql_set_identity = "insert or replace into identity (address, main_key_id, "
190 "user_id) values (?1, ?2, ?3) ;";
192 sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
193 "values (?1, ?2, ?3) ;";
195 sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
196 "and pgp_keypair_fpr = ?2 ;";
199 int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
200 &_session->log, NULL);
201 assert(int_result == SQLITE_OK);
203 int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
204 strlen(sql_safeword), &_session->safeword, NULL);
205 assert(int_result == SQLITE_OK);
207 int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
208 strlen(sql_get_identity), &_session->get_identity, NULL);
209 assert(int_result == SQLITE_OK);
211 int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
212 strlen(sql_set_person), &_session->set_person, NULL);
213 assert(int_result == SQLITE_OK);
215 int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
216 strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
217 assert(int_result == SQLITE_OK);
219 int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
220 strlen(sql_set_identity), &_session->set_identity, NULL);
221 assert(int_result == SQLITE_OK);
223 int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
224 strlen(sql_set_trust), &_session->set_trust, NULL);
225 assert(int_result == SQLITE_OK);
227 int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
228 strlen(sql_get_trust), &_session->get_trust, NULL);
229 assert(int_result == SQLITE_OK);
231 status = init_cryptotech(_session, in_first);
232 if (status != PEP_STATUS_OK)
235 status = init_transport_system(_session, in_first);
236 if (status != PEP_STATUS_OK)
239 status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
240 if (status != PEP_STATUS_OK)
244 return PEP_STATUS_OK;
247 status = PEP_OUT_OF_MEMORY;
254 DYNAMIC_API void release(PEP_SESSION session)
256 bool out_last = false;
258 assert(init_count >= 0);
261 if (!(init_count && session))
264 // a small race condition but still a race condition
265 // mitigated by calling caveat (see documentation)
273 if (session->safeword)
274 sqlite3_finalize(session->safeword);
276 sqlite3_finalize(session->log);
277 if (session->get_identity)
278 sqlite3_finalize(session->get_identity);
279 if (session->set_identity)
280 sqlite3_finalize(session->set_identity);
281 if (session->set_person)
282 sqlite3_finalize(session->set_person);
283 if (session->set_pgp_keypair)
284 sqlite3_finalize(session->set_pgp_keypair);
285 if (session->set_trust)
286 sqlite3_finalize(session->set_trust);
287 if (session->get_trust)
288 sqlite3_finalize(session->get_trust);
291 sqlite3_close_v2(session->db);
292 if (session->system_db)
293 sqlite3_close_v2(session->system_db);
296 release_transport_system(session, out_last);
297 release_cryptotech(session, out_last);
303 DYNAMIC_API PEP_STATUS log_event(
304 PEP_SESSION session, const char *title, const char *entity,
305 const char *description, const char *comment
308 PEP_STATUS status = PEP_STATUS_OK;
315 if (!(session && title && entity))
316 return PEP_ILLEGAL_VALUE;
318 sqlite3_reset(session->log);
319 sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
320 sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
322 sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
324 sqlite3_bind_null(session->log, 3);
326 sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
328 sqlite3_bind_null(session->log, 4);
330 result = sqlite3_step(session->log);
331 assert(result == SQLITE_DONE || result == SQLITE_BUSY);
332 if (result != SQLITE_DONE && result != SQLITE_BUSY)
333 status = PEP_UNKNOWN_ERROR;
334 } while (result == SQLITE_BUSY);
335 sqlite3_reset(session->log);
340 DYNAMIC_API PEP_STATUS safeword(
341 PEP_SESSION session, uint16_t value, const char *lang,
342 char **word, size_t *wsize
345 PEP_STATUS status = PEP_STATUS_OK;
352 if (!(session && word && wsize))
353 return PEP_ILLEGAL_VALUE;
361 assert((lang[0] >= 'A' && lang[0] <= 'Z')
362 || (lang[0] >= 'a' && lang[0] <= 'z'));
363 assert((lang[1] >= 'A' && lang[1] <= 'Z')
364 || (lang[1] >= 'a' && lang[1] <= 'z'));
365 assert(lang[2] == 0);
367 sqlite3_reset(session->safeword);
368 sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
369 sqlite3_bind_int(session->safeword, 2, value);
371 result = sqlite3_step(session->safeword);
372 if (result == SQLITE_ROW) {
373 *word = strdup((const char *) sqlite3_column_text(session->safeword,
376 *wsize = sqlite3_column_bytes(session->safeword, 1);
378 status = PEP_SAFEWORD_NOT_FOUND;
380 status = PEP_SAFEWORD_NOT_FOUND;
382 sqlite3_reset(session->safeword);
386 DYNAMIC_API PEP_STATUS safewords(
387 PEP_SESSION session, const char *fingerprint, const char *lang,
388 char **words, size_t *wsize, int max_words
391 const char *source = fingerprint;
401 assert(max_words >= 0);
403 if (!(session && fingerprint && words && wsize && max_words >= 0))
404 return PEP_ILLEGAL_VALUE;
409 buffer = calloc(1, MAX_SAFEWORDS_SPACE);
412 return PEP_OUT_OF_MEMORY;
415 fsize = strlen(fingerprint);
420 assert((lang[0] >= 'A' && lang[0] <= 'Z')
421 || (lang[0] >= 'a' && lang[0] <= 'z'));
422 assert((lang[1] >= 'A' && lang[1] <= 'Z')
423 || (lang[1] >= 'a' && lang[1] <= 'z'));
424 assert(lang[2] == 0);
427 while (source < fingerprint + fsize) {
433 for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
434 if (*source >= 'a' && *source <= 'f')
435 value += (*source - 'a' + 10) << (3 - j++) * 4;
436 else if (*source >= 'A' && *source <= 'F')
437 value += (*source - 'A' + 10) << (3 - j++) * 4;
438 else if (*source >= '0' && *source <= '9')
439 value += (*source - '0') << (3 - j++) * 4;
444 _status = safeword(session, value, lang, &word, &_wsize);
445 if (_status == PEP_OUT_OF_MEMORY) {
447 return PEP_OUT_OF_MEMORY;
451 return PEP_SAFEWORD_NOT_FOUND;
454 if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
455 strncpy(dest, word, _wsize);
461 break; // buffer full
464 if (source < fingerprint + fsize
465 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
469 if (max_words && n_words >= max_words)
474 *wsize = dest - buffer;
475 return PEP_STATUS_OK;
478 pEp_identity *new_identity(
479 const char *address, const char *fpr, const char *user_id,
483 pEp_identity *result = calloc(1, sizeof(pEp_identity));
487 result->address = strdup(address);
488 assert(result->address);
489 if (result->address == NULL) {
493 result->address_size = strlen(address);
496 result->fpr = strdup(fpr);
498 if (result->fpr == NULL) {
499 free_identity(result);
502 result->fpr_size = strlen(fpr);
505 result->user_id = strdup(user_id);
506 assert(result->user_id);
507 if (result->user_id == NULL) {
508 free_identity(result);
511 result->user_id_size = strlen(user_id);
514 result->username = strdup(username);
515 assert(result->username);
516 if (result->username == NULL) {
517 free_identity(result);
520 result->username_size = strlen(username);
522 result->struct_size = sizeof(pEp_identity);
527 pEp_identity *identity_dup(const pEp_identity *src)
531 pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
536 dup->comm_type = src->comm_type;
537 dup->lang[0] = src->lang[0];
538 dup->lang[1] = src->lang[1];
545 void free_identity(pEp_identity *identity)
548 free(identity->address);
550 free(identity->user_id);
551 free(identity->username);
556 DYNAMIC_API PEP_STATUS get_identity(
557 PEP_SESSION session, const char *address,
558 pEp_identity **identity
561 PEP_STATUS status = PEP_STATUS_OK;
562 static pEp_identity *_identity;
570 if (!(session && address && address[0]))
571 return PEP_ILLEGAL_VALUE;
573 sqlite3_reset(session->get_identity);
574 sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
576 result = sqlite3_step(session->get_identity);
579 _identity = new_identity(
581 (const char *) sqlite3_column_text(session->get_identity, 0),
582 (const char *) sqlite3_column_text(session->get_identity, 1),
583 (const char *) sqlite3_column_text(session->get_identity, 2)
586 if (_identity == NULL)
587 return PEP_OUT_OF_MEMORY;
589 _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 3);
590 _lang = (const char *) sqlite3_column_text(session->get_identity, 4);
591 if (_lang && _lang[0]) {
592 assert(_lang[0] >= 'a' && _lang[0] <= 'z');
593 assert(_lang[1] >= 'a' && _lang[1] <= 'z');
594 assert(_lang[2] == 0);
595 _identity->lang[0] = _lang[0];
596 _identity->lang[1] = _lang[1];
597 _identity->lang[2] = 0;
599 *identity = _identity;
602 status = PEP_CANNOT_FIND_IDENTITY;
606 sqlite3_reset(session->get_identity);
610 DYNAMIC_API PEP_STATUS set_identity(
611 PEP_SESSION session, const pEp_identity *identity
618 assert(identity->address);
619 assert(identity->fpr);
620 assert(identity->user_id);
621 assert(identity->username);
623 if (!(session && identity && identity->address && identity->fpr &&
624 identity->user_id && identity->username))
625 return PEP_ILLEGAL_VALUE;
627 sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
629 sqlite3_reset(session->set_person);
630 sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
632 sqlite3_bind_text(session->set_person, 2, identity->username, -1,
634 if (identity->lang[0])
635 sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
638 sqlite3_bind_null(session->set_person, 3);
639 result = sqlite3_step(session->set_person);
640 sqlite3_reset(session->set_person);
641 if (result != SQLITE_DONE) {
642 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
643 return PEP_CANNOT_SET_PERSON;
646 sqlite3_reset(session->set_pgp_keypair);
647 sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
649 result = sqlite3_step(session->set_pgp_keypair);
650 sqlite3_reset(session->set_pgp_keypair);
651 if (result != SQLITE_DONE) {
652 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
653 return PEP_CANNOT_SET_PGP_KEYPAIR;
656 sqlite3_reset(session->set_identity);
657 sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
659 sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
661 sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
663 result = sqlite3_step(session->set_identity);
664 sqlite3_reset(session->set_identity);
665 if (result != SQLITE_DONE) {
666 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
667 return PEP_CANNOT_SET_IDENTITY;
670 sqlite3_reset(session->set_trust);
671 sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
673 sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
675 sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
676 result = sqlite3_step(session->set_trust);
677 sqlite3_reset(session->set_trust);
678 if (result != SQLITE_DONE) {
679 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
680 return PEP_CANNOT_SET_IDENTITY;
683 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
684 if (result == SQLITE_OK)
685 return PEP_STATUS_OK;
687 return PEP_COMMIT_FAILED;
690 void pEp_free(void *p)
695 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
697 PEP_STATUS status = PEP_STATUS_OK;
702 assert(identity->user_id);
703 assert(identity->user_id[0]);
704 assert(identity->fpr);
705 assert(identity->fpr[0]);
707 if (!(session && identity && identity->user_id && identity->user_id[0] &&
708 identity->fpr && identity->fpr[0]))
709 return PEP_ILLEGAL_VALUE;
711 identity->comm_type = PEP_ct_unknown;
713 sqlite3_reset(session->get_trust);
714 sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
715 sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
717 result = sqlite3_step(session->get_trust);
720 const char * user_id = (const char *) sqlite3_column_text(session->get_trust, 1);
721 int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 2);
723 if (strcmp(user_id, identity->user_id) != 0) {
724 free(identity->user_id);
725 identity->user_id = strdup(user_id);
726 assert(identity->user_id);
727 if (identity->user_id == NULL)
728 return PEP_OUT_OF_MEMORY;
730 identity->comm_type = comm_type;
735 status = PEP_CANNOT_FIND_IDENTITY;
738 sqlite3_reset(session->get_trust);
742 DYNAMIC_API PEP_STATUS decrypt_and_verify(
743 PEP_SESSION session, const char *ctext, size_t csize,
744 char **ptext, size_t *psize, stringlist_t **keylist
754 if (!(session && ctext && csize && ptext && psize && keylist && keylist))
755 return PEP_ILLEGAL_VALUE;
757 return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
760 DYNAMIC_API PEP_STATUS encrypt_and_sign(
761 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
762 size_t psize, char **ctext, size_t *csize
772 if (!(session && keylist && ptext && psize && ctext && csize))
773 return PEP_ILLEGAL_VALUE;
775 return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
778 DYNAMIC_API PEP_STATUS verify_text(
779 PEP_SESSION session, const char *text, size_t size,
780 const char *signature, size_t sig_size, stringlist_t **keylist
790 if (!(session && text && size && signature && sig_size && keylist))
791 return PEP_ILLEGAL_VALUE;
793 return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
796 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
801 if (!(session && fpr))
802 return PEP_ILLEGAL_VALUE;
804 return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
807 DYNAMIC_API PEP_STATUS export_key(
808 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
816 if (!(session && fpr && key_data && size))
817 return PEP_ILLEGAL_VALUE;
819 return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
822 DYNAMIC_API PEP_STATUS find_keys(
823 PEP_SESSION session, const char *pattern, stringlist_t **keylist
830 if (!(session && pattern && keylist))
831 return PEP_ILLEGAL_VALUE;
833 return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
836 DYNAMIC_API PEP_STATUS generate_keypair(
837 PEP_SESSION session, pEp_identity *identity
842 assert(identity->address);
843 assert(identity->fpr == NULL);
844 assert(identity->username);
846 if (!(session && identity && identity->address && identity->fpr == NULL &&
848 return PEP_ILLEGAL_VALUE;
850 return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
853 DYNAMIC_API PEP_STATUS get_key_rating(
856 PEP_comm_type *comm_type
863 if (!(session && fpr && comm_type))
864 return PEP_ILLEGAL_VALUE;
866 return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
869 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
874 if (!(session && key_data))
875 return PEP_ILLEGAL_VALUE;
877 return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
880 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
885 if (!(session && pattern))
886 return PEP_ILLEGAL_VALUE;
888 return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
891 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
896 if (!(session && pattern))
897 return PEP_ILLEGAL_VALUE;
899 return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
902 DYNAMIC_API PEP_STATUS renew_key(
911 if (!(session && fpr))
912 return PEP_ILLEGAL_VALUE;
914 return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
917 DYNAMIC_API PEP_STATUS revoke_key(PEP_SESSION session, const char *fpr)
922 if (!(session && fpr))
923 return PEP_ILLEGAL_VALUE;
925 return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr);