*
* Jonathan McDowell <noodles@earth.li>
*
- * Copyright 2002 Project Purple
+ * Copyright 2002-2004 Project Purple
*/
#include <postgresql/libpq-fe.h>
#include <postgresql/libpq/libpq-fs.h>
-//#include <libpq-fe.h>
-//#include <libpq/libpq-fs.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include "hash.h"
#include "keydb.h"
#include "keyid.h"
-#include "keyindex.h"
+#include "decodekey.h"
#include "keystructs.h"
+#include "log.h"
#include "mem.h"
#include "onak-conf.h"
#include "parsekey.h"
*/
static int keydb_fetchchar(void *fd, size_t count, unsigned char *c)
{
- return (!lo_read(dbconn, *(int *) fd, c, count));
+ return (!lo_read(dbconn, *(int *) fd, (char *) c, count));
}
/**
*/
static int keydb_putchar(void *fd, size_t count, unsigned char *c)
{
- return !(lo_write(dbconn, *(int *) fd, c, count));
+ return !(lo_write(dbconn, *(int *) fd, (char *) c, count));
}
/**
* this file are called in order to allow the DB to be initialized ready
* for access.
*/
-void initdb(void)
+void initdb(bool readonly)
{
dbconn = PQsetdbLogin(config.pg_dbhost, // host
NULL, // port
config.pg_dbpass); // password
if (PQstatus(dbconn) == CONNECTION_BAD) {
- fprintf(stderr, "Connection to database failed.\n");
- fprintf(stderr, "%s\n", PQerrorMessage(dbconn));
+ logthing(LOGTHING_CRITICAL, "Connection to database failed.");
+ logthing(LOGTHING_CRITICAL, "%s", PQerrorMessage(dbconn));
PQfinish(dbconn);
dbconn = NULL;
exit(1);
* in and then parse_keys() to parse the packets into a publickey
* structure.
*/
-int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, bool intrans)
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+ bool intrans)
{
struct openpgp_packet_list *packets = NULL;
PGresult *result = NULL;
fd = lo_open(dbconn, key_oid, INV_READ);
if (fd < 0) {
- fprintf(stderr, "Can't open large object.\n");
+ logthing(LOGTHING_ERROR,
+ "Can't open large object.");
} else {
read_openpgp_stream(keydb_fetchchar, &fd,
- &packets);
+ &packets, 0);
parse_keys(packets, publickey);
lo_close(dbconn, fd);
+ free_packet_list(packets);
+ packets = NULL;
}
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
fd = lo_open(dbconn, key_oid, INV_READ);
if (fd < 0) {
- fprintf(stderr, "Can't open large object.\n");
+ logthing(LOGTHING_ERROR,
+ "Can't open large object.");
} else {
read_openpgp_stream(keydb_fetchchar, &fd,
- &packets);
+ &packets,
+ 0);
parse_keys(packets, publickey);
lo_close(dbconn, fd);
+ free_packet_list(packets);
+ packets = NULL;
}
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
key_oid = lo_creat(dbconn, INV_READ | INV_WRITE);
if (key_oid == 0) {
- fprintf(stderr, "Can't create key OID\n");
+ 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);
}
+ free_packet_list(packets);
+ packets = NULL;
snprintf(statement, 1023,
"INSERT INTO onak_keys (keyid, keydata) VALUES "
result = PQexec(dbconn, statement);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
- fprintf(stderr, "Problem storing key in DB.\n");
- fprintf(stderr, "%s\n", PQresultErrorMessage(result));
+ logthing(LOGTHING_ERROR, "Problem storing key in DB.");
+ logthing(LOGTHING_ERROR, "%s", PQresultErrorMessage(result));
}
PQclear(result);
}
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
- fprintf(stderr, "Problem storing key in DB.\n");
- fprintf(stderr, "%s\n",
+ logthing(LOGTHING_ERROR,
+ "Problem storing key in DB.");
+ logthing(LOGTHING_ERROR, "%s",
PQresultErrorMessage(result));
}
/*
keyid);
result = PQexec(dbconn, statement);
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
+ logthing(LOGTHING_ERROR,
+ "Problem retrieving key (%llX) from DB.",
keyid);
}
PQntuples(result) >= 1) {
uid = strdup(PQgetvalue(result, 0, 0));
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key (%llX) from DB.\n",
+ logthing(LOGTHING_ERROR,
+ "Problem retrieving key (%llX) from DB.",
keyid);
}
/**
* getkeysigs - Gets a linked list of the signatures on a key.
* @keyid: The keyid to get the sigs for.
+ * @revoked: If the key is revoked.
*
* This function gets the list of signatures on a key. Used for key
* indexing and doing stats bits.
*/
-struct ll *getkeysigs(uint64_t keyid)
+struct ll *getkeysigs(uint64_t keyid, bool *revoked)
{
struct ll *sigs = NULL;
PGresult *result = NULL;
uint64_t signer;
char statement[1024];
- int i = 0;
+ int i, j;
int numsigs = 0;
bool intrans = false;
+ char *str;
if (!intrans) {
result = PQexec(dbconn, "BEGIN");
}
snprintf(statement, 1023,
- "SELECT signer FROM onak_sigs WHERE signee = '%llX'",
+ "SELECT DISTINCT signer FROM onak_sigs WHERE signee = '%llX'",
keyid);
result = PQexec(dbconn, statement);
if (PQresultStatus(result) == PGRES_TUPLES_OK) {
numsigs = PQntuples(result);
for (i = 0; i < numsigs; i++) {
- signer = strtol(PQgetvalue(result, i, 0), NULL, 16);
+ j = 0;
+ signer = 0;
+ str = PQgetvalue(result, i, 0);
+ while (str[j] != 0) {
+ signer <<= 4;
+ if (str[j] >= '0' && str[j] <= '9') {
+ signer += str[j] - '0';
+ } else {
+ signer += str[j] - 'A' + 10;
+ }
+ j++;
+ }
sigs = lladd(sigs, createandaddtohash(signer));
}
} else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
- fprintf(stderr, "Problem retrieving key from DB.\n");
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
}
PQclear(result);
result = PQexec(dbconn, "COMMIT");
PQclear(result);
}
+
+ /*
+ * TODO: What do we do about revocations? We don't have the details
+ * stored in a separate table, so we'd have to grab the key and decode
+ * it, which we're trying to avoid by having a signers table.
+ */
+ if (revoked != NULL) {
+ *revoked = false;
+ }
+
return sigs;
}
+/**
+ * dumpdb - dump the key database
+ * @filenamebase: The base filename to use for the dump.
+ *
+ * Dumps the database into one or more files, which contain pure OpenPGP
+ * that can be reimported into onak or gpg. filenamebase provides a base
+ * file name for the dump; several files may be created, all of which will
+ * begin with this string and then have a unique number and a .pgp
+ * extension.
+ * */
+int dumpdb(char *filenamebase)
+{
+ return 0;
+}
+
+/**
+ * iterate_keys - call a function once for each key in the db.
+ * @iterfunc: The function to call.
+ * @ctx: A context pointer
+ *
+ * Calls iterfunc once for each key in the database. ctx is passed
+ * unaltered to iterfunc. This function is intended to aid database dumps
+ * and statistic calculations.
+ *
+ * Returns the number of keys we iterated over.
+ */
+int iterate_keys(void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+ void *ctx)
+{
+ struct openpgp_packet_list *packets = NULL;
+ struct openpgp_publickey *key = NULL;
+ PGresult *result = NULL;
+ char *oids = NULL;
+ char statement[1024];
+ int fd = -1;
+ int i = 0;
+ int numkeys = 0;
+ Oid key_oid;
+
+ result = PQexec(dbconn, "SELECT keydata FROM onak_keys;");
+
+ if (PQresultStatus(result) == PGRES_TUPLES_OK) {
+ numkeys = PQntuples(result);
+ for (i = 0; i < numkeys; i++) {
+ oids = PQgetvalue(result, i, 0);
+ key_oid = (Oid) atoi(oids);
+
+ fd = lo_open(dbconn, key_oid, INV_READ);
+ if (fd < 0) {
+ logthing(LOGTHING_ERROR,
+ "Can't open large object.");
+ } else {
+ read_openpgp_stream(keydb_fetchchar, &fd,
+ &packets, 0);
+ parse_keys(packets, key);
+ lo_close(dbconn, fd);
+
+ iterfunc(ctx, key);
+
+ free_publickey(key);
+ key = NULL;
+ free_packet_list(packets);
+ packets = NULL;
+ }
+ }
+ } else if (PQresultStatus(result) != PGRES_TUPLES_OK) {
+ logthing(LOGTHING_ERROR, "Problem retrieving key from DB.");
+ }
+
+ PQclear(result);
+
+ return (numkeys);
+}
+
/*
* Include the basic keydb routines.
*/
#define NEED_GETFULLKEYID 1
+#define NEED_UPDATEKEYS 1
#include "keydb.c"