diff options
-rw-r--r-- | common/http.c | 59 | ||||
-rw-r--r-- | common/http.h | 13 | ||||
-rw-r--r-- | keyserver/curl-shim.c | 27 | ||||
-rw-r--r-- | keyserver/gpgkeys_hkp.c | 16 |
4 files changed, 79 insertions, 36 deletions
diff --git a/common/http.c b/common/http.c index c12bd2b3e..ea8b8d5fe 100644 --- a/common/http.c +++ b/common/http.c @@ -1,6 +1,6 @@ /* http.c - HTTP protocol handler * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, - * 2009 Free Software Foundation, Inc. + * 2009, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -129,12 +129,12 @@ 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, - const char *srvtag,strlist_t headers); + struct http_srv *srv,strlist_t headers); static char *build_rel_path (parsed_uri_t uri); static gpg_error_t parse_response (http_t hd); static int connect_server (const char *server, unsigned short port, - unsigned int flags, const char *srvtag); + unsigned int flags, struct http_srv *srv); static gpg_error_t write_server (int sock, const char *data, size_t length); #ifdef HTTP_USE_ESTREAM @@ -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, const char *srvtag,strlist_t headers) + void *tls_context, struct http_srv *srv, strlist_t headers) { 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, srvtag, headers); + err = send_request (hd, auth, proxy, srv, headers); if (err) { @@ -457,12 +457,13 @@ 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, const char *srvtag,strlist_t headers) + void *tls_context, struct http_srv *srv, + strlist_t headers) { gpg_error_t err; err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, - proxy, tls_context, srvtag, headers); + proxy, tls_context, srv, headers); if (err) return err; @@ -836,7 +837,7 @@ parse_tuple (char *string) */ static gpg_error_t send_request (http_t hd, const char *auth, - const char *proxy,const char *srvtag,strlist_t headers) + const char *proxy, struct http_srv *srv, strlist_t headers) { gnutls_session_t tls_session; gpg_error_t err; @@ -894,13 +895,13 @@ send_request (http_t hd, const char *auth, hd->sock = connect_server (*uri->host ? uri->host : "localhost", uri->port ? uri->port : 80, - hd->flags, srvtag); + hd->flags, srv); save_errno = errno; http_release_parsed_uri (uri); } else { - hd->sock = connect_server (server, port, hd->flags, srvtag); + hd->sock = connect_server (server, port, hd->flags, srv); save_errno = errno; } @@ -1540,12 +1541,12 @@ start_server () error. ERRNO is set on error. */ static int connect_server (const char *server, unsigned short port, - unsigned int flags, const char *srvtag) + unsigned int flags, struct http_srv *srv) { int sock = -1; int srvcount = 0; int hostfound = 0; - int srv, connected; + int srvindex, connected, chosen=-1; int last_errno = 0; struct srventry *serverlist = NULL; @@ -1587,14 +1588,14 @@ connect_server (const char *server, unsigned short port, #ifdef USE_DNS_SRV /* Do the SRV thing */ - if (srvtag) + if (srv && srv->srvtag) { /* We're using SRV, so append the tags. */ - if (1+strlen (srvtag) + 6 + strlen (server) + 1 <= MAXDNAME) + if (1+strlen (srv->srvtag) + 6 + strlen (server) + 1 <= MAXDNAME) { char srvname[MAXDNAME]; - stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srvtag), + stpcpy (stpcpy (stpcpy (stpcpy (srvname,"_"), srv->srvtag), "._tcp."), server); srvcount = getsrv (srvname, &serverlist); } @@ -1616,15 +1617,15 @@ connect_server (const char *server, unsigned short port, #ifdef HAVE_GETADDRINFO connected = 0; - for (srv=0; srv < srvcount && !connected; srv++) + for (srvindex=0; srvindex < srvcount && !connected; srvindex++) { struct addrinfo hints, *res, *ai; char portstr[35]; - sprintf (portstr, "%hu", port); + sprintf (portstr, "%hu", serverlist[srvindex].port); memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; - if (getaddrinfo (serverlist[srv].target, portstr, &hints, &res)) + if (getaddrinfo (serverlist[srvindex].target, portstr, &hints, &res)) continue; /* Not found - try next one. */ hostfound = 1; @@ -1646,13 +1647,16 @@ connect_server (const char *server, unsigned short port, if (connect (sock, ai->ai_addr, ai->ai_addrlen)) last_errno = errno; else - connected = 1; + { + connected = 1; + chosen = srvindex; + } } freeaddrinfo (res); } #else /* !HAVE_GETADDRINFO */ connected = 0; - for (srv=0; srv < srvcount && !connected; srv++) + for (srvindex=0; srvindex < srvcount && !connected; srvindex++) { int i; struct hostent *host = NULL; @@ -1661,7 +1665,7 @@ connect_server (const char *server, unsigned short port, /* Note: This code is not thread-safe. */ memset (&addr, 0, sizeof (addr)); - host = gethostbyname (serverlist[srv].target); + host = gethostbyname (serverlist[srvindex].target); if (!host) continue; hostfound = 1; @@ -1680,15 +1684,15 @@ connect_server (const char *server, unsigned short port, if (addr.sin_family != AF_INET) { log_error ("unknown address family for `%s'\n", - serverlist[srv].target); + serverlist[srvindex].target); xfree (serverlist); return -1; } - addr.sin_port = htons (serverlist[srv].port); + addr.sin_port = htons (serverlist[srvindex].port); if (host->h_length != 4) { log_error ("illegal address length for `%s'\n", - serverlist[srv].target); + serverlist[srvindex].target); xfree (serverlist); return -1; } @@ -1702,12 +1706,19 @@ connect_server (const char *server, unsigned short port, else { connected = 1; + chosen = srvindex; break; } } } #endif /* !HAVE_GETADDRINFO */ + if(chosen>-1 && srv) + { + srv->used_server = xstrdup (serverlist[chosen].target); + srv->used_port = serverlist[chosen].port; + } + xfree (serverlist); if (!connected) diff --git a/common/http.h b/common/http.h index 28a5304eb..2b17ab7e8 100644 --- a/common/http.h +++ b/common/http.h @@ -1,6 +1,6 @@ /* http.h - HTTP protocol handler * Copyright (C) 1999, 2000, 2001, 2003, - * 2006 Free Software Foundation, Inc. + * 2006, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -76,13 +76,20 @@ gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri); void http_release_parsed_uri (parsed_uri_t uri); +struct http_srv +{ + const char *srvtag; + char *used_server; + unsigned short used_port; +}; + 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, - const char *srvtag, + struct http_srv *srv, strlist_t headers); void http_start_data (http_t hd); @@ -97,7 +104,7 @@ gpg_error_t http_open_document (http_t *r_hd, unsigned int flags, const char *proxy, void *tls_context, - const char *srvtag, + struct http_srv *srv, strlist_t headers); #ifdef HTTP_USE_ESTREAM diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c index 500d9f562..136436a10 100644 --- a/keyserver/curl-shim.c +++ b/keyserver/curl-shim.c @@ -1,7 +1,8 @@ /* curl-shim.c - Implement a small subset of the curl API in terms of * the iobuf HTTP API * - * Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, + * 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -174,6 +175,9 @@ curl_easy_perform(CURL *curl) CURLcode err=CURLE_OK; const char *errstr=NULL; char *proxy=NULL; + struct http_srv srv; + + memset(&srv,0,sizeof(srv)); /* Emulate the libcurl proxy behavior. If the calling program set a proxy, use it. If it didn't set a proxy or set it to NULL, check @@ -186,10 +190,17 @@ curl_easy_perform(CURL *curl) else proxy=getenv(HTTP_PROXY_ENV); + if(curl->srvtag) + srv.srvtag=curl->srvtag; + if(curl->flags.verbose) { fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null"); fprintf(curl->errors,"* HTTP URL is \"%s\"\n",curl->url); + if(srv.srvtag) + fprintf(curl->errors, + "* SRV tag is \"%s\": host and port may be overridden\n", + srv.srvtag); fprintf(curl->errors,"* HTTP auth is \"%s\"\n", curl->auth?curl->auth:"null"); fprintf(curl->errors,"* HTTP method is %s\n", @@ -199,12 +210,16 @@ curl_easy_perform(CURL *curl) if(curl->flags.post) { rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth, - 0, proxy, NULL, curl->srvtag, + 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { unsigned int post_len = strlen(curl->postfields); + if(curl->flags.verbose && srv.used_server && srv.used_port) + fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", + srv.used_server, srv.used_port); + es_fprintf (http_get_write_ptr (curl->hd), "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n", post_len); @@ -223,10 +238,14 @@ curl_easy_perform(CURL *curl) else { rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth, - 0, proxy, NULL, curl->srvtag, + 0, proxy, NULL, &srv, curl->headers?curl->headers->list:NULL); if (!rc) { + if(curl->flags.verbose && srv.used_server && srv.used_port) + fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n", + srv.used_server, srv.used_port); + rc = http_wait_response (curl->hd); curl->status = http_get_status_code (curl->hd); if (!rc) @@ -268,6 +287,8 @@ curl_easy_perform(CURL *curl) } } + xfree(srv.used_server); + switch(gpg_err_code (rc)) { case 0: diff --git a/keyserver/gpgkeys_hkp.c b/keyserver/gpgkeys_hkp.c index ee6421ab7..42113b43e 100644 --- a/keyserver/gpgkeys_hkp.c +++ b/keyserver/gpgkeys_hkp.c @@ -1,6 +1,6 @@ /* gpgkeys_hkp.c - talk to an HKP keyserver * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - * 2009 Free Software Foundation, Inc. + * 2009, 2012 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -693,6 +693,7 @@ main(int argc,char *argv[]) goto fail; } + /* Defaults */ if(ks_strcasecmp(opt->scheme,"hkps")==0) { proto="https"; @@ -725,11 +726,9 @@ 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) + /* Only use SRV if the user does not provide a :port. The semantics + of a specified port and SRV do not play well together. */ + if(!opt->port && try_srv) { char *srvtag; @@ -754,6 +753,11 @@ main(int argc,char *argv[]) #endif } + /* If the user provided a port (or it came in via SRV, above), + replace the default. */ + if(opt->port) + port=opt->port; + curl_easy_setopt(curl,CURLOPT_ERRORBUFFER,errorbuffer); if(opt->auth) |