src/pEpEngine.c
author vb
Mon, 23 Feb 2015 14:32:12 +0100
changeset 67 65cc950ce03d
parent 65 b4b2f063a7c4
child 76 6da29caa5dae
permissions -rw-r--r--
...
     1 #include "pEp_internal.h"
     2 #include "cryptotech.h"
     3 #include "transport.h"
     4 
     5 int init_count = -1;
     6 
     7 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
     8 {
     9     PEP_STATUS status = PEP_STATUS_OK;
    10 	int int_result;
    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;
    20 
    21     assert(sqlite3_threadsafe());
    22     if (!sqlite3_threadsafe())
    23         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    24 
    25     // a little race condition - but still a race condition
    26     // removed by calling caveat (see documentation)
    27 
    28     ++init_count;
    29     if (init_count == 0)
    30         in_first = true;
    31 
    32 	assert(session);
    33 	*session = NULL;
    34 
    35     pEpSession *_session = (pEpSession *) calloc(1, sizeof(pEpSession));
    36 	assert(_session);
    37 	if (_session == NULL)
    38 		goto enomem;
    39 
    40 	_session->version = PEP_ENGINE_VERSION;
    41 
    42     assert(LOCAL_DB);
    43     if (LOCAL_DB == NULL) {
    44         status = PEP_INIT_CANNOT_OPEN_DB;
    45         goto pep_error;
    46     }
    47 
    48 	int_result = sqlite3_open_v2(
    49 			LOCAL_DB,
    50 			&_session->db,
    51 			SQLITE_OPEN_READWRITE
    52 				| SQLITE_OPEN_CREATE
    53 				| SQLITE_OPEN_FULLMUTEX
    54 				| SQLITE_OPEN_PRIVATECACHE,
    55 			NULL 
    56 		);
    57 
    58 	if (int_result != SQLITE_OK) {
    59 		status = PEP_INIT_CANNOT_OPEN_DB;
    60         goto pep_error;
    61 	}
    62 
    63 	sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
    64 
    65     assert(SYSTEM_DB);
    66     if (SYSTEM_DB == NULL) {
    67 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    68         goto pep_error;
    69     }
    70 
    71 	int_result = sqlite3_open_v2(
    72 			SYSTEM_DB, &_session->system_db,
    73 			SQLITE_OPEN_READONLY
    74 				| SQLITE_OPEN_FULLMUTEX
    75 				| SQLITE_OPEN_SHAREDCACHE,
    76 			NULL
    77 		);
    78 
    79 	if (int_result != SQLITE_OK) {
    80 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    81         goto pep_error;
    82 	}
    83 
    84 	sqlite3_busy_timeout(_session->system_db, 1000);
    85 
    86     if (in_first) {
    87         int_result = sqlite3_exec(
    88             _session->db,
    89                 "create table if not exists version_info ("
    90                 "	id integer primary key,"
    91                 "	timestamp integer default (datetime('now')) ,"
    92                 "	version text,"
    93                 "	comment text"
    94                 ");"
    95                 "create table if not exists log ("
    96                 "	timestamp integer default (datetime('now')) ,"
    97                 "	title text not null,"
    98                 "	entity text not null,"
    99                 "	description text,"
   100                 "	comment text"
   101                 ");"
   102                 "create index if not exists log_timestamp on log ("
   103                 "	timestamp"
   104                 ");"
   105                 "create table if not exists pgp_keypair ("
   106                 "	fpr text primary key,"
   107                 "	public_id text unique,"
   108                 "   private_id text,"
   109                 "	created integer,"
   110                 "	expires integer,"
   111                 "	comment text"
   112                 ");"
   113                 "create index if not exists pgp_keypair_expires on pgp_keypair ("
   114                 "	expires"
   115                 ");"
   116                 "create table if not exists person ("
   117                 "	id text primary key,"
   118                 "	username text not null,"
   119                 "	main_key_id text"
   120                 "		references pgp_keypair (fpr)"
   121                 "		on delete set null,"
   122                 "   lang text,"
   123                 "	comment text"
   124                 ");"
   125                 "create table if not exists identity ("
   126                 "	address text primary key,"
   127                 "	user_id text"
   128                 "		references person (id)"
   129                 "		on delete cascade,"
   130                 "	main_key_id text"
   131                 "		references pgp_keypair (fpr)"
   132                 "		on delete set null,"
   133                 "	comment text"
   134                 ");"
   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,"
   143                 "	comment text"
   144                 ");"
   145                 "create unique index if not exists trust_index on trust ("
   146                 "   user_id,"
   147                 "   pgp_keypair_fpr"
   148                 ");",
   149             NULL,
   150             NULL,
   151             NULL
   152         );
   153         assert(int_result == SQLITE_OK);
   154 
   155         int_result = sqlite3_exec(
   156             _session->db,
   157             "insert or replace into version_info (id, version) values (1, '1.0');",
   158             NULL,
   159             NULL,
   160             NULL
   161         );
   162         assert(int_result == SQLITE_OK);
   163 
   164         sql_log = "insert into log (title, entity, description, comment)"
   165                   "values (?1, ?2, ?3, ?4);";
   166 
   167         sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
   168                             "   from identity"
   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 ;";
   174 
   175         sql_safeword = "select id, word from wordlist where lang = lower(?1) "
   176                        "and id = ?2 ;";
   177 
   178         sql_set_person = "insert or replace into person (id, username, lang) "
   179                          "values (?1, ?2, ?3) ;";
   180 
   181         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   182                               "values (?1) ;";
   183 
   184         sql_set_identity = "insert or replace into identity (address, main_key_id, "
   185                            "user_id) values (?1, ?2, ?3) ;";
   186 
   187         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   188                         "values (?1, ?2, ?3) ;";
   189 
   190         sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
   191                         "and pgp_keypair_fpr = ?2 ;";
   192     }
   193 
   194     int_result = sqlite3_prepare_v2(_session->db, sql_log, strlen(sql_log),
   195             &_session->log, NULL);
   196 	assert(int_result == SQLITE_OK);
   197 
   198     int_result = sqlite3_prepare_v2(_session->system_db, sql_safeword,
   199             strlen(sql_safeword), &_session->safeword, NULL);
   200 	assert(int_result == SQLITE_OK);
   201 
   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);
   205 
   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);
   209 
   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);
   213 
   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);
   217 
   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);
   221 
   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);
   225 
   226     status = init_cryptotech(_session, in_first);
   227     if (status != PEP_STATUS_OK)
   228         goto pep_error;
   229 
   230     status = init_transport_system(_session, in_first);
   231     if (status != PEP_STATUS_OK)
   232         goto pep_error;
   233 
   234     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   235     if (status != PEP_STATUS_OK)
   236         goto pep_error;
   237 
   238 	*session = _session;
   239 	return PEP_STATUS_OK;
   240 
   241 enomem:
   242     status = PEP_OUT_OF_MEMORY;
   243 
   244 pep_error:
   245     release(_session);
   246     return status;
   247 }
   248 
   249 DYNAMIC_API void release(PEP_SESSION session)
   250 {
   251     bool out_last = false;
   252 
   253     assert(init_count >= 0);
   254 	assert(session);
   255 
   256     // a small race condition but still a race condition
   257     // removed by calling caveat (see documentation)
   258 
   259     if (init_count == 0)
   260         out_last = true;
   261     --init_count;
   262 
   263 	if (session) {
   264 		if (session->db) {
   265             if (session->safeword)
   266                 sqlite3_finalize(session->safeword);
   267             if (session->log)
   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);
   281 
   282             if (session->db)
   283                 sqlite3_close_v2(session->db);
   284             if (session->system_db)
   285                 sqlite3_close_v2(session->system_db);
   286 		}
   287 
   288         release_transport_system(session, out_last);
   289         release_cryptotech(session, out_last);
   290 
   291         free(session);
   292     }
   293 }
   294 
   295 stringlist_t *new_stringlist(const char *value)
   296 {
   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) {
   302             free(result);
   303             return NULL;
   304         }
   305     }
   306     return result;
   307 }
   308 
   309 DYNAMIC_API stringlist_t *stringlist_dup(const stringlist_t *src)
   310 {
   311     assert(src);
   312     if (src == NULL)
   313         return NULL;
   314 
   315     stringlist_t *dst = new_stringlist(src->value);
   316     if (dst == NULL)
   317         return NULL;
   318 
   319     if (src->next) {
   320         dst->next = stringlist_dup(src->next);
   321         if (dst->next == NULL) {
   322             free(dst);
   323             return NULL;
   324         }
   325     }
   326 
   327     return dst;
   328 }
   329 
   330 stringlist_t *stringlist_add(stringlist_t *stringlist, const char *value)
   331 {
   332     assert(value);
   333 
   334     if (stringlist == NULL)
   335         return new_stringlist(value);
   336 
   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)
   343             return NULL;
   344         return stringlist;
   345     }
   346 
   347     stringlist->next = new_stringlist(value);
   348     assert(stringlist->next);
   349     if (stringlist->next == NULL)
   350         return NULL;
   351 
   352     return stringlist->next;
   353 }
   354 
   355 DYNAMIC_API stringlist_t *stringlist_append(stringlist_t *stringlist,
   356         stringlist_t *second)
   357 {
   358     assert(stringlist);
   359 
   360     if (second == NULL || second->value == NULL)
   361         return stringlist;
   362 
   363     stringlist_t *_s = stringlist;
   364     stringlist_t *_s2;
   365     for (_s2 = second; _s2 != NULL; _s2 = _s2->next) {
   366         _s = stringlist_add(_s, _s2->value);
   367         if (_s == NULL)
   368             return NULL;
   369     }
   370     return _s;
   371 }
   372 
   373 int stringlist_length(const stringlist_t *stringlist)
   374 {
   375     int len = 1;
   376     stringlist_t *_stringlist;
   377 
   378     assert(stringlist);
   379 
   380     if (stringlist->value == NULL)
   381         return 0;
   382 
   383     for (_stringlist=stringlist->next; _stringlist!=NULL; _stringlist=_stringlist->next)
   384         len += 1;
   385 
   386     return len;
   387 }
   388 
   389 void free_stringlist(stringlist_t *stringlist)
   390 {
   391     if (stringlist) {
   392         free_stringlist(stringlist->next);
   393         free(stringlist->value);
   394         free(stringlist);
   395     }
   396 }
   397 
   398 DYNAMIC_API PEP_STATUS log_event(
   399         PEP_SESSION session, const char *title, const char *entity,
   400         const char *description, const char *comment
   401     )
   402 {
   403 	PEP_STATUS status = PEP_STATUS_OK;
   404 	int result;
   405 
   406 	assert(session);
   407 	assert(title);
   408 	assert(entity);
   409 
   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);
   413 	if (description)
   414         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   415 	else
   416 		sqlite3_bind_null(session->log, 3);
   417 	if (comment)
   418 		sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   419 	else
   420 		sqlite3_bind_null(session->log, 4);
   421 	do {
   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);
   428 
   429 	return status;
   430 }
   431 
   432 DYNAMIC_API PEP_STATUS safeword(
   433             PEP_SESSION session, uint16_t value, const char *lang,
   434             char **word, size_t *wsize
   435         )
   436 {
   437 	PEP_STATUS status = PEP_STATUS_OK;
   438 	int result;
   439 
   440 	assert(session);
   441 	assert(word);
   442 	assert(wsize);
   443 
   444 	*word = NULL;
   445 	*wsize = 0;
   446 
   447 	if (lang == NULL)
   448 		lang = "en";
   449 
   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);
   455 
   456 	sqlite3_reset(session->safeword);
   457     sqlite3_bind_text(session->safeword, 1, lang, -1, SQLITE_STATIC);
   458 	sqlite3_bind_int(session->safeword, 2, value);
   459 
   460 	result = sqlite3_step(session->safeword);
   461 	if (result == SQLITE_ROW) {
   462         *word = strdup((const char *) sqlite3_column_text(session->safeword,
   463                     1));
   464 		if (*word)
   465             *wsize = sqlite3_column_bytes(session->safeword, 1);
   466 		else
   467 			status = PEP_SAFEWORD_NOT_FOUND;
   468 	} else
   469 		status = PEP_SAFEWORD_NOT_FOUND;
   470 
   471 	sqlite3_reset(session->safeword);
   472 	return status;
   473 }
   474 
   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
   478     )
   479 {
   480 	const char *source = fingerprint;
   481 	char *buffer = calloc(1, MAX_SAFEWORDS_SPACE);
   482 	char *dest = buffer;
   483 	size_t fsize;
   484     PEP_STATUS _status;
   485 
   486 	assert(session);
   487 	assert(fingerprint);
   488 	assert(words);
   489 	assert(wsize);
   490 	assert(max_words >= 0);
   491 
   492 	*words = NULL;
   493 	*wsize = 0;
   494 
   495     assert(buffer);
   496     if (buffer == NULL)
   497         return PEP_OUT_OF_MEMORY;
   498 
   499 	fsize = strlen(fingerprint);
   500 
   501 	if (lang == NULL)
   502 		lang = "en";
   503 
   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);
   509 
   510 	int n_words = 0;
   511 	while (source < fingerprint + fsize) {
   512 		uint16_t value;
   513 		char *word;
   514 		size_t _wsize;
   515 		int j;
   516 
   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;
   524 			
   525 			source++;
   526 		}
   527 
   528 		_status = safeword(session, value, lang, &word, &_wsize);
   529         if (_status == PEP_OUT_OF_MEMORY) {
   530             free(buffer);
   531             return PEP_OUT_OF_MEMORY;
   532         }
   533 		if (word == NULL) {
   534             free(buffer);
   535 			return PEP_SAFEWORD_NOT_FOUND;
   536         }
   537 
   538 		if (dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1) {
   539 			strncpy(dest, word, _wsize);
   540             free(word);
   541 			dest += _wsize;
   542 		}
   543 		else {
   544             free(word);
   545 			break; // buffer full
   546         }
   547 
   548 		if (source < fingerprint + fsize
   549                 && dest + _wsize < buffer + MAX_SAFEWORDS_SPACE - 1)
   550 			*dest++ = ' ';
   551 
   552 		++n_words;
   553 		if (max_words && n_words >= max_words)
   554 			break;
   555 	}
   556 
   557 	*words = buffer;
   558 	*wsize = dest - buffer;
   559 	return PEP_STATUS_OK;
   560 }
   561 
   562 pEp_identity *new_identity(
   563         const char *address, const char *fpr, const char *user_id,
   564         const char *username
   565     )
   566 {
   567     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   568     assert(result);
   569     if (result) {
   570         if (address) {
   571             result->address = strdup(address);
   572             assert(result->address);
   573             if (result->address == NULL) {
   574                 free(result);
   575                 return NULL;
   576             }
   577             result->address_size = strlen(address);
   578         }
   579         if (fpr) {
   580             result->fpr = strdup(fpr);
   581             assert(result->fpr);
   582             if (result->fpr == NULL) {
   583                 free_identity(result);
   584                 return NULL;
   585             }
   586             result->fpr_size = strlen(fpr);
   587         }
   588         if (user_id) {
   589             result->user_id = strdup(user_id);
   590             assert(result->user_id);
   591             if (result->user_id == NULL) {
   592                 free_identity(result);
   593                 return NULL;
   594             }
   595             result->user_id_size = strlen(user_id);
   596         }
   597         if (username) {
   598             result->username = strdup(username);
   599             assert(result->username);
   600             if (result->username == NULL) {
   601                 free_identity(result);
   602                 return NULL;
   603             }
   604             result->username_size = strlen(username);
   605         }
   606         result->struct_size = sizeof(pEp_identity);
   607     }
   608     return result;
   609 }
   610 
   611 pEp_identity *identity_dup(const pEp_identity *src)
   612 {
   613     assert(src);
   614 
   615     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
   616     assert(dup);
   617     if (dup == NULL)
   618         return NULL;
   619     
   620     dup->comm_type = src->comm_type;
   621     dup->lang[0] = src->lang[0];
   622     dup->lang[1] = src->lang[1];
   623     dup->lang[2] = 0;
   624     dup->me = src->me;
   625 
   626     return dup;
   627 }
   628 
   629 void free_identity(pEp_identity *identity)
   630 {
   631     if (identity) {
   632         free(identity->address);
   633         free(identity->fpr);
   634         free(identity->user_id);
   635         free(identity->username);
   636         free(identity);
   637     }
   638 }
   639 
   640 DYNAMIC_API PEP_STATUS get_identity(
   641         PEP_SESSION session, const char *address,
   642         pEp_identity **identity
   643     )
   644 {
   645 	PEP_STATUS status = PEP_STATUS_OK;
   646 	static pEp_identity *_identity;
   647 	int result;
   648 	const char *_lang;
   649 
   650 	assert(session);
   651 	assert(address);
   652     assert(address[0]);
   653 
   654     sqlite3_reset(session->get_identity);
   655     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   656 
   657     result = sqlite3_step(session->get_identity);
   658 	switch (result) {
   659 	case SQLITE_ROW:
   660         _identity = new_identity(
   661                 address,
   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)
   665                 );
   666         assert(_identity);
   667         if (_identity == NULL)
   668             return PEP_OUT_OF_MEMORY;
   669 
   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;
   679 		}
   680 		*identity = _identity;
   681 		break;
   682 	default:
   683         status = PEP_CANNOT_FIND_IDENTITY;
   684 		*identity = NULL;
   685 	}
   686 
   687     sqlite3_reset(session->get_identity);
   688 	return status;
   689 }
   690 
   691 DYNAMIC_API PEP_STATUS set_identity(
   692         PEP_SESSION session, const pEp_identity *identity
   693     )
   694 {
   695 	int result;
   696 
   697 	assert(session);
   698 	assert(identity);
   699 	assert(identity->address);
   700 	assert(identity->fpr);
   701 	assert(identity->user_id);
   702 	assert(identity->username);
   703 
   704 	sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
   705 
   706 	sqlite3_reset(session->set_person);
   707     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
   708             SQLITE_STATIC);
   709     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
   710             SQLITE_STATIC);
   711 	if (identity->lang[0])
   712         sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
   713                 SQLITE_STATIC);
   714 	else
   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;
   721 	}
   722 
   723 	sqlite3_reset(session->set_pgp_keypair);
   724     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   725             SQLITE_STATIC);
   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;
   731 	}
   732 
   733 	sqlite3_reset(session->set_identity);
   734     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   735             SQLITE_STATIC);
   736     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
   737             SQLITE_STATIC);
   738     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
   739             SQLITE_STATIC);
   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;
   745 	}
   746 
   747 	sqlite3_reset(session->set_trust);
   748     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
   749             SQLITE_STATIC);
   750     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
   751             SQLITE_STATIC);
   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;
   758 	}
   759 
   760     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
   761 	if (result == SQLITE_OK)
   762 		return PEP_STATUS_OK;
   763 	else
   764 		return PEP_COMMIT_FAILED;
   765 }
   766 
   767 void pEp_free(void *p)
   768 {
   769     free(p);
   770 }
   771 
   772 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   773 {
   774     PEP_STATUS status = PEP_STATUS_OK;
   775     int result;
   776 
   777     assert(session);
   778     assert(identity);
   779     assert(identity->user_id);
   780     assert(identity->user_id[0]);
   781     assert(identity->fpr);
   782     assert(identity->fpr[0]);
   783 
   784     identity->comm_type = PEP_ct_unknown;
   785 
   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);
   789 
   790     result = sqlite3_step(session->get_trust);
   791     switch (result) {
   792     case SQLITE_ROW: {
   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);
   795 
   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;
   802         }
   803         identity->comm_type = comm_type;
   804         break;
   805     }
   806  
   807     default:
   808         status = PEP_CANNOT_FIND_IDENTITY;
   809     }
   810 
   811     sqlite3_reset(session->get_trust);
   812     return status;
   813 }
   814 
   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
   818     )
   819 {
   820     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
   821 }
   822 
   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
   826     )
   827 {
   828     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
   829 }
   830 
   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
   834     )
   835 {
   836     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
   837 }
   838 
   839 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
   840 {
   841     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
   842 }
   843 
   844 DYNAMIC_API PEP_STATUS export_key(
   845         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   846     )
   847 {
   848     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
   849 }
   850 
   851 DYNAMIC_API PEP_STATUS find_keys(
   852         PEP_SESSION session, const char *pattern, stringlist_t **keylist
   853     )
   854 {
   855     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
   856 }
   857 
   858 DYNAMIC_API PEP_STATUS generate_keypair(
   859         PEP_SESSION session, pEp_identity *identity
   860     )
   861 {
   862     return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
   863 }
   864 
   865 DYNAMIC_API PEP_STATUS get_key_rating(
   866         PEP_SESSION session,
   867         const char *fpr,
   868         PEP_comm_type *comm_type
   869     )
   870 {
   871     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
   872 }
   873 
   874 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
   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     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
   882 }
   883 
   884 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
   885 {
   886     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
   887 }