/*
* sql_common.h
* ------------
*
* Common definitions and SQL support code for Cryptech PKCS #11 engine.
*
* We could split the functions out of this into a separate .c file,
* but there's no real point in doing so, and it's simpler to keep it
* all in one file, the build process is complex enough already.
*
* Author: Rob Austein
* Copyright (c) 2015, NORDUnet A/S
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the NORDUnet nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SQL_COMMON_H_
#define _SQL_COMMON_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <sqlite3.h>
/*
* Placeholders for PIN length limits. Figure out real values later.
* Minimum length here is much too short, we allow it for now because
* some test programs fail if we insist on a reasonable length.
*/
#warning Figure out PIN length limits
#define P11_MIN_PIN_LENGTH 4
#define P11_MAX_PIN_LENGTH 4096
/*
* Debugging control.
*/
#ifndef DEBUG_SQL
#define DEBUG_SQL 1
#endif
/*
* Default filename for SQL database lives. Can be overriden at
* runtime by setting PKCS11_DATABASE environment variable.
*/
#ifndef SQL_DATABASE
#define SQL_DATABASE ".cryptech-pkcs11.db"
#endif
/*
* SQL database.
*/
static sqlite3 *sqldb = NULL;
/*
* Error checking for SQLite calls.
*/
#if DEBUG_SQL
#define sql_whine(_expr_) \
(fprintf(stderr, "%s:%u: %s returned %s\n", \
__FILE__, __LINE__, #_expr_, sqlite3_errmsg(sqldb)), \
sql_breakpoint())
#else /* DEBUG_SQL */
#define sql_whine(_expr_) \
((void) 0)
#endif /* DEBUG_SQL */
#define sql_check(_good_, _expr_) \
((_expr_) == (_good_) ? 1 : (sql_whine(_expr_), 0))
#define sql_check_ok(_expr_) sql_check(SQLITE_OK, _expr_)
#define sql_check_row(_expr_) sql_check(SQLITE_ROW, _expr_)
#define sql_check_done(_expr_) sql_check(SQLITE_DONE, _expr_)
#define sql_whine_step() sql_whine(sqlite3_step())
/*
* Hook on which to hang a debugger breakpoint on SQL errors.
*/
#if DEBUG_SQL
static void sql_breakpoint(void)
{
fprintf(stderr, "[sql_breakpoint]\n");
}
#endif
/*
* Execute SQL code that doesn't require a prepared query.
*/
static int sql_exec(const char *cmd)
{
char *msg = NULL;
if (sql_check_ok(sqlite3_exec(sqldb, cmd, NULL, NULL, &msg)))
return 1;
#if DEBUG_SQL
if (msg != NULL)
fprintf(stderr, "[%s]\n", msg);
#endif
return 0;
}
/*
* Initialize SQL. This includes loading our schema, portions of
* which live in the temp (memory) database thus always need to be
* created on startup.
*/
static int sql_init(void)
{
static const char schema[] =
#include "schema.h"
;
assert(sqldb == NULL);
const char * const env = getenv("PKCS11_DATABASE");
const char * const home = getenv("HOME");
const char * const base = SQL_DATABASE;
int ok;
if (env != NULL) {
ok = sql_check_ok(sqlite3_open(env, &sqldb));
}
else if (home == NULL) {
ok = sql_check_ok(sqlite3_open(base, &sqldb));
}
else {
char fn[strlen(home) + strlen(base) + 2];
snprintf(fn, sizeof(fn), "%s/%s", home, base);
ok = sql_check_ok(sqlite3_open(fn, &sqldb));
}
return ok && sql_exec(schema);
}
/*
* Shut down SQL.
*
* Yes, this can return failure, although it's not clear what we're
* meant to do about that if the application is going to shut down
* regardless of what we do. I guess we could loop retrying a few
* times for errors like SQLITE_BUSY, but that's about it.
*/
static int sql_fini(void)
{
if (!sql_check_ok(sqlite3_close(sqldb)))
return 0;
sqldb = NULL;
return 1;
}
/*
* GCC attribute declaration to help catch format string errors,
* ignored by other compilers.
*/
#ifdef __GNUC__
static int sql_prepare(sqlite3_stmt **q,
const char *format, ...)
__attribute__ ((format (printf, 2, 3)));
#endif
/*
* Prepare an SQLite3 query, using vsnprintf() to format the query.
*
* WARNING WARNING WARNING WARNING
*
* Do not use this formatting mechanism for anything involving
* user-supplied data. It's only intended to handle things like
* selecting between two parallel table structures or queries using
* manifest constants that are only available in C header files.
*/
static int sql_prepare(sqlite3_stmt **q, const char *format, ...)
{
char buffer[2048];
va_list ap;
size_t n;
va_start(ap, format);
n = vsnprintf(buffer, sizeof(buffer), format, ap);
va_end(ap);
if (n >= sizeof(buffer))
return SQLITE_TOOBIG;
return sqlite3_prepare_v2(sqldb, buffer, -1, q, NULL);
}
/*
* This idiom occurs frequently, bundle it so we have the option of
* doing it along with the normal conditional control flow that SQL
* queries seem to follow.
*/
static int sql_finalize_and_clear(sqlite3_stmt **q)
{
assert(q != NULL);
int err = sqlite3_finalize(*q);
if (err != SQLITE_OK)
return err;
*q = NULL;
return SQLITE_OK;
}
#endif /* _SQL_COMMON_H_ */
/*
* Local variables:
* indent-tabs-mode: nil
* End:
*/