...
1 #include "dynamic_api.h"
2 #include "pEp_internal.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 // removed by calling caveat (see documentation)
36 pEpSession *_session = calloc(1, sizeof(pEpSession));
41 _session->version = PEP_ENGINE_VERSION;
44 if (LOCAL_DB == NULL) {
45 status = PEP_INIT_CANNOT_OPEN_DB;
49 int_result = sqlite3_open_v2(
54 | SQLITE_OPEN_FULLMUTEX
55 | SQLITE_OPEN_PRIVATECACHE,
59 if (int_result != SQLITE_OK) {
60 status = PEP_INIT_CANNOT_OPEN_DB;
64 sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
67 if (SYSTEM_DB == NULL) {
68 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
72 int_result = sqlite3_open_v2(
73 SYSTEM_DB, &_session->system_db,
75 | SQLITE_OPEN_FULLMUTEX
76 | SQLITE_OPEN_SHAREDCACHE,
80 if (int_result != SQLITE_OK) {
81 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
85 sqlite3_busy_timeout(_session->system_db, 1000);
88 int_result = sqlite3_exec(
90 "create table if not exists version_info ("
91 " id integer primary key,"
92 " timestamp integer default (datetime('now')) ,"
96 "create table if not exists log ("
97 " timestamp integer default (datetime('now')) ,"
98 " title text not null,"
99 " entity text not null,"
103 "create index if not exists log_timestamp on log ("
106 "create table if not exists pgp_keypair ("
107 " fpr text primary key,"
108 " public_id text unique,"
114 "create index if not exists pgp_keypair_expires on pgp_keypair ("
117 "create table if not exists person ("
118 " id text primary key,"
119 " username text not null,"
121 " references pgp_keypair (fpr)"
122 " on delete set null,"
126 "create table if not exists identity ("
127 " address text primary key,"
129 " references person (id)"
130 " on delete cascade,"
132 " references pgp_keypair (fpr)"
133 " on delete set null,"
136 "create table if not exists trust ("
137 " user_id text not null"
138 " references person (id)"
139 " on delete cascade,"
140 " pgp_keypair_fpr text not null"
141 " references pgp_keypair (fpr)"
142 " on delete cascade,"
143 " comm_type integer not null,"
146 "create unique index if not exists trust_index on trust ("
154 assert(int_result == SQLITE_OK);
156 int_result = sqlite3_exec(
158 "insert or replace into version_info (id, version) values (1, '1.0');",
163 assert(int_result == SQLITE_OK);
165 sql_log = "insert into log (title, entity, description, comment)"
166 "values (?1, ?2, ?3, ?4);";
168 sql_get_identity = "select fpr, identity.user_id, username, comm_type, lang"
170 " join person on id = identity.user_id"
171 " join pgp_keypair on fpr = identity.main_key_id"
172 " join trust on id = trust.user_id"
173 " and pgp_keypair_fpr = identity.main_key_id"
174 " where address = ?1 ;";
176 sql_safeword = "select id, word from wordlist where lang = lower(?1) "
179 sql_set_person = "insert or replace into person (id, username, lang) "
180 "values (?1, ?2, ?3) ;";
182 sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
185 sql_set_identity = "insert or replace into identity (address, main_key_id, "
186 "user_id) values (?1, ?2, ?3) ;";
188 sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
189 "values (?1, ?2, ?3) ;";
191 sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
192 "and pgp_keypair_fpr = ?2 ;";
195 int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
196 &_session->log, NULL);
197 assert(int_result == SQLITE_OK);
199 int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
200 strlen(sql_safeword), &_session->safeword, NULL);
201 assert(int_result == SQLITE_OK);
203 int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
204 strlen(sql_get_identity), &_session->get_identity, NULL);
205 assert(int_result == SQLITE_OK);
207 int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
208 strlen(sql_set_person), &_session->set_person, NULL);
209 assert(int_result == SQLITE_OK);
211 int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
212 strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
213 assert(int_result == SQLITE_OK);
215 int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
216 strlen(sql_set_identity), &_session->set_identity, NULL);
217 assert(int_result == SQLITE_OK);
219 int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
220 strlen(sql_set_trust), &_session->set_trust, NULL);
221 assert(int_result == SQLITE_OK);
223 int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
224 strlen(sql_get_trust), &_session->get_trust, NULL);
225 assert(int_result == SQLITE_OK);
227 status = init_cryptotech(_session, in_first);
228 if (status != PEP_STATUS_OK)
231 status = init_transport_system(_session, in_first);
232 if (status != PEP_STATUS_OK)
235 status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
236 if (status != PEP_STATUS_OK)
240 return PEP_STATUS_OK;
243 status = PEP_OUT_OF_MEMORY;
250 DYNAMIC_API void release(PEP_SESSION session)
252 bool out_last = false;
254 assert(init_count >= 0);
257 // a small race condition but still a race condition
258 // removed by calling caveat (see documentation)
266 if (session->safeword)
267 sqlite3_finalize(session->safeword);
269 sqlite3_finalize(session->log);
270 if (session->get_identity)
271 sqlite3_finalize(session->get_identity);
272 if (session->set_identity)
273 sqlite3_finalize(session->set_identity);
274 if (session->set_person)
275 sqlite3_finalize(session->set_person);
276 if (session->set_pgp_keypair)
277 sqlite3_finalize(session->set_pgp_keypair);
278 if (session->set_trust)
279 sqlite3_finalize(session->set_trust);
280 if (session->get_trust)
281 sqlite3_finalize(session->get_trust);
284 sqlite3_close_v2(session->db);
285 if (session->system_db)
286 sqlite3_close_v2(session->system_db);
289 release_transport_system(session, out_last);
290 release_cryptotech(session, out_last);
296 DYNAMIC_API PEP_STATUS log_event(
297 PEP_SESSION session, const char *title, const char *entity,
298 const char *description, const char *comment
301 PEP_STATUS status = PEP_STATUS_OK;
308 sqlite3_reset(session->log);
309 sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
310 sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
312 sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
314 sqlite3_bind_null(session->log, 3);
316 sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
318 sqlite3_bind_null(session->log, 4);
320 result = sqlite3_step(session->log);
321 assert(result == SQLITE_DONE || result == SQLITE_BUSY);
322 if (result != SQLITE_DONE && result != SQLITE_BUSY)
323 status = PEP_UNKNOWN_ERROR;
324 } while (result == SQLITE_BUSY);
325 sqlite3_reset(session->log);
330 DYNAMIC_API PEP_STATUS safeword(
331 PEP_SESSION session, uint16_t value, const char *lang,
332 char **word, size_t *wsize
335 PEP_STATUS status = PEP_STATUS_OK;
348 assert((lang[0] >= 'A' && lang[0] <= 'Z')
349 || (lang[0] >= 'a' && lang[0] <= 'z'));
350 assert((lang[1] >= 'A' && lang[1] <= 'Z')
351 || (lang[1] >= 'a' && lang[1] <= 'z'));
352 assert(lang[2] == 0);
354 sqlite3_reset(session->safeword);
355 sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
356 sqlite3_bind_int(session->safeword, 2, value);
358 result = sqlite3_step(session->safeword);
359 if (result == SQLITE_ROW) {
360 *word = strdup((const char *) sqlite3_column_text(session->safeword,
363 *wsize = sqlite3_column_bytes(session->safeword, 1);
365 status = PEP_SAFEWORD_NOT_FOUND;
367 status = PEP_SAFEWORD_NOT_FOUND;
369 sqlite3_reset(session->safeword);
373 DYNAMIC_API PEP_STATUS safewords(
374 PEP_SESSION session, const char *fingerprint, const char *lang,
375 char **words, size_t *wsize, int max_words
378 const char *source = fingerprint;
379 char *buffer = calloc(1, MAX_SAFEWORDS_SPACE);
388 assert(max_words >= 0);
395 return PEP_OUT_OF_MEMORY;
397 fsize = strlen(fingerprint);
402 assert((lang[0] >= 'A' && lang[0] <= 'Z')
403 || (lang[0] >= 'a' && lang[0] <= 'z'));
404 assert((lang[1] >= 'A' && lang[1] <= 'Z')
405 || (lang[1] >= 'a' && lang[1] <= 'z'));
406 assert(lang[2] == 0);
409 while (source < fingerprint + fsize) {
415 for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
416 if (*source >= 'a' && *source <= 'f')
417 value += (*source - 'a' + 10) << (3 - j++) * 4;
418 else if (*source >= 'A' && *source <= 'F')
419 value += (*source - 'A' + 10) << (3 - j++) * 4;
420 else if (*source >= '0' && *source <= '9')
421 value += (*source - '0') << (3 - j++) * 4;
426 _status = safeword(session, value, lang, &word, &_wsize);
427 if (_status == PEP_OUT_OF_MEMORY) {
429 return PEP_OUT_OF_MEMORY;
433 return PEP_SAFEWORD_NOT_FOUND;
436 if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
437 strncpy(dest, word, _wsize);
443 break; // buffer full
446 if (source < fingerprint + fsize
447 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
451 if (max_words && n_words >= max_words)
456 *wsize = dest - buffer;
457 return PEP_STATUS_OK;
460 pEp_identity *new_identity(
461 const char *address, const char *fpr, const char *user_id,
465 pEp_identity *result = calloc(1, sizeof(pEp_identity));
469 result->address = strdup(address);
470 assert(result->address);
471 if (result->address == NULL) {
475 result->address_size = strlen(address);
478 result->fpr = strdup(fpr);
480 if (result->fpr == NULL) {
481 free_identity(result);
484 result->fpr_size = strlen(fpr);
487 result->user_id = strdup(user_id);
488 assert(result->user_id);
489 if (result->user_id == NULL) {
490 free_identity(result);
493 result->user_id_size = strlen(user_id);
496 result->username = strdup(username);
497 assert(result->username);
498 if (result->username == NULL) {
499 free_identity(result);
502 result->username_size = strlen(username);
504 result->struct_size = sizeof(pEp_identity);
509 pEp_identity *identity_dup(const pEp_identity *src)
513 pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
518 dup->comm_type = src->comm_type;
519 dup->lang[0] = src->lang[0];
520 dup->lang[1] = src->lang[1];
527 void free_identity(pEp_identity *identity)
530 free(identity->address);
532 free(identity->user_id);
533 free(identity->username);
538 DYNAMIC_API PEP_STATUS get_identity(
539 PEP_SESSION session, const char *address,
540 pEp_identity **identity
543 PEP_STATUS status = PEP_STATUS_OK;
544 static pEp_identity *_identity;
552 sqlite3_reset(session->get_identity);
553 sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
555 result = sqlite3_step(session->get_identity);
558 _identity = new_identity(
560 (const char *) sqlite3_column_text(session->get_identity, 0),
561 (const char *) sqlite3_column_text(session->get_identity, 1),
562 (const char *) sqlite3_column_text(session->get_identity, 2)
565 if (_identity == NULL)
566 return PEP_OUT_OF_MEMORY;
568 _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 3);
569 _lang = (const char *) sqlite3_column_text(session->get_identity, 4);
570 if (_lang && _lang[0]) {
571 assert(_lang[0] >= 'a' && _lang[0] <= 'z');
572 assert(_lang[1] >= 'a' && _lang[1] <= 'z');
573 assert(_lang[2] == 0);
574 _identity->lang[0] = _lang[0];
575 _identity->lang[1] = _lang[1];
576 _identity->lang[2] = 0;
578 *identity = _identity;
581 status = PEP_CANNOT_FIND_IDENTITY;
585 sqlite3_reset(session->get_identity);
589 DYNAMIC_API PEP_STATUS set_identity(
590 PEP_SESSION session, const pEp_identity *identity
597 assert(identity->address);
598 assert(identity->fpr);
599 assert(identity->user_id);
600 assert(identity->username);
602 sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
604 sqlite3_reset(session->set_person);
605 sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
607 sqlite3_bind_text(session->set_person, 2, identity->username, -1,
609 if (identity->lang[0])
610 sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
613 sqlite3_bind_null(session->set_person, 3);
614 result = sqlite3_step(session->set_person);
615 sqlite3_reset(session->set_person);
616 if (result != SQLITE_DONE) {
617 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
618 return PEP_CANNOT_SET_PERSON;
621 sqlite3_reset(session->set_pgp_keypair);
622 sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
624 result = sqlite3_step(session->set_pgp_keypair);
625 sqlite3_reset(session->set_pgp_keypair);
626 if (result != SQLITE_DONE) {
627 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
628 return PEP_CANNOT_SET_PGP_KEYPAIR;
631 sqlite3_reset(session->set_identity);
632 sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
634 sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
636 sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
638 result = sqlite3_step(session->set_identity);
639 sqlite3_reset(session->set_identity);
640 if (result != SQLITE_DONE) {
641 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
642 return PEP_CANNOT_SET_IDENTITY;
645 sqlite3_reset(session->set_trust);
646 sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
648 sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
650 sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
651 result = sqlite3_step(session->set_trust);
652 sqlite3_reset(session->set_trust);
653 if (result != SQLITE_DONE) {
654 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
655 return PEP_CANNOT_SET_IDENTITY;
658 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
659 if (result == SQLITE_OK)
660 return PEP_STATUS_OK;
662 return PEP_COMMIT_FAILED;
665 void pEp_free(void *p)
670 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
672 PEP_STATUS status = PEP_STATUS_OK;
677 assert(identity->user_id);
678 assert(identity->user_id[0]);
679 assert(identity->fpr);
680 assert(identity->fpr[0]);
682 identity->comm_type = PEP_ct_unknown;
684 sqlite3_reset(session->get_trust);
685 sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
686 sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
688 result = sqlite3_step(session->get_trust);
691 const char * user_id = (const char *) sqlite3_column_text(session->get_trust, 1);
692 int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 2);
694 if (strcmp(user_id, identity->user_id) != 0) {
695 free(identity->user_id);
696 identity->user_id = strdup(user_id);
697 assert(identity->user_id);
698 if (identity->user_id == NULL)
699 return PEP_OUT_OF_MEMORY;
701 identity->comm_type = comm_type;
706 status = PEP_CANNOT_FIND_IDENTITY;
709 sqlite3_reset(session->get_trust);
713 DYNAMIC_API PEP_STATUS decrypt_and_verify(
714 PEP_SESSION session, const char *ctext, size_t csize,
715 char **ptext, size_t *psize, stringlist_t **keylist
718 return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
721 DYNAMIC_API PEP_STATUS encrypt_and_sign(
722 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
723 size_t psize, char **ctext, size_t *csize
726 return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
729 DYNAMIC_API PEP_STATUS verify_text(
730 PEP_SESSION session, const char *text, size_t size,
731 const char *signature, size_t sig_size, stringlist_t **keylist
734 return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
737 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
739 return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
742 DYNAMIC_API PEP_STATUS export_key(
743 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
746 return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
749 DYNAMIC_API PEP_STATUS find_keys(
750 PEP_SESSION session, const char *pattern, stringlist_t **keylist
753 return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
756 DYNAMIC_API PEP_STATUS generate_keypair(
757 PEP_SESSION session, pEp_identity *identity
760 return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
763 DYNAMIC_API PEP_STATUS get_key_rating(
766 PEP_comm_type *comm_type
769 return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
772 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
774 return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
777 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
779 return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
782 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
784 return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);