From a7205a080cf1b17d385453c8ec244d3bf67bf537 Mon Sep 17 00:00:00 2001 From: David Shaw Date: Thu, 28 May 2009 04:25:25 +0000 Subject: [PATCH] * http.h, http.c (send_request): Pass in srvtag and make its presence sufficient to turn the feature on. (http_open): From here. (http_document): And here. * gpgkeys_hkp.c (srv_replace): New function to transform a SRV hostname to a real hostname. (main): Call it from here for the HAVE_LIBCURL case (without libcurl is handled via the curl-shim). * curl-shim.h, curl-shim.c (curl_easy_setopt, curl_easy_perform): Add a CURLOPT_SRVTAG_GPG_HACK (passed through the the http engine). --- common/ChangeLog | 7 +++ common/http.c | 23 +++++----- common/http.h | 11 ++--- keyserver/ChangeLog | 13 ++++++ keyserver/curl-shim.c | 7 ++- keyserver/curl-shim.h | 4 +- keyserver/gpgkeys_hkp.c | 95 +++++++++++++++++++++++++++++++++-------- 7 files changed, 125 insertions(+), 35 deletions(-) diff --git a/common/ChangeLog b/common/ChangeLog index 1e2119b53..a03105a15 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,12 @@ 2009-05-27 David Shaw + From 1.4: + + * http.h, http.c (send_request): Pass in srvtag and make its + presence sufficient to turn the feature on. + (http_open): From here. + (http_document): And here. + * srv.c (getsrv): Raise maximum packet size to 2048, as PACKETSZ is too small these days. diff --git a/common/http.c b/common/http.c index 73a6cb8fb..4999ce7d1 100644 --- a/common/http.c +++ b/common/http.c @@ -128,8 +128,8 @@ static int remove_escapes (char *string); static int insert_escapes (char *buffer, const char *string, const char *special); static uri_tuple_t parse_tuple (char *string); -static gpg_error_t send_request (http_t hd, - const char *auth, const char *proxy); +static gpg_error_t send_request (http_t hd, const char *auth, + const char *proxy, const char *srvtag); static char *build_rel_path (parsed_uri_t uri); static gpg_error_t parse_response (http_t hd); @@ -317,7 +317,7 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) ) gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *url, const char *auth, unsigned int flags, const char *proxy, - void *tls_context) + void *tls_context, const char *srvtag) { gpg_error_t err; http_t hd; @@ -338,7 +338,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, err = http_parse_uri (&hd->uri, url); if (!err) - err = send_request (hd, auth, proxy); + err = send_request (hd, auth, proxy, srvtag); if (err) { @@ -457,12 +457,12 @@ http_wait_response (http_t hd) gpg_error_t http_open_document (http_t *r_hd, const char *document, const char *auth, unsigned int flags, const char *proxy, - void *tls_context) + void *tls_context, const char *srvtag) { gpg_error_t err; err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, - proxy, tls_context); + proxy, tls_context, srvtag); if (err) return err; @@ -835,7 +835,7 @@ parse_tuple (char *string) * Returns 0 if the request was successful */ static gpg_error_t -send_request (http_t hd, const char *auth, const char *proxy) +send_request (http_t hd, const char *auth, const char *proxy,const char *srvtag) { gnutls_session_t tls_session; gpg_error_t err; @@ -893,13 +893,13 @@ send_request (http_t hd, const char *auth, const char *proxy) hd->sock = connect_server (*uri->host ? uri->host : "localhost", uri->port ? uri->port : 80, - hd->flags, hd->uri->scheme); + hd->flags, srvtag); save_errno = errno; http_release_parsed_uri (uri); } else { - hd->sock = connect_server (server, port, hd->flags, hd->uri->scheme); + hd->sock = connect_server (server, port, hd->flags, srvtag); save_errno = errno; } @@ -1524,6 +1524,9 @@ connect_server (const char *server, unsigned short port, int last_errno = 0; struct srventry *serverlist = NULL; + /* Not currently using the flags */ + (void)flags; + #ifdef HAVE_W32_SYSTEM unsigned long inaddr; @@ -1559,7 +1562,7 @@ connect_server (const char *server, unsigned short port, #ifdef USE_DNS_SRV /* Do the SRV thing */ - if ((flags & HTTP_FLAG_TRY_SRV) && srvtag) + if (srvtag) { /* We're using SRV, so append the tags. */ if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME) diff --git a/common/http.h b/common/http.h index c92bbf1e6..3b049a7f2 100644 --- a/common/http.h +++ b/common/http.h @@ -63,9 +63,8 @@ enum { HTTP_FLAG_TRY_PROXY = 1, HTTP_FLAG_NO_SHUTDOWN = 2, - HTTP_FLAG_TRY_SRV = 4, - HTTP_FLAG_LOG_RESP = 8, - HTTP_FLAG_NEED_HEADER = 16 + HTTP_FLAG_LOG_RESP = 4, + HTTP_FLAG_NEED_HEADER = 8 }; struct http_context_s; @@ -82,7 +81,8 @@ gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *auth, unsigned int flags, const char *proxy, - void *tls_context); + void *tls_context, + const char *srvtag); void http_start_data (http_t hd); @@ -95,7 +95,8 @@ gpg_error_t http_open_document (http_t *r_hd, const char *auth, unsigned int flags, const char *proxy, - void *tls_context); + void *tls_context, + const char *srvtag); #ifdef HTTP_USE_ESTREAM estream_t http_get_read_ptr (http_t hd); diff --git a/keyserver/ChangeLog b/keyserver/ChangeLog index 2b403379d..26abf0fba 100644 --- a/keyserver/ChangeLog +++ b/keyserver/ChangeLog @@ -1,3 +1,16 @@ +2009-05-27 David Shaw + + From 1.4: + + * gpgkeys_hkp.c (srv_replace): New function to transform a SRV + hostname to a real hostname. + (main): Call it from here for the HAVE_LIBCURL case (without + libcurl is handled via the curl-shim). + + * curl-shim.h, curl-shim.c (curl_easy_setopt, curl_easy_perform): + Add a CURLOPT_SRVTAG_GPG_HACK (passed through the the http + engine). + 2009-05-10 David Shaw From 1.4: diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c index 0c8bfdc9b..98b5b24c7 100644 --- a/keyserver/curl-shim.c +++ b/keyserver/curl-shim.c @@ -144,6 +144,9 @@ curl_easy_setopt(CURL *curl,CURLoption option,...) case CURLOPT_POSTFIELDS: curl->postfields=va_arg(ap,char *); break; + case CURLOPT_SRVTAG_GPG_HACK: + curl->srvtag=va_arg(ap,char *); + break; case CURLOPT_FAILONERROR: curl->flags.failonerror=va_arg(ap,long)?1:0; break; @@ -193,7 +196,7 @@ curl_easy_perform(CURL *curl) if(curl->flags.post) { rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth, - 0, proxy, NULL); + 0, proxy, NULL, curl->srvtag); if (!rc) { unsigned int post_len = strlen(curl->postfields); @@ -216,7 +219,7 @@ curl_easy_perform(CURL *curl) else { rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth, - 0, proxy, NULL); + 0, proxy, NULL, curl->srvtag); if (!rc) { rc = http_wait_response (curl->hd); diff --git a/keyserver/curl-shim.h b/keyserver/curl-shim.h index 3b254ac03..793d484b9 100644 --- a/keyserver/curl-shim.h +++ b/keyserver/curl-shim.h @@ -48,7 +48,8 @@ typedef enum CURLOPT_CAINFO, CURLOPT_POST, CURLOPT_POSTFIELDS, - CURLOPT_FAILONERROR + CURLOPT_FAILONERROR, + CURLOPT_SRVTAG_GPG_HACK } CURLoption; typedef size_t (*write_func)(char *buffer,size_t size, @@ -63,6 +64,7 @@ typedef struct write_func writer; void *file; char *postfields; + char *srvtag; unsigned int status; FILE *errors; struct diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c index ef6fd7cb4..0764fe2ac 100644 --- a/keyserver/gpgkeys_hkp.c +++ b/keyserver/gpgkeys_hkp.c @@ -43,6 +43,9 @@ #else #include "curl-shim.h" #endif +#ifdef USE_DNS_SRV +#include "srv.h" +#endif #include "keyserver.h" #include "ksutil.h" @@ -183,6 +186,7 @@ send_key(int *r_eof) strcat(key,encoded_key); strcpy(request,proto); + strcat(request,"://"); strcat(request,opt->host); strcat(request,":"); strcat(request,port); @@ -247,6 +251,7 @@ get_key(char *getkey) } strcpy(request,proto); + strcat(request,"://"); strcat(request,opt->host); strcat(request,":"); strcat(request,port); @@ -325,6 +330,7 @@ get_name(const char *getkey) fprintf(output,"NAME %s BEGIN\n",getkey); strcpy(request,proto); + strcat(request,"://"); strcat(request,opt->host); strcat(request,":"); strcat(request,port); @@ -408,6 +414,7 @@ search_key(const char *searchkey) fprintf(output,"SEARCH %s BEGIN\n",searchkey); strcpy(request,proto); + strcat(request,"://"); strcat(request,opt->host); strcat(request,":"); strcat(request,port); @@ -478,6 +485,51 @@ fail_all(struct keylist *keylist,int err) } } +#ifdef HAVE_LIBCURL +/* If there is a SRV record, take the highest ranked possibility. + This is a hack, as we don't proceed downwards. */ +static void +srv_replace(void) +{ +#ifdef USE_DNS_SRV + struct srventry *srvlist=NULL; + int srvcount; + + if(1+strlen(opt->scheme)+6+strlen(opt->host)+1<=MAXDNAME) + { + char srvname[MAXDNAME]; + + strcpy(srvname,"_"); + strcat(srvname,opt->scheme); + strcat(srvname,"._tcp."); + strcat(srvname,opt->host); + srvcount=getsrv(srvname,&srvlist); + } + + if(srvlist) + { + char *newname,*newport; + + newname=strdup(srvlist->target); + newport=malloc(MAX_PORT); + if(newname && newport) + { + free(opt->host); + free(opt->port); + opt->host=newname; + snprintf(newport,MAX_PORT,"%u",srvlist->port); + opt->port=newport; + } + else + { + free(newname); + free(newport); + } + } +#endif +} +#endif + static void show_help (FILE *fp) { @@ -490,7 +542,7 @@ show_help (FILE *fp) int main(int argc,char *argv[]) { - int arg,ret=KEYSERVER_INTERNAL_ERROR; + int arg,ret=KEYSERVER_INTERNAL_ERROR,try_srv=1; char line[MAX_LINE]; int failed=0; struct keylist *keylist=NULL,*keyptr=NULL; @@ -604,15 +656,14 @@ main(int argc,char *argv[]) } } } -#if 0 else if(strcasecmp(start,"try-dns-srv")==0) { if(no) - http_flags&=~HTTP_FLAG_TRY_SRV; + try_srv=0; else - http_flags|=HTTP_FLAG_TRY_SRV; + try_srv=1; } -#endif + continue; } } @@ -626,18 +677,15 @@ main(int argc,char *argv[]) if(ks_strcasecmp(opt->scheme,"hkps")==0) { - proto="https://"; + proto="https"; port="443"; } else { - proto="http://"; + proto="http"; port="11371"; } - if(opt->port) - port=opt->port; - if(!opt->host) { fprintf(console,"gpgkeys: no keyserver host provided\n"); @@ -659,6 +707,26 @@ main(int argc,char *argv[]) goto fail; } + /* If the user gives a :port, then disable SRV. The semantics of a + specified port and SRV do not play well together. */ + if(opt->port) + port=opt->port; + else if(try_srv) + { +#ifdef HAVE_LIBCURL + /* We're using libcurl, so fake SRV support via our wrapper. + This isn't as good as true SRV support, as we do not try all + possible targets at one particular level and work our way + down the list, but it's better than nothing. */ + srv_replace(); +#else + /* We're using our internal curl shim, so we can use its (true) + SRV support. Obviously, CURLOPT_SRVTAG_GPG_HACK isn't a real + libcurl option. It's specific to our shim. */ + curl_easy_setopt(curl,CURLOPT_SRVTAG_GPG_HACK,opt->scheme); +#endif + } + curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); if(opt->auth) @@ -677,13 +745,6 @@ main(int argc,char *argv[]) if(proxy) curl_easy_setopt(curl,CURLOPT_PROXY,proxy); -#if 0 - /* By suggested convention, if the user gives a :port, then disable - SRV. */ - 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. */