X-Git-Url: http://the.earth.li/gitweb/?a=blobdiff_plain;f=keydb_pg.c;h=7d59640b0fd2a82189f0411fe2f0d5018c7fdf97;hb=5e2c81ee4acb5bf3eb4afdbc766646ba06f96dd9;hp=8e0543b9f061210c5afda582f889d1d0009156cc;hpb=5e1b22d763640c4d7a09d07920403d8d491b4410;p=onak.git
diff --git a/keydb_pg.c b/keydb_pg.c
index 8e0543b..7d59640 100644
--- a/keydb_pg.c
+++ b/keydb_pg.c
@@ -13,8 +13,7 @@
* more details.
*
* You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * this program. If not, see .
*/
#include
@@ -39,63 +38,29 @@
#include "onak-conf.h"
#include "parsekey.h"
-/**
- * dbconn - our connection to the database.
- */
-static PGconn *dbconn = NULL;
+struct pg_fc_ctx {
+ PGconn *dbconn;
+ int fd;
+};
/**
* keydb_fetchchar - Fetches a char from a file.
*/
-static int keydb_fetchchar(void *fd, size_t count, void *c)
+static int keydb_fetchchar(void *_ctx, size_t count, void *c)
{
- return (!lo_read(dbconn, *(int *) fd, (char *) c, count));
-}
+ struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
-/**
- * keydb_putchar - Puts a char to a file.
- */
-static int keydb_putchar(void *fd, size_t count, void *c)
-{
- return !(lo_write(dbconn, *(int *) fd, (char *) c, count));
+ return (!lo_read(ctx->dbconn, ctx->fd, (char *) c, count));
}
/**
- * initdb - Initialize the key database.
- *
- * This function should be called before any of the other functions in
- * this file are called in order to allow the DB to be initialized ready
- * for access.
+ * keydb_putchar - Puts a char to a file.
*/
-static void pg_initdb(bool readonly)
+static int keydb_putchar(void *_ctx, size_t count, void *c)
{
- dbconn = PQsetdbLogin(config.pg_dbhost, // host
- NULL, // port
- NULL, // options
- NULL, // tty
- config.pg_dbname, // database
- config.pg_dbuser, //login
- config.pg_dbpass); // password
-
- if (PQstatus(dbconn) == CONNECTION_BAD) {
- logthing(LOGTHING_CRITICAL, "Connection to database failed.");
- logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
- PQfinish(dbconn);
- dbconn = NULL;
- exit(1);
- }
-}
+ struct pg_fc_ctx *ctx = (struct pg_fc_ctx *) _ctx;
-/**
- * cleanupdb - De-initialize the key database.
- *
- * This function should be called upon program exit to allow the DB to
- * cleanup after itself.
- */
-static void pg_cleanupdb(void)
-{
- PQfinish(dbconn);
- dbconn = NULL;
+ return !(lo_write(ctx->dbconn, ctx->fd, (char *) c, count));
}
/**
@@ -105,8 +70,9 @@ static void pg_cleanupdb(void)
* operations on the database to help speed it all up, or if we want
* something to only succeed if all relevant operations are successful.
*/
-static bool pg_starttrans(void)
+static bool pg_starttrans(struct onak_dbctx *dbctx)
{
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
result = PQexec(dbconn, "BEGIN");
@@ -120,8 +86,9 @@ static bool pg_starttrans(void)
*
* Ends a transaction.
*/
-static void pg_endtrans(void)
+static void pg_endtrans(struct onak_dbctx *dbctx)
{
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
result = PQexec(dbconn, "COMMIT");
@@ -131,7 +98,7 @@ static void pg_endtrans(void)
}
/**
- * fetch_key - Given a keyid fetch the key from storage.
+ * fetch_key_id - Given a keyid fetch the key from storage.
* @keyid: The keyid to fetch.
* @publickey: A pointer to a structure to return the key in.
* @intrans: If we're already in a transaction.
@@ -142,17 +109,20 @@ static void pg_endtrans(void)
* in and then parse_keys() to parse the packets into a publickey
* structure.
*/
-static int pg_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+static int pg_fetch_key_id(struct onak_dbctx *dbctx,
+ uint64_t keyid,
+ struct openpgp_publickey **publickey,
bool intrans)
{
struct openpgp_packet_list *packets = NULL;
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char *oids = NULL;
char statement[1024];
- int fd = -1;
int i = 0;
int numkeys = 0;
Oid key_oid;
+ struct pg_fc_ctx fcctx;
if (!intrans) {
result = PQexec(dbconn, "BEGIN");
@@ -178,15 +148,16 @@ static int pg_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
oids = PQgetvalue(result, i, 0);
key_oid = (Oid) atoi(oids);
- fd = lo_open(dbconn, key_oid, INV_READ);
- if (fd < 0) {
+ fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+ if (fcctx.fd < 0) {
logthing(LOGTHING_ERROR,
"Can't open large object.");
} else {
- read_openpgp_stream(keydb_fetchchar, &fd,
+ fcctx.dbconn = dbconn;
+ read_openpgp_stream(keydb_fetchchar, &fcctx,
&packets, 0);
parse_keys(packets, publickey);
- lo_close(dbconn, fd);
+ lo_close(dbconn, fcctx.fd);
free_packet_list(packets);
packets = NULL;
}
@@ -212,18 +183,20 @@ static int pg_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
* This function searches for the supplied text and returns the keys that
* contain it.
*/
-static int pg_fetch_key_text(const char *search,
+static int pg_fetch_key_text(struct onak_dbctx *dbctx,
+ const char *search,
struct openpgp_publickey **publickey)
{
struct openpgp_packet_list *packets = NULL;
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char *oids = NULL;
char statement[1024];
- int fd = -1;
int i = 0;
int numkeys = 0;
Oid key_oid;
char *newsearch = NULL;
+ struct pg_fc_ctx fcctx;
result = PQexec(dbconn, "BEGIN");
PQclear(result);
@@ -246,16 +219,17 @@ static int pg_fetch_key_text(const char *search,
oids = PQgetvalue(result, i, 0);
key_oid = (Oid) atoi(oids);
- fd = lo_open(dbconn, key_oid, INV_READ);
- if (fd < 0) {
+ fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+ if (fcctx.fd < 0) {
logthing(LOGTHING_ERROR,
"Can't open large object.");
} else {
- read_openpgp_stream(keydb_fetchchar, &fd,
+ fcctx.dbconn = dbconn;
+ read_openpgp_stream(keydb_fetchchar, &fcctx,
&packets,
0);
parse_keys(packets, publickey);
- lo_close(dbconn, fd);
+ lo_close(dbconn, fcctx.fd);
free_packet_list(packets);
packets = NULL;
}
@@ -273,25 +247,30 @@ static int pg_fetch_key_text(const char *search,
/**
* delete_key - Given a keyid delete the key from storage.
- * @keyid: The keyid to delete.
+ * @fp: The fingerprint of the key to delete.
* @intrans: If we're already in a transaction.
*
* This function deletes a public key from whatever storage mechanism we
* are using. Returns 0 if the key existed.
*/
-static int pg_delete_key(uint64_t keyid, bool intrans)
+static int pg_delete_key(struct onak_dbctx *dbctx,
+ struct openpgp_fingerprint *fp, bool intrans)
{
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char *oids = NULL;
char statement[1024];
int found = 1;
int i;
Oid key_oid;
+ uint64_t keyid;
if (!intrans) {
result = PQexec(dbconn, "BEGIN");
PQclear(result);
}
+
+ keyid = fingerprint2keyid(fp);
snprintf(statement, 1023,
"SELECT keydata FROM onak_keys WHERE keyid = '%"
@@ -354,27 +333,36 @@ static int pg_delete_key(uint64_t keyid, bool intrans)
* the file. If update is true then we delete the old key first, otherwise
* we trust that it doesn't exist.
*/
-static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
+static int pg_store_key(struct onak_dbctx *dbctx,
+ struct openpgp_publickey *publickey, bool intrans,
bool update)
{
struct openpgp_packet_list *packets = NULL;
struct openpgp_packet_list *list_end = NULL;
struct openpgp_publickey *next = NULL;
struct openpgp_signedpacket_list *curuid = NULL;
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char statement[1024];
Oid key_oid;
- int fd;
char **uids = NULL;
char *primary = NULL;
char *safeuid = NULL;
int i;
+ uint64_t keyid;
+ struct pg_fc_ctx fcctx;
+ struct openpgp_fingerprint fp;
if (!intrans) {
result = PQexec(dbconn, "BEGIN");
PQclear(result);
}
+ if (get_keyid(publickey, &keyid) != ONAK_E_OK) {
+ logthing(LOGTHING_ERROR, "Couldn't find key ID for key.");
+ return 0;
+ }
+
/*
* Delete the key if we already have it.
*
@@ -384,7 +372,8 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
* it definitely needs updated.
*/
if (update) {
- pg_delete_key(get_keyid(publickey), true);
+ get_fingerprint(publickey->publickey, &fp);
+ pg_delete_key(dbctx, &fp, true);
}
next = publickey->next;
@@ -396,9 +385,10 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
if (key_oid == 0) {
logthing(LOGTHING_ERROR, "Can't create key OID");
} else {
- fd = lo_open(dbconn, key_oid, INV_WRITE);
- write_openpgp_stream(keydb_putchar, &fd, packets);
- lo_close(dbconn, fd);
+ fcctx.fd = lo_open(dbconn, key_oid, INV_WRITE);
+ fcctx.dbconn = dbconn;
+ write_openpgp_stream(keydb_putchar, &fcctx, packets);
+ lo_close(dbconn, fcctx.fd);
}
free_packet_list(packets);
packets = NULL;
@@ -406,7 +396,7 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
snprintf(statement, 1023,
"INSERT INTO onak_keys (keyid, keydata) VALUES "
"('%" PRIX64 "', '%d')",
- get_keyid(publickey),
+ keyid,
key_oid);
result = PQexec(dbconn, statement);
@@ -429,7 +419,7 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
"INSERT INTO onak_uids "
"(keyid, uid, pri) "
"VALUES ('%" PRIX64 "', '%s', '%c')",
- get_keyid(publickey),
+ keyid,
safeuid,
(uids[i] == primary) ? 't' : 'f');
result = PQexec(dbconn, statement);
@@ -464,7 +454,7 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
"INSERT INTO onak_sigs (signer, signee) "
"VALUES ('%" PRIX64 "', '%" PRIX64 "')",
sig_keyid(packets->packet),
- get_keyid(publickey));
+ keyid);
result = PQexec(dbconn, statement);
PQclear(result);
}
@@ -482,8 +472,9 @@ static int pg_store_key(struct openpgp_publickey *publickey, bool intrans,
* keyid2uid - Takes a keyid and returns the primary UID for it.
* @keyid: The keyid to lookup.
*/
-static char *pg_keyid2uid(uint64_t keyid)
+static char *pg_keyid2uid(struct onak_dbctx *dbctx, uint64_t keyid)
{
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char statement[1024];
char *uid = NULL;
@@ -524,9 +515,11 @@ static char *pg_keyid2uid(uint64_t keyid)
* This function gets the list of signatures on a key. Used for key
* indexing and doing stats bits.
*/
-static struct ll *pg_getkeysigs(uint64_t keyid, bool *revoked)
+static struct ll *pg_getkeysigs(struct onak_dbctx *dbctx,
+ uint64_t keyid, bool *revoked)
{
struct ll *sigs = NULL;
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
uint64_t signer;
char statement[1024];
@@ -597,17 +590,19 @@ static struct ll *pg_getkeysigs(uint64_t keyid, bool *revoked)
*
* Returns the number of keys we iterated over.
*/
-static int pg_iterate_keys(void (*iterfunc)(void *ctx,
+static int pg_iterate_keys(struct onak_dbctx *dbctx,
+ void (*iterfunc)(void *ctx,
struct openpgp_publickey *key), void *ctx)
{
struct openpgp_packet_list *packets = NULL;
struct openpgp_publickey *key = NULL;
+ PGconn *dbconn = (PGconn *) dbctx->priv;
PGresult *result = NULL;
char *oids = NULL;
- int fd = -1;
int i = 0;
int numkeys = 0;
Oid key_oid;
+ struct pg_fc_ctx fcctx;
result = PQexec(dbconn, "SELECT keydata FROM onak_keys;");
@@ -617,15 +612,16 @@ static int pg_iterate_keys(void (*iterfunc)(void *ctx,
oids = PQgetvalue(result, i, 0);
key_oid = (Oid) atoi(oids);
- fd = lo_open(dbconn, key_oid, INV_READ);
- if (fd < 0) {
+ fcctx.fd = lo_open(dbconn, key_oid, INV_READ);
+ if (fcctx.fd < 0) {
logthing(LOGTHING_ERROR,
"Can't open large object.");
} else {
- read_openpgp_stream(keydb_fetchchar, &fd,
+ fcctx.dbconn = dbconn;
+ read_openpgp_stream(keydb_fetchchar, &fcctx,
&packets, 0);
parse_keys(packets, &key);
- lo_close(dbconn, fd);
+ lo_close(dbconn, fcctx.fd);
iterfunc(ctx, key);
@@ -647,23 +643,75 @@ static int pg_iterate_keys(void (*iterfunc)(void *ctx,
/*
* Include the basic keydb routines.
*/
-#define NEED_GETFULLKEYID 1
#define NEED_UPDATEKEYS 1
+#define NEED_GET_FP 1
#include "keydb.c"
-struct dbfuncs keydb_pg_funcs = {
- .initdb = pg_initdb,
- .cleanupdb = pg_cleanupdb,
- .starttrans = pg_starttrans,
- .endtrans = pg_endtrans,
- .fetch_key = pg_fetch_key,
- .fetch_key_text = pg_fetch_key_text,
- .store_key = pg_store_key,
- .update_keys = generic_update_keys,
- .delete_key = pg_delete_key,
- .getkeysigs = pg_getkeysigs,
- .cached_getkeysigs = generic_cached_getkeysigs,
- .keyid2uid = pg_keyid2uid,
- .getfullkeyid = generic_getfullkeyid,
- .iterate_keys = pg_iterate_keys,
-};
+/**
+ * cleanupdb - De-initialize the key database.
+ *
+ * This function should be called upon program exit to allow the DB to
+ * cleanup after itself.
+ */
+static void pg_cleanupdb(struct onak_dbctx *dbctx)
+{
+ PGconn *dbconn = (PGconn *) dbctx->priv;
+
+ PQfinish(dbconn);
+ dbconn = NULL;
+
+ free(dbctx);
+}
+
+/**
+ * initdb - Initialize the key database.
+ *
+ * This function should be called before any of the other functions in
+ * this file are called in order to allow the DB to be initialized ready
+ * for access.
+ */
+struct onak_dbctx *keydb_pg_init(struct onak_db_config *dbcfg, bool readonly)
+{
+ struct onak_dbctx *dbctx;
+ PGconn *dbconn;
+
+ dbctx = malloc(sizeof(struct onak_dbctx));
+ if (dbctx == NULL) {
+ return NULL;
+ }
+ dbctx->config = dbcfg;
+
+ dbconn = PQsetdbLogin(dbcfg->hostname, // host
+ NULL, // port
+ NULL, // options
+ NULL, // tty
+ dbcfg->location, // database
+ dbcfg->username, //login
+ dbcfg->password); // password
+
+ if (PQstatus(dbconn) == CONNECTION_BAD) {
+ logthing(LOGTHING_CRITICAL, "Connection to database failed.");
+ logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
+ PQfinish(dbconn);
+ dbconn = NULL;
+ exit(1);
+ }
+
+ dbctx->priv = dbconn;
+
+ dbctx->cleanupdb = pg_cleanupdb;
+ dbctx->starttrans = pg_starttrans;
+ dbctx->endtrans = pg_endtrans;
+ dbctx->fetch_key_id = pg_fetch_key_id;
+ dbctx->fetch_key_fp = generic_fetch_key_fp;
+ dbctx->fetch_key_text = pg_fetch_key_text;
+ dbctx->store_key = pg_store_key;
+ dbctx->update_keys = generic_update_keys;
+ dbctx->delete_key = pg_delete_key;
+ dbctx->getkeysigs = pg_getkeysigs;
+ dbctx->cached_getkeysigs = generic_cached_getkeysigs;
+ dbctx->keyid2uid = pg_keyid2uid;
+ dbctx->iterate_keys = pg_iterate_keys;
+
+ return dbctx;
+}