gnupg/keyserver (ChangeLog Makefile.am curl-shim.c gpgkeys_hkp.c)
cvs user dshaw
cvs at cvs.gnupg.org
Sun Apr 17 04:01:59 CEST 2005
Date: Sunday, April 17, 2005 @ 04:18:32
Author: dshaw
Path: /cvs/gnupg/gnupg/keyserver
Modified: ChangeLog Makefile.am curl-shim.c gpgkeys_hkp.c
* gpgkeys_hkp.c: New hkp handler that uses curl or curl-shim.
* Makefile.am: Build new gpgkeys_hkp.
* curl-shim.c (curl_easy_perform): Cleanup.
---------------+
ChangeLog | 6
Makefile.am | 14
curl-shim.c | 121 +++---
gpgkeys_hkp.c | 969 ++++++++++++++------------------------------------------
4 files changed, 328 insertions(+), 782 deletions(-)
Index: gnupg/keyserver/ChangeLog
diff -u gnupg/keyserver/ChangeLog:1.124 gnupg/keyserver/ChangeLog:1.125
--- gnupg/keyserver/ChangeLog:1.124 Sun Apr 17 03:52:04 2005
+++ gnupg/keyserver/ChangeLog Sun Apr 17 04:18:32 2005
@@ -1,5 +1,11 @@
2005-04-16 David Shaw <dshaw at jabberwocky.com>
+ * gpgkeys_hkp.c: New hkp handler that uses curl or curl-shim.
+
+ * Makefile.am: Build new gpgkeys_hkp.
+
+ * curl-shim.c (curl_easy_perform): Cleanup.
+
* ksutil.h, ksutil.c (curl_writer), gpgkeys_curl.c (get_key): Pass
a context to curl_writer so we can support multiple fetches in a
single session.
Index: gnupg/keyserver/Makefile.am
diff -u gnupg/keyserver/Makefile.am:1.27 gnupg/keyserver/Makefile.am:1.28
--- gnupg/keyserver/Makefile.am:1.27 Fri Mar 18 00:16:41 2005
+++ gnupg/keyserver/Makefile.am Sun Apr 17 04:18:32 2005
@@ -29,7 +29,7 @@
noinst_SCRIPTS = gpgkeys_test
gpgkeys_ldap_SOURCES = gpgkeys_ldap.c ksutil.c ksutil.h
-gpgkeys_hkp_SOURCES = gpgkeys_hkp.c ksutil.c ksutil.h
+gpgkeys_hkp_SOURCES = ksutil.c ksutil.h
gpgkeys_http_SOURCES = gpgkeys_http.c ksutil.c ksutil.h
gpgkeys_finger_SOURCES = gpgkeys_finger.c ksutil.c ksutil.h
gpgkeys_curl_SOURCES = gpgkeys_curl.c ksutil.c ksutil.h
@@ -37,15 +37,25 @@
other_libs = $(LIBICONV) $(LIBINTL) $(CAPLIBS)
gpgkeys_ldap_LDADD = ../util/libutil.a @LDAPLIBS@ @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
-gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
gpgkeys_http_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
gpgkeys_finger_LDADD = ../util/libutil.a @NETLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
+if WITH_CURL
+gpgkeys_hkp_SOURCES += gpgkeys_hkp.c
if FAKE_CURL
gpgkeys_curl_SOURCES += curl-shim.c curl-shim.h
gpgkeys_curl_CPPFLAGS = -DFAKE_CURL
gpgkeys_curl_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
+gpgkeys_hkp_SOURCES += curl-shim.c curl-shim.h
+gpgkeys_hkp_CPPFLAGS = -DFAKE_CURL
+gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
else
gpgkeys_curl_CPPFLAGS = @LIBCURL_CPPFLAGS@
gpgkeys_curl_LDADD = @LIBCURL@ @GETOPT@
+gpgkeys_hkp_CPPFLAGS = @LIBCURL_CPPFLAGS@
+gpgkeys_hkp_LDADD = @LIBCURL@ @GETOPT@
+endif
+else
+gpgkeys_hkp_SOURCES += gpgkeys_oldhkp.c
+gpgkeys_hkp_LDADD = ../util/libutil.a @NETLIBS@ @SRVLIBS@ $(other_libs) @GETOPT@ @W32LIBS@
endif
Index: gnupg/keyserver/curl-shim.c
diff -u gnupg/keyserver/curl-shim.c:1.4 gnupg/keyserver/curl-shim.c:1.5
--- gnupg/keyserver/curl-shim.c:1.4 Sun Apr 17 03:39:24 2005
+++ gnupg/keyserver/curl-shim.c Sun Apr 17 04:18:32 2005
@@ -30,10 +30,13 @@
#include "util.h"
#include "curl-shim.h"
-static CURLcode handle_error(CURL *curl,CURLcode err,const char *str)
+static CURLcode
+handle_error(CURL *curl,CURLcode err,const char *str)
{
if(curl->errorbuffer)
{
+ /* Make sure you never exceed CURL_ERROR_SIZE, currently set to
+ 256 in curl-shim.h */
switch(err)
{
case CURLE_OK:
@@ -67,24 +70,29 @@
return err;
}
-CURLcode curl_global_init(long flags)
+CURLcode
+curl_global_init(long flags)
{
return CURLE_OK;
}
-void curl_global_cleanup(void) {}
+void
+curl_global_cleanup(void) {}
-CURL *curl_easy_init(void)
+CURL *
+curl_easy_init(void)
{
return calloc(1,sizeof(CURL));
}
-void curl_easy_cleanup(CURL *curl)
+void
+curl_easy_cleanup(CURL *curl)
{
free(curl);
}
-CURLcode curl_easy_setopt(CURL *curl,CURLoption option,...)
+CURLcode
+curl_easy_setopt(CURL *curl,CURLoption option,...)
{
va_list ap;
@@ -124,7 +132,8 @@
return handle_error(curl,CURLE_OK,NULL);
}
-CURLcode curl_easy_perform(CURL *curl)
+CURLcode
+curl_easy_perform(CURL *curl)
{
int rc;
CURLcode err=CURLE_OK;
@@ -133,16 +142,7 @@
if(curl->flags.post)
{
rc=http_open(&curl->hd,HTTP_REQ_POST,curl->url,0,curl->proxy);
- if(rc!=0)
- {
- if(rc==G10ERR_NETWORK)
- errstr=strerror(errno);
- else
- errstr=g10_errstr(rc);
-
- err=CURLE_COULDNT_CONNECT;
- }
- else
+ if(rc==0)
{
char content_len[50];
unsigned int post_len=strlen(curl->postfields);
@@ -156,73 +156,58 @@
http_start_data(&curl->hd);
iobuf_write(curl->hd.fp_write,curl->postfields,post_len);
rc=http_wait_response(&curl->hd,&curl->status);
- if(rc!=0)
- {
- if(rc==G10ERR_NETWORK)
- errstr=strerror(errno);
- else
- errstr=g10_errstr(rc);
-
- err=CURLE_COULDNT_CONNECT;
- }
-
- if(curl->flags.failonerror && curl->status>=300)
+ if(rc==0 && curl->flags.failonerror && curl->status>=300)
err=CURLE_HTTP_RETURNED_ERROR;
}
}
else
{
rc=http_open(&curl->hd,HTTP_REQ_GET,curl->url,0,curl->proxy);
- if(rc!=0)
- {
- if(rc==G10ERR_NETWORK)
- errstr=strerror(errno);
- else
- errstr=g10_errstr(rc);
-
- err=CURLE_COULDNT_CONNECT;
- }
- else
+ if(rc==0)
{
rc=http_wait_response(&curl->hd,&curl->status);
- if(rc)
+ if(rc==0)
{
- http_close(&curl->hd);
-
- if(rc==G10ERR_NETWORK)
- errstr=strerror(errno);
+ if(curl->flags.failonerror && curl->status>=300)
+ err=CURLE_HTTP_RETURNED_ERROR;
else
- errstr=g10_errstr(rc);
-
- err=CURLE_COULDNT_CONNECT;
- }
- else if(curl->flags.failonerror && curl->status>=300)
- err=CURLE_HTTP_RETURNED_ERROR;
- else
- {
- unsigned int maxlen=1024,buflen,len;
- byte *line=NULL;
-
- while((len=iobuf_read_line(curl->hd.fp_read,
- &line,&buflen,&maxlen)))
{
- maxlen=1024;
- size_t ret;
+ unsigned int maxlen=1024,buflen,len;
+ byte *line=NULL;
- ret=(curl->writer)(line,len,1,curl->file);
- if(ret!=len)
+ while((len=iobuf_read_line(curl->hd.fp_read,
+ &line,&buflen,&maxlen)))
{
- err=CURLE_WRITE_ERROR;
- break;
+ maxlen=1024;
+ size_t ret;
+
+ ret=(curl->writer)(line,len,1,curl->file);
+ if(ret!=len)
+ {
+ err=CURLE_WRITE_ERROR;
+ break;
+ }
}
- }
- m_free(line);
- http_close(&curl->hd);
+ m_free(line);
+ http_close(&curl->hd);
+ }
}
+ else
+ http_close(&curl->hd);
}
}
+ if(rc!=0)
+ {
+ if(rc==G10ERR_NETWORK)
+ errstr=strerror(errno);
+ else
+ errstr=g10_errstr(rc);
+
+ err=CURLE_COULDNT_CONNECT;
+ }
+
return handle_error(curl,err,errstr);
}
@@ -232,7 +217,8 @@
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"0123456789"
-char *curl_escape(char *str,int length)
+char *
+curl_escape(char *str,int length)
{
int len,max,idx,enc_idx=0;
char *enc;
@@ -282,7 +268,8 @@
return enc;
}
-void curl_free(char *ptr)
+void
+curl_free(char *ptr)
{
free(ptr);
}
Index: gnupg/keyserver/gpgkeys_hkp.c
diff -u gnupg/keyserver/gpgkeys_hkp.c:1.50 gnupg/keyserver/gpgkeys_hkp.c:1.51
--- gnupg/keyserver/gpgkeys_hkp.c:1.50 Wed Mar 23 00:41:08 2005
+++ gnupg/keyserver/gpgkeys_hkp.c Sun Apr 17 04:18:32 2005
@@ -21,81 +21,73 @@
#include <config.h>
#include <stdio.h>
#include <string.h>
-#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
-#define INCLUDED_BY_MAIN_MODULE 1
-#include "util.h"
-#include "http.h"
+#ifdef FAKE_CURL
+#include "curl-shim.h"
+#else
+#include <curl/curl.h>
+#endif
#include "keyserver.h"
#include "ksutil.h"
extern char *optarg;
extern int optind;
-static int verbose=0,include_revoked=0,include_disabled=0;
-static unsigned int http_flags=0;
-static char host[MAX_HOST+1]={'\0'},proxy[MAX_PROXY+1]={'\0'},port[MAX_PORT+1]={'\0'};
-static FILE *input=NULL,*output=NULL,*console=NULL;
-
-#ifdef __riscos__
-#define HTTP_PROXY_ENV "GnuPG$HttpProxy"
-#else
-#define HTTP_PROXY_ENV "http_proxy"
-#endif
+static char proxy[MAX_PROXY+1];
+static FILE *input,*output,*console;
+static CURL *curl;
+static struct ks_options *opt;
+static char errorbuffer[CURL_ERROR_SIZE];
-int
-urlencode_filter( void *opaque, int control,
- IOBUF a, byte *buf, size_t *ret_len)
+static size_t
+curl_mrindex_writer(const void *ptr,size_t size,size_t nmemb,void *stream)
{
- size_t size = *ret_len;
- int rc=0;
+ static int checked=0,swallow=0;
- if( control == IOBUFCTRL_FLUSH ) {
- const byte *p;
- for(p=buf; size; p++, size-- ) {
- if( isalnum(*p) || *p == '-' )
- iobuf_put( a, *p );
- else if( *p == ' ' )
- iobuf_put( a, '+' );
- else {
- char numbuf[5];
- sprintf(numbuf, "%%%02X", *p );
- iobuf_writestr(a, numbuf );
- }
- }
+ if(!checked)
+ {
+ /* If the document begins with a '<', assume it's a HTML
+ response, which we don't support. Discard the whole message
+ body. GPG can handle it, but this is an optimization to deal
+ with it on this side of the pipe. */
+ const char *buf=ptr;
+ if(buf[0]=='<')
+ swallow=1;
+
+ checked=1;
}
- else if( control == IOBUFCTRL_DESC )
- *(char**)buf = "urlencode_filter";
- return rc;
+
+ if(swallow || fwrite(ptr,size,nmemb,stream)==nmemb)
+ return size*nmemb;
+ else
+ return 0;
}
int
send_key(int *eof)
{
- int rc,begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
+ CURLcode res;
+ char request[MAX_URL+100];
+ int begin=0,end=0,ret=KEYSERVER_INTERNAL_ERROR;
char keyid[17];
- char *request;
- struct http_context hd;
- unsigned int status;
- IOBUF temp = iobuf_temp();
char line[MAX_LINE];
+ char *key,*encoded_key=NULL;
+ size_t keylen=8,keymax=8;
- memset(&hd,0,sizeof(hd));
-
- request=malloc(strlen(host)+100);
- if(!request)
+ key=malloc(9);
+ strcpy(key,"keytext=");
+ if(!key)
{
fprintf(console,"gpgkeys: out of memory\n");
- return KEYSERVER_NO_MEMORY;
+ ret=KEYSERVER_NO_MEMORY;
+ goto fail;
}
- iobuf_push_filter(temp,urlencode_filter,NULL);
-
/* Read and throw away input until we see the BEGIN */
while(fgets(line,MAX_LINE,input)!=NULL)
@@ -123,11 +115,27 @@
break;
}
else
- if(iobuf_writestr(temp,line))
- {
- fprintf(console,"gpgkeys: internal iobuf error\n");
- goto fail;
- }
+ {
+ if(strlen(line)+keylen>keymax)
+ {
+ char *tmp;
+
+ keymax+=200;
+ tmp=realloc(key,keymax+1);
+ if(!tmp)
+ {
+ free(key);
+ fprintf(console,"gpgkeys: out of memory\n");
+ ret=KEYSERVER_NO_MEMORY;
+ goto fail;
+ }
+
+ key=tmp;
+ }
+
+ strcpy(&key[keylen],line);
+ keylen+=strlen(line);
+ }
if(!end)
{
@@ -137,57 +145,45 @@
goto fail;
}
- iobuf_flush_temp(temp);
-
- sprintf(request,"hkp://%s%s%s/pks/add",host,port[0]?":":"",port[0]?port:"");
-
- if(verbose>2)
- fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
-
- rc=http_open(&hd,HTTP_REQ_POST,request,http_flags,proxy[0]?proxy:NULL);
- if(rc)
+ encoded_key=curl_escape(key,keylen);
+ if(!encoded_key)
{
- fprintf(console,"gpgkeys: unable to connect to `%s'\n",host);
+ fprintf(console,"gpgkeys: out of memory\n");
+ ret=KEYSERVER_NO_MEMORY;
goto fail;
}
- /* Some keyservers require this Content-Type (e.g. CryptoEx). */
- iobuf_writestr(hd.fp_write,
- "Content-Type: application/x-www-form-urlencoded\r\n");
-
- sprintf(request,"Content-Length: %u\r\n",
- (unsigned)iobuf_get_temp_length(temp)+9);
- iobuf_writestr(hd.fp_write,request);
-
- http_start_data(&hd);
-
- iobuf_writestr(hd.fp_write,"keytext=");
- iobuf_write(hd.fp_write,
- iobuf_get_temp_buffer(temp),iobuf_get_temp_length(temp));
- iobuf_put(hd.fp_write,'\n');
+ strcpy(request,"http://");
+ strcat(request,opt->host);
+ strcat(request,":");
+ if(opt->port)
+ strcat(request,opt->port);
+ else
+ strcat(request,"11371");
+ strcat(request,"/pks/add");
- rc=http_wait_response(&hd,&status);
- if(rc)
- {
- fprintf(console,"gpgkeys: error sending to `%s': %s\n",
- host,g10_errstr(rc));
- goto fail;
- }
+ if(opt->verbose>2)
+ fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
- if((status/100)!=2)
+ curl_easy_setopt(curl,CURLOPT_URL,request);
+ curl_easy_setopt(curl,CURLOPT_POST,1);
+ curl_easy_setopt(curl,CURLOPT_POSTFIELDS,encoded_key);
+ curl_easy_setopt(curl,CURLOPT_FAILONERROR,1);
+
+ res=curl_easy_perform(curl);
+ if(res!=0)
{
- fprintf(console,"gpgkeys: remote server returned error %d\n",status);
- goto fail;
+ fprintf(console,"gpgkeys: HTTP post error %d: %s\n",res,errorbuffer);
+ ret=curl_err_to_gpg_err(res);
}
-
- fprintf(output,"KEY %s SENT\n",keyid);
+ else
+ fprintf(output,"\nKEY %s SENT\n",keyid);
ret=KEYSERVER_OK;
fail:
- free(request);
- iobuf_close(temp);
- http_close(&hd);
+ free(key);
+ curl_free(encoded_key);
if(ret!=0 && begin)
fprintf(output,"KEY %s FAILED %d\n",keyid,ret);
@@ -195,469 +191,89 @@
return ret;
}
-int
+static int
get_key(char *getkey)
{
- int rc,gotit=0;
- char search[29];
- char *request;
- struct http_context hd;
+ CURLcode res;
+ char request[MAX_URL+100];
+ char *offset;
+ struct curl_writer_ctx ctx;
+
+ memset(&ctx,0,sizeof(ctx));
/* Build the search string. HKP only uses the short key IDs. */
if(strncmp(getkey,"0x",2)==0)
getkey+=2;
+ fprintf(output,"KEY 0x%s BEGIN\n",getkey);
+
if(strlen(getkey)==32)
{
fprintf(console,
"gpgkeys: HKP keyservers do not support v3 fingerprints\n");
- fprintf(output,"KEY 0x%s BEGIN\n",getkey);
fprintf(output,"KEY 0x%s FAILED %d\n",getkey,KEYSERVER_NOT_SUPPORTED);
return KEYSERVER_NOT_SUPPORTED;
}
- if(strlen(getkey)>8)
- {
- char *offset=&getkey[strlen(getkey)-8];
-
- /* fingerprint or long key id. Take the last 8 characters and
- treat it like a short key id */
-
- sprintf(search,"0x%.8s",offset);
- }
- else
- {
- /* short key id */
-
- sprintf(search,"0x%.8s",getkey);
- }
-
- fprintf(output,"KEY 0x%s BEGIN\n",getkey);
+ strcpy(request,"http://");
+ strcat(request,opt->host);
+ strcat(request,":");
+ if(opt->port)
+ strcat(request,opt->port);
+ else
+ strcat(request,"11371");
+ strcat(request,"/pks/lookup?op=get&options=mr&search=0x");
- request=malloc(strlen(host)+100);
- if(!request)
- {
- fprintf(console,"gpgkeys: out of memory\n");
- return KEYSERVER_NO_MEMORY;
- }
+ /* fingerprint or long key id. Take the last 8 characters and treat
+ it like a short key id */
+ if(strlen(getkey)>8)
+ offset=&getkey[strlen(getkey)-8];
+ else
+ offset=getkey;
- sprintf(request,"hkp://%s%s%s/pks/lookup?op=get&options=mr&search=%s",
- host,port[0]?":":"",port[0]?port:"", search);
+ strcat(request,offset);
- if(verbose>2)
+ if(opt->verbose>2)
fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
- rc=http_open_document(&hd,request,http_flags,proxy[0]?proxy:NULL);
- if(rc!=0)
+ curl_easy_setopt(curl,CURLOPT_URL,request);
+ curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_writer);
+ ctx.stream=output;
+ curl_easy_setopt(curl,CURLOPT_FILE,&ctx);
+
+ res=curl_easy_perform(curl);
+ if(res!=0)
{
- fprintf(console,"gpgkeys: HKP fetch error: %s\n",
- rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
- fprintf(output,"KEY 0x%s FAILED %d\n",getkey,
- rc==G10ERR_NETWORK?KEYSERVER_UNREACHABLE:KEYSERVER_INTERNAL_ERROR);
+ fprintf(console,"gpgkeys: HTTP fetch error %d: %s\n",res,errorbuffer);
+ fprintf(output,"\nKEY 0x%s FAILED %d\n",getkey,curl_err_to_gpg_err(res));
}
else
{
- unsigned int maxlen=1024,buflen;
- byte *line=NULL;
-
- while(iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen))
- {
- maxlen=1024;
-
- if(gotit)
- {
- print_nocr(output,line);
- if(strncmp(line,END,strlen(END))==0)
- break;
- }
- else
- if(strncmp(line,BEGIN,strlen(BEGIN))==0)
- {
- print_nocr(output,line);
- gotit=1;
- }
- }
-
- if(gotit)
- fprintf(output,"KEY 0x%s END\n",getkey);
+ if(ctx.done)
+ fprintf(output,"\nKEY 0x%s END\n",getkey);
else
{
fprintf(console,"gpgkeys: key %s not found on keyserver\n",getkey);
fprintf(output,"KEY 0x%s FAILED %d\n",
getkey,KEYSERVER_KEY_NOT_FOUND);
}
-
- m_free(line);
- http_close(&hd);
}
- free(request);
-
return KEYSERVER_OK;
}
-/* Remove anything <between brackets> and de-urlencode in place. Note
- that this requires all brackets to be closed on the same line. It
- also means that the result is never larger than the input. */
-void
-dehtmlize(char *line)
-{
- int parsedindex=0;
- char *parsed=line;
-
- while(*line!='\0')
- {
- switch(*line)
- {
- case '<':
- while(*line!='>' && *line!='\0')
- line++;
-
- if(*line!='\0')
- line++;
- break;
-
- case '&':
- if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='l') &&
- (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
- (*(line+3)!='\0' && *(line+3)==';'))
- {
- parsed[parsedindex++]='<';
- line+=4;
- break;
- }
- else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='g') &&
- (*(line+2)!='\0' && ascii_tolower(*(line+2))=='t') &&
- (*(line+3)!='\0' && *(line+3)==';'))
- {
- parsed[parsedindex++]='>';
- line+=4;
- break;
- }
- else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='a') &&
- (*(line+2)!='\0' && ascii_tolower(*(line+2))=='m') &&
- (*(line+3)!='\0' && ascii_tolower(*(line+3))=='p') &&
- (*(line+4)!='\0' && *(line+4)==';'))
- {
- parsed[parsedindex++]='&';
- line+=5;
- break;
- }
- else if((*(line+1)!='\0' && ascii_tolower(*(line+1))=='q') &&
- (*(line+2)!='\0' && ascii_tolower(*(line+2))=='u') &&
- (*(line+3)!='\0' && ascii_tolower(*(line+3))=='o') &&
- (*(line+4)!='\0' && ascii_tolower(*(line+4))=='t') &&
- (*(line+5)!='\0' && *(line+5)==';'))
- {
- parsed[parsedindex++]='"';
- line+=6;
- break;
- }
-
- default:
- parsed[parsedindex++]=*line;
- line++;
- break;
- }
- }
-
- parsed[parsedindex]='\0';
-
- /* Chop off any trailing whitespace. Note that the HKP servers have
- \r\n as line endings, and the NAI HKP servers have just \n. */
-
- if(parsedindex>0)
- {
- parsedindex--;
- while(isspace(((unsigned char *)parsed)[parsedindex]))
- {
- parsed[parsedindex]='\0';
- if(parsedindex==0)
- break;
- parsedindex--;
- }
- }
-}
-
-int
-write_quoted(IOBUF a, const char *buf, char delim)
-{
- while(*buf)
- {
- if(*buf==delim)
- {
- char quoted[5];
- sprintf(quoted,"%%%02X",delim);
- if(iobuf_writestr(a,quoted))
- return -1;
- }
- else if(*buf=='%')
- {
- if(iobuf_writestr(a,"%25"))
- return -1;
- }
- else
- {
- if(iobuf_writebyte(a,*buf))
- return -1;
- }
-
- buf++;
- }
-
- return 0;
-}
-
-/* pub 2048/<a href="/pks/lookup?op=get&search=0x3CB3B415">3CB3B415</a> 1998/04/03 David M. Shaw <<a href="/pks/lookup?op=get&search=0x3CB3B415">dshaw at jabberwocky.com</a>> */
-
-/* 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. */
-
-int
-parse_hkp_index(IOBUF buffer,char *line)
-{
- int ret=0;
-
- /* printf("Open %d, LINE: `%s'\n",open,line); */
-
- dehtmlize(line);
-
- /* printf("Now open %d, LINE: `%s'\n",open,line); */
-
- if(line[0]=='\0')
- return 0;
- else if(ascii_strncasecmp(line,"pub",3)==0)
- {
- char *tok,*keyid,*uid=NULL,number[15];
- int bits=0,type=0,disabled=0,revoked=0;
- u32 createtime=0;
-
- line+=3;
-
- if(*line=='-')
- {
- disabled=1;
- if(!include_disabled)
- return 0;
- }
-
- line++;
-
- tok=strsep(&line,"/");
- if(tok==NULL || strlen(tok)==0)
- return ret;
-
- if(tok[strlen(tok)-1]=='R')
- type=1;
- else if(tok[strlen(tok)-1]=='D')
- type=17;
-
- bits=atoi(tok);
-
- keyid=strsep(&line," ");
-
- tok=strsep(&line," ");
- if(tok!=NULL)
- {
- char *temp=tok;
-
- /* The date parser wants '-' instead of '/', so... */
- while(*temp!='\0')
- {
- if(*temp=='/')
- *temp='-';
-
- temp++;
- }
-
- createtime=scan_isodatestr(tok);
- }
-
- if(line!=NULL)
- {
- while(*line==' ' && *line!='\0')
- line++;
-
- if(*line!='\0')
- {
- if(strncmp(line,"*** KEY REVOKED ***",19)==0)
- {
- revoked=1;
- if(!include_revoked)
- return 0;
- }
- else
- uid=line;
- }
- }
-
- if(keyid)
- {
- iobuf_writestr(buffer,"pub:");
-
- write_quoted(buffer,keyid,':');
-
- iobuf_writestr(buffer,":");
-
- if(type)
- {
- sprintf(number,"%d",type);
- write_quoted(buffer,number,':');
- }
-
- iobuf_writestr(buffer,":");
-
- if(bits)
- {
- sprintf(number,"%d",bits);
- write_quoted(buffer,number,':');
- }
-
- iobuf_writestr(buffer,":");
-
- if(createtime)
- {
- sprintf(number,"%d",createtime);
- write_quoted(buffer,number,':');
- }
-
- iobuf_writestr(buffer,"::");
-
- if(revoked)
- write_quoted(buffer,"r",':');
-
- if(disabled)
- write_quoted(buffer,"d",':');
-
- if(uid)
- {
- iobuf_writestr(buffer,"\nuid:");
- write_quoted(buffer,uid,':');
- }
-
- iobuf_writestr(buffer,"\n");
-
- ret=1;
- }
- }
- else if(ascii_strncasecmp(line," ",3)==0)
- {
- while(*line==' ' && *line!='\0')
- line++;
-
- if(*line!='\0')
- {
- iobuf_writestr(buffer,"uid:");
- write_quoted(buffer,line,':');
- iobuf_writestr(buffer,"\n");
- }
- }
-
-#if 0
- else if(open)
- {
- /* Try and catch some bastardization of HKP. If we don't have
- certain unchanging landmarks, we can't reliably parse the
- response. This only complains about problems within the key
- section itself. Headers and footers should not matter. */
-
- fprintf(console,"gpgkeys: this keyserver does not support searching\n");
- ret=-1;
- }
-#endif
-
- return ret;
-}
-
-void
-handle_old_hkp_index(IOBUF inp)
-{
- int ret,rc,count=0;
- unsigned int buflen;
- byte *line=NULL;
- IOBUF buffer=iobuf_temp();
-
- do
- {
- unsigned int maxlen=1024;
-
- /* 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(inp,&line,&buflen,&maxlen);
-
- ret=parse_hkp_index(buffer,line);
- if(ret==-1)
- break;
-
- if(rc!=0)
- count+=ret;
- }
- while(rc!=0);
-
- m_free(line);
-
- if(ret>-1)
- fprintf(output,"info:1:%d\n%s",count,iobuf_get_temp_buffer(buffer));
-
- iobuf_close(buffer);
-}
-
int
search_key(char *searchkey)
{
- int max=0,len=0,ret=KEYSERVER_INTERNAL_ERROR,rc;
- struct http_context hd;
- char *search=NULL,*request=NULL;
- unsigned char *skey=(unsigned char*) searchkey;
-
- fprintf(output,"SEARCH %s BEGIN\n",searchkey);
-
- /* Build the search string. It's going to need url-encoding. */
-
- while(*skey!='\0')
- {
- if(max-len<3)
- {
- max+=100;
- search=realloc(search,max+1); /* Note +1 for \0 */
- if (!search)
- {
- fprintf(console,"gpgkeys: out of memory\n");
- ret=KEYSERVER_NO_MEMORY;
- goto fail;
- }
- }
-
- if(isalnum(*skey) || *skey=='-')
- search[len++]=*skey;
- else if(*skey==' ')
- search[len++]='+';
- else
- {
- sprintf(&search[len],"%%%02X",*skey);
- len+=3;
- }
-
- skey++;
- }
-
- if(!search)
- {
- fprintf(console,"gpgkeys: corrupt input?\n");
- return -1;
- }
+ CURLcode res;
+ char *request;
+ char *searchkey_encoded;
+ int ret=KEYSERVER_INTERNAL_ERROR;
- search[len]='\0';
+ searchkey_encoded=curl_escape(searchkey,0);
- request=malloc(strlen(host)+100+strlen(search));
+ request=malloc(MAX_URL+100+strlen(searchkey_encoded));
if(!request)
{
fprintf(console,"gpgkeys: out of memory\n");
@@ -665,65 +281,55 @@
goto fail;
}
- sprintf(request,"hkp://%s%s%s/pks/lookup?op=index&options=mr&search=%s",
- host,port[0]?":":"",port[0]?port:"",search);
+ fprintf(output,"SEARCH %s BEGIN\n",searchkey);
+
+ strcpy(request,"http://");
+ strcat(request,opt->host);
+ strcat(request,":");
+ if(opt->port)
+ strcat(request,opt->port);
+ else
+ strcat(request,"11371");
+ strcat(request,"/pks/lookup?op=index&options=mr&search=");
+ strcat(request,searchkey_encoded);
- if(verbose>2)
+ if(opt->verbose>2)
fprintf(console,"gpgkeys: HTTP URL is `%s'\n",request);
- rc=http_open_document(&hd,request,http_flags,proxy[0]?proxy:NULL);
- if(rc)
+ curl_easy_setopt(curl,CURLOPT_URL,request);
+ curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,curl_mrindex_writer);
+ curl_easy_setopt(curl,CURLOPT_FILE,output);
+
+ res=curl_easy_perform(curl);
+ if(res!=0)
{
- fprintf(console,"gpgkeys: can't search keyserver `%s': %s\n",
- host,rc==G10ERR_NETWORK?strerror(errno):g10_errstr(rc));
+ fprintf(console,"gpgkeys: HTTP search error %d: %s\n",res,errorbuffer);
+ ret=curl_err_to_gpg_err(res);
}
else
{
- unsigned int maxlen=1024,buflen;
- byte *line=NULL;
-
- /* Is it a pksd that knows how to handle machine-readable
- format? */
-
- rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
- if(line[0]=='<')
- handle_old_hkp_index(hd.fp_read);
- else
- do
- {
- fprintf(output,"%s",line);
- maxlen=1024;
- rc=iobuf_read_line(hd.fp_read,&line,&buflen,&maxlen);
- }
- while(rc!=0);
-
- m_free(line);
-
- http_close(&hd);
-
- fprintf(output,"SEARCH %s END\n",searchkey);
-
+ fprintf(output,"\nSEARCH %s END\n",searchkey);
ret=KEYSERVER_OK;
}
fail:
+ curl_free(searchkey_encoded);
free(request);
- free(search);
if(ret!=KEYSERVER_OK)
- fprintf(output,"SEARCH %s FAILED %d\n",searchkey,ret);
+ fprintf(output,"\nSEARCH %s FAILED %d\n",searchkey,ret);
return ret;
}
void
-fail_all(struct keylist *keylist,int action,int err)
+fail_all(struct keylist *keylist,int err)
{
if(!keylist)
return;
- if(action==SEARCH)
+ if(opt->action==KS_SEARCH)
{
fprintf(output,"SEARCH ");
while(keylist)
@@ -752,11 +358,10 @@
int
main(int argc,char *argv[])
{
- int arg,action=-1,ret=KEYSERVER_INTERNAL_ERROR;
+ int arg,ret=KEYSERVER_INTERNAL_ERROR;
char line[MAX_LINE];
int failed=0;
struct keylist *keylist=NULL,*keyptr=NULL;
- unsigned int timeout=DEFAULT_KEYSERVER_TIMEOUT;
console=stderr;
@@ -813,57 +418,28 @@
if(output==NULL)
output=stdout;
+ opt=init_ks_options();
+ if(!opt)
+ return KEYSERVER_NO_MEMORY;
+
/* Get the command and info block */
while(fgets(line,MAX_LINE,input)!=NULL)
{
- int version;
- char command[MAX_COMMAND+1];
+ int err;
char option[MAX_OPTION+1];
- char hash;
if(line[0]=='\n')
break;
- if(sscanf(line,"%c",&hash)==1 && hash=='#')
- continue;
-
- if(sscanf(line,"COMMAND %" MKSTRING(MAX_COMMAND) "s\n",command)==1)
+ err=parse_ks_options(line,opt);
+ if(err>0)
{
- command[MAX_COMMAND]='\0';
-
- if(strcasecmp(command,"get")==0)
- action=GET;
- else if(strcasecmp(command,"send")==0)
- action=SEND;
- else if(strcasecmp(command,"search")==0)
- action=SEARCH;
-
- continue;
- }
-
- if(sscanf(line,"HOST %" MKSTRING(MAX_HOST) "s\n",host)==1)
- {
- host[MAX_HOST]='\0';
- continue;
- }
-
- if(sscanf(line,"PORT %" MKSTRING(MAX_PORT) "s\n",port)==1)
- {
- port[MAX_PORT]='\0';
- continue;
- }
-
- if(sscanf(line,"VERSION %d\n",&version)==1)
- {
- if(version!=KEYSERVER_PROTO_VERSION)
- {
- ret=KEYSERVER_VERSION_ERROR;
- goto fail;
- }
-
- continue;
+ ret=err;
+ goto fail;
}
+ else if(err==0)
+ continue;
if(sscanf(line,"OPTION %" MKSTRING(MAX_OPTION) "s\n",option)==1)
{
@@ -878,28 +454,7 @@
start=&option[3];
}
- if(strcasecmp(start,"verbose")==0)
- {
- if(no)
- verbose--;
- else
- verbose++;
- }
- else if(strcasecmp(start,"include-revoked")==0)
- {
- if(no)
- include_revoked=0;
- else
- include_revoked=1;
- }
- else if(strcasecmp(start,"include-disabled")==0)
- {
- if(no)
- include_disabled=0;
- else
- include_disabled=1;
- }
- else if(strncasecmp(start,"http-proxy",10)==0)
+ if(strncasecmp(start,"http-proxy",10)==0)
{
if(no)
proxy[0]='\0';
@@ -918,13 +473,7 @@
}
}
}
- else if(strcasecmp(start,"broken-http-proxy")==0)
- {
- if(no)
- http_flags&=~HTTP_FLAG_NO_SHUTDOWN;
- else
- http_flags|=HTTP_FLAG_NO_SHUTDOWN;
- }
+#if 0
else if(strcasecmp(start,"try-dns-srv")==0)
{
if(no)
@@ -932,37 +481,56 @@
else
http_flags|=HTTP_FLAG_TRY_SRV;
}
- else if(strncasecmp(start,"timeout",7)==0)
- {
- if(no)
- timeout=0;
- else if(start[7]=='=')
- timeout=atoi(&start[8]);
- else if(start[7]=='\0')
- timeout=DEFAULT_KEYSERVER_TIMEOUT;
- }
-
+#endif
continue;
}
}
- if(timeout && register_timeout()==-1)
+ if(!opt->host)
+ {
+ fprintf(console,"gpgkeys: no keyserver host provided\n");
+ goto fail;
+ }
+
+ if(opt->timeout && register_timeout()==-1)
{
fprintf(console,"gpgkeys: unable to register timeout handler\n");
return KEYSERVER_INTERNAL_ERROR;
}
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl=curl_easy_init();
+ if(!curl)
+ {
+ fprintf(console,"gpgkeys: unable to initialize curl\n");
+ ret=KEYSERVER_INTERNAL_ERROR;
+ goto fail;
+ }
+
+ curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer);
+
+ if(opt->debug)
+ {
+ curl_easy_setopt(curl,CURLOPT_STDERR,console);
+ curl_easy_setopt(curl,CURLOPT_VERBOSE,1);
+ }
+
+ if(proxy[0])
+ curl_easy_setopt(curl,CURLOPT_PROXY,proxy);
+
+#if 0
/* By suggested convention, if the user gives a :port, then disable
SRV. */
- if(port[0])
+ if(opt->port)
http_flags&=~HTTP_FLAG_TRY_SRV;
+#endif
/* If it's a GET or a SEARCH, the next thing to come in is the
keyids. If it's a SEND, then there are no keyids. */
- if(action==SEND)
+ if(opt->action==KS_SEND)
while(fgets(line,MAX_LINE,input)!=NULL && line[0]!='\n');
- else if(action==GET || action==SEARCH)
+ else if(opt->action==KS_GET || opt->action==KS_SEARCH)
{
for(;;)
{
@@ -1013,112 +581,87 @@
fprintf(output,"VERSION %d\n",KEYSERVER_PROTO_VERSION);
fprintf(output,"PROGRAM %s\n\n",VERSION);
- if(verbose>1)
- {
- fprintf(console,"Host:\t\t%s\n",host);
- if(port[0])
- fprintf(console,"Port:\t\t%s\n",port);
- fprintf(console,"Command:\t%s\n",action==GET?"GET":
- action==SEND?"SEND":"SEARCH");
- }
-
-#if 0
- if(verbose>1)
+ if(opt->verbose>1)
{
- vals=ldap_get_values(ldap,res,"software");
- if(vals!=NULL)
- {
- fprintf(console,"Server: \t%s\n",vals[0]);
- ldap_value_free(vals);
- }
-
- vals=ldap_get_values(ldap,res,"version");
- if(vals!=NULL)
- {
- fprintf(console,"Version:\t%s\n",vals[0]);
- ldap_value_free(vals);
- }
+ fprintf(console,"Host:\t\t%s\n",opt->host);
+ if(opt->port)
+ fprintf(console,"Port:\t\t%s\n",opt->port);
+ fprintf(console,"Command:\t%s\n",ks_action_to_string(opt->action));
}
-#endif
- switch(action)
+ if(opt->action==KS_GET)
{
- case GET:
keyptr=keylist;
while(keyptr!=NULL)
{
- set_timeout(timeout);
+ set_timeout(opt->timeout);
if(get_key(keyptr->str)!=KEYSERVER_OK)
failed++;
keyptr=keyptr->next;
}
- break;
-
- case SEND:
- {
- int eof=0;
-
- do
- {
- set_timeout(timeout);
+ }
+ else if(opt->action==KS_SEND)
+ {
+ int eof=0;
- if(send_key(&eof)!=KEYSERVER_OK)
- failed++;
- }
- while(!eof);
- }
- break;
+ do
+ {
+ set_timeout(opt->timeout);
- case SEARCH:
- {
- char *searchkey=NULL;
- int len=0;
+ if(send_key(&eof)!=KEYSERVER_OK)
+ failed++;
+ }
+ while(!eof);
+ }
+ else if(opt->action==KS_SEARCH)
+ {
+ char *searchkey=NULL;
+ int len=0;
- set_timeout(timeout);
+ set_timeout(opt->timeout);
- /* To search, we stick a space in between each key to search
- for. */
+ /* To search, we stick a space in between each key to search
+ for. */
- keyptr=keylist;
- while(keyptr!=NULL)
- {
- len+=strlen(keyptr->str)+1;
- keyptr=keyptr->next;
- }
-
- searchkey=malloc(len+1);
- if(searchkey==NULL)
- {
- ret=KEYSERVER_NO_MEMORY;
- fail_all(keylist,action,KEYSERVER_NO_MEMORY);
- goto fail;
- }
+ keyptr=keylist;
+ while(keyptr!=NULL)
+ {
+ len+=strlen(keyptr->str)+1;
+ keyptr=keyptr->next;
+ }
- searchkey[0]='\0';
+ searchkey=malloc(len+1);
+ if(searchkey==NULL)
+ {
+ ret=KEYSERVER_NO_MEMORY;
+ fail_all(keylist,KEYSERVER_NO_MEMORY);
+ goto fail;
+ }
- keyptr=keylist;
- while(keyptr!=NULL)
- {
- strcat(searchkey,keyptr->str);
- strcat(searchkey," ");
- keyptr=keyptr->next;
- }
+ searchkey[0]='\0';
- /* Nail that last space */
- if(*searchkey)
- searchkey[strlen(searchkey)-1]='\0';
+ keyptr=keylist;
+ while(keyptr!=NULL)
+ {
+ strcat(searchkey,keyptr->str);
+ strcat(searchkey," ");
+ keyptr=keyptr->next;
+ }
- if(search_key(searchkey)!=KEYSERVER_OK)
- failed++;
+ /* Nail that last space */
+ if(*searchkey)
+ searchkey[strlen(searchkey)-1]='\0';
- free(searchkey);
- }
+ if(search_key(searchkey)!=KEYSERVER_OK)
+ failed++;
- break;
+ free(searchkey);
}
+ else
+ abort();
if(!failed)
ret=KEYSERVER_OK;
More information about the Gnupg-commits
mailing list