aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g10/Makefile.am4
-rw-r--r--g10/g10.c72
-rw-r--r--g10/gpgv.c3
-rw-r--r--g10/hkp.c479
-rw-r--r--g10/hkp.h4
-rw-r--r--g10/main.h1
-rw-r--r--g10/mainproc.c6
-rw-r--r--g10/options.h16
-rw-r--r--g10/options.skel74
9 files changed, 462 insertions, 197 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 9828da796..7251cf645 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -86,7 +86,9 @@ gpg_SOURCES = g10.c \
delkey.c \
keygen.c \
pipemode.c \
- helptext.c
+ helptext.c \
+ keyserver.c \
+ keyserver-internal.h
gpgv_SOURCES = gpgv.c \
$(common_source) \
diff --git a/g10/g10.c b/g10/g10.c
index 95f53de74..f3588151d 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -48,7 +48,7 @@
#include "i18n.h"
#include "status.h"
#include "g10defs.h"
-#include "hkp.h"
+#include "keyserver-internal.h"
enum cmd_and_opt_values { aNull = 0,
oArmor = 'a',
@@ -92,6 +92,7 @@ enum cmd_and_opt_values { aNull = 0,
aListSecretKeys,
aSendKeys,
aRecvKeys,
+ aSearchKeys,
aExport,
aExportAll,
aExportSecret,
@@ -193,6 +194,8 @@ enum cmd_and_opt_values { aNull = 0,
oLockMultiple,
oLockNever,
oKeyServer,
+ oKeyServerOptions,
+ oTempDir,
oEncryptTo,
oNoEncryptTo,
oLoggerFD,
@@ -218,6 +221,7 @@ enum cmd_and_opt_values { aNull = 0,
oShowSessionKey,
oOverrideSessionKey,
oNoRandomSeedFile,
+ oAutoKeyRetrieve,
oNoAutoKeyRetrieve,
oUseAgent,
oMergeOnly,
@@ -265,6 +269,8 @@ static ARGPARSE_OPTS opts[] = {
{ aExport, "export" , 256, N_("export keys") },
{ aSendKeys, "send-keys" , 256, N_("export keys to 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,
N_("update all keys from a keyserver")},
{ aExportAll, "export-all" , 256, "@" },
@@ -301,6 +307,7 @@ static ARGPARSE_OPTS opts[] = {
{ oDefRecipientSelf, "default-recipient-self" ,0,
N_("use the default key as default recipient")},
{ oNoDefRecipient, "no-default-recipient", 0, "@" },
+ { oTempDir, "temp-directory", 2, "@" },
{ oEncryptTo, "encrypt-to", 2, "@" },
{ oNoEncryptTo, "no-encrypt-to", 0, "@" },
{ 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")},
{ oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
{ 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") },
{ oOptions, "options" , 2, N_("read options from file")},
@@ -437,6 +445,7 @@ static ARGPARSE_OPTS opts[] = {
{ oShowSessionKey, "show-session-key", 0, "@" },
{ oOverrideSessionKey, "override-session-key", 2, "@" },
{ oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
+ { oAutoKeyRetrieve, "auto-key-retrieve", 0, "@" },
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
{ oNoSigCache, "no-sig-cache", 0, "@" },
{ oNoSigCreateCheck, "no-sig-create-check", 0, "@" },
@@ -707,7 +716,6 @@ main( int argc, char **argv )
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
opt.pgp2_workarounds = 1;
- opt.auto_key_retrieve = 1;
#ifdef __MINGW32__
opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
#else
@@ -811,6 +819,7 @@ main( int argc, char **argv )
case aFastImport: set_cmd( &cmd, aFastImport); break;
case aSendKeys: set_cmd( &cmd, aSendKeys); break;
case aRecvKeys: set_cmd( &cmd, aRecvKeys); break;
+ case aSearchKeys: set_cmd( &cmd, aSearchKeys); break;
case aRefreshKeys: set_cmd( &cmd, aRefreshKeys); break;
case aExport: set_cmd( &cmd, aExport); break;
case aExportAll: set_cmd( &cmd, aExportAll); break;
@@ -1061,8 +1070,14 @@ main( int argc, char **argv )
not_implemented("lock-multiple");
#endif /* __riscos__ */
break;
-
- case oKeyServer: opt.keyserver_name = pargs.r.ret_str; break;
+ case oKeyServer:
+ 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 oUtf8Strings: utf8_strings = 1; 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 oNoLiteral: opt.no_literal = 1; 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 oFixedListMode: opt.fixed_list_mode = 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 oIgnoreCrcError: opt.ignore_crc_error = 1; 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 oShowSessionKey: opt.show_session_key = 1; break;
case oOverrideSessionKey:
@@ -1519,19 +1539,30 @@ main( int argc, char **argv )
for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings );
if( cmd == aSendKeys )
- hkp_export( sl );
+ keyserver_export( sl );
else if( cmd == aRecvKeys )
- hkp_import( sl );
+ keyserver_import( sl );
else
export_pubkeys( sl, (cmd == aExport) );
free_strlist(sl);
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:
- if (argc)
- wrong_args("--refresh-keys");
- hkp_refresh_keys ();
- break;
+ sl = NULL;
+ for( ; argc; argc--, argv++ )
+ add_to_strlist2( &sl, *argv, utf8_strings );
+ keyserver_refresh(sl);
+ free_strlist(sl);
+ break;
case aExportSecret:
sl = NULL;
@@ -1995,3 +2026,22 @@ check_policy_url( const char *s )
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
+}
diff --git a/g10/gpgv.c b/g10/gpgv.c
index d80cbd51f..b3076e706 100644
--- a/g10/gpgv.c
+++ b/g10/gpgv.c
@@ -48,7 +48,6 @@
#include "i18n.h"
#include "status.h"
#include "g10defs.h"
-#include "hkp.h"
enum cmd_and_opt_values { aNull = 0,
@@ -247,7 +246,7 @@ get_ownertrust_info (PKT_public_key *pk)
* get them from a keyserver
*/
int
-hkp_ask_import( u32 *keyid, void *dummy )
+keyserver_import_keyid( u32 *keyid, void *dummy )
{
return -1;
}
diff --git a/g10/hkp.c b/g10/hkp.c
index e15d76908..2586bdb5d 100644
--- a/g10/hkp.c
+++ b/g10/hkp.c
@@ -34,6 +34,7 @@
#include "filter.h"
#include "http.h"
#include "main.h"
+#include "keyserver-internal.h"
static int urlencode_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len);
@@ -54,30 +55,28 @@ hkp_ask_import( u32 *keyid, void *stats_handle)
int rc;
unsigned int hflags = opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY : 0;
- if( !opt.keyserver_name )
- return -1;
- log_info(_("requesting key %08lX from %s ...\n"), (ulong)keyid[1],
- opt.keyserver_name );
- request = m_alloc( strlen( opt.keyserver_name ) + 100 );
+ log_info(_("requesting key %08lX from HKP keyserver %s\n"),
+ (ulong)keyid[1],opt.keyserver_host );
+ request = m_alloc( strlen( opt.keyserver_host ) + 100 );
/* hkp does not accept the long keyid - we should really write a
* nicer one :-)
* FIXME: request binary mode - need to pass no_armor mode
* down to the import function. Marc told that there is such a
* binary mode ... how?
*/
- if ( !strncmp (opt.keyserver_name, "x-broken-hkp://", 15) ) {
- sprintf( request, "x-hkp://%s/pks/lookup?op=get&search=0x%08lX",
- opt.keyserver_name+15, (ulong)keyid[1] );
- hflags |= HTTP_FLAG_NO_SHUTDOWN;
- }
- else if ( !strncmp (opt.keyserver_name, "x-hkp://", 8) ) {
- sprintf( request, "%s/pks/lookup?op=get&search=0x%08lX",
- opt.keyserver_name, (ulong)keyid[1] );
- }
- else {
- sprintf( request, "x-hkp://%s/pks/lookup?op=get&search=0x%08lX",
- opt.keyserver_name, (ulong)keyid[1] );
- }
+
+ if(strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
+ hflags |= HTTP_FLAG_NO_SHUTDOWN;
+
+ sprintf(request,"x-hkp://%s%s%s/pks/lookup?op=get&search=0x%08lX",
+ opt.keyserver_host,
+ atoi(opt.keyserver_port)>0?":":"",
+ atoi(opt.keyserver_port)>0?opt.keyserver_port:"",
+ (ulong)keyid[1] );
+
+ if(opt.keyserver_options.verbose>2)
+ log_info("Request is \"%s\"\n",request);
+
rc = http_open_document( &hd, request, hflags );
if( rc ) {
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) );
}
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 );
}
@@ -93,41 +93,6 @@ hkp_ask_import( u32 *keyid, void *stats_handle)
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
hkp_export( STRLIST users )
{
@@ -139,11 +104,6 @@ hkp_export( STRLIST users )
unsigned int status;
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 );
memset( &afx, 0, sizeof afx);
@@ -158,21 +118,23 @@ hkp_export( STRLIST users )
iobuf_flush_temp( temp );
- request = m_alloc( strlen( opt.keyserver_name ) + 100 );
- if ( !strncmp (opt.keyserver_name, "x-broken-hkp://", 15) ) {
- sprintf( request, "x-hkp://%s/pks/add", opt.keyserver_name+15 );
- hflags |= HTTP_FLAG_NO_SHUTDOWN;
- }
- else if ( !strncmp (opt.keyserver_name, "x-hkp://", 8) ) {
- sprintf( request, "%s/pks/add", opt.keyserver_name );
- }
- else {
- sprintf( request, "x-hkp://%s/pks/add", opt.keyserver_name );
- }
+ request = m_alloc( strlen( opt.keyserver_host ) + 100 );
+
+ if(strcasecmp(opt.keyserver_scheme,"x-broken-hkp")==0)
+ hflags |= HTTP_FLAG_NO_SHUTDOWN;
+
+ sprintf( request, "x-hkp://%s%s%s/pks/add",
+ opt.keyserver_host,
+ atoi(opt.keyserver_port)>0?":":"",
+ atoi(opt.keyserver_port)>0?opt.keyserver_port:"");
+
+ if(opt.keyserver_options.verbose>2)
+ log_info("Request is \"%s\"\n",request);
+
rc = http_open( &hd, HTTP_REQ_POST, request , hflags );
if( rc ) {
log_error(_("can't connect to `%s': %s\n"),
- opt.keyserver_name,
+ opt.keyserver_host,
rc == G10ERR_NETWORK? strerror(errno)
: g10_errstr(rc) );
iobuf_close(temp);
@@ -196,7 +158,7 @@ hkp_export( STRLIST users )
rc = http_wait_response( &hd, &status );
if( rc ) {
log_error(_("error sending to `%s': %s\n"),
- opt.keyserver_name, g10_errstr(rc) );
+ opt.keyserver_host, g10_errstr(rc) );
}
else {
#if 1
@@ -208,10 +170,10 @@ hkp_export( STRLIST users )
#endif
if( (status/100) == 2 )
log_info(_("success sending to `%s' (status=%u)\n"),
- opt.keyserver_name, status );
+ opt.keyserver_host, status );
else
log_error(_("failed sending to `%s': status=%u\n"),
- opt.keyserver_name, status );
+ opt.keyserver_host, status );
}
http_close( &hd );
return rc;
@@ -243,93 +205,294 @@ urlencode_filter( void *opaque, int control,
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">[email protected]</a>&gt; */
-int
-hkp_refresh_keys (void)
+/* Luckily enough, both the HKP server and NAI HKP interface to their
+ 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;
- KBNODE node, keyblock = NULL;
- PKT_public_key *pk;
- u32 keyid[2];
- u32 *keys = NULL;
- size_t n, nkeys=0, maxkeys=0;
- void *stats_handle;
- int rc = 0;
-
- /* fist take a snapshot of all keys */
- hd = keydb_new(0);
- rc = keydb_search_first(hd);
- if (rc) {
- if (rc != -1)
- log_error ("keydb_search_first failed: %s\n", g10_errstr(rc));
- goto leave;
+ static int open=0,revoked=0;
+ static char *key,*uid;
+ static u32 bits,createtime;
+ int ret=0;
+
+ /* printf("Open %d, LINE: %s\n",open,line); */
+
+ /* For multiple UIDs */
+ if(open && uid!=NULL)
+ {
+ ret=0;
+
+ 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 (rc) {
- log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
- goto leave;
- }
-
- node = keyblock;
- if ( node->pkt->pkttype != PKT_PUBLIC_KEY) {
- log_debug ("invalid pkttype %d encountered\n",
- node->pkt->pkttype);
- dump_kbnode (node);
- release_kbnode(keyblock);
- continue;
- }
- pk = node->pkt->pkt.public_key;
- keyid_from_pk(pk, keyid);
- release_kbnode(keyblock);
- keyblock = NULL;
- /* fixme: replace the linear search */
- for (n=0; n < nkeys; n++) {
- if (keys[n] == keyid[1]) {
- log_info (_("duplicate (short) key ID %08lX\n"),
- (ulong)keyid[1]);
- break;
- }
- }
- if (n == nkeys) /* not a duplicate */
- keys[nkeys++] = keyid[1];
- } while ( !(rc = keydb_search_next(hd)) );
- if (rc == -1)
- rc = 0;
- if (rc)
- log_error ("keydb_search_next failed: %s\n", g10_errstr(rc));
- keydb_release(hd);
- hd = NULL;
-
- /* and now refresh them */
- stats_handle = import_new_stats_handle ();
- log_info (_("%lu key(s) to refresh\n"), (ulong)nkeys);
- for (n=0; n < nkeys; n++) {
- /* Note: We do only use the short keyID */
- keyid[0] = 0;
- keyid[1] = keys[n];
- if ( hkp_ask_import(keyid, stats_handle) )
- log_inc_errorcount();
+
+ if(strncasecmp(line,"pub ",5)==0)
+ {
+ char *tok,*temp;
+
+ open=1;
+
+ line+=4;
+
+ tok=strsep(&line,"/");
+ if(tok==NULL)
+ return ret;
+
+ bits=atoi(tok);
+
+ tok=strsep(&line,">");
+ if(tok==NULL)
+ return ret;
+
+ tok=strsep(&line,"<");
+ if(tok==NULL)
+ return ret;
+
+ key=m_strdup(tok);
+
+ tok=strsep(&line," ");
+ if(tok==NULL)
+ return ret;
+
+ tok=strsep(&line," ");
+ if(tok==NULL)
+ return ret;
+
+ /* The date parser wants '-' instead of '/', so... */
+ temp=tok;
+ while(*temp!='\0')
+ {
+ if(*temp=='/')
+ *temp='-';
+
+ temp++;
+ }
+
+ createtime=scan_isodatestr(tok);
}
- import_print_stats (stats_handle);
- import_release_stats_handle (stats_handle);
-
- leave:
- m_free (keys);
- if (keyblock)
- release_kbnode(keyblock);
- keydb_release(hd);
- return rc;
+
+ if(open)
+ {
+ int uidindex=0;
+
+ /* All that's left is the user name. Strip off anything
+ <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;
+}
diff --git a/g10/hkp.h b/g10/hkp.h
index 003f89965..9ff8511d2 100644
--- a/g10/hkp.h
+++ b/g10/hkp.h
@@ -21,11 +21,9 @@
#ifndef G10_HKP_H
#define G10_HKP_H 1
-
int hkp_ask_import( u32 *keyid, void *stats_handle);
int hkp_import( STRLIST users );
int hkp_export( STRLIST users );
-int hkp_refresh_keys (void);
-
+int hkp_search(STRLIST tokens);
#endif /*G10_HKP_H*/
diff --git a/g10/main.h b/g10/main.h
index 4ffe3b5da..92050146a 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -48,6 +48,7 @@ extern int g10_errors_seen;
void print_pubkey_algo_note( int algo );
void print_cipher_algo_note( int algo );
void print_digest_algo_note( int algo );
+const char *get_temp_dir(void);
/*-- armor.c --*/
char *make_radix64_string( const byte *data, size_t len );
diff --git a/g10/mainproc.c b/g10/mainproc.c
index f2d29b2bd..57cf22139 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -37,7 +37,7 @@
#include "status.h"
#include "i18n.h"
#include "trustdb.h"
-#include "hkp.h"
+#include "keyserver-internal.h"
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] );
rc = do_check_sig(c, node, NULL );
- if( rc == G10ERR_NO_PUBKEY && opt.keyserver_name && opt.auto_key_retrieve) {
- if( !hkp_ask_import( sig->keyid, NULL ) )
+ if( rc == G10ERR_NO_PUBKEY && opt.keyserver_scheme && opt.auto_key_retrieve) {
+ if( keyserver_import_keyid ( sig->keyid )==0 )
rc = do_check_sig(c, node, NULL );
}
if( !rc || rc == G10ERR_BAD_SIGN ) {
diff --git a/g10/options.h b/g10/options.h
index 24012ff10..09a8f173f 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -1,3 +1,4 @@
+
/* options.h
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
*
@@ -88,7 +89,20 @@ struct {
int not_dash_escaped;
int escape_from;
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 interactive;
STRLIST notation_data;
diff --git a/g10/options.skel b/g10/options.skel
index f32a9fa08..6f262ac12 100644
--- a/g10/options.skel
+++ b/g10/options.skel
@@ -91,29 +91,67 @@ lock-once
#load-extension rndunix
#load-extension rndegd
-
-# GnuPG can import a key from a HKP keyerver if one is missing
-# for certain operations. Is you set this option to a keyserver
-# 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.
+# GnuPG can send and receive keys to and from a keyserver. These
+# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP
+# support).
+#
+# Example HKP keyserver:
+# x-hkp://wwwkeys.nl.pgp.net
+#
+# Example email keyserver:
+#
+# 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 do not want to use the default port 11371, you can give the
-# name of the keyserver like this:
-# x-hkp://keyserver.example.net:22742
-# If you have problems connecting through a buggy proxy, you can use this:
-# x-broken-hkp://keyserver.example.net:11371
+# 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
-# proxies (--honor-http-proxy)
-# Most users just set the name of the preferred keyserver.
-#keyserver wwwkeys.nl.pgp.net
+# proxies (honor-http-proxy)
+#
+# 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.
-# The environment variable http_proxy is only used when the
-# this option is set.
+#keyserver mailto:[email protected]
+#keyserver ldap://keyserver.pgp.com
+#keyserver x-hkp://wwwkeys.nl.pgp.net
-honor-http-proxy
+# 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
+# this option is set.
+#honor-http-proxy