diff options
-rw-r--r-- | lib/auth_cert.h | 5 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 4 | ||||
-rw-r--r-- | lib/gnutls_int.h | 4 | ||||
-rw-r--r-- | lib/gnutls_openpgp.c | 39 | ||||
-rw-r--r-- | lib/opencdk/keydb.c | 384 | ||||
-rw-r--r-- | lib/opencdk/keydb.h | 48 | ||||
-rw-r--r-- | lib/opencdk/opencdk.h | 2 | ||||
-rw-r--r-- | lib/opencdk/stream.c | 37 | ||||
-rw-r--r-- | lib/openpgp/compat.c | 33 | ||||
-rw-r--r-- | lib/openpgp/extras.c | 234 | ||||
-rw-r--r-- | lib/openpgp/openpgp.h | 1 |
11 files changed, 364 insertions, 427 deletions
diff --git a/lib/auth_cert.h b/lib/auth_cert.h index d2db7ab158..7d9381a8cb 100644 --- a/lib/auth_cert.h +++ b/lib/auth_cert.h @@ -64,12 +64,7 @@ typedef struct gnutls_certificate_credentials_st /* OpenPGP specific stuff */ -#ifndef KEYRING_HACK gnutls_openpgp_keyring_t keyring; -#else - gnutls_datum_t keyring; - int keyring_format; -#endif /* X509 specific stuff */ diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 669deb33cc..dad38ad1c9 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -194,12 +194,8 @@ gnutls_certificate_free_credentials (gnutls_certificate_credentials_t sc) #endif #ifdef ENABLE_OPENPGP -#ifndef KEYRING_HACK if (_E_gnutls_openpgp_keyring_deinit) _E_gnutls_openpgp_keyring_deinit( sc->keyring); -#else - _gnutls_free_datum( &sc->keyring); -#endif #endif gnutls_free (sc); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index d8d94c706d..679e563d04 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -31,10 +31,6 @@ #include <gnutls/gnutls.h> #include <gnutls/extra.h> -/* FIXME: delete this once opencdk has reentrant keyring functions - */ -#define KEYRING_HACK - /* * They are not needed any more. You can simply enable * the gnutls_log callback to get error descriptions. diff --git a/lib/gnutls_openpgp.c b/lib/gnutls_openpgp.c index 7968eab4c9..3a5f3c034f 100644 --- a/lib/gnutls_openpgp.c +++ b/lib/gnutls_openpgp.c @@ -598,7 +598,6 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t c, const opaque * data, size_t dlen, gnutls_openpgp_crt_fmt_t format) { -#ifndef KEYRING_HACK cdk_stream_t inp; size_t count; uint8_t *buf; @@ -628,21 +627,6 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t } return 0; -#else - - c->keyring_format = format; - - c->keyring.data = gnutls_malloc( dlen+1); - if (c->keyring.data == NULL) - { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - memcpy(c->keyring.data, data, dlen); - c->keyring.data[dlen]=0; - c->keyring.size = dlen; - -#endif } /*- @@ -662,9 +646,6 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, opaque * key_fpr, int key_fpr_size) { int rc = 0; -#ifdef KEYRING_HACK - gnutls_openpgp_keyring_t kring; -#endif if (!ret || !cred || !key_fpr) { @@ -675,22 +656,8 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, if (key_fpr_size != 16 && key_fpr_size != 20) return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */ -#ifndef KEYRING_HACK rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr); -#else - rc = gnutls_openpgp_keyring_init( &kring); - if ( rc < 0) { - gnutls_assert(); - return rc; - } - - rc = gnutls_openpgp_keyring_import( kring, &cred->keyring, cred->keyring_format); - if ( rc < 0) { - gnutls_assert(); - gnutls_openpgp_keyring_deinit( kring); - return rc; - } -#endif + if (rc >= 0) /* key was found */ { rc = 0; @@ -714,9 +681,7 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret, } error: -#ifdef KEYRING_HACK - gnutls_openpgp_keyring_deinit( kring); -#endif + return rc; } diff --git a/lib/opencdk/keydb.c b/lib/opencdk/keydb.c index 4638ed3e5d..0a236ff753 100644 --- a/lib/opencdk/keydb.c +++ b/lib/opencdk/keydb.c @@ -38,69 +38,10 @@ #define KEYID_CMP(a, b) ((a[0]) == (b[0]) && (a[1]) == (b[1])) #define KEYDB_CACHE_ENTRIES 8 - -/* Internal key index structure. */ -struct key_idx_s -{ - off_t offset; - u32 keyid[2]; - byte fpr[KEY_FPR_LEN]; -}; -typedef struct key_idx_s *key_idx_t; - - -/* Internal handle for the search operation. */ -struct cdk_dbsearch_s -{ - union - { - char *pattern; /* A search is performed by pattern. */ - u32 keyid[2]; /* A search by keyid. */ - byte fpr[KEY_FPR_LEN]; /* A search by fingerprint. */ - } u; - int type; -}; -typedef struct cdk_dbsearch_s *cdk_dbsearch_t; - -/* Internal key cache to associate a key with an file offset. */ -struct key_table_s -{ - struct key_table_s *next; - off_t offset; - cdk_dbsearch_t desc; -}; -typedef struct key_table_s *key_table_t; - -/* Internal key database handle. */ -struct cdk_keydb_hd_s -{ - int type; /* type of the key db handle. */ - int fp_ref; /* 1=means it is a reference and shall not be closed. */ - cdk_stream_t fp; - cdk_stream_t idx; - cdk_dbsearch_t dbs; - char *name; /* name of the underlying file or NULL. */ - char *idx_name; /* name of the index file or NULL. */ - struct key_table_s *cache; - size_t ncache; - unsigned int secret:1; /* contain secret keys. */ - unsigned int isopen:1; /* the underlying stream is opened. */ - unsigned int no_cache:1; /* disable the index cache. */ - unsigned int search:1; /* handle is in search mode. */ - - /* structure to store some stats about the keydb. */ - struct { - size_t new_keys; /* amount of new keys that were imported. */ - } stats; -}; - - static void keydb_cache_free (key_table_t cache); -static int keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src); -static void keydb_search_free (cdk_dbsearch_t dbs); +static int keydb_search_copy (cdk_keydb_search_t *r_dst, cdk_keydb_search_t src); static int classify_data (const byte * buf, size_t len); static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk); - static char* keydb_idx_mkname (const char *file) @@ -198,14 +139,14 @@ keydb_idx_build (const char *file) * Rebuild the key index files for the given key database. **/ cdk_error_t -cdk_keydb_idx_rebuild (cdk_keydb_hd_t db) +cdk_keydb_idx_rebuild (cdk_keydb_hd_t db, cdk_keydb_search_t dbs) { struct stat stbuf; char *tmp_idx_name; cdk_error_t rc; int err; - if (!db || !db->name) + if (!db || !db->name|| !dbs) return CDK_Inv_Value; if (db->secret) return 0; @@ -220,17 +161,17 @@ cdk_keydb_idx_rebuild (cdk_keydb_hd_t db) if (err) return 0; - cdk_stream_close (db->idx); - db->idx = NULL; - if (!db->idx_name) + cdk_stream_close (dbs->idx); + dbs->idx = NULL; + if (!dbs->idx_name) { - db->idx_name = keydb_idx_mkname (db->name); - if (!db->idx_name) + dbs->idx_name = keydb_idx_mkname (db->name); + if (!dbs->idx_name) return CDK_Out_Of_Core; } rc = keydb_idx_build (db->name); if (!rc) - rc = cdk_stream_open (db->idx_name, &db->idx); + rc = cdk_stream_open (dbs->idx_name, &dbs->idx); return rc; } @@ -447,19 +388,9 @@ cdk_keydb_free (cdk_keydb_hd_t hd) hd->fp = NULL; } - if (hd->idx) - { - cdk_stream_close (hd->idx); - hd->idx = NULL; - } hd->isopen = 0; - hd->no_cache = 0; hd->secret = 0; - keydb_cache_free (hd->cache); - hd->cache = NULL; - keydb_search_free (hd->dbs); - hd->dbs = NULL; cdk_free (hd); } @@ -468,6 +399,7 @@ cdk_error_t _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr) { cdk_error_t rc, ec; + cdk_stream_t kr; if (!hd || !ret_kr) return CDK_Inv_Value; @@ -475,76 +407,33 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr) rc = 0; if ((hd->type == CDK_DBTYPE_DATA || hd->type == CDK_DBTYPE_STREAM) && hd->fp) - cdk_stream_seek (hd->fp, 0); + { + kr = hd->fp; + cdk_stream_seek (kr, 0); + } else if (hd->type == CDK_DBTYPE_PK_KEYRING || hd->type == CDK_DBTYPE_SK_KEYRING) { - if (!hd->isopen && hd->name) - { - rc = cdk_stream_open (hd->name, &hd->fp); - if (rc) - goto leave; - if (cdk_armor_filter_use (hd->fp)) - cdk_stream_set_armor_flag (hd->fp, 0); - hd->isopen = 1; - /* We disable the index cache for smaller keyrings. */ - if (cdk_stream_get_length (hd->fp) < 524288) - { - hd->no_cache = 1; - goto leave; - } - cdk_free (hd->idx_name); - hd->idx_name = keydb_idx_mkname (hd->name); - if (!hd->idx_name) - { - rc = CDK_Out_Of_Core; - goto leave; - } - ec = cdk_stream_open (hd->idx_name, &hd->idx); - if (ec && !hd->secret) - { - rc = keydb_idx_build (hd->name); - if (!rc) - rc = cdk_stream_open (hd->idx_name, &hd->idx); - if (!rc) - _cdk_log_debug ("create key index table\n"); - else - { - /* This is no real error, it just means we can't create - the index at the given directory. maybe we've no write - access. in this case, we simply disable the index. */ - _cdk_log_debug ("disable key index table err=%d\n", rc); - rc = 0; - hd->no_cache = 1; - } - } - } - else - { - /* We use the cache to search keys, so we always rewind the - STREAM. Except when the _NEXT search mode is used because - this mode is an enumeration and no seeking is needed. */ - if (!hd->search || - (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT)) - cdk_stream_seek (hd->fp, 0); - } + rc = cdk_stream_open (hd->name, &kr); + + if (rc) + goto leave; + + if (cdk_armor_filter_use (kr)) + cdk_stream_set_armor_flag (kr, 0); } else return CDK_Inv_Mode; leave: - if (rc) - { - cdk_stream_close (hd->fp); - hd->fp = NULL; - } - *ret_kr = hd->fp; + + *ret_kr = kr; return rc; } static int -find_by_keyid (cdk_kbnode_t knode, cdk_dbsearch_t ks) +find_by_keyid (cdk_kbnode_t knode, cdk_keydb_search_t ks) { cdk_kbnode_t node; u32 keyid[2]; @@ -580,7 +469,7 @@ find_by_keyid (cdk_kbnode_t knode, cdk_dbsearch_t ks) static int -find_by_fpr (cdk_kbnode_t knode, cdk_dbsearch_t ks) +find_by_fpr (cdk_kbnode_t knode, cdk_keydb_search_t ks) { cdk_kbnode_t node; byte fpr[KEY_FPR_LEN]; @@ -607,7 +496,7 @@ find_by_fpr (cdk_kbnode_t knode, cdk_dbsearch_t ks) static int -find_by_pattern (cdk_kbnode_t knode, cdk_dbsearch_t ks) +find_by_pattern (cdk_kbnode_t knode, cdk_keydb_search_t ks) { cdk_kbnode_t node; size_t uidlen; @@ -648,19 +537,6 @@ find_by_pattern (cdk_kbnode_t knode, cdk_dbsearch_t ks) static void -keydb_search_free (cdk_dbsearch_t dbs) -{ - if (!dbs) - return; - if (dbs->type == CDK_DBSEARCH_EXACT || - dbs->type == CDK_DBSEARCH_SUBSTR) - cdk_free (dbs->u.pattern); - dbs->type = 0; - cdk_free (dbs); -} - - -static void keydb_cache_free (key_table_t cache) { key_table_t c2; @@ -669,7 +545,6 @@ keydb_cache_free (key_table_t cache) { c2 = cache->next; cache->offset = 0; - keydb_search_free (cache->desc); cdk_free (cache); cache = c2; } @@ -677,35 +552,34 @@ keydb_cache_free (key_table_t cache) static key_table_t -keydb_cache_find (key_table_t cache, cdk_dbsearch_t desc) +keydb_cache_find ( cdk_keydb_search_t desc) { + key_table_t cache = desc->cache; key_table_t t; for (t = cache; t; t = t->next) { - if (t->desc->type != desc->type) - continue; - switch (t->desc->type) + switch (desc->type) { case CDK_DBSEARCH_SHORT_KEYID: case CDK_DBSEARCH_KEYID: - if (KEYID_CMP (t->desc->u.keyid, desc->u.keyid)) + if (KEYID_CMP (desc->u.keyid, desc->u.keyid)) return t; break; case CDK_DBSEARCH_EXACT: - if (strlen (t->desc->u.pattern) == strlen (desc->u.pattern) && - !strcmp (t->desc->u.pattern, desc->u.pattern)) + if (strlen (desc->u.pattern) == strlen (desc->u.pattern) && + !strcmp (desc->u.pattern, desc->u.pattern)) return t; break; case CDK_DBSEARCH_SUBSTR: - if (strstr (t->desc->u.pattern, desc->u.pattern)) + if (strstr (desc->u.pattern, desc->u.pattern)) return t; break; case CDK_DBSEARCH_FPR: - if (!memcmp (t->desc->u.fpr, desc->u.fpr, KEY_FPR_LEN)) + if (!memcmp (desc->u.fpr, desc->u.fpr, KEY_FPR_LEN)) return t; break; } @@ -716,32 +590,30 @@ keydb_cache_find (key_table_t cache, cdk_dbsearch_t desc) static cdk_error_t -keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, off_t offset) +keydb_cache_add ( cdk_keydb_search_t dbs, off_t offset) { key_table_t k; - if (!hd) - return CDK_Inv_Value; - - if (hd->ncache > KEYDB_CACHE_ENTRIES) + if (dbs->ncache > KEYDB_CACHE_ENTRIES) return 0; /* FIXME: we should replace the last entry. */ k = cdk_calloc (1, sizeof *k); if (!k) return CDK_Out_Of_Core; + k->offset = offset; - keydb_search_copy (&k->desc, dbs); - k->next = hd->cache; - hd->cache = k; - hd->ncache++; + + k->next = dbs->cache; + dbs->cache = k; + dbs->ncache++; _cdk_log_debug ("cache: add entry off=%d type=%d\n", offset, dbs->type); return 0; } static cdk_error_t -keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src) +keydb_search_copy (cdk_keydb_search_t *r_dst, cdk_keydb_search_t src) { - cdk_dbsearch_t dst; + cdk_keydb_search_t dst; if (!r_dst || !src) return CDK_Inv_Value; @@ -750,6 +622,8 @@ keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src) dst = cdk_calloc (1, sizeof *dst); if (!dst) return CDK_Out_Of_Core; + + dst->off = src->off; dst->type = src->type; switch (src->type) { @@ -774,6 +648,46 @@ keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src) return 0; } +static cdk_error_t idx_init( cdk_keydb_hd_t db, cdk_keydb_search_t dbs) +{ +cdk_error_t ec, rc = 0; + + if (cdk_stream_get_length (db->fp) < 524288) + { + dbs->no_cache = 1; + goto leave; + } + + dbs->idx_name = keydb_idx_mkname (db->name); + if (!dbs->idx_name) + { + rc = CDK_Out_Of_Core; + goto leave; + } + ec = cdk_stream_open (dbs->idx_name, &dbs->idx); + + if (ec && !db->secret) + { + rc = keydb_idx_build (db->name); + if (!rc) + rc = cdk_stream_open (dbs->idx_name, &dbs->idx); + if (!rc) + _cdk_log_debug ("create key index table\n"); + else + { + /* This is no real error, it just means we can't create + the index at the given directory. maybe we've no write + access. in this case, we simply disable the index. */ + _cdk_log_debug ("disable key index table err=%d\n", rc); + rc = 0; + dbs->no_cache = 1; + } + } + +leave: + + return rc; +} /** * cdk_keydb_search_start: @@ -787,10 +701,10 @@ keydb_search_copy (cdk_dbsearch_t *r_dst, cdk_dbsearch_t src) cdk_error_t cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, void *desc) { - cdk_dbsearch_t dbs; u32 *keyid; char *p, tmp[3]; int i; + cdk_error_t rc; if (!db) return CDK_Inv_Value; @@ -801,36 +715,40 @@ cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, voi if (!(*st)) return CDK_Out_Of_Core; - dbs = cdk_calloc (1, sizeof *dbs); - if (!dbs) - return CDK_Out_Of_Core; - dbs->type = type; + rc = idx_init( db, *st); + if (rc != CDK_Success) + { + free(*st); + return rc; + } + + (*st)->type = type; switch (type) { case CDK_DBSEARCH_EXACT: case CDK_DBSEARCH_SUBSTR: - cdk_free (dbs->u.pattern); - dbs->u.pattern = cdk_strdup (desc); - if (!dbs->u.pattern) + cdk_free ((*st)->u.pattern); + (*st)->u.pattern = cdk_strdup (desc); + if (!(*st)->u.pattern) { - cdk_free (dbs); + cdk_free (*st); return CDK_Out_Of_Core; } break; case CDK_DBSEARCH_SHORT_KEYID: keyid = desc; - dbs->u.keyid[1] = keyid[0]; + (*st)->u.keyid[1] = keyid[0]; break; case CDK_DBSEARCH_KEYID: keyid = desc; - dbs->u.keyid[0] = keyid[0]; - dbs->u.keyid[1] = keyid[1]; + (*st)->u.keyid[0] = keyid[0]; + (*st)->u.keyid[1] = keyid[1]; break; case CDK_DBSEARCH_FPR: - memcpy (dbs->u.fpr, desc, KEY_FPR_LEN); + memcpy ((*st)->u.fpr, desc, KEY_FPR_LEN); break; case CDK_DBSEARCH_NEXT: @@ -838,16 +756,16 @@ cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, voi case CDK_DBSEARCH_AUTO: /* Override the type with the actual db search type. */ - dbs->type = classify_data (desc, strlen (desc)); - switch (dbs->type) + (*st)->type = classify_data (desc, strlen (desc)); + switch ((*st)->type) { case CDK_DBSEARCH_SUBSTR: case CDK_DBSEARCH_EXACT: - cdk_free (dbs->u.pattern); - p = dbs->u.pattern = cdk_strdup (desc); + cdk_free ((*st)->u.pattern); + p = (*st)->u.pattern = cdk_strdup (desc); if (!p) { - cdk_free (dbs); + cdk_free (*st); return CDK_Out_Of_Core; } break; @@ -859,17 +777,17 @@ cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, voi p += 2; if (strlen (p) == 8) { - dbs->u.keyid[0] = 0; - dbs->u.keyid[1] = strtoul (p, NULL, 16); + (*st)->u.keyid[0] = 0; + (*st)->u.keyid[1] = strtoul (p, NULL, 16); } else if (strlen (p) == 16) { - dbs->u.keyid[0] = strtoul (p , NULL, 16); - dbs->u.keyid[1] = strtoul (p + 8, NULL, 16); + (*st)->u.keyid[0] = strtoul (p , NULL, 16); + (*st)->u.keyid[1] = strtoul (p + 8, NULL, 16); } else { /* Invalid key ID object. */ - cdk_free (dbs); + cdk_free (*st); return CDK_Inv_Mode; } break; @@ -878,7 +796,7 @@ cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, voi p = desc; if (strlen (p) != 2*KEY_FPR_LEN) { - cdk_free (dbs); + cdk_free (*st); return CDK_Inv_Mode; } for (i = 0; i < KEY_FPR_LEN; i++) @@ -886,26 +804,24 @@ cdk_keydb_search_start (cdk_keydb_search_t* st, cdk_keydb_hd_t db, int type, voi tmp[0] = p[2*i]; tmp[1] = p[2*i+1]; tmp[2] = 0x00; - dbs->u.fpr[i] = strtoul (tmp, NULL, 16); + (*st)->u.fpr[i] = strtoul (tmp, NULL, 16); } break; } break; default: - cdk_free (dbs); + cdk_free (*st); _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type); return CDK_Inv_Mode; } - keydb_search_free (db->dbs); - db->dbs = dbs; return 0; } static cdk_error_t -keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, +keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_keydb_search_t ks, int *r_cache_hit, off_t *r_off) { key_table_t c; @@ -917,7 +833,7 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, *r_cache_hit = 0; *r_off = 0; - c = keydb_cache_find (hd->cache, ks); + c = keydb_cache_find ( ks); if (c != NULL) { _cdk_log_debug ("cache: found entry in cache.\n"); @@ -927,21 +843,21 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, } /* No index cache available so we just return here. */ - if (!hd->idx) + if (!ks->idx) return 0; - if (hd->idx) + if (ks->idx) { if (ks->type == CDK_DBSEARCH_KEYID) { - if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, r_off)) + if (keydb_idx_search (ks->idx, ks->u.keyid, NULL, r_off)) return CDK_Error_No_Key; _cdk_log_debug ("cache: found keyid entry in idx table.\n"); *r_cache_hit = 1; } else if (ks->type == CDK_DBSEARCH_FPR) { - if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, r_off)) + if (keydb_idx_search (ks->idx, NULL, ks->u.fpr, r_off)) return CDK_Error_No_Key; _cdk_log_debug ("cache: found fpr entry in idx table.\n"); *r_cache_hit = 1; @@ -953,14 +869,24 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, void cdk_keydb_search_release( cdk_keydb_search_t st) { - free( st); + keydb_cache_free ( st->cache); + + if (st->idx) + cdk_stream_close (st->idx); + + if (!st) + return; + if (st->type == CDK_DBSEARCH_EXACT || + st->type == CDK_DBSEARCH_SUBSTR) + cdk_free (st->u.pattern); + + cdk_free (st); } /** * cdk_keydb_search: * @st: the search handle * @hd: the keydb object - * @ks: the keydb search object * @ret_key: kbnode object to store the key * * Search for a key in the given keyring. The search mode is handled @@ -971,7 +897,6 @@ cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, cdk_kbnode_t *ret_ke { cdk_stream_t kr; cdk_kbnode_t knode; - cdk_dbsearch_t ks; cdk_error_t rc = 0; off_t pos = 0, off = 0; int key_found = 0, cache_hit = 0; @@ -981,33 +906,34 @@ cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, cdk_kbnode_t *ret_ke *ret_key = NULL; kr = NULL; - hd->search = 1; + rc = _cdk_keydb_open (hd, &kr); if (rc) return rc; - if (!hd->no_cache) + if (!st->no_cache) { /* It is possible the index is not up-to-date and thus we do not find the requesed key. In this case, we reset cache hit and continue our normal search procedure. */ - rc = keydb_pos_from_cache (hd, hd->dbs, &cache_hit, &off); + rc = keydb_pos_from_cache (hd, st, &cache_hit, &off); if (rc) cache_hit = 0; } knode = NULL; - ks = hd->dbs; + while (!key_found && !rc) { - if (cache_hit && ks->type != CDK_DBSEARCH_NEXT) + if (cache_hit && st->type != CDK_DBSEARCH_NEXT) cdk_stream_seek (kr, off); - else if ( ks->type == CDK_DBSEARCH_NEXT) + else if ( st->type == CDK_DBSEARCH_NEXT) cdk_stream_seek (kr, st->off); pos = cdk_stream_tell (kr); rc = cdk_keydb_get_keyblock (kr, &knode); + if (rc) { if (rc == CDK_EOF) @@ -1016,20 +942,20 @@ cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, cdk_kbnode_t *ret_ke return rc; } - switch (ks->type) + switch (st->type) { case CDK_DBSEARCH_SHORT_KEYID: case CDK_DBSEARCH_KEYID: - key_found = find_by_keyid (knode, ks); + key_found = find_by_keyid (knode, st); break; case CDK_DBSEARCH_FPR: - key_found = find_by_fpr (knode, ks); + key_found = find_by_fpr (knode, st); break; case CDK_DBSEARCH_EXACT: case CDK_DBSEARCH_SUBSTR: - key_found = find_by_pattern (knode, ks); + key_found = find_by_pattern (knode, st); break; case CDK_DBSEARCH_NEXT: @@ -1040,8 +966,8 @@ cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, cdk_kbnode_t *ret_ke if (key_found) { - if (!keydb_cache_find (hd->cache, ks)) - keydb_cache_add (hd, ks, pos); + if (!keydb_cache_find ( st)) + keydb_cache_add ( st, pos); break; } @@ -1049,7 +975,6 @@ cdk_keydb_search (cdk_keydb_search_t st, cdk_keydb_hd_t hd, cdk_kbnode_t *ret_ke knode = NULL; } - hd->search = 0; if (key_found && rc == CDK_EOF) rc = 0; else if (rc == CDK_EOF && !key_found) @@ -1798,10 +1723,10 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode) u32 keyid[2], main_keyid[2]; off_t old_off; int key_seen, got_key; - + if (!inp || !r_knode) return CDK_Inv_Value; - + /* Reset all values. */ keyid[0] = keyid[1] = 0; main_keyid[0] = main_keyid[1] = 0; @@ -1812,7 +1737,7 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode) *r_knode = NULL; rc = CDK_EOF; while (!cdk_stream_eof (inp)) - { + { cdk_pkt_new (&pkt); old_off = cdk_stream_tell (inp); rc = cdk_pkt_read (inp, pkt); @@ -1828,6 +1753,7 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode) return rc; } } + if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || pkt->pkttype == CDK_PKT_SECRET_KEY || @@ -1882,7 +1808,7 @@ cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t *r_knode) else _cdk_kbnode_add (knode, node); } - + if (got_key) { keydb_merge_selfsig (knode, main_keyid); @@ -2118,8 +2044,6 @@ cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode) } cdk_stream_close (out); - if (!hd->no_cache) - cdk_keydb_idx_rebuild (hd); hd->stats.new_keys++; return 0; @@ -2160,13 +2084,13 @@ _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 *keyid, const char *id) check = 0; cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_KEYID, keyid); - if (unode && find_by_keyid (unode, hd->dbs)) + if (unode && find_by_keyid (unode, st)) check++; cdk_keydb_search_release( st); cdk_kbnode_release (unode); cdk_keydb_search_start (&st, hd, CDK_DBSEARCH_EXACT, (char *)id); - if (knode && find_by_pattern (knode, hd->dbs)) + if (knode && find_by_pattern (knode, st)) check++; cdk_keydb_search_release( st); cdk_kbnode_release (knode); @@ -2312,7 +2236,7 @@ cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key) else if (ctx->type) { cdk_kbnode_t node; - struct cdk_dbsearch_s ks; + struct cdk_keydb_search_s ks; cdk_error_t rc; for (;;) diff --git a/lib/opencdk/keydb.h b/lib/opencdk/keydb.h index 932a17b798..054d2c4a55 100644 --- a/lib/opencdk/keydb.h +++ b/lib/opencdk/keydb.h @@ -1,6 +1,52 @@ +/* Internal key index structure. */ +struct key_idx_s +{ + off_t offset; + u32 keyid[2]; + byte fpr[KEY_FPR_LEN]; +}; +typedef struct key_idx_s *key_idx_t; + +/* Internal key cache to associate a key with an file offset. */ +struct key_table_s +{ + struct key_table_s *next; + off_t offset; +}; +typedef struct key_table_s *key_table_t; typedef struct cdk_keydb_search_s { - off_t off; /* last file offset */ + off_t off; /* last file offset */ + union + { + char *pattern; /* A search is performed by pattern. */ + u32 keyid[2]; /* A search by keyid. */ + byte fpr[KEY_FPR_LEN]; /* A search by fingerprint. */ + } u; + int type; + struct key_table_s *cache; + size_t ncache; + unsigned int no_cache:1; /* disable the index cache. */ + + cdk_stream_t idx; + char *idx_name; /* name of the index file or NULL. */ + } cdk_keydb_search_s; +/* Internal key database handle. */ +struct cdk_keydb_hd_s +{ + int type; /* type of the key db handle. */ + int fp_ref; /* 1=means it is a reference and shall not be closed. */ + cdk_stream_t fp; + char *name; /* name of the underlying file or NULL. */ + unsigned int secret:1; /* contain secret keys. */ + unsigned int isopen:1; /* the underlying stream is opened. */ + + /* structure to store some stats about the keydb. */ + struct { + size_t new_keys; /* amount of new keys that were imported. */ + } stats; +}; + diff --git a/lib/opencdk/opencdk.h b/lib/opencdk/opencdk.h index b488bc9c50..43ed3252c0 100644 --- a/lib/opencdk/opencdk.h +++ b/lib/opencdk/opencdk.h @@ -996,7 +996,7 @@ cdk_error_t cdk_keydb_get_sk (cdk_keydb_hd_t khd, unsigned int * keyid, cdk_error_t cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * ret_key); /* Rebuild the key db index if possible. */ -cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd); +cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t db, cdk_keydb_search_t dbs); /* Export one or more keys from the given key db handle into the stream @OUT. The export is done by substring search and diff --git a/lib/opencdk/stream.c b/lib/opencdk/stream.c index 2e43b8bff4..0360c43146 100644 --- a/lib/opencdk/stream.c +++ b/lib/opencdk/stream.c @@ -43,6 +43,7 @@ static int stream_flush (cdk_stream_t s); static int stream_filter_write (cdk_stream_t s); static int stream_cache_flush (cdk_stream_t s, FILE *fp); +struct stream_filter_s* filter_add (cdk_stream_t s, filter_fnct_t fnc, int type); /* Customized tmpfile() version from misc.c */ FILE *my_tmpfile (void); @@ -146,7 +147,7 @@ cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa, * @file: The name of the new file * @ret_s: The new STREAM object * - * Create a new stream into into the given file. + * Create a new stream into the given file. **/ cdk_error_t cdk_stream_new (const char *file, cdk_stream_t *ret_s) @@ -185,7 +186,6 @@ cdk_stream_new (const char *file, cdk_stream_t *ret_s) return 0; } - /** * cdk_stream_create: * @file: the filename @@ -569,6 +569,21 @@ filter_search (cdk_stream_t s, filter_fnct_t fnc) return NULL; } +static inline +void set_opaque( struct stream_filter_s* f) +{ + switch (f->type) + { + case fARMOR : f->opaque = &f->u.afx; break; + case fCIPHER : f->opaque = &f->u.cfx; break; + case fLITERAL : f->opaque = &f->u.pfx; break; + case fCOMPRESS: f->opaque = &f->u.zfx; break; + case fHASH : f->opaque = &f->u.mfx; break; + case fTEXT : f->opaque = &f->u.tfx; break; + default : f->opaque = NULL; + } + +} struct stream_filter_s* filter_add (cdk_stream_t s, filter_fnct_t fnc, int type) @@ -588,21 +603,12 @@ filter_add (cdk_stream_t s, filter_fnct_t fnc, int type) f->flags.enabled = 1; f->tmp = NULL; f->type = type; - switch (type) - { - case fARMOR : f->opaque = &f->u.afx; break; - case fCIPHER : f->opaque = &f->u.cfx; break; - case fLITERAL : f->opaque = &f->u.pfx; break; - case fCOMPRESS: f->opaque = &f->u.zfx; break; - case fHASH : f->opaque = &f->u.mfx; break; - case fTEXT : f->opaque = &f->u.tfx; break; - default : f->opaque = NULL; - } - + + set_opaque(f); + return f; } - static int stream_get_mode (cdk_stream_t s) { @@ -866,11 +872,14 @@ cdk_stream_read (cdk_stream_t s, void *buf, size_t buflen) } s->flags.filtrated = 1; } + if (!buf && !buflen) return 0; + nread = fread (buf, 1, buflen, s->fp); if (!nread) nread = EOF; + if (feof (s->fp)) { s->error = 0; diff --git a/lib/openpgp/compat.c b/lib/openpgp/compat.c index c04d861ab7..7bcf38f147 100644 --- a/lib/openpgp/compat.c +++ b/lib/openpgp/compat.c @@ -70,7 +70,6 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, goto leave; } -#ifndef KEYRING_HACK if (cred->keyring != NULL) { ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify); @@ -80,33 +79,6 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, goto leave; } } -#else - { - gnutls_openpgp_keyring_t kring; - - ret = gnutls_openpgp_keyring_init( &kring); - if ( ret < 0) { - gnutls_assert(); - return ret; - } - - ret = gnutls_openpgp_keyring_import( kring, &cred->keyring, cred->keyring_format); - if ( ret < 0) { - gnutls_assert(); - gnutls_openpgp_keyring_deinit( kring); - return ret; - } - - ret = gnutls_openpgp_crt_verify_ring (key, kring, 0, &verify); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_keyring_deinit( kring); - return ret; - } - gnutls_openpgp_keyring_deinit( kring); - } -#endif /* Now try the self signature. */ ret = gnutls_openpgp_crt_verify_self (key, 0, &verify_self); @@ -118,15 +90,10 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, *status = verify_self | verify; -#ifndef KEYRING_HACK /* If we only checked the self signature. */ if (!cred->keyring) -#else - if (!cred->keyring.data || !cred->keyring.size) -#endif *status |= GNUTLS_CERT_SIGNER_NOT_FOUND; - ret = 0; leave: diff --git a/lib/openpgp/extras.c b/lib/openpgp/extras.c index d9a28f3c3c..2b99452007 100644 --- a/lib/openpgp/extras.c +++ b/lib/openpgp/extras.c @@ -48,7 +48,7 @@ gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring) *keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int)); if (*keyring) - return 0; /* success */ + return 0; /* success */ return GNUTLS_E_MEMORY_ERROR; } @@ -71,14 +71,6 @@ gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring) cdk_keydb_free (keyring->db); keyring->db = NULL; } - - /* In some cases the stream is also stored outside the keydb context - and we need to close it here then. */ - if (keyring->db_stream) - { - cdk_stream_close (keyring->db_stream); - keyring->db_stream = NULL; - } gnutls_free (keyring); } @@ -110,8 +102,8 @@ gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, cdk_pk_release (pk); return 0; } - - _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long)id[1]); + + _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long) id[1]); return GNUTLS_E_NO_CERTIFICATE_FOUND; } @@ -130,44 +122,88 @@ gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, **/ int gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring, - const gnutls_datum_t *data, + const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format) { cdk_error_t err; - cdk_stream_t input; - + cdk_stream_t input = NULL; + size_t raw_len = 0, i; + opaque *raw_data = NULL; + _gnutls_debug_log ("PGP: keyring import format '%s'\n", - format == GNUTLS_OPENPGP_FMT_RAW? "raw" : "base64"); - - if (format == GNUTLS_OPENPGP_FMT_RAW) + format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64"); + + /* Create a new stream from the given data, decode it, and import + * the raw database. This to avoid using opencdk streams which are + * not thread safe. + */ + if (format == GNUTLS_OPENPGP_FMT_BASE64) { - err = cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, - data->data, data->size); + err = cdk_stream_tmp_from_mem (data->data, data->size, &input); + if (!err) + err = cdk_stream_set_armor_flag (input, 0); if (err) - gnutls_assert (); - return _gnutls_map_cdk_rc (err); + { + gnutls_assert (); + err = _gnutls_map_cdk_rc (err); + goto error; + } + + raw_len = cdk_stream_get_length (input); + if (raw_len == 0) + { + gnutls_assert (); + err = GNUTLS_E_BASE64_DECODING_ERROR; + goto error; + } + + raw_data = gnutls_malloc (raw_len); + if (raw_data == NULL) + { + gnutls_assert (); + err = GNUTLS_E_MEMORY_ERROR; + goto error; + } + +#if 0 + i = 0; + do { + err = cdk_stream_getc( input); + if (err != EOF) raw_data[i++] = err; + } while( err != EOF); + + raw_len = i; +#else + ssize_t written=0; + do + { + err = cdk_stream_read (input, raw_data+written, raw_len-written); + + if (err > 0) written += err; + } + while( written < raw_len && err != EOF && err > 0); + + raw_len = written; +#endif + } - - /* Create a new stream from the given data, which means to - allocate a new stream and to write the data in the stream. - Then push the armor filter to decode the data and to store - it in the raw format. */ - err = cdk_stream_tmp_from_mem (data->data, data->size, &input); - if (!err) - err = cdk_stream_set_armor_flag (input, 0); - if (!err) - err = cdk_keydb_new_from_stream (&keyring->db, 0, input); - if (err) - { - cdk_stream_close (input); - gnutls_assert (); + else + { /* RAW */ + raw_len = data->size; + raw_data = data->data; } - else - /* The keydb function will not close the stream itself, so we need to - store it separately to close it later. */ - keyring->db_stream = input; - + + err = cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, raw_data, raw_len); + if (err) + gnutls_assert (); + return _gnutls_map_cdk_rc (err); + +error: + gnutls_free (raw_data); + cdk_stream_close (input); + + return err; } #define knode_is_pkey(node) \ @@ -190,31 +226,33 @@ gnutls_openpgp_keyring_get_crt_count (gnutls_openpgp_keyring_t ring) cdk_error_t err; cdk_keydb_search_t st; int ret = 0; - - err = cdk_keydb_search_start( &st, ring->db, CDK_DBSEARCH_NEXT, NULL); - if (err != CDK_Success) + + err = cdk_keydb_search_start (&st, ring->db, CDK_DBSEARCH_NEXT, NULL); + if (err != CDK_Success) { - gnutls_assert(); - return _gnutls_map_cdk_rc(err); + gnutls_assert (); + return _gnutls_map_cdk_rc (err); + } + + do + { + err = cdk_keydb_search (st, ring->db, &knode); + if (err != CDK_Error_No_Key && err != CDK_Success) + { + gnutls_assert (); + cdk_keydb_search_release (st); + return _gnutls_map_cdk_rc (err); + } + + if (knode_is_pkey (knode)) + ret++; + + cdk_kbnode_release (knode); + } + while (err != CDK_Error_No_Key); - do { - err = cdk_keydb_search( st, ring->db, &knode); - if (err != CDK_Error_No_Key && err != CDK_Success) - { - gnutls_assert(); - cdk_keydb_search_release(st); - return _gnutls_map_cdk_rc(err); - } - - if (knode_is_pkey( knode)) - ret++; - - cdk_kbnode_release(knode); - - } while( err != CDK_Error_No_Key); - - cdk_keydb_search_release(st); + cdk_keydb_search_release (st); return ret; } @@ -232,47 +270,49 @@ gnutls_openpgp_keyring_get_crt_count (gnutls_openpgp_keyring_t ring) * **/ int -gnutls_openpgp_keyring_get_crt (gnutls_openpgp_keyring_t ring, unsigned int idx, - gnutls_openpgp_crt_t* cert) +gnutls_openpgp_keyring_get_crt (gnutls_openpgp_keyring_t ring, + unsigned int idx, + gnutls_openpgp_crt_t * cert) { cdk_kbnode_t knode; cdk_error_t err; - int ret = 0; + int ret = 0, count = 0; cdk_keydb_search_t st; - err = cdk_keydb_search_start( &st, ring->db, CDK_DBSEARCH_NEXT, NULL); - if (err != CDK_Success) + err = cdk_keydb_search_start (&st, ring->db, CDK_DBSEARCH_NEXT, NULL); + if (err != CDK_Success) { - gnutls_assert(); - return _gnutls_map_cdk_rc(err); + gnutls_assert (); + return _gnutls_map_cdk_rc (err); } - - do { - err = cdk_keydb_search( st, ring->db, &knode); - if (err != CDK_EOF && err != CDK_Success) - { - gnutls_assert(); - cdk_keydb_search_release(st); - return _gnutls_map_cdk_rc(err); - } - - if (idx == ret) - { - ret = gnutls_openpgp_crt_init( cert); - if (ret == 0) - (*cert)->knode = knode; - cdk_keydb_search_release(st); - return ret; - } - - if (knode_is_pkey( knode)) - ret++; - - cdk_kbnode_release(knode); - - } while( err != CDK_EOF); - - cdk_keydb_search_release(st); + + do + { + err = cdk_keydb_search (st, ring->db, &knode); + if (err != CDK_EOF && err != CDK_Success) + { + gnutls_assert (); + cdk_keydb_search_release (st); + return _gnutls_map_cdk_rc (err); + } + + if (idx == count && err == CDK_Success) + { + ret = gnutls_openpgp_crt_init (cert); + if (ret == 0) + (*cert)->knode = knode; + cdk_keydb_search_release (st); + return ret; + } + + if (knode_is_pkey (knode)) + count++; + + cdk_kbnode_release (knode); + + } + while (err != CDK_EOF); + + cdk_keydb_search_release (st); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - diff --git a/lib/openpgp/openpgp.h b/lib/openpgp/openpgp.h index 9eacadfd10..7548dafe73 100644 --- a/lib/openpgp/openpgp.h +++ b/lib/openpgp/openpgp.h @@ -30,7 +30,6 @@ typedef struct gnutls_openpgp_privkey_int typedef struct gnutls_openpgp_keyring_int { cdk_keydb_hd_t db; - cdk_stream_t db_stream; } gnutls_openpgp_keyring_int; int _gnutls_map_cdk_rc (int rc); |