blob: 7dc9cdf28e32fa9c7c820cb7f8a8ecb6fd4258df [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001/*
2 Copyright (C) 2012-2013 Werner Dittmann
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdint.h>
25#include <string.h>
26#include <time.h>
27#include <sqlite3.h>
28
29#include <crypto/zrtpDH.h>
30
31#include <libzrtpcpp/zrtpB64Encode.h>
32#include <libzrtpcpp/zrtpB64Decode.h>
33
34#include <libzrtpcpp/zrtpCacheDbBackend.h>
35
36/* Some ported SQLite3 libs do not support the _v2 variants */
37#define SQLITE_USE_V2
38
39#ifdef SQLITE_USE_V2
40#define SQLITE_PREPARE sqlite3_prepare_v2
41#else
42#define SQLITE_PREPARE sqlite3_prepare
43#endif
44
45#if defined(_WIN32) || defined(_WIN64)
46# define snprintf _snprintf
47#endif
48
49#ifdef TRANSACTIONS
50static const char *beginTransactionSql = "BEGIN TRANSACTION;";
51static const char *commitTransactionSql = "COMMIT;";
52#endif
53
54/*
55 * The database backend uses the following definitions if it implements the localZid storage.
56 */
57
58/* The type field in zrtpIdOwn stores the following values */
59static const int32_t localZidStandard = 1; /* this local ZID is not tied to a specific account */
60static const int32_t localZidWithAccount = 2;
61
62/* Default data for account info if none specified */
63static const char *defaultAccountString = "_STANDARD_";
64
65
66/* *****************************************************************************
67 * The SQLite master table.
68 *
69 * Used to check if we have valid ZRTP cache tables.
70 */
71static char *lookupTables = "SELECT name FROM sqlite_master WHERE type='table' AND name='zrtpIdOwn';";
72
73
74/* *****************************************************************************
75 * SQL statements to process the zrtpIdOwn table.
76 */
77static const char *dropZrtpIdOwn = "DROP TABLE zrtpIdOwn;";
78
79/* SQLite doesn't care about the VARCHAR length. */
80static char *createZrtpIdOwn = "CREATE TABLE zrtpIdOwn(localZid CHAR(18), type INTEGER, accountInfo VARCHAR(1000));";
81
82static char *selectZrtpIdOwn = "SELECT localZid FROM zrtpIdOwn WHERE type = ?1 AND accountInfo = ?2;";
83static char *insertZrtpIdOwn = "INSERT INTO zrtpIdOwn (localZid, type, accountInfo) VALUES (?1, ?2, ?3);";
84
85
86/* *****************************************************************************
87 * SQL statements to process the remoteId table.
88 */
89static const char *dropZrtpIdRemote = "DROP TABLE zrtpIdRemote;";
90
91static const char *createZrtpIdRemote =
92 "CREATE TABLE zrtpIdRemote "
93 "(remoteZid CHAR(16), localZid CHAR(16), flags INTEGER,"
94 "rs1 BLOB(32), rs1LastUsed TIMESTAMP, rs1TimeToLive TIMESTAMP,"
95 "rs2 BLOB(32), rs2LastUsed TIMESTAMP, rs2TimeToLive TIMESTAMP,"
96 "mitmKey BLOB(32), mitmLastUsed TIMESTAMP, secureSince TIMESTAMP, preshCounter INTEGER);";
97
98static const char *selectZrtpIdRemoteAll =
99 "SELECT flags,"
100 "rs1, strftime('%s', rs1LastUsed, 'unixepoch'), strftime('%s', rs1TimeToLive, 'unixepoch'),"
101 "rs2, strftime('%s', rs2LastUsed, 'unixepoch'), strftime('%s', rs2TimeToLive, 'unixepoch'),"
102 "mitmKey, strftime('%s', mitmLastUsed, 'unixepoch'), strftime('%s', secureSince, 'unixepoch'),"
103 "preshCounter "
104 "FROM zrtpIdRemote WHERE remoteZid=?1 AND localZid=?2;";
105
106static const char *insertZrtpIdRemote =
107 "INSERT INTO zrtpIdRemote "
108 "(remoteZid, localZid, flags,"
109 "rs1, rs1LastUsed, rs1TimeToLive,"
110 "rs2, rs2LastUsed, rs2TimeToLive,"
111 "mitmKey, mitmLastUsed, secureSince, preshCounter)"
112 "VALUES"
113 "(?1, ?12, ?2,"
114 "?3, strftime('%s', ?4, 'unixepoch'), strftime('%s', ?5, 'unixepoch'),"
115 "?6, strftime('%s', ?7, 'unixepoch'), strftime('%s', ?8, 'unixepoch'),"
116 "?9, strftime('%s', ?10, 'unixepoch'), strftime('%s', ?11, 'unixepoch'), ?13);";
117
118static const char *updateZrtpIdRemote =
119 "UPDATE zrtpIdRemote SET "
120 "flags=?2,"
121 "rs1=?3, rs1LastUsed=strftime('%s', ?4, 'unixepoch'), rs1TimeToLive=strftime('%s', ?5, 'unixepoch'),"
122 "rs2=?6, rs2LastUsed=strftime('%s', ?7, 'unixepoch'), rs2TimeToLive=strftime('%s', ?8, 'unixepoch'),"
123 "mitmKey=?9, mitmLastUsed=strftime('%s', ?10, 'unixepoch'),"
124 "secureSince=strftime('%s', ?11, 'unixepoch'), preshCounter=?13 "
125 "WHERE remoteZid=?1 AND localZid=?12;";
126
127
128/* *****************************************************************************
129 * SQL statements to process the name table.
130 *
131 * The name tables holds free format information and binds it to the combination
132 * of local, remote ZIDs and an optional account information.
133 */
134static const char *dropZrtpNames = "DROP TABLE zrtpNames;";
135
136static const char *createZrtpNames =
137 "CREATE TABLE zrtpNames "
138 "(remoteZid CHAR(16), localZid CHAR(16), flags INTEGER, "
139 "lastUpdate TIMESTAMP, accountInfo VARCHAR(1000), name VARCHAR(1000));";
140
141static const char *selectZrtpNames =
142 "SELECT flags, strftime('%s', lastUpdate, 'unixepoch'), name "
143 "FROM zrtpNames "
144 "WHERE remoteZid=?1 AND localZid=?2 AND accountInfo=?3;";
145
146static const char *insertZrtpNames =
147 "INSERT INTO zrtpNames "
148 "(remoteZid, localZid, flags, lastUpdate, accountInfo, name)"
149 "VALUES"
150 "(?1, ?2, ?4, strftime('%s', ?5, 'unixepoch'), ?3, ?6);";
151
152static const char *updateZrtpNames =
153 "UPDATE zrtpNames SET "
154 "flags=?4,"
155 "lastUpdate=strftime('%s', ?5, 'unixepoch'), name=?6 "
156 "WHERE remoteZid=?1 AND localZid=?2 AND accountInfo=?3;";
157
158
159/* *****************************************************************************
160 * A few helping macros.
161 * These macros require some names/patterns in the methods that use these
162 * macros:
163 *
164 * ERRMSG requires:
165 * - a variable with name "db" is the pointer to sqlite3
166 * - a char* with name "errString" points to a buffer of at least SQL_CACHE_ERR_BUFF_SIZE chars
167 *
168 * SQLITE_CHK requires:
169 * - a cleanup label, the macro goes to that label in case of error
170 * - an integer (int) variable with name "rc" that stores return codes from sqlite
171 * - ERRMSG
172 */
173#define ERRMSG {if (errString) snprintf(errString, (size_t)DB_CACHE_ERR_BUFF_SIZE, \
174 "SQLite3 error: %s, line: %d, error message: %s\n", __FILE__, __LINE__, sqlite3_errmsg(db));}
175#define SQLITE_CHK(func) { \
176 rc = (func); \
177 if(rc != SQLITE_OK) { \
178 ERRMSG; \
179 goto cleanup; \
180 } \
181 }
182
183static int b64Encode(const uint8_t *binData, int32_t binLength, char *b64Data, int32_t b64Length)
184{
185 base64_encodestate _state;
186 int codelength;
187
188 base64_init_encodestate(&_state, 0);
189 codelength = base64_encode_block(binData, binLength, b64Data, &_state);
190 codelength += base64_encode_blockend(b64Data+codelength, &_state);
191
192 return codelength;
193}
194
195static int b64Decode(const char *b64Data, int32_t b64length, uint8_t *binData, int32_t binLength)
196{
197 base64_decodestate _state;
198 int codelength;
199
200 base64_init_decodestate(&_state);
201 codelength = base64_decode_block(b64Data, b64length, binData, &_state);
202 return codelength;
203}
204
205#ifdef TRANSACTIONS
206static int beginTransaction(sqlite3 *db, char* errString)
207{
208 sqlite3_stmt *stmt;
209 int rc;
210
211 SQLITE_CHK(SQLITE_PREPARE(db, beginTransactionSql, strlen(beginTransactionSql)+1, &stmt, NULL));
212
213 rc = sqlite3_step(stmt);
214 sqlite3_finalize(stmt);
215 if (rc != SQLITE_DONE) {
216 ERRMSG;
217 return rc;
218 }
219 return SQLITE_OK;
220
221 cleanup:
222 sqlite3_finalize(stmt);
223 return rc;
224}
225
226static int commitTransaction(sqlite3 *db, char* errString)
227{
228 sqlite3_stmt *stmt;
229 int rc;
230
231 SQLITE_CHK(SQLITE_PREPARE(db, commitTransactionSql, strlen(commitTransactionSql)+1, &stmt, NULL));
232
233 rc = sqlite3_step(stmt);
234 sqlite3_finalize(stmt);
235 if (rc != SQLITE_DONE) {
236 ERRMSG;
237 return rc;
238 }
239 return SQLITE_OK;
240
241 cleanup:
242 sqlite3_finalize(stmt);
243 return rc;
244}
245#endif
246
247/**
248 * Initialize remote ZID and remote name tables.
249 *
250 * First drop the remote ZID and remote name tables and create them again.
251 * All information regarding remote peers is lost.
252 */
253static int initializeRemoteTables(sqlite3 *db, char* errString)
254{
255 sqlite3_stmt * stmt;
256 int rc;
257
258 /* First drop them, just to be on the save side
259 * Ignore errors, there is nothing to drop on empty DB. If ZrtpIdOwn was
260 * deleted using DB admin command then we need to drop the remote id table
261 * and names also to have a clean state.
262 */
263 rc = SQLITE_PREPARE(db, dropZrtpIdRemote, strlen(dropZrtpIdRemote)+1, &stmt, NULL);
264 rc = sqlite3_step(stmt);
265 sqlite3_finalize(stmt);
266
267 rc = SQLITE_PREPARE(db, dropZrtpNames, strlen(dropZrtpNames)+1, &stmt, NULL);
268 rc = sqlite3_step(stmt);
269 sqlite3_finalize(stmt);
270
271 SQLITE_CHK(SQLITE_PREPARE(db, createZrtpIdRemote, strlen(createZrtpIdRemote)+1, &stmt, NULL));
272 rc = sqlite3_step(stmt);
273 sqlite3_finalize(stmt);
274 if (rc != SQLITE_DONE) {
275 ERRMSG;
276 return rc;
277 }
278 SQLITE_CHK(SQLITE_PREPARE(db, createZrtpNames, strlen(createZrtpNames)+1, &stmt, NULL));
279 rc = sqlite3_step(stmt);
280 sqlite3_finalize(stmt);
281 if (rc != SQLITE_DONE) {
282 ERRMSG;
283 return rc;
284 }
285 return 0;
286
287 cleanup:
288 sqlite3_finalize(stmt);
289 return rc;
290
291}
292/**
293 * Create ZRTP cache tables in database.
294 *
295 * openCache calls this function if it cannot find the table zrtpId_own. This indicates
296 * that no ZRTP cache tables are available in the database.
297 */
298static int createTables(sqlite3 *db, char* errString)
299{
300 sqlite3_stmt * stmt;
301 int rc;
302
303 /* no ZRTP cache tables were found - create them, first the OwnId table */
304 SQLITE_CHK(SQLITE_PREPARE(db, createZrtpIdOwn, strlen(createZrtpIdOwn)+1, &stmt, NULL));
305
306 rc = sqlite3_step(stmt);
307 sqlite3_finalize(stmt);
308 if (rc != SQLITE_DONE) {
309 ERRMSG;
310 return rc;
311 }
312 return initializeRemoteTables(db, errString);
313
314 cleanup:
315 sqlite3_finalize(stmt);
316 return rc;
317}
318
319static int insertRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
320 const remoteZidRecord_t *remZid, char* errString)
321{
322 sqlite3 *db = (sqlite3*)vdb;
323 sqlite3_stmt *stmt;
324 int rc = 0;
325
326 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
327 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
328
329 /* Get B64 code for remoteZid first */
330 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
331
332 /* Get B64 code for localZid now */
333 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
334
335 SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpIdRemote, strlen(insertZrtpIdRemote)+1, &stmt, NULL));
336
337 /* For *_bind_* methods: column index starts with 1 (one), not zero */
338 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
339 SQLITE_CHK(sqlite3_bind_text(stmt, 12, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
340 SQLITE_CHK(sqlite3_bind_int(stmt, 2, remZid->flags));
341 SQLITE_CHK(sqlite3_bind_blob(stmt, 3, remZid->rs1, RS_LENGTH, SQLITE_STATIC));
342 SQLITE_CHK(sqlite3_bind_int64(stmt, 4, remZid->rs1LastUse));
343 SQLITE_CHK(sqlite3_bind_int64(stmt, 5, remZid->rs1Ttl));
344 SQLITE_CHK(sqlite3_bind_blob(stmt, 6, remZid->rs2, RS_LENGTH, SQLITE_STATIC));
345 SQLITE_CHK(sqlite3_bind_int64(stmt, 7, remZid->rs2LastUse));
346 SQLITE_CHK(sqlite3_bind_int64(stmt, 8, remZid->rs2Ttl));
347 SQLITE_CHK(sqlite3_bind_blob(stmt, 9, remZid->mitmKey, RS_LENGTH, SQLITE_STATIC));
348 SQLITE_CHK(sqlite3_bind_int64(stmt, 10, remZid->mitmLastUse));
349 SQLITE_CHK(sqlite3_bind_int64(stmt, 11, remZid->secureSince));
350 SQLITE_CHK(sqlite3_bind_int(stmt, 13, remZid->preshCounter));
351
352 rc = sqlite3_step(stmt);
353 sqlite3_finalize(stmt);
354 if (rc != SQLITE_DONE) {
355 ERRMSG;
356 return rc;
357 }
358 return SQLITE_OK;
359
360 cleanup:
361 sqlite3_finalize(stmt);
362 return rc;
363
364}
365
366static int updateRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
367 const remoteZidRecord_t *remZid, char* errString)
368{
369 sqlite3 *db = (sqlite3*)vdb;
370 sqlite3_stmt *stmt;
371 int rc;
372
373 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
374 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
375
376 /* Get B64 code for remoteZid first */
377 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
378
379 /* Get B64 code for localZid now */
380 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
381
382 SQLITE_CHK(SQLITE_PREPARE(db, updateZrtpIdRemote, strlen(updateZrtpIdRemote)+1, &stmt, NULL));
383
384 /* For *_bind_* methods: column index starts with 1 (one), not zero */
385 /* Select for update with the following keys */
386 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
387 SQLITE_CHK(sqlite3_bind_text(stmt, 12, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
388
389 /* Update the following values */
390 SQLITE_CHK(sqlite3_bind_int(stmt, 2, remZid->flags));
391 SQLITE_CHK(sqlite3_bind_blob(stmt, 3, remZid->rs1, RS_LENGTH, SQLITE_STATIC));
392 SQLITE_CHK(sqlite3_bind_int64(stmt, 4, remZid->rs1LastUse));
393 SQLITE_CHK(sqlite3_bind_int64(stmt, 5, remZid->rs1Ttl));
394 SQLITE_CHK(sqlite3_bind_blob(stmt, 6, remZid->rs2, RS_LENGTH, SQLITE_STATIC));
395 SQLITE_CHK(sqlite3_bind_int64(stmt, 7, remZid->rs2LastUse));
396 SQLITE_CHK(sqlite3_bind_int64(stmt, 8, remZid->rs2Ttl));
397 SQLITE_CHK(sqlite3_bind_blob(stmt, 9, remZid->mitmKey, RS_LENGTH, SQLITE_STATIC));
398 SQLITE_CHK(sqlite3_bind_int64(stmt, 10, remZid->mitmLastUse));
399 SQLITE_CHK(sqlite3_bind_int64(stmt, 11, remZid->secureSince));
400 SQLITE_CHK(sqlite3_bind_int(stmt, 13, remZid->preshCounter));
401
402 rc = sqlite3_step(stmt);
403 sqlite3_finalize(stmt);
404 if (rc != SQLITE_DONE) {
405 ERRMSG;
406 return rc;
407 }
408 return SQLITE_OK;
409
410 cleanup:
411 sqlite3_finalize(stmt);
412 return rc;
413}
414
415static int readRemoteZidRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
416 remoteZidRecord_t *remZid, char* errString)
417{
418 sqlite3 *db = (sqlite3*)vdb;
419 sqlite3_stmt *stmt;
420 int rc;
421 int found = 0;
422
423 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
424 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
425
426 /* Get B64 code for remoteZid */
427 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
428
429 /* Get B64 code for localZid */
430 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
431
432 SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpIdRemoteAll, strlen(selectZrtpIdRemoteAll)+1, &stmt, NULL));
433 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
434 SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
435
436 /* Getting data from result set: column index starts with 0 (zero), not one */
437 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
438 remZid->flags = sqlite3_column_int(stmt, 0);
439 memcpy(remZid->rs1, sqlite3_column_blob(stmt, 1), RS_LENGTH);
440 remZid->rs1LastUse = sqlite3_column_int64(stmt, 2);
441 remZid->rs1Ttl = sqlite3_column_int64(stmt, 3);
442 memcpy(remZid->rs2, sqlite3_column_blob(stmt, 4), RS_LENGTH);
443 remZid->rs2LastUse = sqlite3_column_int64(stmt, 5);
444 remZid->rs2Ttl = sqlite3_column_int64(stmt, 6);
445 memcpy(remZid->mitmKey, sqlite3_column_blob(stmt, 7), RS_LENGTH);
446 remZid->mitmLastUse = sqlite3_column_int64(stmt, 8);
447 remZid->secureSince = sqlite3_column_int64(stmt, 9);
448 remZid->preshCounter = sqlite3_column_int(stmt, 10);
449 found++;
450 }
451 sqlite3_finalize(stmt);
452
453 if (rc != SQLITE_DONE) {
454 ERRMSG;
455 return rc;
456 }
457 if (found == 0) {
458 remZid->flags = 0;
459 }
460 else if (found > 1) {
461 if (errString)
462 snprintf(errString, DB_CACHE_ERR_BUFF_SIZE, "ZRTP cache inconsistent. More than one remote ZID found: %d\n", found);
463 return 1;
464 }
465 return SQLITE_OK;
466
467 cleanup:
468 sqlite3_finalize(stmt);
469 return rc;
470}
471
472
473static int readLocalZid(void *vdb, uint8_t *localZid, const char *accountInfo, char *errString)
474{
475 sqlite3 *db = (sqlite3*)vdb;
476 sqlite3_stmt *stmt;
477 char *zidBase64Text;
478 int rc = 0;
479 int found = 0;
480 int type = localZidWithAccount;
481
482 if (accountInfo == NULL || !strcmp(accountInfo, defaultAccountString)) {
483 accountInfo = defaultAccountString;
484 type = localZidStandard;
485 }
486
487 /* Find a localZid record for this combination */
488 SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpIdOwn, strlen(selectZrtpIdOwn)+1, &stmt, NULL));
489
490 SQLITE_CHK(sqlite3_bind_int(stmt, 1, type));
491 SQLITE_CHK(sqlite3_bind_text(stmt, 2, accountInfo, strlen(accountInfo), SQLITE_STATIC));
492
493 /* Loop over result set and count it. However, use only the localZid of first row */
494 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
495 if (found == 0) {
496 zidBase64Text = (char *)sqlite3_column_text(stmt, 0);
497 b64Decode(zidBase64Text, strlen(zidBase64Text), localZid, IDENTIFIER_LEN);
498 }
499 found++;
500 }
501 sqlite3_finalize(stmt);
502
503 if (rc != SQLITE_DONE) {
504 ERRMSG;
505 return rc;
506 }
507 /* No matching record found, create new local ZID for this combination and store in DB */
508 if (found == 0) {
509 char b64zid[IDENTIFIER_LEN+IDENTIFIER_LEN] = {0};
510 int b64len = 0;
511
512 /* create a 12 byte random value, convert to base 64, insert in zrtpIdOwn table */
513 randomZRTP(localZid, IDENTIFIER_LEN);
514 b64len = b64Encode(localZid, IDENTIFIER_LEN, b64zid, IDENTIFIER_LEN+IDENTIFIER_LEN);
515
516 SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpIdOwn, strlen(insertZrtpIdOwn)+1, &stmt, NULL));
517
518 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64zid, b64len, SQLITE_STATIC));
519 SQLITE_CHK(sqlite3_bind_int(stmt, 2, type));
520 SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC));
521
522 rc = sqlite3_step(stmt);
523 sqlite3_finalize(stmt);
524 if (rc != SQLITE_DONE) {
525 ERRMSG;
526 return rc;
527 }
528 }
529 else if (found > 1) {
530 if (errString)
531 snprintf(errString, DB_CACHE_ERR_BUFF_SIZE,
532 "ZRTP cache inconsistent. Found %d matching local ZID for account: %s\n", found, accountInfo);
533 return 1;
534 }
535 return SQLITE_OK;
536
537 cleanup:
538 sqlite3_finalize(stmt);
539 return rc;
540}
541
542/*
543 * SQLite use the following table structure to manage some internal data
544 *
545 * CREATE TABLE sqlite_master (
546 * type TEXT,
547 * name TEXT,
548 * tbl_name TEXT,
549 * rootpage INTEGER,
550 * sql TEXT
551 * );
552 */
553
554static int openCache(const char* name, void **vpdb, char *errString)
555{
556 sqlite3_stmt *stmt;
557 int found = 0;
558 sqlite3 **pdb = (sqlite3**)vpdb;
559 sqlite3 *db;
560
561#ifdef SQLITE_USE_V2
562 int rc = sqlite3_open_v2(name, pdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL);
563#else
564 int rc = sqlite3_open(name, pdb);
565#endif
566 db = *pdb;
567 if (rc) {
568 ERRMSG;
569 return(rc);
570 }
571
572 /* check if ZRTP cache tables are already available, look if zrtpIdOwn is available */
573 SQLITE_CHK(SQLITE_PREPARE(db, lookupTables, strlen(lookupTables)+1, &stmt, NULL));
574 rc = sqlite3_step(stmt);
575 sqlite3_finalize(stmt);
576
577 if (rc == SQLITE_ROW) {
578 found++;
579 }
580 else if (rc != SQLITE_DONE) {
581 ERRMSG;
582 return rc;
583 }
584 /* If table zrtpOwnId not found then we have an empty cache DB */
585 if (found == 0) {
586 rc = createTables(db, errString);
587 if (rc)
588 return rc;
589 }
590 return SQLITE_OK;
591
592 cleanup:
593 sqlite3_finalize(stmt);
594 return rc;
595}
596
597static int closeCache(void *vdb)
598{
599
600 sqlite3 *db = (sqlite3*)vdb;
601 sqlite3_close(db);
602 return SQLITE_OK;
603}
604
605static int clearCache(void *vdb, char *errString)
606{
607
608 sqlite3 *db = (sqlite3*)vdb;
609 sqlite3_stmt * stmt;
610 int rc;
611
612 rc = SQLITE_PREPARE(db, dropZrtpIdOwn, strlen(dropZrtpIdOwn)+1, &stmt, NULL);
613 rc = sqlite3_step(stmt);
614 sqlite3_finalize(stmt);
615
616 rc = createTables(db, errString);
617 if (rc)
618 return rc;
619 return SQLITE_OK;
620}
621
622static int insertZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
623 const char *accountInfo, zidNameRecord_t *zidName, char* errString)
624{
625 sqlite3 *db = (sqlite3*)vdb;
626 sqlite3_stmt *stmt;
627 int rc = 0;
628 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
629 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
630
631 if (accountInfo == NULL) {
632 accountInfo = defaultAccountString;
633 }
634
635 /* Get B64 code for remoteZid */
636 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
637
638 /* Get B64 code for localZid */
639 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
640
641 SQLITE_CHK(SQLITE_PREPARE(db, insertZrtpNames, strlen(insertZrtpNames)+1, &stmt, NULL));
642
643 /* For *_bind_* methods: column index starts with 1 (one), not zero */
644 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
645 SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
646 SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC));
647 SQLITE_CHK(sqlite3_bind_int(stmt, 4, zidName->flags));
648 SQLITE_CHK(sqlite3_bind_int64(stmt, 5, (int64_t)time(NULL)));
649 if (zidName->name != NULL) {
650 SQLITE_CHK(sqlite3_bind_text(stmt, 6, zidName->name, strlen(zidName->name), SQLITE_STATIC));
651 }
652 else {
653 SQLITE_CHK(sqlite3_bind_text(stmt, 6, "_NO_NAME_", 9, SQLITE_STATIC));
654 }
655 rc = sqlite3_step(stmt);
656 sqlite3_finalize(stmt);
657 if (rc != SQLITE_DONE) {
658 ERRMSG;
659 return rc;
660 }
661 return SQLITE_OK;
662
663 cleanup:
664 sqlite3_finalize(stmt);
665 return rc;
666
667}
668
669
670static int updateZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
671 const char *accountInfo, zidNameRecord_t *zidName, char* errString)
672{
673 sqlite3 *db = (sqlite3*)vdb;
674 sqlite3_stmt *stmt;
675 int rc = 0;
676 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
677 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
678
679 if (accountInfo == NULL) {
680 accountInfo = defaultAccountString;
681 }
682
683 /* Get B64 code for remoteZid */
684 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
685
686 /* Get B64 code for localZid */
687 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
688
689 SQLITE_CHK(SQLITE_PREPARE(db, updateZrtpNames, strlen(updateZrtpNames)+1, &stmt, NULL));
690
691 /* For *_bind_* methods: column index starts with 1 (one), not zero */
692 /* Select for update with the following values */
693 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
694 SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
695 SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC));
696
697 /* Update the following vaulues */
698 SQLITE_CHK(sqlite3_bind_int(stmt, 4, zidName->flags));
699 SQLITE_CHK(sqlite3_bind_int64(stmt, 5, (int64_t)time(NULL)));
700 if (zidName->name != NULL) {
701 SQLITE_CHK(sqlite3_bind_text(stmt, 6, zidName->name, strlen(zidName->name), SQLITE_STATIC));
702 }
703 else {
704 SQLITE_CHK(sqlite3_bind_text(stmt, 6, "_NO_NAME_", 9, SQLITE_STATIC));
705 }
706 rc = sqlite3_step(stmt);
707 sqlite3_finalize(stmt);
708 if (rc != SQLITE_DONE) {
709 ERRMSG;
710 return rc;
711 }
712 return SQLITE_OK;
713
714 cleanup:
715 sqlite3_finalize(stmt);
716 return rc;
717
718}
719
720static int readZidNameRecord(void *vdb, const uint8_t *remoteZid, const uint8_t *localZid,
721 const char *accountInfo, zidNameRecord_t *zidName, char* errString)
722{
723 sqlite3 *db = (sqlite3*)vdb;
724 sqlite3_stmt *stmt;
725 int rc;
726 int found = 0;
727
728 char b64RemoteZid[IDENTIFIER_LEN*2] = {0};
729 char b64LocalZid[IDENTIFIER_LEN*2] = {0};
730
731 if (accountInfo == NULL) {
732 accountInfo = defaultAccountString;
733 }
734 /* Get B64 code for remoteZid */
735 b64Encode(remoteZid, IDENTIFIER_LEN, b64RemoteZid, IDENTIFIER_LEN*2);
736
737 /* Get B64 code for localZid */
738 b64Encode(localZid, IDENTIFIER_LEN, b64LocalZid, IDENTIFIER_LEN*2);
739
740 SQLITE_CHK(SQLITE_PREPARE(db, selectZrtpNames, strlen(selectZrtpNames)+1, &stmt, NULL));
741
742 SQLITE_CHK(sqlite3_bind_text(stmt, 1, b64RemoteZid, strlen(b64RemoteZid), SQLITE_STATIC));
743 SQLITE_CHK(sqlite3_bind_text(stmt, 2, b64LocalZid, strlen(b64LocalZid), SQLITE_STATIC));
744 SQLITE_CHK(sqlite3_bind_text(stmt, 3, accountInfo, strlen(accountInfo), SQLITE_STATIC));
745
746 /* Getting data from result set: column index starts with 0 (zero), not one */
747 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
748 zidName->flags = sqlite3_column_int(stmt, 0);
749 strncpy(zidName->name, (const char*)sqlite3_column_text(stmt, 2), zidName->nameLength);
750 zidName->nameLength = sqlite3_column_bytes(stmt, 2); /* Return number of bytes in string */
751 found++;
752 }
753 sqlite3_finalize(stmt);
754
755 if (rc != SQLITE_DONE) {
756 ERRMSG;
757 return rc;
758 }
759 if (found == 0)
760 zidName->flags = 0;
761 else if (found > 1) {
762 if (errString)
763 snprintf(errString, DB_CACHE_ERR_BUFF_SIZE, "ZRTP name cache inconsistent. More than one ZID name found: %d\n", found);
764 return 1;
765 }
766 return SQLITE_OK;
767
768 cleanup:
769 sqlite3_finalize(stmt);
770 return rc;
771}
772
773void getDbCacheOps(dbCacheOps_t *ops)
774{
775 ops->openCache = openCache;
776 ops->closeCache = closeCache;
777 ops->cleanCache = clearCache;
778
779 ops->readLocalZid = readLocalZid;
780
781 ops->readRemoteZidRecord = readRemoteZidRecord;
782 ops->updateRemoteZidRecord = updateRemoteZidRecord;
783 ops->insertRemoteZidRecord = insertRemoteZidRecord;
784
785 ops->readZidNameRecord = readZidNameRecord;
786 ops->updateZidNameRecord = updateZidNameRecord;
787 ops->insertZidNameRecord = insertZidNameRecord;
788}
789