1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-07-03 02:58:57 +02:00

Generic keyserver API code

This commit is contained in:
David Shaw 2001-12-06 21:43:04 +00:00
parent 4b01e2a943
commit b7a4656965
9 changed files with 460 additions and 195 deletions

View File

@ -86,7 +86,9 @@ gpg_SOURCES = g10.c \
delkey.c \ delkey.c \
keygen.c \ keygen.c \
pipemode.c \ pipemode.c \
helptext.c helptext.c \
keyserver.c \
keyserver-internal.h
gpgv_SOURCES = gpgv.c \ gpgv_SOURCES = gpgv.c \
$(common_source) \ $(common_source) \

View File

@ -48,7 +48,7 @@
#include "i18n.h" #include "i18n.h"
#include "status.h" #include "status.h"
#include "g10defs.h" #include "g10defs.h"
#include "hkp.h" #include "keyserver-internal.h"
enum cmd_and_opt_values { aNull = 0, enum cmd_and_opt_values { aNull = 0,
oArmor = 'a', oArmor = 'a',
@ -92,6 +92,7 @@ enum cmd_and_opt_values { aNull = 0,
aListSecretKeys, aListSecretKeys,
aSendKeys, aSendKeys,
aRecvKeys, aRecvKeys,
aSearchKeys,
aExport, aExport,
aExportAll, aExportAll,
aExportSecret, aExportSecret,
@ -193,6 +194,8 @@ enum cmd_and_opt_values { aNull = 0,
oLockMultiple, oLockMultiple,
oLockNever, oLockNever,
oKeyServer, oKeyServer,
oKeyServerOptions,
oTempDir,
oEncryptTo, oEncryptTo,
oNoEncryptTo, oNoEncryptTo,
oLoggerFD, oLoggerFD,
@ -218,6 +221,7 @@ enum cmd_and_opt_values { aNull = 0,
oShowSessionKey, oShowSessionKey,
oOverrideSessionKey, oOverrideSessionKey,
oNoRandomSeedFile, oNoRandomSeedFile,
oAutoKeyRetrieve,
oNoAutoKeyRetrieve, oNoAutoKeyRetrieve,
oUseAgent, oUseAgent,
oMergeOnly, oMergeOnly,
@ -265,6 +269,8 @@ static ARGPARSE_OPTS opts[] = {
{ aExport, "export" , 256, N_("export keys") }, { aExport, "export" , 256, N_("export keys") },
{ aSendKeys, "send-keys" , 256, N_("export keys to a key server") }, { aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
{ aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") }, { aRecvKeys, "recv-keys" , 256, N_("import keys from a key server") },
{ aSearchKeys, "search-keys" , 256,
N_("search for keys on a key server") },
{ aRefreshKeys, "refresh-keys", 256, { aRefreshKeys, "refresh-keys", 256,
N_("update all keys from a keyserver")}, N_("update all keys from a keyserver")},
{ aExportAll, "export-all" , 256, "@" }, { aExportAll, "export-all" , 256, "@" },
@ -301,6 +307,7 @@ static ARGPARSE_OPTS opts[] = {
{ oDefRecipientSelf, "default-recipient-self" ,0, { oDefRecipientSelf, "default-recipient-self" ,0,
N_("use the default key as default recipient")}, N_("use the default key as default recipient")},
{ oNoDefRecipient, "no-default-recipient", 0, "@" }, { oNoDefRecipient, "no-default-recipient", 0, "@" },
{ oTempDir, "temp-directory", 2, "@" },
{ oEncryptTo, "encrypt-to", 2, "@" }, { oEncryptTo, "encrypt-to", 2, "@" },
{ oNoEncryptTo, "no-encrypt-to", 0, "@" }, { oNoEncryptTo, "no-encrypt-to", 0, "@" },
{ oUser, "local-user",2, N_("use this user-id to sign or decrypt")}, { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
@ -326,6 +333,7 @@ static ARGPARSE_OPTS opts[] = {
{ oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")}, { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
{ oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")}, { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
{ oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")}, { oKeyServer, "keyserver",2, N_("|HOST|use this keyserver to lookup keys")},
{ oKeyServerOptions, "keyserver-options",2,"@"},
{ oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") }, { oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
{ oOptions, "options" , 2, N_("read options from file")}, { oOptions, "options" , 2, N_("read options from file")},
@ -437,6 +445,7 @@ static ARGPARSE_OPTS opts[] = {
{ oShowSessionKey, "show-session-key", 0, "@" }, { oShowSessionKey, "show-session-key", 0, "@" },
{ oOverrideSessionKey, "override-session-key", 2, "@" }, { oOverrideSessionKey, "override-session-key", 2, "@" },
{ oNoRandomSeedFile, "no-random-seed-file", 0, "@" }, { oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
{ oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" },
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" }, { oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
{ oNoSigCache, "no-sig-cache", 0, "@" }, { oNoSigCache, "no-sig-cache", 0, "@" },
{ oNoSigCreateCheck, "no-sig-create-check", 0, "@" }, { oNoSigCreateCheck, "no-sig-create-check", 0, "@" },
@ -707,7 +716,6 @@ main( int argc, char **argv )
opt.marginals_needed = 3; opt.marginals_needed = 3;
opt.max_cert_depth = 5; opt.max_cert_depth = 5;
opt.pgp2_workarounds = 1; opt.pgp2_workarounds = 1;
opt.auto_key_retrieve = 1;
#ifdef __MINGW32__ #ifdef __MINGW32__
opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" ); opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
#else #else
@ -811,6 +819,7 @@ main( int argc, char **argv )
case aFastImport: set_cmd( &cmd, aFastImport); break; case aFastImport: set_cmd( &cmd, aFastImport); break;
case aSendKeys: set_cmd( &cmd, aSendKeys); break; case aSendKeys: set_cmd( &cmd, aSendKeys); break;
case aRecvKeys: set_cmd( &cmd, aRecvKeys); break; case aRecvKeys: set_cmd( &cmd, aRecvKeys); break;
case aSearchKeys: set_cmd( &cmd, aSearchKeys); break;
case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break; case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break;
case aExport: set_cmd( &cmd, aExport); break; case aExport: set_cmd( &cmd, aExport); break;
case aExportAll: set_cmd( &cmd, aExportAll); break; case aExportAll: set_cmd( &cmd, aExportAll); break;
@ -1061,8 +1070,14 @@ main( int argc, char **argv )
not_implemented("lock-multiple"); not_implemented("lock-multiple");
#endif /* __riscos__ */ #endif /* __riscos__ */
break; break;
case oKeyServer:
case oKeyServer: opt.keyserver_name = pargs.r.ret_str; break; if(parse_keyserver_uri(pargs.r.ret_str))
log_error(_("Could not parse keyserver URI\n"));
break;
case oKeyServerOptions:
parse_keyserver_options(pargs.r.ret_str);
break;
case oTempDir: opt.temp_dir=pargs.r.ret_str; break;
case oNotation: add_notation_data( pargs.r.ret_str ); break; case oNotation: add_notation_data( pargs.r.ret_str ); break;
case oUtf8Strings: utf8_strings = 1; break; case oUtf8Strings: utf8_strings = 1; break;
case oNoUtf8Strings: utf8_strings = 0; break; case oNoUtf8Strings: utf8_strings = 0; break;
@ -1078,7 +1093,11 @@ main( int argc, char **argv )
case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
case oNoLiteral: opt.no_literal = 1; break; case oNoLiteral: opt.no_literal = 1; break;
case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
case oHonorHttpProxy: opt.honor_http_proxy = 1; break; case oHonorHttpProxy:
opt.honor_http_proxy = 1;
log_info("WARNING: --honor-http-proxy is deprecated.\n");
log_info("Please use \"--keyserver-options honor-http-proxy\" instead\n");
break;
case oFastListMode: opt.fast_list_mode = 1; break; case oFastListMode: opt.fast_list_mode = 1; break;
case oFixedListMode: opt.fixed_list_mode = 1; break; case oFixedListMode: opt.fixed_list_mode = 1; break;
case oListOnly: opt.list_only=1; break; case oListOnly: opt.list_only=1; break;
@ -1086,6 +1105,7 @@ main( int argc, char **argv )
case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; case oIgnoreValidFrom: opt.ignore_valid_from = 1; break;
case oIgnoreCrcError: opt.ignore_crc_error = 1; break; case oIgnoreCrcError: opt.ignore_crc_error = 1; break;
case oNoRandomSeedFile: use_random_seed = 0; break; case oNoRandomSeedFile: use_random_seed = 0; break;
case oAutoKeyRetrieve: opt.auto_key_retrieve = 1; break;
case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break; case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break;
case oShowSessionKey: opt.show_session_key = 1; break; case oShowSessionKey: opt.show_session_key = 1; break;
case oOverrideSessionKey: case oOverrideSessionKey:
@ -1519,19 +1539,30 @@ main( int argc, char **argv )
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
if( cmd == aSendKeys ) if( cmd == aSendKeys )
hkp_export( sl ); keyserver_export( sl );
else if( cmd == aRecvKeys ) else if( cmd == aRecvKeys )
hkp_import( sl ); keyserver_import( sl );
else else
export_pubkeys( sl, (cmd == aExport) ); export_pubkeys( sl, (cmd == aExport) );
free_strlist(sl); free_strlist(sl);
break; break;
case aSearchKeys:
sl = NULL;
for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings );
keyserver_search( sl );
free_strlist(sl);
break;
case aRefreshKeys: case aRefreshKeys:
if (argc) sl = NULL;
wrong_args("--refresh-keys"); for( ; argc; argc--, argv++ )
hkp_refresh_keys (); add_to_strlist2( &sl, *argv, utf8_strings );
break; keyserver_refresh(sl);
free_strlist(sl);
break;
case aExportSecret: case aExportSecret:
sl = NULL; sl = NULL;
@ -1995,3 +2026,22 @@ check_policy_url( const char *s )
return 0; return 0;
} }
const char *get_temp_dir(void)
{
char *tmp;
if(opt.temp_dir)
return opt.temp_dir;
if((tmp=getenv("TMPDIR")))
return tmp;
if((tmp=getenv("TMP")))
return tmp;
#ifdef __riscos__
return "<Wimp$ScrapDir>";
#else
return "/tmp";
#endif
}

View File

@ -48,7 +48,6 @@
#include "i18n.h" #include "i18n.h"
#include "status.h" #include "status.h"
#include "g10defs.h" #include "g10defs.h"
#include "hkp.h"
enum cmd_and_opt_values { aNull = 0, enum cmd_and_opt_values { aNull = 0,
@ -247,7 +246,7 @@ get_ownertrust_info (PKT_public_key *pk)
* get them from a keyserver * get them from a keyserver
*/ */
int int
hkp_ask_import( u32 *keyid, void *dummy ) keyserver_import_keyid( u32 *keyid, void *dummy )
{ {
return -1; return -1;
} }

471
g10/hkp.c
View File

@ -34,6 +34,7 @@
#include "filter.h" #include "filter.h"
#include "http.h" #include "http.h"
#include "main.h" #include "main.h"
#include "keyserver-internal.h"
static int urlencode_filter( void *opaque, int control, static int urlencode_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len); IOBUF a, byte *buf, size_t *ret_len);
@ -54,30 +55,28 @@ hkp_ask_import( u32 *keyid, void *stats_handle)
int rc; int rc;
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0; unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name ) log_info(_("requesting key %08lX from HKP keyserver %s\n"),
return -1; (ulong)keyid[1],opt.keyserver_host );
log_info(_("requesting key %08lX from %s ...\n"), (ulong)keyid[1], request = m_alloc( strlen( opt.keyserver_host ) + 100 );
opt.keyserver_name );
request = m_alloc( strlen( opt.keyserver_name ) + 100 );
/* hkp does not accept the long keyid - we should really write a /* hkp does not accept the long keyid - we should really write a
* nicer one :-) * nicer one :-)
* FIXME: request binary mode - need to pass no_armor mode * FIXME: request binary mode - need to pass no_armor mode
* down to the import function. Marc told that there is such a * down to the import function. Marc told that there is such a
* binary mode ... how? * binary mode ... how?
*/ */
if ( !strncmp (opt.keyserver_name, "x-broken-hkp://", 15) ) {
sprintf( request, "x-hkp://%s/pks/lookup?op=get&search=0x%08lX", if(strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
opt.keyserver_name+15, (ulong)keyid[1] ); hflags |= HTTP_FLAG_NO_SHUTDOWN;
hflags |= HTTP_FLAG_NO_SHUTDOWN;
} sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=get&search=0x%08lX",
else if ( !strncmp (opt.keyserver_name, "x-hkp://", 8) ) { opt.keyserver_host,
sprintf( request, "%s/pks/lookup?op=get&search=0x%08lX", atoi(opt.keyserver_port)>0?":":"",
opt.keyserver_name, (ulong)keyid[1] ); atoi(opt.keyserver_port)>0?opt.keyserver_port:"",
} (ulong)keyid[1] );
else {
sprintf( request, "x-hkp://%s/pks/lookup?op=get&search=0x%08lX", if(opt.keyserver_options.verbose>2)
opt.keyserver_name, (ulong)keyid[1] ); log_info("Request is \"%s\"\n",request);
}
rc = http_open_document( &hd, request, hflags ); rc = http_open_document( &hd, request, hflags );
if( rc ) { if( rc ) {
log_info(_("can't get key from keyserver: %s\n"), log_info(_("can't get key from keyserver: %s\n"),
@ -85,7 +84,8 @@ hkp_ask_import( u32 *keyid, void *stats_handle)
: g10_errstr(rc) ); : g10_errstr(rc) );
} }
else { else {
rc = import_keys_stream( hd.fp_read , 0, stats_handle ); rc = import_keys_stream( hd.fp_read,
opt.keyserver_options.fast_import,stats_handle);
http_close( &hd ); http_close( &hd );
} }
@ -93,41 +93,6 @@ hkp_ask_import( u32 *keyid, void *stats_handle)
return rc; return rc;
} }
int
hkp_import( STRLIST users )
{
void *stats_handle;
if( !opt.keyserver_name ) {
log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
stats_handle = import_new_stats_handle ();
for( ; users; users = users->next ) {
KEYDB_SEARCH_DESC desc;
classify_user_id (users->d, &desc);
if( desc.mode != KEYDB_SEARCH_MODE_SHORT_KID
&& desc.mode != KEYDB_SEARCH_MODE_LONG_KID ) {
log_error (_("%s: not a valid key ID\n"), users->d );
continue;
}
/* because the function may use log_info in some situations, the
* errorcounter ist not increaed and the program will return
* with success - which is not good when this function is used.
*/
if( hkp_ask_import( desc.u.kid, stats_handle ) )
log_inc_errorcount();
}
import_print_stats (stats_handle);
import_release_stats_handle (stats_handle);
return 0;
}
int int
hkp_export( STRLIST users ) hkp_export( STRLIST users )
{ {
@ -139,11 +104,6 @@ hkp_export( STRLIST users )
unsigned int status; unsigned int status;
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0; unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
if( !opt.keyserver_name ) {
log_error(_("no keyserver known (use option --keyserver)\n"));
return -1;
}
iobuf_push_filter( temp, urlencode_filter, NULL ); iobuf_push_filter( temp, urlencode_filter, NULL );
memset( &afx, 0, sizeof afx); memset( &afx, 0, sizeof afx);
@ -158,21 +118,23 @@ hkp_export( STRLIST users )
iobuf_flush_temp( temp ); iobuf_flush_temp( temp );
request = m_alloc( strlen( opt.keyserver_name ) + 100 ); request = m_alloc( strlen( opt.keyserver_host ) + 100 );
if ( !strncmp (opt.keyserver_name, "x-broken-hkp://", 15) ) {
sprintf( request, "x-hkp://%s/pks/add", opt.keyserver_name+15 ); if(strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
hflags |= HTTP_FLAG_NO_SHUTDOWN; hflags |= HTTP_FLAG_NO_SHUTDOWN;
}
else if ( !strncmp (opt.keyserver_name, "x-hkp://", 8) ) { sprintf( request, "x-hkp://%s%s%s/pks/add",
sprintf( request, "%s/pks/add", opt.keyserver_name ); opt.keyserver_host,
} atoi(opt.keyserver_port)>0?":":"",
else { atoi(opt.keyserver_port)>0?opt.keyserver_port:"");
sprintf( request, "x-hkp://%s/pks/add", opt.keyserver_name );
} if(opt.keyserver_options.verbose>2)
log_info("Request is \"%s\"\n",request);
rc = http_open( &hd, HTTP_REQ_POST, request , hflags ); rc = http_open( &hd, HTTP_REQ_POST, request , hflags );
if( rc ) { if( rc ) {
log_error(_("can't connect to `%s': %s\n"), log_error(_("can't connect to `%s': %s\n"),
opt.keyserver_name, opt.keyserver_host,
rc == G10ERR_NETWORK? strerror(errno) rc == G10ERR_NETWORK? strerror(errno)
: g10_errstr(rc) ); : g10_errstr(rc) );
iobuf_close(temp); iobuf_close(temp);
@ -196,7 +158,7 @@ hkp_export( STRLIST users )
rc = http_wait_response( &hd, &status ); rc = http_wait_response( &hd, &status );
if( rc ) { if( rc ) {
log_error(_("error sending to `%s': %s\n"), log_error(_("error sending to `%s': %s\n"),
opt.keyserver_name, g10_errstr(rc) ); opt.keyserver_host, g10_errstr(rc) );
} }
else { else {
#if 1 #if 1
@ -208,10 +170,10 @@ hkp_export( STRLIST users )
#endif #endif
if( (status/100) == 2 ) if( (status/100) == 2 )
log_info(_("success sending to `%s' (status=%u)\n"), log_info(_("success sending to `%s' (status=%u)\n"),
opt.keyserver_name, status ); opt.keyserver_host, status );
else else
log_error(_("failed sending to `%s': status=%u\n"), log_error(_("failed sending to `%s': status=%u\n"),
opt.keyserver_name, status ); opt.keyserver_host, status );
} }
http_close( &hd ); http_close( &hd );
return rc; return rc;
@ -243,93 +205,294 @@ urlencode_filter( void *opaque, int control,
return rc; return rc;
} }
/* pub 2048/<a href="/pks/lookup?op=get&search=0x3CB3B415">3CB3B415</a> 1998/04/03 David M. Shaw &lt;<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw@jabberwocky.com</a>&gt; */
int /* Luckily enough, both the HKP server and NAI HKP interface to their
hkp_refresh_keys (void) LDAP server are close enough in output so the same function can
parse them both. */
static int parse_hkp_index(IOBUF buffer,char *line)
{ {
KEYDB_HANDLE hd; static int open=0,revoked=0;
KBNODE node, keyblock = NULL; static char *key,*uid;
PKT_public_key *pk; static u32 bits,createtime;
u32 keyid[2]; int ret=0;
u32 *keys = NULL;
size_t n, nkeys=0, maxkeys=0;
void *stats_handle;
int rc = 0;
/* fist take a snapshot of all keys */ /* printf("Open %d, LINE: %s\n",open,line); */
hd = keydb_new(0);
rc = keydb_search_first(hd); /* For multiple UIDs */
if (rc) { if(open && uid!=NULL)
if (rc != -1) {
log_error ("keydb_search_first failed: %s\n", g10_errstr(rc)); ret=0;
goto leave;
if(!(revoked && !opt.keyserver_options.include_revoked))
{
char intstr[11];
iobuf_writestr(buffer,key);
iobuf_writestr(buffer,":");
iobuf_writestr(buffer,uid);
iobuf_writestr(buffer,":");
iobuf_writestr(buffer,revoked?"1:":":");
sprintf(intstr,"%u",createtime);
iobuf_writestr(buffer,intstr);
iobuf_writestr(buffer,"::::");
sprintf(intstr,"%u",bits);
iobuf_writestr(buffer,intstr);
iobuf_writestr(buffer,"\n");
ret=1;
}
if(strncmp(line," ",5)!=0)
{
m_free(key);
m_free(uid);
uid=NULL;
open=0;
}
} }
do {
if (!keys) {
maxkeys = 10000;
keys = m_alloc (maxkeys * sizeof *keys);
nkeys = 0;
}
else if ( nkeys == maxkeys ) {
maxkeys += 10000;
keys = m_realloc (keys, maxkeys * sizeof *keys);
}
rc = keydb_get_keyblock (hd, &keyblock); if(strncasecmp(line,"pub ",5)==0)
if (rc) { {
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc)); char *tok,*temp;
goto leave;
}
node = keyblock; open=1;
if ( node->pkt->pkttype != PKT_PUBLIC_KEY) {
log_debug ("invalid pkttype %d encountered\n", line+=4;
node->pkt->pkttype);
dump_kbnode (node); tok=strsep(&line,"/");
release_kbnode(keyblock); if(tok==NULL)
continue; return ret;
}
pk = node->pkt->pkt.public_key; bits=atoi(tok);
keyid_from_pk(pk, keyid);
release_kbnode(keyblock); tok=strsep(&line,">");
keyblock = NULL; if(tok==NULL)
/* fixme: replace the linear search */ return ret;
for (n=0; n < nkeys; n++) {
if (keys[n] == keyid[1]) { tok=strsep(&line,"<");
log_info (_("duplicate (short) key ID %08lX\n"), if(tok==NULL)
(ulong)keyid[1]); return ret;
break;
} key=m_strdup(tok);
}
if (n == nkeys) /* not a duplicate */ tok=strsep(&line," ");
keys[nkeys++] = keyid[1]; if(tok==NULL)
} while ( !(rc = keydb_search_next(hd)) ); return ret;
if (rc == -1)
rc = 0; tok=strsep(&line," ");
if (rc) if(tok==NULL)
log_error ("keydb_search_next failed: %s\n", g10_errstr(rc)); return ret;
keydb_release(hd);
hd = NULL; /* The date parser wants '-' instead of '/', so... */
temp=tok;
/* and now refresh them */ while(*temp!='\0')
stats_handle = import_new_stats_handle (); {
log_info (_("%lu key(s) to refresh\n"), (ulong)nkeys); if(*temp=='/')
for (n=0; n < nkeys; n++) { *temp='-';
/* Note: We do only use the short keyID */
keyid[0] = 0; temp++;
keyid[1] = keys[n]; }
if ( hkp_ask_import(keyid, stats_handle) )
log_inc_errorcount(); createtime=scan_isodatestr(tok);
} }
import_print_stats (stats_handle);
import_release_stats_handle (stats_handle);
leave: if(open)
m_free (keys); {
if (keyblock) int uidindex=0;
release_kbnode(keyblock);
keydb_release(hd); /* All that's left is the user name. Strip off anything
return rc; <between brackets> and de-urlencode it. */
while(*line==' ' && *line!='\0')
line++;
if(strncmp(line,"*** KEY REVOKED ***",19)==0)
{
revoked=1;
return ret;
}
uid=m_alloc(strlen(line)+1);
while(*line!='\0')
{
switch(*line)
{
case '<':
while(*line!='>' && *line!='\0')
line++;
if(*line!='\0')
line++;
break;
case '&':
if((*(line+1)!='\0' && tolower(*(line+1))=='l') &&
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
(*(line+3)!='\0' && *(line+3)==';'))
{
uid[uidindex++]='<';
line+=4;
break;
}
if((*(line+1)!='\0' && tolower(*(line+1))=='g') &&
(*(line+2)!='\0' && tolower(*(line+2))=='t') &&
(*(line+3)!='\0' && *(line+3)==';'))
{
uid[uidindex++]='>';
line+=4;
break;
}
default:
uid[uidindex++]=*line;
line++;
break;
}
}
uid[uidindex]='\0';
/* Chop off the trailing \r, \n, or both. This is fussy as the
true HKP servers have \r\n, and the NAI HKP servers have just
\n. */
if(isspace(uid[uidindex-1]))
uid[uidindex-1]='\0';
if(isspace(uid[uidindex-2]))
uid[uidindex-2]='\0';
}
return ret;
} }
int hkp_search(STRLIST tokens)
{
int rc=0,len=0,first=1;
unsigned int maxlen=1024,buflen=0;
char *searchstr=NULL,*searchurl=NULL,*request;
struct http_context hd;
unsigned int hflags=opt.honor_http_proxy?HTTP_FLAG_TRY_PROXY:0;
byte *line=NULL;
/* Glue the tokens together to make a search string */
for(;tokens;tokens=tokens->next)
{
len+=strlen(tokens->d)+1;
searchstr=m_realloc(searchstr,len+1);
if(first)
{
searchstr[0]='\0';
first=0;
}
strcat(searchstr,tokens->d);
strcat(searchstr," ");
}
if(len<=1)
{
m_free(searchstr);
return 0;
}
searchstr[len-1]='\0';
log_info(_("searching for \"%s\" from HKP server %s\n"),
searchstr,opt.keyserver_host);
/* Now make it url-ish */
len=0;
request=searchstr;
while(*request!='\0')
{
if(isalnum(*request) || *request=='-')
{
searchurl=m_realloc(searchurl,len+1);
searchurl[len++]=*request;
}
else if(*request==' ')
{
searchurl=m_realloc(searchurl,len+1);
searchurl[len++]='+';
}
else
{
searchurl=m_realloc(searchurl,len+3);
sprintf(&searchurl[len],"%%%02X",*request);
len+=3;
}
request++;
}
searchurl=m_realloc(searchurl,len+1);
searchurl[len]='\0';
request=m_alloc(strlen(opt.keyserver_host) + 100 + strlen(searchurl));
if(strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
hflags |= HTTP_FLAG_NO_SHUTDOWN;
sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=index&search=%s",
opt.keyserver_host,
atoi(opt.keyserver_port)>0?":":"",
atoi(opt.keyserver_port)>0?opt.keyserver_port:"",
searchurl);
if(opt.keyserver_options.verbose>2)
log_info("Request is \"%s\"\n",request);
rc=http_open_document(&hd,request,hflags);
if(rc)
{
log_error(_("can't search keyserver: %s\n"),
rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
}
else
{
IOBUF buffer;
int count=1;
buffer=iobuf_temp();
rc=1;
while(rc!=0)
{
/* This is a judgement call. Is it better to slurp up all
the results before prompting the user? On the one hand,
it probably makes the keyserver happier to not be blocked
on sending for a long time while the user picks a key.
On the other hand, it might be nice for the server to be
able to stop sending before a large search result page is
complete. */
rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
if(rc!=0)
count+=parse_hkp_index(buffer,line);
}
http_close(&hd);
count--;
keyserver_search_prompt(buffer,count,searchstr);
iobuf_close(buffer);
m_free(line);
}
m_free(request);
m_free(searchurl);
m_free(searchstr);
return rc;
}

View File

@ -21,11 +21,9 @@
#ifndef G10_HKP_H #ifndef G10_HKP_H
#define G10_HKP_H 1 #define G10_HKP_H 1
int hkp_ask_import( u32 *keyid, void *stats_handle); int hkp_ask_import( u32 *keyid, void *stats_handle);
int hkp_import( STRLIST users ); int hkp_import( STRLIST users );
int hkp_export( STRLIST users ); int hkp_export( STRLIST users );
int hkp_refresh_keys (void); int hkp_search(STRLIST tokens);
#endif /*G10_HKP_H*/ #endif /*G10_HKP_H*/

View File

@ -48,6 +48,7 @@ extern int g10_errors_seen;
void print_pubkey_algo_note( int algo ); void print_pubkey_algo_note( int algo );
void print_cipher_algo_note( int algo ); void print_cipher_algo_note( int algo );
void print_digest_algo_note( int algo ); void print_digest_algo_note( int algo );
const char *get_temp_dir(void);
/*-- armor.c --*/ /*-- armor.c --*/
char *make_radix64_string( const byte *data, size_t len ); char *make_radix64_string( const byte *data, size_t len );

View File

@ -37,7 +37,7 @@
#include "status.h" #include "status.h"
#include "i18n.h" #include "i18n.h"
#include "trustdb.h" #include "trustdb.h"
#include "hkp.h" #include "keyserver-internal.h"
struct kidlist_item { struct kidlist_item {
@ -1254,8 +1254,8 @@ check_sig_and_print( CTX c, KBNODE node )
(int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] ); (int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] );
rc = do_check_sig(c, node, NULL ); rc = do_check_sig(c, node, NULL );
if( rc == G10ERR_NO_PUBKEY && opt.keyserver_name && opt.auto_key_retrieve) { if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.auto_key_retrieve) {
if( !hkp_ask_import( sig->keyid, NULL ) ) if( keyserver_import_keyid ( sig->keyid )==0 )
rc = do_check_sig(c, node, NULL ); rc = do_check_sig(c, node, NULL );
} }
if( !rc || rc == G10ERR_BAD_SIGN ) { if( !rc || rc == G10ERR_BAD_SIGN ) {

View File

@ -1,3 +1,4 @@
/* options.h /* options.h
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* *
@ -88,7 +89,20 @@ struct {
int not_dash_escaped; int not_dash_escaped;
int escape_from; int escape_from;
int lock_once; int lock_once;
const char *keyserver_name; char *keyserver_scheme;
char *keyserver_host;
char *keyserver_port;
struct
{
int verbose;
int fast_import:1;
int include_revoked:1;
int include_disabled:1;
int use_temp_files:1;
int keep_temp_files:1;
STRLIST other;
} keyserver_options;
char *temp_dir;
int no_encrypt_to; int no_encrypt_to;
int interactive; int interactive;
STRLIST notation_data; STRLIST notation_data;

View File

@ -91,29 +91,67 @@ lock-once
#load-extension rndunix #load-extension rndunix
#load-extension rndegd #load-extension rndegd
# GnuPG can send and receive keys to and from a keyserver. These
# GnuPG can import a key from a HKP keyerver if one is missing # servers can be HKP, email, or LDAP (if GnuPG is built with LDAP
# for certain operations. Is you set this option to a keyserver # support).
# you will be asked in such a case whether GnuPG should try to
# import the key from that server (server do syncronize with each
# other and DNS Round-Robin may give you a random server each time).
# Use "host -l pgp.net | grep www" to figure out a keyserver.
# #
# If you do not want to use the default port 11371, you can give the # Example HKP keyserver:
# name of the keyserver like this: # x-hkp://wwwkeys.nl.pgp.net
# x-hkp://keyserver.example.net:22742 #
# If you have problems connecting through a buggy proxy, you can use this: # Example email keyserver:
# x-broken-hkp://keyserver.example.net:11371 # mailto:pgp-public-keys@keys.nl.pgp.net
#
# Example LDAP keyserver:
# ldap://keyserver.pgp.com
#
# Regular URL syntax applies, and you can set an alternate port
# through the usual method:
# x-hkp://keyserver.example.net:22742
#
# If you have problems connecting to a HKP server through a buggy
# http proxy, you can use this:
# x-broken-hkp://keyserver.example.net
# But first you should make sure that you have read the man page regarding # But first you should make sure that you have read the man page regarding
# proxies (--honor-http-proxy) # proxies (honor-http-proxy)
# Most users just set the name of the preferred keyserver. #
#keyserver wwwkeys.nl.pgp.net # Most users just set the name and type of their preferred keyserver.
# Most servers do syncronize with each other and DNS round-robin may
# give you a quasi-random server each time.
#keyserver mailto:pgp-public-keys@keys.nl.pgp.net
#keyserver ldap://keyserver.pgp.com
#keyserver x-hkp://wwwkeys.nl.pgp.net
# Options for keyserver functions
#
# include-disabled = when searching, include keys marked as "disabled"
# on the keyserver (not all keyservers support this).
#
# include-revoked = when searching, include keys marked as "revoked"
# on the keyserver.
#
# verbose = show more information as the keys are fetched.
# Can be included more than once to increase the amount
# of information shown.
#
# use-temp-files = use temporary files instead of a pipe to talk to the
# keyserver. Some platforms (Win32 for one) always
# have this on.
#
# keep-temp-files = don't delete the temporary files after using them
# (really only useful for debugging)
#
# honor-http-proxy = if the keyserver uses http, honor the http_proxy
# environment variable
#keyserver-options include-disabled include-revoked
# Uncomment this line to automatically fetch a key from a keyserver
# (which must be set - see above) when verifying signatures.
#auto-key-retrieve
# The environment variable http_proxy is only used when the # The environment variable http_proxy is only used when the
# this option is set. # this option is set.
honor-http-proxy #honor-http-proxy