...
1 #include "pEp_internal.h"
2 #include "cryptotech.h"
7 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
9 PEP_STATUS status = PEP_STATUS_OK;
11 static const char *sql_log;
12 static const char *sql_safeword;
13 static const char *sql_get_identity;
14 static const char *sql_set_person;
15 static const char *sql_set_pgp_keypair;
16 static const char *sql_set_identity;
17 static const char *sql_set_trust;
18 static const char *sql_get_trust;
19 bool in_first = false;
21 assert(sqlite3_threadsafe());
22 if (!sqlite3_threadsafe())
23 return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
25 // a little race condition - but still a race condition
26 // removed by calling caveat (see documentation)
35 pEpSession *_session = (pEpSession *) calloc(1, sizeof(pEpSession));
40 _session->version = PEP_ENGINE_VERSION;
43 if (LOCAL_DB == NULL) {
44 status = PEP_INIT_CANNOT_OPEN_DB;
48 int_result = sqlite3_open_v2(
53 | SQLITE_OPEN_FULLMUTEX
54 | SQLITE_OPEN_PRIVATECACHE,
58 if (int_result != SQLITE_OK) {
59 status = PEP_INIT_CANNOT_OPEN_DB;
63 sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
66 if (SYSTEM_DB == NULL) {
67 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
71 int_result = sqlite3_open_v2(
72 SYSTEM_DB, &_session->system_db,
74 | SQLITE_OPEN_FULLMUTEX
75 | SQLITE_OPEN_SHAREDCACHE,
79 if (int_result != SQLITE_OK) {
80 status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
84 sqlite3_busy_timeout(_session->system_db, 1000);
87 int_result = sqlite3_exec(
89 "create table if not exists version_info ("
90 " id integer primary key,"
91 " timestamp integer default (datetime('now')) ,"
95 "create table if not exists log ("
96 " timestamp integer default (datetime('now')) ,"
97 " title text not null,"
98 " entity text not null,"
102 "create index if not exists log_timestamp on log ("
105 "create table if not exists pgp_keypair ("
106 " fpr text primary key,"
107 " public_id text unique,"
113 "create index if not exists pgp_keypair_expires on pgp_keypair ("
116 "create table if not exists person ("
117 " id text primary key,"
118 " username text not null,"
120 " references pgp_keypair (fpr)"
121 " on delete set null,"
125 "create table if not exists identity ("
126 " address text primary key,"
128 " references person (id)"
129 " on delete cascade,"
131 " references pgp_keypair (fpr)"
132 " on delete set null,"
135 "create table if not exists trust ("
136 " user_id text not null"
137 " references person (id)"
138 " on delete cascade,"
139 " pgp_keypair_fpr text not null"
140 " references pgp_keypair (fpr)"
141 " on delete cascade,"
142 " comm_type integer not null,"
145 "create unique index if not exists trust_index on trust ("
153 assert(int_result == SQLITE_OK);
155 int_result = sqlite3_exec(
157 "insert or replace into version_info (id, version) values (1, '1.0');",
162 assert(int_result == SQLITE_OK);
164 sql_log = "insert into log (title, entity, description, comment)"
165 "values (?1, ?2, ?3, ?4);";
167 sql_get_identity = "select fpr, identity.user_id, username, comm_type, lang"
169 " join person on id = identity.user_id"
170 " join pgp_keypair on fpr = identity.main_key_id"
171 " join trust on id = trust.user_id"
172 " and pgp_keypair_fpr = identity.main_key_id"
173 " where address = ?1 ;";
175 sql_safeword = "select id, word from wordlist where lang = lower(?1) "
178 sql_set_person = "insert or replace into person (id, username, lang) "
179 "values (?1, ?2, ?3) ;";
181 sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
184 sql_set_identity = "insert or replace into identity (address, main_key_id, "
185 "user_id) values (?1, ?2, ?3) ;";
187 sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
188 "values (?1, ?2, ?3) ;";
190 sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
191 "and pgp_keypair_fpr = ?2 ;";
194 int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
195 &_session->log, NULL);
196 assert(int_result == SQLITE_OK);
198 int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
199 strlen(sql_safeword), &_session->safeword, NULL);
200 assert(int_result == SQLITE_OK);
202 int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
203 strlen(sql_get_identity), &_session->get_identity, NULL);
204 assert(int_result == SQLITE_OK);
206 int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
207 strlen(sql_set_person), &_session->set_person, NULL);
208 assert(int_result == SQLITE_OK);
210 int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
211 strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
212 assert(int_result == SQLITE_OK);
214 int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
215 strlen(sql_set_identity), &_session->set_identity, NULL);
216 assert(int_result == SQLITE_OK);
218 int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
219 strlen(sql_set_trust), &_session->set_trust, NULL);
220 assert(int_result == SQLITE_OK);
222 int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
223 strlen(sql_get_trust), &_session->get_trust, NULL);
224 assert(int_result == SQLITE_OK);
226 status = init_cryptotech(_session, in_first);
227 if (status != PEP_STATUS_OK)
230 status = init_transport_system(_session, in_first);
231 if (status != PEP_STATUS_OK)
234 status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
235 if (status != PEP_STATUS_OK)
239 return PEP_STATUS_OK;
242 status = PEP_OUT_OF_MEMORY;
249 DYNAMIC_API void release(PEP_SESSION session)
251 bool out_last = false;
253 assert(init_count >= 0);
256 // a small race condition but still a race condition
257 // removed by calling caveat (see documentation)
265 if (session->safeword)
266 sqlite3_finalize(session->safeword);
268 sqlite3_finalize(session->log);
269 if (session->get_identity)
270 sqlite3_finalize(session->get_identity);
271 if (session->set_identity)
272 sqlite3_finalize(session->set_identity);
273 if (session->set_person)
274 sqlite3_finalize(session->set_person);
275 if (session->set_pgp_keypair)
276 sqlite3_finalize(session->set_pgp_keypair);
277 if (session->set_trust)
278 sqlite3_finalize(session->set_trust);
279 if (session->get_trust)
280 sqlite3_finalize(session->get_trust);
283 sqlite3_close_v2(session->db);
284 if (session->system_db)
285 sqlite3_close_v2(session->system_db);
288 release_transport_system(session, out_last);
289 release_cryptotech(session, out_last);
295 stringlist_t *new_stringlist(const char *value)
297 stringlist_t *result = (stringlist_t *) calloc(1, sizeof(stringlist_t));
298 if (result && value) {
299 result->value = strdup(value);
300 assert(result->value);
301 if (result->value == 0) {
309 DYNAMIC_API stringlist_t *stringlist_dup(const stringlist_t *src)
315 stringlist_t *dst = new_stringlist(src->value);
320 dst->next = stringlist_dup(src->next);
321 if (dst->next == NULL) {
330 stringlist_t *stringlist_add(stringlist_t *stringlist, const char *value)
334 if (stringlist == NULL)
335 return new_stringlist(value);
337 if (stringlist->next != NULL)
338 return stringlist_add(stringlist->next, value);
339 if (stringlist->value == NULL) {
340 stringlist->value = strdup(value);
341 assert(stringlist->value);
342 if (stringlist->value == NULL)
347 stringlist->next = new_stringlist(value);
348 assert(stringlist->next);
349 if (stringlist->next == NULL)
352 return stringlist->next;
355 DYNAMIC_API stringlist_t *stringlist_append(stringlist_t *stringlist,
356 stringlist_t *second)
360 if (second == NULL || second->value == NULL)
363 stringlist_t *_s = stringlist;
365 for (_s2 = second; _s2 != NULL; _s2 = _s2->next) {
366 _s = stringlist_add(_s, _s2->value);
373 int stringlist_length(const stringlist_t *stringlist)
376 stringlist_t *_stringlist;
380 if (stringlist->value == NULL)
383 for (_stringlist=stringlist->next; _stringlist!=NULL; _stringlist=_stringlist->next)
389 void free_stringlist(stringlist_t *stringlist)
392 free_stringlist(stringlist->next);
393 free(stringlist->value);
398 DYNAMIC_API PEP_STATUS log_event(
399 PEP_SESSION session, const char *title, const char *entity,
400 const char *description, const char *comment
403 PEP_STATUS status = PEP_STATUS_OK;
410 sqlite3_reset(session->log);
411 sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
412 sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
414 sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
416 sqlite3_bind_null(session->log, 3);
418 sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
420 sqlite3_bind_null(session->log, 4);
422 result = sqlite3_step(session->log);
423 assert(result == SQLITE_DONE || result == SQLITE_BUSY);
424 if (result != SQLITE_DONE && result != SQLITE_BUSY)
425 status = PEP_UNKNOWN_ERROR;
426 } while (result == SQLITE_BUSY);
427 sqlite3_reset(session->log);
432 DYNAMIC_API PEP_STATUS safeword(
433 PEP_SESSION session, uint16_t value, const char *lang,
434 char **word, size_t *wsize
437 PEP_STATUS status = PEP_STATUS_OK;
450 assert((lang[0] >= 'A' && lang[0] <= 'Z')
451 || (lang[0] >= 'a' && lang[0] <= 'z'));
452 assert((lang[1] >= 'A' && lang[1] <= 'Z')
453 || (lang[1] >= 'a' && lang[1] <= 'z'));
454 assert(lang[2] == 0);
456 sqlite3_reset(session->safeword);
457 sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
458 sqlite3_bind_int(session->safeword, 2, value);
460 result = sqlite3_step(session->safeword);
461 if (result == SQLITE_ROW) {
462 *word = strdup((const char *) sqlite3_column_text(session->safeword,
465 *wsize = sqlite3_column_bytes(session->safeword, 1);
467 status = PEP_SAFEWORD_NOT_FOUND;
469 status = PEP_SAFEWORD_NOT_FOUND;
471 sqlite3_reset(session->safeword);
475 DYNAMIC_API PEP_STATUS safewords(
476 PEP_SESSION session, const char *fingerprint, const char *lang,
477 char **words, size_t *wsize, int max_words
480 const char *source = fingerprint;
481 char *buffer = calloc(1, MAX_SAFEWORDS_SPACE);
490 assert(max_words >= 0);
497 return PEP_OUT_OF_MEMORY;
499 fsize = strlen(fingerprint);
504 assert((lang[0] >= 'A' && lang[0] <= 'Z')
505 || (lang[0] >= 'a' && lang[0] <= 'z'));
506 assert((lang[1] >= 'A' && lang[1] <= 'Z')
507 || (lang[1] >= 'a' && lang[1] <= 'z'));
508 assert(lang[2] == 0);
511 while (source < fingerprint + fsize) {
517 for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
518 if (*source >= 'a' && *source <= 'f')
519 value += (*source - 'a' + 10) << (3 - j++) * 4;
520 else if (*source >= 'A' && *source <= 'F')
521 value += (*source - 'A' + 10) << (3 - j++) * 4;
522 else if (*source >= '0' && *source <= '9')
523 value += (*source - '0') << (3 - j++) * 4;
528 _status = safeword(session, value, lang, &word, &_wsize);
529 if (_status == PEP_OUT_OF_MEMORY) {
531 return PEP_OUT_OF_MEMORY;
535 return PEP_SAFEWORD_NOT_FOUND;
538 if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
539 strncpy(dest, word, _wsize);
545 break; // buffer full
548 if (source < fingerprint + fsize
549 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
553 if (max_words && n_words >= max_words)
558 *wsize = dest - buffer;
559 return PEP_STATUS_OK;
562 pEp_identity *new_identity(
563 const char *address, const char *fpr, const char *user_id,
567 pEp_identity *result = calloc(1, sizeof(pEp_identity));
571 result->address = strdup(address);
572 assert(result->address);
573 if (result->address == NULL) {
577 result->address_size = strlen(address);
580 result->fpr = strdup(fpr);
582 if (result->fpr == NULL) {
583 free_identity(result);
586 result->fpr_size = strlen(fpr);
589 result->user_id = strdup(user_id);
590 assert(result->user_id);
591 if (result->user_id == NULL) {
592 free_identity(result);
595 result->user_id_size = strlen(user_id);
598 result->username = strdup(username);
599 assert(result->username);
600 if (result->username == NULL) {
601 free_identity(result);
604 result->username_size = strlen(username);
606 result->struct_size = sizeof(pEp_identity);
611 pEp_identity *identity_dup(const pEp_identity *src)
615 pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
620 dup->comm_type = src->comm_type;
621 dup->lang[0] = src->lang[0];
622 dup->lang[1] = src->lang[1];
629 void free_identity(pEp_identity *identity)
632 free(identity->address);
634 free(identity->user_id);
635 free(identity->username);
640 DYNAMIC_API PEP_STATUS get_identity(
641 PEP_SESSION session, const char *address,
642 pEp_identity **identity
645 PEP_STATUS status = PEP_STATUS_OK;
646 static pEp_identity *_identity;
654 sqlite3_reset(session->get_identity);
655 sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
657 result = sqlite3_step(session->get_identity);
660 _identity = new_identity(
662 (const char *) sqlite3_column_text(session->get_identity, 0),
663 (const char *) sqlite3_column_text(session->get_identity, 1),
664 (const char *) sqlite3_column_text(session->get_identity, 2)
667 if (_identity == NULL)
668 return PEP_OUT_OF_MEMORY;
670 _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 3);
671 _lang = (const char *) sqlite3_column_text(session->get_identity, 4);
672 if (_lang && _lang[0]) {
673 assert(_lang[0] >= 'a' && _lang[0] <= 'z');
674 assert(_lang[1] >= 'a' && _lang[1] <= 'z');
675 assert(_lang[2] == 0);
676 _identity->lang[0] = _lang[0];
677 _identity->lang[1] = _lang[1];
678 _identity->lang[2] = 0;
680 *identity = _identity;
683 status = PEP_CANNOT_FIND_IDENTITY;
687 sqlite3_reset(session->get_identity);
691 DYNAMIC_API PEP_STATUS set_identity(
692 PEP_SESSION session, const pEp_identity *identity
699 assert(identity->address);
700 assert(identity->fpr);
701 assert(identity->user_id);
702 assert(identity->username);
704 sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
706 sqlite3_reset(session->set_person);
707 sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
709 sqlite3_bind_text(session->set_person, 2, identity->username, -1,
711 if (identity->lang[0])
712 sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
715 sqlite3_bind_null(session->set_person, 3);
716 result = sqlite3_step(session->set_person);
717 sqlite3_reset(session->set_person);
718 if (result != SQLITE_DONE) {
719 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
720 return PEP_CANNOT_SET_PERSON;
723 sqlite3_reset(session->set_pgp_keypair);
724 sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
726 result = sqlite3_step(session->set_pgp_keypair);
727 sqlite3_reset(session->set_pgp_keypair);
728 if (result != SQLITE_DONE) {
729 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
730 return PEP_CANNOT_SET_PGP_KEYPAIR;
733 sqlite3_reset(session->set_identity);
734 sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
736 sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
738 sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
740 result = sqlite3_step(session->set_identity);
741 sqlite3_reset(session->set_identity);
742 if (result != SQLITE_DONE) {
743 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
744 return PEP_CANNOT_SET_IDENTITY;
747 sqlite3_reset(session->set_trust);
748 sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
750 sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
752 sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
753 result = sqlite3_step(session->set_trust);
754 sqlite3_reset(session->set_trust);
755 if (result != SQLITE_DONE) {
756 sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
757 return PEP_CANNOT_SET_IDENTITY;
760 result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
761 if (result == SQLITE_OK)
762 return PEP_STATUS_OK;
764 return PEP_COMMIT_FAILED;
767 void pEp_free(void *p)
772 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
774 PEP_STATUS status = PEP_STATUS_OK;
779 assert(identity->user_id);
780 assert(identity->user_id[0]);
781 assert(identity->fpr);
782 assert(identity->fpr[0]);
784 identity->comm_type = PEP_ct_unknown;
786 sqlite3_reset(session->get_trust);
787 sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
788 sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
790 result = sqlite3_step(session->get_trust);
793 const char * user_id = (const char *) sqlite3_column_text(session->get_trust, 1);
794 int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 2);
796 if (strcmp(user_id, identity->user_id) != 0) {
797 free(identity->user_id);
798 identity->user_id = strdup(user_id);
799 assert(identity->user_id);
800 if (identity->user_id == NULL)
801 return PEP_OUT_OF_MEMORY;
803 identity->comm_type = comm_type;
808 status = PEP_CANNOT_FIND_IDENTITY;
811 sqlite3_reset(session->get_trust);
815 DYNAMIC_API PEP_STATUS decrypt_and_verify(
816 PEP_SESSION session, const char *ctext, size_t csize,
817 char **ptext, size_t *psize, stringlist_t **keylist
820 return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
823 DYNAMIC_API PEP_STATUS encrypt_and_sign(
824 PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
825 size_t psize, char **ctext, size_t *csize
828 return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
831 DYNAMIC_API PEP_STATUS verify_text(
832 PEP_SESSION session, const char *text, size_t size,
833 const char *signature, size_t sig_size, stringlist_t **keylist
836 return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
839 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
841 return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
844 DYNAMIC_API PEP_STATUS export_key(
845 PEP_SESSION session, const char *fpr, char **key_data, size_t *size
848 return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
851 DYNAMIC_API PEP_STATUS find_keys(
852 PEP_SESSION session, const char *pattern, stringlist_t **keylist
855 return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
858 DYNAMIC_API PEP_STATUS generate_keypair(
859 PEP_SESSION session, pEp_identity *identity
862 return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
865 DYNAMIC_API PEP_STATUS get_key_rating(
868 PEP_comm_type *comm_type
871 return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
874 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
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)
881 return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
884 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
886 return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);