src/pEpEngine.c
author Volker Birk <vb@pep-project.org>
Wed, 15 Apr 2015 12:53:50 +0200
changeset 191 3bb51ee8f90d
parent 125 5119178815d8
child 196 2d7c5fb43387
permissions -rw-r--r--
safety
     1 #include "pEp_internal.h"
     2 #include "dynamic_api.h"
     3 #include "cryptotech.h"
     4 #include "transport.h"
     5 
     6 int init_count = -1;
     7 
     8 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
     9 {
    10     PEP_STATUS status = PEP_STATUS_OK;
    11 	int int_result;
    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;
    21 
    22     assert(sqlite3_threadsafe());
    23     if (!sqlite3_threadsafe())
    24         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    25 
    26     // a little race condition - but still a race condition
    27     // mitigated by calling caveat (see documentation)
    28 
    29     ++init_count;
    30     if (init_count == 0)
    31         in_first = true;
    32 
    33 	assert(session);
    34     if (session == NULL)
    35         return PEP_ILLEGAL_VALUE;
    36 
    37 	*session = NULL;
    38 
    39     pEpSession *_session = calloc(1, sizeof(pEpSession));
    40 	assert(_session);
    41 	if (_session == NULL)
    42 		goto enomem;
    43 
    44 	_session->version = PEP_ENGINE_VERSION;
    45 
    46     assert(LOCAL_DB);
    47     if (LOCAL_DB == NULL) {
    48         status = PEP_INIT_CANNOT_OPEN_DB;
    49         goto pep_error;
    50     }
    51 
    52 	int_result = sqlite3_open_v2(
    53 			LOCAL_DB,
    54 			&_session->db,
    55 			SQLITE_OPEN_READWRITE
    56 				| SQLITE_OPEN_CREATE
    57 				| SQLITE_OPEN_FULLMUTEX
    58 				| SQLITE_OPEN_PRIVATECACHE,
    59 			NULL 
    60 		);
    61 
    62 	if (int_result != SQLITE_OK) {
    63 		status = PEP_INIT_CANNOT_OPEN_DB;
    64         goto pep_error;
    65 	}
    66 
    67 	sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
    68 
    69     assert(SYSTEM_DB);
    70     if (SYSTEM_DB == NULL) {
    71 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    72         goto pep_error;
    73     }
    74 
    75 	int_result = sqlite3_open_v2(
    76 			SYSTEM_DB, &_session->system_db,
    77 			SQLITE_OPEN_READONLY
    78 				| SQLITE_OPEN_FULLMUTEX
    79 				| SQLITE_OPEN_SHAREDCACHE,
    80 			NULL
    81 		);
    82 
    83 	if (int_result != SQLITE_OK) {
    84 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    85         goto pep_error;
    86 	}
    87 
    88 	sqlite3_busy_timeout(_session->system_db, 1000);
    89 
    90     if (in_first) {
    91         int_result = sqlite3_exec(
    92             _session->db,
    93                 "create table if not exists version_info ("
    94                 "	id integer primary key,"
    95                 "	timestamp integer default (datetime('now')) ,"
    96                 "	version text,"
    97                 "	comment text"
    98                 ");"
    99                 "create table if not exists log ("
   100                 "	timestamp integer default (datetime('now')) ,"
   101                 "	title text not null,"
   102                 "	entity text not null,"
   103                 "	description text,"
   104                 "	comment text"
   105                 ");"
   106                 "create index if not exists log_timestamp on log ("
   107                 "	timestamp"
   108                 ");"
   109                 "create table if not exists pgp_keypair ("
   110                 "	fpr text primary key,"
   111                 "	public_id text unique,"
   112                 "   private_id text,"
   113                 "	created integer,"
   114                 "	expires integer,"
   115                 "	comment text"
   116                 ");"
   117                 "create index if not exists pgp_keypair_expires on pgp_keypair ("
   118                 "	expires"
   119                 ");"
   120                 "create table if not exists person ("
   121                 "	id text primary key,"
   122                 "	username text not null,"
   123                 "	main_key_id text"
   124                 "		references pgp_keypair (fpr)"
   125                 "		on delete set null,"
   126                 "   lang text,"
   127                 "	comment text"
   128                 ");"
   129                 "create table if not exists identity ("
   130                 "	address text primary key,"
   131                 "	user_id text"
   132                 "		references person (id)"
   133                 "		on delete cascade,"
   134                 "	main_key_id text"
   135                 "		references pgp_keypair (fpr)"
   136                 "		on delete set null,"
   137                 "	comment text"
   138                 ");"
   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,"
   147                 "	comment text"
   148                 ");"
   149                 "create unique index if not exists trust_index on trust ("
   150                 "   user_id,"
   151                 "   pgp_keypair_fpr"
   152                 ");",
   153             NULL,
   154             NULL,
   155             NULL
   156         );
   157         assert(int_result == SQLITE_OK);
   158 
   159         int_result = sqlite3_exec(
   160             _session->db,
   161             "insert or replace into version_info (id, version) values (1, '1.0');",
   162             NULL,
   163             NULL,
   164             NULL
   165         );
   166         assert(int_result == SQLITE_OK);
   167 
   168         sql_log = "insert into log (title, entity, description, comment)"
   169                   "values (?1, ?2, ?3, ?4);";
   170 
   171         sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
   172                             "   from identity"
   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 ;";
   178 
   179         sql_safeword = "select id, word from wordlist where lang = lower(?1) "
   180                        "and id = ?2 ;";
   181 
   182         sql_set_person = "insert or replace into person (id, username, lang) "
   183                          "values (?1, ?2, ?3) ;";
   184 
   185         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   186                               "values (?1) ;";
   187 
   188         sql_set_identity = "insert or replace into identity (address, main_key_id, "
   189                            "user_id) values (?1, ?2, ?3) ;";
   190 
   191         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   192                         "values (?1, ?2, ?3) ;";
   193 
   194         sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
   195                         "and pgp_keypair_fpr = ?2 ;";
   196     }
   197 
   198     int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
   199             &_session->log, NULL);
   200 	assert(int_result == SQLITE_OK);
   201 
   202     int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
   203             strlen(sql_safeword), &_session->safeword, NULL);
   204 	assert(int_result == SQLITE_OK);
   205 
   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);
   209 
   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);
   213 
   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);
   217 
   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);
   221 
   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);
   225 
   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);
   229 
   230     status = init_cryptotech(_session, in_first);
   231     if (status != PEP_STATUS_OK)
   232         goto pep_error;
   233 
   234     status = init_transport_system(_session, in_first);
   235     if (status != PEP_STATUS_OK)
   236         goto pep_error;
   237 
   238     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   239     if (status != PEP_STATUS_OK)
   240         goto pep_error;
   241 
   242 	*session = _session;
   243 	return PEP_STATUS_OK;
   244 
   245 enomem:
   246     status = PEP_OUT_OF_MEMORY;
   247 
   248 pep_error:
   249     release(_session);
   250     return status;
   251 }
   252 
   253 DYNAMIC_API void release(PEP_SESSION session)
   254 {
   255     bool out_last = false;
   256 
   257     assert(init_count >= 0);
   258 	assert(session);
   259 
   260     if (!(init_count && session))
   261         return;
   262 
   263     // a small race condition but still a race condition
   264     // mitigated by calling caveat (see documentation)
   265 
   266     if (init_count == 0)
   267         out_last = true;
   268     --init_count;
   269 
   270 	if (session) {
   271 		if (session->db) {
   272             if (session->safeword)
   273                 sqlite3_finalize(session->safeword);
   274             if (session->log)
   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);
   288 
   289             if (session->db)
   290                 sqlite3_close_v2(session->db);
   291             if (session->system_db)
   292                 sqlite3_close_v2(session->system_db);
   293 		}
   294 
   295         release_transport_system(session, out_last);
   296         release_cryptotech(session, out_last);
   297 
   298         free(session);
   299     }
   300 }
   301 
   302 DYNAMIC_API PEP_STATUS log_event(
   303         PEP_SESSION session, const char *title, const char *entity,
   304         const char *description, const char *comment
   305     )
   306 {
   307 	PEP_STATUS status = PEP_STATUS_OK;
   308 	int result;
   309 
   310 	assert(session);
   311 	assert(title);
   312 	assert(entity);
   313 
   314     if (!(session && title && entity))
   315         return PEP_ILLEGAL_VALUE;
   316 
   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);
   320 	if (description)
   321         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   322 	else
   323 		sqlite3_bind_null(session->log, 3);
   324 	if (comment)
   325 		sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   326 	else
   327 		sqlite3_bind_null(session->log, 4);
   328 	do {
   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);
   335 
   336 	return status;
   337 }
   338 
   339 DYNAMIC_API PEP_STATUS safeword(
   340             PEP_SESSION session, uint16_t value, const char *lang,
   341             char **word, size_t *wsize
   342         )
   343 {
   344 	PEP_STATUS status = PEP_STATUS_OK;
   345 	int result;
   346 
   347 	assert(session);
   348 	assert(word);
   349 	assert(wsize);
   350 
   351     if (!(session && word && wsize))
   352         return PEP_ILLEGAL_VALUE;
   353 
   354 	*word = NULL;
   355 	*wsize = 0;
   356 
   357 	if (lang == NULL)
   358 		lang = "en";
   359 
   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);
   365 
   366 	sqlite3_reset(session->safeword);
   367     sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
   368 	sqlite3_bind_int(session->safeword, 2, value);
   369 
   370 	result = sqlite3_step(session->safeword);
   371 	if (result == SQLITE_ROW) {
   372         *word = strdup((const char *) sqlite3_column_text(session->safeword,
   373                     1));
   374 		if (*word)
   375             *wsize = sqlite3_column_bytes(session->safeword, 1);
   376 		else
   377 			status = PEP_SAFEWORD_NOT_FOUND;
   378 	} else
   379 		status = PEP_SAFEWORD_NOT_FOUND;
   380 
   381 	sqlite3_reset(session->safeword);
   382 	return status;
   383 }
   384 
   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
   388     )
   389 {
   390 	const char *source = fingerprint;
   391 	char *buffer;
   392 	char *dest;
   393 	size_t fsize;
   394     PEP_STATUS _status;
   395 
   396 	assert(session);
   397 	assert(fingerprint);
   398 	assert(words);
   399 	assert(wsize);
   400 	assert(max_words >= 0);
   401 
   402     if (!(session && fingerprint && words && wsize && max_words >= 0))
   403         return PEP_ILLEGAL_VALUE;
   404 
   405 	*words = NULL;
   406 	*wsize = 0;
   407 
   408     buffer = calloc(1, MAX_SAFEWORDS_SPACE);
   409     assert(buffer);
   410     if (buffer == NULL)
   411         return PEP_OUT_OF_MEMORY;
   412     dest = buffer;
   413 
   414 	fsize = strlen(fingerprint);
   415 
   416 	if (lang == NULL)
   417 		lang = "en";
   418 
   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);
   424 
   425 	int n_words = 0;
   426 	while (source < fingerprint + fsize) {
   427 		uint16_t value;
   428 		char *word;
   429 		size_t _wsize;
   430 		int j;
   431 
   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;
   439 			
   440 			source++;
   441 		}
   442 
   443 		_status = safeword(session, value, lang, &word, &_wsize);
   444         if (_status == PEP_OUT_OF_MEMORY) {
   445             free(buffer);
   446             return PEP_OUT_OF_MEMORY;
   447         }
   448 		if (word == NULL) {
   449             free(buffer);
   450 			return PEP_SAFEWORD_NOT_FOUND;
   451         }
   452 
   453 		if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
   454 			strncpy(dest, word, _wsize);
   455             free(word);
   456 			dest += _wsize;
   457 		}
   458 		else {
   459             free(word);
   460 			break; // buffer full
   461         }
   462 
   463 		if (source < fingerprint + fsize
   464                 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
   465 			*dest++ = ' ';
   466 
   467 		++n_words;
   468 		if (max_words && n_words >= max_words)
   469 			break;
   470 	}
   471 
   472 	*words = buffer;
   473 	*wsize = dest - buffer;
   474 	return PEP_STATUS_OK;
   475 }
   476 
   477 pEp_identity *new_identity(
   478         const char *address, const char *fpr, const char *user_id,
   479         const char *username
   480     )
   481 {
   482     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   483     assert(result);
   484     if (result) {
   485         if (address) {
   486             result->address = strdup(address);
   487             assert(result->address);
   488             if (result->address == NULL) {
   489                 free(result);
   490                 return NULL;
   491             }
   492             result->address_size = strlen(address);
   493         }
   494         if (fpr) {
   495             result->fpr = strdup(fpr);
   496             assert(result->fpr);
   497             if (result->fpr == NULL) {
   498                 free_identity(result);
   499                 return NULL;
   500             }
   501             result->fpr_size = strlen(fpr);
   502         }
   503         if (user_id) {
   504             result->user_id = strdup(user_id);
   505             assert(result->user_id);
   506             if (result->user_id == NULL) {
   507                 free_identity(result);
   508                 return NULL;
   509             }
   510             result->user_id_size = strlen(user_id);
   511         }
   512         if (username) {
   513             result->username = strdup(username);
   514             assert(result->username);
   515             if (result->username == NULL) {
   516                 free_identity(result);
   517                 return NULL;
   518             }
   519             result->username_size = strlen(username);
   520         }
   521         result->struct_size = sizeof(pEp_identity);
   522     }
   523     return result;
   524 }
   525 
   526 pEp_identity *identity_dup(const pEp_identity *src)
   527 {
   528     assert(src);
   529 
   530     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
   531     assert(dup);
   532     if (dup == NULL)
   533         return NULL;
   534     
   535     dup->comm_type = src->comm_type;
   536     dup->lang[0] = src->lang[0];
   537     dup->lang[1] = src->lang[1];
   538     dup->lang[2] = 0;
   539     dup->me = src->me;
   540 
   541     return dup;
   542 }
   543 
   544 void free_identity(pEp_identity *identity)
   545 {
   546     if (identity) {
   547         free(identity->address);
   548         free(identity->fpr);
   549         free(identity->user_id);
   550         free(identity->username);
   551         free(identity);
   552     }
   553 }
   554 
   555 DYNAMIC_API PEP_STATUS get_identity(
   556         PEP_SESSION session, const char *address,
   557         pEp_identity **identity
   558     )
   559 {
   560 	PEP_STATUS status = PEP_STATUS_OK;
   561 	static pEp_identity *_identity;
   562 	int result;
   563 	const char *_lang;
   564 
   565 	assert(session);
   566 	assert(address);
   567     assert(address[0]);
   568 
   569     if (!(session && address && address[0]))
   570         return PEP_ILLEGAL_VALUE;
   571 
   572     sqlite3_reset(session->get_identity);
   573     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   574 
   575     result = sqlite3_step(session->get_identity);
   576 	switch (result) {
   577 	case SQLITE_ROW:
   578         _identity = new_identity(
   579                 address,
   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)
   583                 );
   584         assert(_identity);
   585         if (_identity == NULL)
   586             return PEP_OUT_OF_MEMORY;
   587 
   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;
   597 		}
   598 		*identity = _identity;
   599 		break;
   600 	default:
   601         status = PEP_CANNOT_FIND_IDENTITY;
   602 		*identity = NULL;
   603 	}
   604 
   605     sqlite3_reset(session->get_identity);
   606 	return status;
   607 }
   608 
   609 DYNAMIC_API PEP_STATUS set_identity(
   610         PEP_SESSION session, const pEp_identity *identity
   611     )
   612 {
   613 	int result;
   614 
   615 	assert(session);
   616 	assert(identity);
   617 	assert(identity->address);
   618 	assert(identity->fpr);
   619 	assert(identity->user_id);
   620 	assert(identity->username);
   621 
   622     if (!(session && identity && identity->address && identity->fpr &&
   623                 identity->user_id && identity->username))
   624         return PEP_ILLEGAL_VALUE;
   625 
   626 	sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
   627 
   628 	sqlite3_reset(session->set_person);
   629     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
   630             SQLITE_STATIC);
   631     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
   632             SQLITE_STATIC);
   633 	if (identity->lang[0])
   634         sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
   635                 SQLITE_STATIC);
   636 	else
   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;
   643 	}
   644 
   645 	sqlite3_reset(session->set_pgp_keypair);
   646     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   647             SQLITE_STATIC);
   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;
   653 	}
   654 
   655 	sqlite3_reset(session->set_identity);
   656     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   657             SQLITE_STATIC);
   658     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
   659             SQLITE_STATIC);
   660     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
   661             SQLITE_STATIC);
   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;
   667 	}
   668 
   669 	sqlite3_reset(session->set_trust);
   670     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
   671             SQLITE_STATIC);
   672     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
   673             SQLITE_STATIC);
   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;
   680 	}
   681 
   682     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
   683 	if (result == SQLITE_OK)
   684 		return PEP_STATUS_OK;
   685 	else
   686 		return PEP_COMMIT_FAILED;
   687 }
   688 
   689 void pEp_free(void *p)
   690 {
   691     free(p);
   692 }
   693 
   694 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   695 {
   696     PEP_STATUS status = PEP_STATUS_OK;
   697     int result;
   698 
   699     assert(session);
   700     assert(identity);
   701     assert(identity->user_id);
   702     assert(identity->user_id[0]);
   703     assert(identity->fpr);
   704     assert(identity->fpr[0]);
   705 
   706     if (!(session && identity && identity->user_id && identity->user_id[0] &&
   707                 identity->fpr && identity->fpr[0]))
   708         return PEP_ILLEGAL_VALUE;
   709 
   710     identity->comm_type = PEP_ct_unknown;
   711 
   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);
   715 
   716     result = sqlite3_step(session->get_trust);
   717     switch (result) {
   718     case SQLITE_ROW: {
   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);
   721 
   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;
   728         }
   729         identity->comm_type = comm_type;
   730         break;
   731     }
   732  
   733     default:
   734         status = PEP_CANNOT_FIND_IDENTITY;
   735     }
   736 
   737     sqlite3_reset(session->get_trust);
   738     return status;
   739 }
   740 
   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
   744     )
   745 {
   746     assert(session);
   747     assert(ctext);
   748     assert(csize);
   749     assert(ptext);
   750     assert(psize);
   751     assert(keylist);
   752 
   753     if (!(session && ctext && csize && ptext && psize && keylist && keylist))
   754         return PEP_ILLEGAL_VALUE;
   755 
   756     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
   757 }
   758 
   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
   762     )
   763 {
   764     assert(session);
   765     assert(keylist);
   766     assert(ptext);
   767     assert(psize);
   768     assert(ctext);
   769     assert(csize);
   770 
   771     if (!(session && keylist && ptext && psize && ctext && csize))
   772         return PEP_ILLEGAL_VALUE;
   773 
   774     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
   775 }
   776 
   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
   780     )
   781 {
   782     assert(session);
   783     assert(text);
   784     assert(size);
   785     assert(signature);
   786     assert(sig_size);
   787     assert(keylist);
   788 
   789     if (!(session && text && size && signature && sig_size && keylist))
   790         return PEP_ILLEGAL_VALUE;
   791 
   792     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
   793 }
   794 
   795 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
   796 {
   797     assert(session);
   798     assert(fpr);
   799 
   800     if (!(session && fpr))
   801         return PEP_ILLEGAL_VALUE;
   802 
   803     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
   804 }
   805 
   806 DYNAMIC_API PEP_STATUS export_key(
   807         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   808     )
   809 {
   810     assert(session);
   811     assert(fpr);
   812     assert(key_data);
   813     assert(size);
   814 
   815     if (!(session && fpr && key_data && size))
   816         return PEP_ILLEGAL_VALUE;
   817 
   818     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
   819 }
   820 
   821 DYNAMIC_API PEP_STATUS find_keys(
   822         PEP_SESSION session, const char *pattern, stringlist_t **keylist
   823     )
   824 {
   825     assert(session);
   826     assert(pattern);
   827     assert(keylist);
   828 
   829     if (!(session && pattern && keylist))
   830         return PEP_ILLEGAL_VALUE;
   831 
   832     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
   833 }
   834 
   835 DYNAMIC_API PEP_STATUS generate_keypair(
   836         PEP_SESSION session, pEp_identity *identity
   837     )
   838 {
   839     assert(session);
   840     assert(identity);
   841     assert(identity->address);
   842     assert(identity->fpr == NULL);
   843     assert(identity->username);
   844 
   845     if (!(session && identity && identity->address && identity->fpr == NULL &&
   846                 identity->username))
   847         return PEP_ILLEGAL_VALUE;
   848 
   849     return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
   850 }
   851 
   852 DYNAMIC_API PEP_STATUS get_key_rating(
   853         PEP_SESSION session,
   854         const char *fpr,
   855         PEP_comm_type *comm_type
   856     )
   857 {
   858     assert(session);
   859     assert(fpr);
   860     assert(comm_type);
   861 
   862     if (!(session && fpr && comm_type))
   863         return PEP_ILLEGAL_VALUE;
   864 
   865     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
   866 }
   867 
   868 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
   869 {
   870     assert(session);
   871     assert(key_data);
   872 
   873     if (!(session && key_data))
   874         return PEP_ILLEGAL_VALUE;
   875 
   876     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
   877 }
   878 
   879 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
   880 {
   881     assert(session);
   882     assert(pattern);
   883 
   884     if (!(session && pattern))
   885         return PEP_ILLEGAL_VALUE;
   886 
   887     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
   888 }
   889 
   890 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
   891 {
   892     assert(session);
   893     assert(pattern);
   894 
   895     if (!(session && pattern))
   896         return PEP_ILLEGAL_VALUE;
   897 
   898     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
   899 }