X-Git-Url: https://the.earth.li/gitweb/?a=blobdiff_plain;f=keydb_hkp.c;h=3ec46a4f2cf7b9e9bb40ca1e806961727fa40370;hb=85187675424f3854869f1607afd8a1e84e536946;hp=3fa15935196b4222d86075d86573942822435acd;hpb=c04c1c60469823c01268187ec49102d1ff540806;p=onak.git diff --git a/keydb_hkp.c b/keydb_hkp.c index 3fa1593..3ec46a4 100644 --- a/keydb_hkp.c +++ b/keydb_hkp.c @@ -13,16 +13,18 @@ * 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 +#include #include #include #include -#include #include +#include "build-config.h" + #include "armor.h" #include "charfuncs.h" #include "keydb.h" @@ -31,13 +33,14 @@ #include "mem.h" #include "onak-conf.h" #include "parsekey.h" -#include "version.h" - -static CURL *curl = NULL; -static char hkpbase[1024]; +struct onak_hkp_dbctx { + struct onak_db_config *config; /* Our DB config info */ + CURL *curl; + char hkpbase[512]; +}; -static int hkp_parse_url(const char *url) +static int hkp_parse_url(struct onak_hkp_dbctx *privctx, const char *url) { char proto[6], host[256]; unsigned int port; @@ -47,11 +50,11 @@ static int hkp_parse_url(const char *url) proto[0] = host[0] = 0; port = 0; - matched = sscanf(url, "%5[a-z]://%256[a-zA-Z0-9.]:%u", proto, host, + matched = sscanf(url, "%5[a-z]://%256[a-zA-Z0-9.-]:%u", proto, host, &port); if (matched < 2) { proto[0] = 0; - matched = sscanf(url, "%256[a-zA-Z0-9.]:%u", host, &port); + sscanf(url, "%256[a-zA-Z0-9.-]:%u", host, &port); } if (host[0] == 0) { @@ -65,13 +68,13 @@ static int hkp_parse_url(const char *url) if (port == 0) { port = 11371; } - snprintf(hkpbase, sizeof(hkpbase), + snprintf(privctx->hkpbase, sizeof(privctx->hkpbase), "http://%s:%u/pks", host, port); } else if (!strcmp(proto, "hkps")) { if (port == 0) { port = 11372; } - snprintf(hkpbase, sizeof(hkpbase), + snprintf(privctx->hkpbase, sizeof(privctx->hkpbase), "https://%s:%u/pks", host, port); } else if (strcmp(proto, "http") && strcmp(proto, "https")) { logthing(LOGTHING_CRITICAL, "Unknown HKP protocol: %s", @@ -79,10 +82,10 @@ static int hkp_parse_url(const char *url) ret = 0; goto out; } else if (port == 0) { - snprintf(hkpbase, sizeof(hkpbase), + snprintf(privctx->hkpbase, sizeof(privctx->hkpbase), "%s://%s/pks", proto, host); } else { - snprintf(hkpbase, sizeof(hkpbase), + snprintf(privctx->hkpbase, sizeof(privctx->hkpbase), "%s://%s:%u/pks", proto, host, port); } @@ -90,52 +93,6 @@ out: return ret; } -/** - * cleanupdb - De-initialize the key database. - * - * We cleanup CURL here. - */ -static void hkp_cleanupdb(void) -{ - if (curl) { - curl_easy_cleanup(curl); - curl = NULL; - } - curl_global_cleanup(); -} - -/** - * initdb - Initialize the key database. - * - * We initialize CURL here. - */ -static void hkp_initdb(bool readonly) -{ - curl_version_info_data *curl_info; - - if (!hkp_parse_url(config.db_dir)) { - exit(EXIT_FAILURE); - } - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - if (curl == NULL) { - logthing(LOGTHING_CRITICAL, "Could not initialize CURL."); - exit(EXIT_FAILURE); - } - curl_easy_setopt(curl, CURLOPT_USERAGENT, "onak/" ONAK_VERSION); - - if (strncmp(hkpbase, "https://", 8) == 0) { - curl_info = curl_version_info(CURLVERSION_NOW); - if (! (curl_info->features & CURL_VERSION_SSL)) { - logthing(LOGTHING_CRITICAL, - "CURL lacks SSL support; cannot use HKP url: %s", - hkpbase); - hkp_cleanupdb(); - exit(EXIT_FAILURE); - } - } -} - /** * Receive data from a CURL request and process it into a buffer context. */ @@ -147,10 +104,12 @@ static size_t hkp_curl_recv_data(void *buffer, size_t size, size_t nmemb, return (nmemb * size); } -static int hkp_fetch_key_url(char *url, +static int hkp_fetch_key_url(struct onak_dbctx *dbctx, + char *url, struct openpgp_publickey **publickey, bool intrans) { + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; struct openpgp_packet_list *packets = NULL; CURLcode res; struct buffer_ctx buf; @@ -160,11 +119,11 @@ static int hkp_fetch_key_url(char *url, buf.size = 8192; buf.buffer = malloc(8192); - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + curl_easy_setopt(privctx->curl, CURLOPT_URL, url); + curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION, hkp_curl_recv_data); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf); - res = curl_easy_perform(curl); + curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf); + res = curl_easy_perform(privctx->curl); if (res == 0) { buf.offset = 0; @@ -187,45 +146,49 @@ static int hkp_fetch_key_url(char *url, /** * hkp_fetch_key_id - Given a keyid fetch the key from HKP server. */ -static int hkp_fetch_key_id(uint64_t keyid, +static int hkp_fetch_key_id(struct onak_dbctx *dbctx, + uint64_t keyid, struct openpgp_publickey **publickey, bool intrans) { + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; char keyurl[1024]; snprintf(keyurl, sizeof(keyurl), "%s/lookup?op=get&search=0x%08" PRIX64, - hkpbase, keyid); + privctx->hkpbase, keyid); - return (hkp_fetch_key_url(keyurl, publickey, intrans)); + return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans)); } /** * hkp_fetch_key_fp - Given a fingerprint fetch the key from HKP server. */ -static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize, +static int hkp_fetch_key_fp(struct onak_dbctx *dbctx, + struct openpgp_fingerprint *fingerprint, struct openpgp_publickey **publickey, bool intrans) { + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; char keyurl[1024]; int i, ofs; - if (fpsize > MAX_FINGERPRINT_LEN) { + if (fingerprint->length > MAX_FINGERPRINT_LEN) { return 0; } ofs = snprintf(keyurl, sizeof(keyurl), - "%s/lookup?op=get&search=0x", hkpbase); + "%s/lookup?op=get&search=0x", privctx->hkpbase); - if ((ofs + fpsize * 2 + 1)> sizeof(keyurl)) { + if ((ofs + fingerprint->length * 2 + 1)> sizeof(keyurl)) { return 0; } - for (i = 0; i < fpsize; i++) { - ofs += sprintf(&keyurl[ofs], "%02X", fp[i]); + for (i = 0; i < fingerprint->length; i++) { + ofs += sprintf(&keyurl[ofs], "%02X", fingerprint->fp[i]); } - return (hkp_fetch_key_url(keyurl, publickey, intrans)); + return (hkp_fetch_key_url(dbctx, keyurl, publickey, intrans)); } /** @@ -238,16 +201,18 @@ static int hkp_fetch_key_fp(uint8_t *fp, size_t fpsize, * * TODO: Write for flat file access. Some sort of grep? */ -static int hkp_fetch_key_text(const char *search, +static int hkp_fetch_key_text(struct onak_dbctx *dbctx, + const char *search, struct openpgp_publickey **publickey) { + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; char keyurl[1024]; snprintf(keyurl, sizeof(keyurl), "%s/lookup?op=get&search=%s", - hkpbase, search); + privctx->hkpbase, search); - return (hkp_fetch_key_url(keyurl, publickey, false)); + return (hkp_fetch_key_url(dbctx, keyurl, publickey, false)); } /** @@ -257,9 +222,11 @@ static int hkp_fetch_key_text(const char *search, * @update: If true the key exists and should be updated. * */ -static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans, +static int hkp_store_key(struct onak_dbctx *dbctx, + struct openpgp_publickey *publickey, bool intrans, bool update) { + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; struct openpgp_packet_list *packets = NULL; struct openpgp_packet_list *list_end = NULL; char keyurl[1024]; @@ -274,18 +241,18 @@ static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans, flatten_publickey(publickey, &packets, &list_end); armor_openpgp_stream(buffer_putchar, &buf, packets); - addform = curl_easy_escape(curl, buf.buffer, buf.offset); + addform = curl_easy_escape(privctx->curl, buf.buffer, buf.offset); addform[7] = '='; - snprintf(keyurl, sizeof(keyurl), "%s/add", hkpbase); + snprintf(keyurl, sizeof(keyurl), "%s/add", privctx->hkpbase); - curl_easy_setopt(curl, CURLOPT_URL, keyurl); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, addform); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + curl_easy_setopt(privctx->curl, CURLOPT_URL, keyurl); + curl_easy_setopt(privctx->curl, CURLOPT_POSTFIELDS, addform); + curl_easy_setopt(privctx->curl, CURLOPT_WRITEFUNCTION, hkp_curl_recv_data); buf.offset = 0; - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf); - res = curl_easy_perform(curl); + curl_easy_setopt(privctx->curl, CURLOPT_WRITEDATA, &buf); + res = curl_easy_perform(privctx->curl); if (res != 0) { logthing(LOGTHING_ERROR, "Couldn't send key: %s (%d)", @@ -309,7 +276,8 @@ static int hkp_store_key(struct openpgp_publickey *publickey, bool intrans, * * No op for HKP. */ -static int hkp_delete_key(uint64_t keyid, bool intrans) +static int hkp_delete_key(struct onak_dbctx *dbctx, + uint64_t keyid, bool intrans) { return -1; } @@ -321,8 +289,9 @@ static int hkp_delete_key(uint64_t keyid, bool intrans) * * Not applicable for HKP backend. */ -static int hkp_iterate_keys(void (*iterfunc)(void *ctx, - struct openpgp_publickey *key), void *ctx) +static int hkp_iterate_keys(struct onak_dbctx *dbctx, + void (*iterfunc)(void *ctx, struct openpgp_publickey *key), + void *ctx) { return 0; } @@ -332,7 +301,7 @@ static int hkp_iterate_keys(void (*iterfunc)(void *ctx, * * This is just a no-op for HKP access. */ -static bool hkp_starttrans(void) +static bool hkp_starttrans(struct onak_dbctx *dbctx) { return true; } @@ -342,7 +311,7 @@ static bool hkp_starttrans(void) * * This is just a no-op for HKP access. */ -static void hkp_endtrans(void) +static void hkp_endtrans(struct onak_dbctx *dbctx) { return; } @@ -356,20 +325,84 @@ static void hkp_endtrans(void) #define NEED_UPDATEKEYS 1 #include "keydb.c" -struct dbfuncs keydb_hkp_funcs = { - .initdb = hkp_initdb, - .cleanupdb = hkp_cleanupdb, - .starttrans = hkp_starttrans, - .endtrans = hkp_endtrans, - .fetch_key_id = hkp_fetch_key_id, - .fetch_key_fp = hkp_fetch_key_fp, - .fetch_key_text = hkp_fetch_key_text, - .store_key = hkp_store_key, - .update_keys = generic_update_keys, - .delete_key = hkp_delete_key, - .getkeysigs = generic_getkeysigs, - .cached_getkeysigs = generic_cached_getkeysigs, - .keyid2uid = generic_keyid2uid, - .getfullkeyid = generic_getfullkeyid, - .iterate_keys = hkp_iterate_keys, -}; +/** + * cleanupdb - De-initialize the key database. + * + * We cleanup CURL here. + */ +static void hkp_cleanupdb(struct onak_dbctx *dbctx) +{ + struct onak_hkp_dbctx *privctx = (struct onak_hkp_dbctx *) dbctx->priv; + + if (privctx->curl) { + curl_easy_cleanup(privctx->curl); + privctx->curl = NULL; + } + curl_global_cleanup(); + free(privctx); + free(dbctx); +} + +/** + * initdb - Initialize the key database. + * + * We initialize CURL here. + */ +struct onak_dbctx *keydb_hkp_init(struct onak_db_config *dbcfg, bool readonly) +{ + struct onak_dbctx *dbctx; + struct onak_hkp_dbctx *privctx; + curl_version_info_data *curl_info; + + dbctx = malloc(sizeof(struct onak_dbctx)); + if (dbctx == NULL) { + return NULL; + } + + dbctx->config = dbcfg; + dbctx->priv = privctx = malloc(sizeof(*privctx)); + dbctx->cleanupdb = hkp_cleanupdb; + dbctx->starttrans = hkp_starttrans; + dbctx->endtrans = hkp_endtrans; + dbctx->fetch_key_id = hkp_fetch_key_id; + dbctx->fetch_key_fp = hkp_fetch_key_fp; + dbctx->fetch_key_text = hkp_fetch_key_text; + dbctx->store_key = hkp_store_key; + dbctx->update_keys = generic_update_keys; + dbctx->delete_key = hkp_delete_key; + dbctx->getkeysigs = generic_getkeysigs; + dbctx->cached_getkeysigs = generic_cached_getkeysigs; + dbctx->keyid2uid = generic_keyid2uid; + dbctx->getfullkeyid = generic_getfullkeyid; + dbctx->iterate_keys = hkp_iterate_keys; + + if (!hkp_parse_url(privctx, dbcfg->location)) { + exit(EXIT_FAILURE); + } + logthing(LOGTHING_INFO, "Using %s as HKP forwarding URL.", + privctx->hkpbase); + curl_global_init(CURL_GLOBAL_DEFAULT); + privctx->curl = curl_easy_init(); + if (privctx->curl == NULL) { + logthing(LOGTHING_CRITICAL, "Could not initialize CURL."); + hkp_cleanupdb(dbctx); + dbctx = NULL; + exit(EXIT_FAILURE); + } + curl_easy_setopt(privctx->curl, CURLOPT_USERAGENT, + "onak/" ONAK_VERSION); + + if (strncmp(privctx->hkpbase, "https://", 8) == 0) { + curl_info = curl_version_info(CURLVERSION_NOW); + if (! (curl_info->features & CURL_VERSION_SSL)) { + logthing(LOGTHING_CRITICAL, + "CURL lacks SSL support; cannot use HKP url: %s", + privctx->hkpbase); + hkp_cleanupdb(dbctx); + dbctx = NULL; + exit(EXIT_FAILURE); + } + } + + return dbctx; +}