src/pEpEngine.c
author Edouard Tisserant
Wed, 20 Jan 2016 17:19:31 +0100
changeset 417 323a3d09dc08
parent 410 00adb9b21ae9
child 425 8f08f2ffbdb8
permissions -rw-r--r--
Fixed some issues reported by static analyzer.
     1 #include "pEp_internal.h"
     2 #include "dynamic_api.h"
     3 #include "cryptotech.h"
     4 #include "transport.h"
     5 
     6 static 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_trustword;
    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     static const char *sql_least_trust;
    21     static const char *sql_mark_as_compromized;
    22     static const char *sql_reset_trust;
    23     bool in_first = false;
    24 
    25     assert(sqlite3_threadsafe());
    26     if (!sqlite3_threadsafe())
    27         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    28 
    29     // a little race condition - but still a race condition
    30     // mitigated by calling caveat (see documentation)
    31 
    32     ++init_count;
    33     if (init_count == 0)
    34         in_first = true;
    35 
    36 	assert(session);
    37     if (session == NULL)
    38         return PEP_ILLEGAL_VALUE;
    39 
    40 	*session = NULL;
    41 
    42     pEpSession *_session = calloc(1, sizeof(pEpSession));
    43 	assert(_session);
    44 	if (_session == NULL)
    45 		goto enomem;
    46 
    47 	_session->version = PEP_ENGINE_VERSION;
    48 
    49     assert(LOCAL_DB);
    50     if (LOCAL_DB == NULL) {
    51         status = PEP_INIT_CANNOT_OPEN_DB;
    52         goto pep_error;
    53     }
    54 
    55 	int_result = sqlite3_open_v2(
    56 			LOCAL_DB,
    57 			&_session->db,
    58 			SQLITE_OPEN_READWRITE
    59 				| SQLITE_OPEN_CREATE
    60 				| SQLITE_OPEN_FULLMUTEX
    61 				| SQLITE_OPEN_PRIVATECACHE,
    62 			NULL 
    63 		);
    64 
    65 	if (int_result != SQLITE_OK) {
    66 		status = PEP_INIT_CANNOT_OPEN_DB;
    67         goto pep_error;
    68 	}
    69 
    70 	sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
    71 
    72     assert(SYSTEM_DB);
    73     if (SYSTEM_DB == NULL) {
    74 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    75         goto pep_error;
    76     }
    77 
    78 	int_result = sqlite3_open_v2(
    79 			SYSTEM_DB, &_session->system_db,
    80 			SQLITE_OPEN_READONLY
    81 				| SQLITE_OPEN_FULLMUTEX
    82 				| SQLITE_OPEN_SHAREDCACHE,
    83 			NULL
    84 		);
    85 
    86 	if (int_result != SQLITE_OK) {
    87 		status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
    88         goto pep_error;
    89 	}
    90 
    91 	sqlite3_busy_timeout(_session->system_db, 1000);
    92 
    93     if (in_first) {
    94         int_result = sqlite3_exec(
    95             _session->db,
    96                 "create table if not exists version_info ("
    97                 "	id integer primary key,"
    98                 "	timestamp integer default (datetime('now')) ,"
    99                 "	version text,"
   100                 "	comment text"
   101                 ");"
   102                 "create table if not exists log ("
   103                 "	timestamp integer default (datetime('now')) ,"
   104                 "	title text not null,"
   105                 "	entity text not null,"
   106                 "	description text,"
   107                 "	comment text"
   108                 ");"
   109                 "create index if not exists log_timestamp on log ("
   110                 "	timestamp"
   111                 ");"
   112                 "create table if not exists pgp_keypair ("
   113                 "	fpr text primary key,"
   114                 "	public_id text unique,"
   115                 "   private_id text,"
   116                 "	created integer,"
   117                 "	expires integer,"
   118                 "	comment text"
   119                 ");"
   120                 "create index if not exists pgp_keypair_expires on pgp_keypair ("
   121                 "	expires"
   122                 ");"
   123                 "create table if not exists person ("
   124                 "	id text primary key,"
   125                 "	username text not null,"
   126                 "	main_key_id text"
   127                 "		references pgp_keypair (fpr)"
   128                 "		on delete set null,"
   129                 "   lang text,"
   130                 "	comment text"
   131                 ");"
   132                 "create table if not exists identity ("
   133                 "	address text primary key,"
   134                 "	user_id text"
   135                 "		references person (id)"
   136                 "		on delete cascade,"
   137                 "	main_key_id text"
   138                 "		references pgp_keypair (fpr)"
   139                 "		on delete set null,"
   140                 "	comment text"
   141                 ");"
   142                 "create table if not exists trust ("
   143                 "   user_id text not null"
   144                 "       references person (id)"
   145                 "		on delete cascade,"
   146                 "   pgp_keypair_fpr text not null"
   147                 "       references pgp_keypair (fpr)"
   148                 "       on delete cascade,"
   149                 "   comm_type integer not null,"
   150                 "	comment text"
   151                 ");"
   152                 "create unique index if not exists trust_index on trust ("
   153                 "   user_id,"
   154                 "   pgp_keypair_fpr"
   155                 ");",
   156             NULL,
   157             NULL,
   158             NULL
   159         );
   160         assert(int_result == SQLITE_OK);
   161 
   162         int_result = sqlite3_exec(
   163             _session->db,
   164             "insert or replace into version_info (id, version) values (1, '1.0');",
   165             NULL,
   166             NULL,
   167             NULL
   168         );
   169         assert(int_result == SQLITE_OK);
   170 
   171         sql_log = "insert into log (title, entity, description, comment)"
   172                   "values (?1, ?2, ?3, ?4);";
   173 
   174         sql_get_identity =	"select fpr, identity.user_id, username, comm_type, lang"
   175                             "   from identity"
   176                             "   join person on id = identity.user_id"
   177                             "   join pgp_keypair on fpr = identity.main_key_id"
   178                             "   join trust on id = trust.user_id"
   179                             "       and pgp_keypair_fpr = identity.main_key_id"
   180                             "   where address = ?1 ;";
   181 
   182         sql_trustword = "select id, word from wordlist where lang = lower(?1) "
   183                        "and id = ?2 ;";
   184 
   185         sql_set_person = "insert or replace into person (id, username, lang) "
   186                          "values (?1, ?2, ?3) ;";
   187 
   188         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   189                               "values (?1) ;";
   190 
   191         sql_set_identity = "insert or replace into identity (address, main_key_id, "
   192                            "user_id) values (?1, ?2, ?3) ;";
   193 
   194         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   195                         "values (?1, ?2, ?3) ;";
   196 
   197         sql_get_trust = "select user_id, comm_type from trust where user_id = ?1 "
   198                         "and pgp_keypair_fpr = ?2 ;";
   199 
   200         sql_least_trust = "select min(comm_type) from trust where pgp_keypair_fpr = ?1 ;";
   201 
   202         sql_mark_as_compromized = "update trust set comm_type = 15 where pgp_keypair_fpr = ?1 ;";
   203 
   204         sql_reset_trust = "delete from trust where pgp_keypair_fpr = ?1 ;";
   205     }
   206 
   207     int_result = sqlite3_prepare_v2(_session->db, sql_log, (int)strlen(sql_log),
   208             &_session->log, NULL);
   209 	assert(int_result == SQLITE_OK);
   210 
   211     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   212             (int)strlen(sql_trustword), &_session->trustword, NULL);
   213 	assert(int_result == SQLITE_OK);
   214 
   215     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   216             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   217 	assert(int_result == SQLITE_OK);
   218 
   219     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   220             (int)strlen(sql_set_person), &_session->set_person, NULL);
   221     assert(int_result == SQLITE_OK);
   222 
   223     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   224             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair, NULL);
   225 	assert(int_result == SQLITE_OK);
   226 
   227     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   228             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   229 	assert(int_result == SQLITE_OK);
   230 
   231     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   232             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   233 	assert(int_result == SQLITE_OK);
   234 
   235     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   236             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   237     assert(int_result == SQLITE_OK);
   238 
   239     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   240             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   241     assert(int_result == SQLITE_OK);
   242 
   243     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   244             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized, NULL);
   245     assert(int_result == SQLITE_OK);
   246 
   247     int_result = sqlite3_prepare_v2(_session->db, sql_reset_trust,
   248                                     (int)strlen(sql_reset_trust), &_session->reset_trust, NULL);
   249     assert(int_result == SQLITE_OK);
   250     
   251     status = init_cryptotech(_session, in_first);
   252     if (status != PEP_STATUS_OK)
   253         goto pep_error;
   254 
   255     status = init_transport_system(_session, in_first);
   256     if (status != PEP_STATUS_OK)
   257         goto pep_error;
   258 
   259     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   260     if (status != PEP_STATUS_OK)
   261         goto pep_error;
   262 
   263 	*session = _session;
   264 	return PEP_STATUS_OK;
   265 
   266 enomem:
   267     status = PEP_OUT_OF_MEMORY;
   268 
   269 pep_error:
   270     release(_session);
   271     return status;
   272 }
   273 
   274 DYNAMIC_API void release(PEP_SESSION session)
   275 {
   276     bool out_last = false;
   277 
   278     assert(init_count >= 0);
   279 	assert(session);
   280 
   281     if (!((init_count >= 0) && session))
   282         return;
   283 
   284     // a small race condition but still a race condition
   285     // mitigated by calling caveat (see documentation)
   286 
   287     if (init_count == 0)
   288         out_last = true;
   289     --init_count;
   290 
   291 	if (session) {
   292 		if (session->db) {
   293             if (session->trustword)
   294                 sqlite3_finalize(session->trustword);
   295             if (session->log)
   296                 sqlite3_finalize(session->log);
   297             if (session->get_identity)
   298                 sqlite3_finalize(session->get_identity);
   299             if (session->set_identity)
   300                 sqlite3_finalize(session->set_identity);
   301             if (session->set_person)
   302                 sqlite3_finalize(session->set_person);
   303             if (session->set_pgp_keypair)
   304                 sqlite3_finalize(session->set_pgp_keypair);
   305             if (session->set_trust)
   306                 sqlite3_finalize(session->set_trust);
   307             if (session->get_trust)
   308                 sqlite3_finalize(session->get_trust);
   309             if (session->least_trust)
   310                 sqlite3_finalize(session->least_trust);
   311 
   312             if (session->db)
   313                 sqlite3_close_v2(session->db);
   314             if (session->system_db)
   315                 sqlite3_close_v2(session->system_db);
   316 		}
   317 
   318         release_transport_system(session, out_last);
   319         release_cryptotech(session, out_last);
   320 
   321         free(session);
   322     }
   323 }
   324 
   325 DYNAMIC_API PEP_STATUS log_event(
   326         PEP_SESSION session, const char *title, const char *entity,
   327         const char *description, const char *comment
   328     )
   329 {
   330 	PEP_STATUS status = PEP_STATUS_OK;
   331 	int result;
   332 
   333 	assert(session);
   334 	assert(title);
   335 	assert(entity);
   336 
   337     if (!(session && title && entity))
   338         return PEP_ILLEGAL_VALUE;
   339 
   340 	sqlite3_reset(session->log);
   341 	sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
   342 	sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
   343 	if (description)
   344         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   345 	else
   346 		sqlite3_bind_null(session->log, 3);
   347 	if (comment)
   348 		sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   349 	else
   350 		sqlite3_bind_null(session->log, 4);
   351 	do {
   352 		result = sqlite3_step(session->log);
   353 		assert(result == SQLITE_DONE || result == SQLITE_BUSY);
   354 		if (result != SQLITE_DONE && result != SQLITE_BUSY)
   355 			status = PEP_UNKNOWN_ERROR;
   356 	} while (result == SQLITE_BUSY);
   357 	sqlite3_reset(session->log);
   358 
   359 	return status;
   360 }
   361 
   362 DYNAMIC_API PEP_STATUS trustword(
   363             PEP_SESSION session, uint16_t value, const char *lang,
   364             char **word, size_t *wsize
   365         )
   366 {
   367 	PEP_STATUS status = PEP_STATUS_OK;
   368 	int result;
   369 
   370 	assert(session);
   371 	assert(word);
   372 	assert(wsize);
   373 
   374     if (!(session && word && wsize))
   375         return PEP_ILLEGAL_VALUE;
   376 
   377 	*word = NULL;
   378 	*wsize = 0;
   379 
   380 	if (lang == NULL)
   381 		lang = "en";
   382 
   383 	assert((lang[0] >= 'A' && lang[0] <= 'Z')
   384             || (lang[0] >= 'a' && lang[0] <= 'z'));
   385 	assert((lang[1] >= 'A' && lang[1] <= 'Z')
   386             || (lang[1] >= 'a' && lang[1] <= 'z'));
   387 	assert(lang[2] == 0);
   388 
   389 	sqlite3_reset(session->trustword);
   390     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   391 	sqlite3_bind_int(session->trustword, 2, value);
   392 
   393 	result = sqlite3_step(session->trustword);
   394 	if (result == SQLITE_ROW) {
   395         *word = strdup((const char *) sqlite3_column_text(session->trustword,
   396                     1));
   397 		if (*word)
   398             *wsize = sqlite3_column_bytes(session->trustword, 1);
   399 		else
   400 			status = PEP_TRUSTWORD_NOT_FOUND;
   401 	} else
   402 		status = PEP_TRUSTWORD_NOT_FOUND;
   403 
   404 	sqlite3_reset(session->trustword);
   405 	return status;
   406 }
   407 
   408 DYNAMIC_API PEP_STATUS trustwords(
   409         PEP_SESSION session, const char *fingerprint, const char *lang,
   410         char **words, size_t *wsize, int max_words
   411     )
   412 {
   413 	const char *source = fingerprint;
   414 	char *buffer;
   415 	char *dest;
   416 	size_t fsize;
   417     PEP_STATUS _status;
   418 
   419 	assert(session);
   420 	assert(fingerprint);
   421 	assert(words);
   422 	assert(wsize);
   423 	assert(max_words >= 0);
   424 
   425     if (!(session && fingerprint && words && wsize && max_words >= 0))
   426         return PEP_ILLEGAL_VALUE;
   427 
   428 	*words = NULL;
   429 	*wsize = 0;
   430 
   431     buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
   432     assert(buffer);
   433     if (buffer == NULL)
   434         return PEP_OUT_OF_MEMORY;
   435     dest = buffer;
   436 
   437 	fsize = strlen(fingerprint);
   438 
   439 	if (!lang || !lang[0])
   440 		lang = "en";
   441 
   442 	assert((lang[0] >= 'A' && lang[0] <= 'Z')
   443             || (lang[0] >= 'a' && lang[0] <= 'z'));
   444 	assert((lang[1] >= 'A' && lang[1] <= 'Z')
   445             || (lang[1] >= 'a' && lang[1] <= 'z'));
   446 	assert(lang[2] == 0);
   447 
   448 	int n_words = 0;
   449 	while (source < fingerprint + fsize) {
   450 		uint16_t value;
   451 		char *word;
   452 		size_t _wsize;
   453 		int j;
   454 
   455         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
   456 			if (*source >= 'a' && *source <= 'f')
   457 				value += (*source - 'a' + 10) << (3 - j++) * 4;
   458 			else if (*source >= 'A' && *source <= 'F')
   459 				value += (*source - 'A' + 10) << (3 - j++) * 4;
   460 			else if (*source >= '0' && *source <= '9')
   461 				value += (*source - '0') << (3 - j++) * 4;
   462 			
   463 			source++;
   464 		}
   465 
   466 		_status = trustword(session, value, lang, &word, &_wsize);
   467         if (_status == PEP_OUT_OF_MEMORY) {
   468             free(buffer);
   469             return PEP_OUT_OF_MEMORY;
   470         }
   471 		if (word == NULL) {
   472             free(buffer);
   473 			return PEP_TRUSTWORD_NOT_FOUND;
   474         }
   475 
   476 		if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
   477 			strncpy(dest, word, _wsize);
   478             free(word);
   479 			dest += _wsize;
   480 		}
   481 		else {
   482             free(word);
   483 			break; // buffer full
   484         }
   485 
   486 		if (source < fingerprint + fsize
   487                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
   488 			*dest++ = ' ';
   489 
   490 		++n_words;
   491 		if (max_words && n_words >= max_words)
   492 			break;
   493 	}
   494 
   495 	*words = buffer;
   496 	*wsize = dest - buffer;
   497 	return PEP_STATUS_OK;
   498 }
   499 
   500 pEp_identity *new_identity(
   501         const char *address, const char *fpr, const char *user_id,
   502         const char *username
   503     )
   504 {
   505     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   506     assert(result);
   507     if (result) {
   508         if (address) {
   509             result->address = strdup(address);
   510             assert(result->address);
   511             if (result->address == NULL) {
   512                 free(result);
   513                 return NULL;
   514             }
   515             result->address_size = strlen(address);
   516         }
   517         if (fpr) {
   518             result->fpr = strdup(fpr);
   519             assert(result->fpr);
   520             if (result->fpr == NULL) {
   521                 free_identity(result);
   522                 return NULL;
   523             }
   524             result->fpr_size = strlen(fpr);
   525         }
   526         if (user_id) {
   527             result->user_id = strdup(user_id);
   528             assert(result->user_id);
   529             if (result->user_id == NULL) {
   530                 free_identity(result);
   531                 return NULL;
   532             }
   533             result->user_id_size = strlen(user_id);
   534         }
   535         if (username) {
   536             result->username = strdup(username);
   537             assert(result->username);
   538             if (result->username == NULL) {
   539                 free_identity(result);
   540                 return NULL;
   541             }
   542             result->username_size = strlen(username);
   543         }
   544         result->struct_size = sizeof(pEp_identity);
   545     }
   546     return result;
   547 }
   548 
   549 pEp_identity *identity_dup(const pEp_identity *src)
   550 {
   551     assert(src);
   552 
   553     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id, src->username);
   554     assert(dup);
   555     if (dup == NULL)
   556         return NULL;
   557     
   558     dup->comm_type = src->comm_type;
   559     dup->lang[0] = src->lang[0];
   560     dup->lang[1] = src->lang[1];
   561     dup->lang[2] = 0;
   562     dup->me = src->me;
   563 
   564     return dup;
   565 }
   566 
   567 void free_identity(pEp_identity *identity)
   568 {
   569     if (identity) {
   570         free(identity->address);
   571         free(identity->fpr);
   572         free(identity->user_id);
   573         free(identity->username);
   574         free(identity);
   575     }
   576 }
   577 
   578 DYNAMIC_API PEP_STATUS get_identity(
   579         PEP_SESSION session, const char *address,
   580         pEp_identity **identity
   581     )
   582 {
   583 	PEP_STATUS status = PEP_STATUS_OK;
   584 	static pEp_identity *_identity;
   585 	int result;
   586 	const char *_lang;
   587 
   588 	assert(session);
   589 	assert(address);
   590     assert(address[0]);
   591 
   592     if (!(session && address && address[0]))
   593         return PEP_ILLEGAL_VALUE;
   594 
   595     sqlite3_reset(session->get_identity);
   596     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   597 
   598     result = sqlite3_step(session->get_identity);
   599 	switch (result) {
   600 	case SQLITE_ROW:
   601         _identity = new_identity(
   602                 address,
   603                 (const char *) sqlite3_column_text(session->get_identity, 0),
   604                 (const char *) sqlite3_column_text(session->get_identity, 1),
   605                 (const char *) sqlite3_column_text(session->get_identity, 2)
   606                 );
   607         assert(_identity);
   608         if (_identity == NULL)
   609             return PEP_OUT_OF_MEMORY;
   610 
   611         _identity->comm_type = (PEP_comm_type) sqlite3_column_int(session->get_identity, 3);
   612         _lang = (const char *) sqlite3_column_text(session->get_identity, 4);
   613         if (_lang && _lang[0]) {
   614 			assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   615 			assert(_lang[1] >= 'a' && _lang[1] <= 'z');
   616 			assert(_lang[2] == 0);
   617 			_identity->lang[0] = _lang[0];
   618 			_identity->lang[1] = _lang[1];
   619             _identity->lang[2] = 0;
   620 		}
   621 		*identity = _identity;
   622 		break;
   623 	default:
   624         status = PEP_CANNOT_FIND_IDENTITY;
   625 		*identity = NULL;
   626 	}
   627 
   628     sqlite3_reset(session->get_identity);
   629 	return status;
   630 }
   631 
   632 DYNAMIC_API PEP_STATUS set_identity(
   633         PEP_SESSION session, const pEp_identity *identity
   634     )
   635 {
   636 	int result;
   637 
   638 	assert(session);
   639 	assert(identity);
   640 	assert(identity->address);
   641 	assert(identity->fpr);
   642 	assert(identity->user_id);
   643 	assert(identity->username);
   644 
   645     if (!(session && identity && identity->address && identity->fpr &&
   646                 identity->user_id && identity->username))
   647         return PEP_ILLEGAL_VALUE;
   648 
   649 	sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
   650 
   651 	sqlite3_reset(session->set_person);
   652     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
   653             SQLITE_STATIC);
   654     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
   655             SQLITE_STATIC);
   656 	if (identity->lang[0])
   657         sqlite3_bind_text(session->set_person, 3, identity->lang, 1,
   658                 SQLITE_STATIC);
   659 	else
   660 		sqlite3_bind_null(session->set_person, 3);
   661 	result = sqlite3_step(session->set_person);
   662 	sqlite3_reset(session->set_person);
   663 	if (result != SQLITE_DONE) {
   664 		sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   665 		return PEP_CANNOT_SET_PERSON;
   666 	}
   667 
   668 	sqlite3_reset(session->set_pgp_keypair);
   669     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
   670             SQLITE_STATIC);
   671 	result = sqlite3_step(session->set_pgp_keypair);
   672 	sqlite3_reset(session->set_pgp_keypair);
   673 	if (result != SQLITE_DONE) {
   674 		sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   675 		return PEP_CANNOT_SET_PGP_KEYPAIR;
   676 	}
   677 
   678 	sqlite3_reset(session->set_identity);
   679     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
   680             SQLITE_STATIC);
   681     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
   682             SQLITE_STATIC);
   683     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
   684             SQLITE_STATIC);
   685 	result = sqlite3_step(session->set_identity);
   686 	sqlite3_reset(session->set_identity);
   687 	if (result != SQLITE_DONE) {
   688 		sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   689 		return PEP_CANNOT_SET_IDENTITY;
   690 	}
   691 
   692 	sqlite3_reset(session->set_trust);
   693     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
   694             SQLITE_STATIC);
   695     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
   696             SQLITE_STATIC);
   697 	sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
   698 	result = sqlite3_step(session->set_trust);
   699 	sqlite3_reset(session->set_trust);
   700 	if (result != SQLITE_DONE) {
   701 		sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
   702 		return PEP_CANNOT_SET_IDENTITY;
   703 	}
   704 
   705     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
   706 	if (result == SQLITE_OK)
   707 		return PEP_STATUS_OK;
   708 	else
   709 		return PEP_COMMIT_FAILED;
   710 }
   711 
   712 DYNAMIC_API PEP_STATUS mark_as_compromized(
   713         PEP_SESSION session,
   714         const char *fpr
   715     )
   716 {
   717 	int result;
   718 
   719 	assert(session);
   720     assert(fpr && fpr[0]);
   721 
   722     if (!(session && fpr && fpr[0]))
   723         return PEP_ILLEGAL_VALUE;
   724 
   725 	sqlite3_reset(session->mark_compromized);
   726     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
   727             SQLITE_STATIC);
   728     result = sqlite3_step(session->mark_compromized);
   729 	sqlite3_reset(session->mark_compromized);
   730 
   731     if (result != SQLITE_DONE)
   732         return PEP_CANNOT_SET_IDENTITY;
   733 
   734     return PEP_STATUS_OK;
   735 }
   736 
   737 DYNAMIC_API PEP_STATUS reset_trust(
   738         PEP_SESSION session,
   739         const char *fpr
   740     )
   741 {
   742     int result;
   743     
   744     assert(session);
   745     assert(fpr && fpr[0]);
   746     
   747     if (!(session && fpr && fpr[0]))
   748         return PEP_ILLEGAL_VALUE;
   749     
   750     sqlite3_reset(session->reset_trust);
   751     sqlite3_bind_text(session->reset_trust, 1, fpr, -1,
   752                       SQLITE_STATIC);
   753     result = sqlite3_step(session->reset_trust);
   754     sqlite3_reset(session->reset_trust);
   755     
   756     if (result != SQLITE_DONE)
   757         return PEP_CANNOT_SET_IDENTITY;
   758     
   759     return PEP_STATUS_OK;
   760 }
   761 
   762 void pEp_free(void *p)
   763 {
   764     free(p);
   765 }
   766 
   767 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
   768 {
   769     PEP_STATUS status = PEP_STATUS_OK;
   770     int result;
   771 
   772     assert(session);
   773     assert(identity);
   774     assert(identity->user_id);
   775     assert(identity->user_id[0]);
   776     assert(identity->fpr);
   777     assert(identity->fpr[0]);
   778 
   779     if (!(session && identity && identity->user_id && identity->user_id[0] &&
   780                 identity->fpr && identity->fpr[0]))
   781         return PEP_ILLEGAL_VALUE;
   782 
   783     identity->comm_type = PEP_ct_unknown;
   784 
   785     sqlite3_reset(session->get_trust);
   786     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1, SQLITE_STATIC);
   787     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
   788 
   789     result = sqlite3_step(session->get_trust);
   790     switch (result) {
   791     case SQLITE_ROW: {
   792         const char * user_id = (const char *) sqlite3_column_text(session->get_trust, 0);
   793         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust, 1);
   794 
   795         if (strcmp(user_id, identity->user_id) != 0) {
   796             free(identity->user_id);
   797             identity->user_id = strdup(user_id);
   798             assert(identity->user_id);
   799             if (identity->user_id == NULL)
   800                 return PEP_OUT_OF_MEMORY;
   801         }
   802         identity->comm_type = comm_type;
   803         break;
   804     }
   805  
   806     default:
   807         status = PEP_CANNOT_FIND_IDENTITY;
   808     }
   809 
   810     sqlite3_reset(session->get_trust);
   811     return status;
   812 }
   813 
   814 DYNAMIC_API PEP_STATUS least_trust(
   815         PEP_SESSION session,
   816         const char *fpr,
   817         PEP_comm_type *comm_type
   818     )
   819 {
   820     PEP_STATUS status = PEP_STATUS_OK;
   821     int result;
   822 
   823     assert(session);
   824     assert(fpr);
   825     assert(comm_type);
   826 
   827     *comm_type = PEP_ct_unknown;
   828 
   829     if (!(session && fpr && comm_type))
   830         return PEP_ILLEGAL_VALUE;
   831 
   832     sqlite3_reset(session->least_trust);
   833     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
   834 
   835     result = sqlite3_step(session->least_trust);
   836     switch (result) {
   837         case SQLITE_ROW: {
   838             int _comm_type = sqlite3_column_int(session->least_trust, 0);
   839             *comm_type = (PEP_comm_type) _comm_type;
   840             break;
   841         }
   842         default:
   843             status = PEP_CANNOT_FIND_IDENTITY;
   844     }
   845 
   846     sqlite3_reset(session->least_trust);
   847     return status;
   848 }
   849 
   850 DYNAMIC_API PEP_STATUS decrypt_and_verify(
   851     PEP_SESSION session, const char *ctext, size_t csize,
   852     char **ptext, size_t *psize, stringlist_t **keylist
   853     )
   854 {
   855     assert(session);
   856     assert(ctext);
   857     assert(csize);
   858     assert(ptext);
   859     assert(psize);
   860     assert(keylist);
   861 
   862     if (!(session && ctext && csize && ptext && psize && keylist && keylist))
   863         return PEP_ILLEGAL_VALUE;
   864 
   865     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(session, ctext, csize, ptext, psize, keylist);
   866 }
   867 
   868 DYNAMIC_API PEP_STATUS encrypt_and_sign(
   869     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
   870     size_t psize, char **ctext, size_t *csize
   871     )
   872 {
   873     assert(session);
   874     assert(keylist);
   875     assert(ptext);
   876     assert(psize);
   877     assert(ctext);
   878     assert(csize);
   879 
   880     if (!(session && keylist && ptext && psize && ctext && csize))
   881         return PEP_ILLEGAL_VALUE;
   882 
   883     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session, keylist, ptext, psize, ctext, csize);
   884 }
   885 
   886 DYNAMIC_API PEP_STATUS verify_text(
   887     PEP_SESSION session, const char *text, size_t size,
   888     const char *signature, size_t sig_size, stringlist_t **keylist
   889     )
   890 {
   891     assert(session);
   892     assert(text);
   893     assert(size);
   894     assert(signature);
   895     assert(sig_size);
   896     assert(keylist);
   897 
   898     if (!(session && text && size && signature && sig_size && keylist))
   899         return PEP_ILLEGAL_VALUE;
   900 
   901     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text, size, signature, sig_size, keylist);
   902 }
   903 
   904 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
   905 {
   906     assert(session);
   907     assert(fpr);
   908 
   909     if (!(session && fpr))
   910         return PEP_ILLEGAL_VALUE;
   911 
   912     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
   913 }
   914 
   915 DYNAMIC_API PEP_STATUS export_key(
   916         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
   917     )
   918 {
   919     assert(session);
   920     assert(fpr);
   921     assert(key_data);
   922     assert(size);
   923 
   924     if (!(session && fpr && key_data && size))
   925         return PEP_ILLEGAL_VALUE;
   926 
   927     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr, key_data, size);
   928 }
   929 
   930 DYNAMIC_API PEP_STATUS find_keys(
   931         PEP_SESSION session, const char *pattern, stringlist_t **keylist
   932     )
   933 {
   934     assert(session);
   935     assert(pattern);
   936     assert(keylist);
   937 
   938     if (!(session && pattern && keylist))
   939         return PEP_ILLEGAL_VALUE;
   940 
   941     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern, keylist);
   942 }
   943 
   944 DYNAMIC_API PEP_STATUS generate_keypair(
   945         PEP_SESSION session, pEp_identity *identity
   946     )
   947 {
   948     assert(session);
   949     assert(identity);
   950     assert(identity->address);
   951     assert(identity->fpr == NULL || identity->fpr[0] == 0);
   952     assert(identity->username);
   953 
   954     if (!(session && identity && identity->address &&
   955         (identity->fpr == NULL || identity->fpr[0] == 0) && identity->username))
   956         return PEP_ILLEGAL_VALUE;
   957 
   958     return session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session, identity);
   959 }
   960 
   961 DYNAMIC_API PEP_STATUS get_key_rating(
   962         PEP_SESSION session,
   963         const char *fpr,
   964         PEP_comm_type *comm_type
   965     )
   966 {
   967     assert(session);
   968     assert(fpr);
   969     assert(comm_type);
   970 
   971     if (!(session && fpr && comm_type))
   972         return PEP_ILLEGAL_VALUE;
   973 
   974     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr, comm_type);
   975 }
   976 
   977 DYNAMIC_API PEP_STATUS import_key(PEP_SESSION session, const char *key_data, size_t size)
   978 {
   979     assert(session);
   980     assert(key_data);
   981 
   982     if (!(session && key_data))
   983         return PEP_ILLEGAL_VALUE;
   984 
   985     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data, size);
   986 }
   987 
   988 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
   989 {
   990     assert(session);
   991     assert(pattern);
   992 
   993     if (!(session && pattern))
   994         return PEP_ILLEGAL_VALUE;
   995 
   996     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
   997 }
   998 
   999 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1000 {
  1001     assert(session);
  1002     assert(pattern);
  1003 
  1004     if (!(session && pattern))
  1005         return PEP_ILLEGAL_VALUE;
  1006 
  1007     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1008 }
  1009 
  1010 DYNAMIC_API PEP_STATUS renew_key(
  1011         PEP_SESSION session,
  1012         const char *fpr,
  1013         const timestamp *ts
  1014     )
  1015 {
  1016     assert(session);
  1017     assert(fpr);
  1018 
  1019     if (!(session && fpr))
  1020         return PEP_ILLEGAL_VALUE;
  1021 
  1022     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  1023 }
  1024 
  1025 DYNAMIC_API PEP_STATUS revoke_key(
  1026         PEP_SESSION session,
  1027         const char *fpr,
  1028         const char *reason
  1029     )
  1030 {
  1031     assert(session);
  1032     assert(fpr);
  1033 
  1034     if (!(session && fpr))
  1035         return PEP_ILLEGAL_VALUE;
  1036 
  1037     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1038             reason);
  1039 }
  1040 
  1041 DYNAMIC_API PEP_STATUS key_expired(
  1042         PEP_SESSION session,
  1043         const char *fpr,
  1044         bool *expired
  1045     )
  1046 {
  1047     assert(session);
  1048     assert(fpr);
  1049     assert(expired);
  1050 
  1051     if (!(session && fpr && expired))
  1052         return PEP_ILLEGAL_VALUE;
  1053 
  1054     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1055             expired);
  1056 }
  1057