diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 1e575e1e9..757eb78ac 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,3 +1,11 @@ +2011-02-09 Werner Koch + + * ks-action.c (ks_action_fetch): Support http URLs. + * ks-engine-http.c: New. + + * ks-engine-finger.c (ks_finger_get): Rename to ks_finger_fetch. + Change caller. + 2011-02-08 Werner Koch * server.c (cmd_ks_fetch): New. diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index a030f3861..6b27c7abc 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -51,7 +51,7 @@ dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c \ cdb.h cdblib.c ldap.c misc.c dirmngr-err.h w32-ldap-help.h \ ocsp.c ocsp.h validate.c validate.h ldap-wrapper.h $(ldap_url) \ ks-action.c ks-action.h ks-engine.h \ - ks-engine-hkp.c ks-engine-finger.c + ks-engine-hkp.c ks-engine-http.c ks-engine-finger.c if USE_LDAPWRAPPER dirmngr_SOURCES += ldap-wrapper.c diff --git a/dirmngr/ks-action.c b/dirmngr/ks-action.c index dff49979f..ec691fe2a 100644 --- a/dirmngr/ks-action.c +++ b/dirmngr/ks-action.c @@ -167,7 +167,12 @@ ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp) if (parsed_uri->is_http) { - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + err = ks_http_fetch (ctrl, url, &infp); + if (!err) + { + err = copy_stream (infp, outfp); + es_fclose (infp); + } } else if (!parsed_uri->opaque) { @@ -175,12 +180,10 @@ ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp) } else if (!strcmp (parsed_uri->scheme, "finger")) { - err = ks_finger_get (ctrl, parsed_uri, &infp); + err = ks_finger_fetch (ctrl, parsed_uri, &infp); if (!err) { err = copy_stream (infp, outfp); - /* Reading from the finger serrver should not fail, thus - return this error. */ es_fclose (infp); } } diff --git a/dirmngr/ks-engine-finger.c b/dirmngr/ks-engine-finger.c index c54e34351..c9e897f84 100644 --- a/dirmngr/ks-engine-finger.c +++ b/dirmngr/ks-engine-finger.c @@ -1,4 +1,4 @@ -/* ks-engine-finger.c - HKP keyserver engine +/* ks-engine-finger.c - Finger OpenPGP key access * Copyright (C) 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -33,7 +33,7 @@ /* Get the key from URI which is expected to specify a finger scheme. On success R_FP has an open stream to read the data. */ gpg_error_t -ks_finger_get (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp) +ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp) { gpg_error_t err; estream_t fp; diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c new file mode 100644 index 000000000..304e793f7 --- /dev/null +++ b/dirmngr/ks-engine-http.c @@ -0,0 +1,141 @@ +/* ks-engine-http.c - HTTP OpenPGP key access + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include + +#include +#include +#include +#include + +#include "dirmngr.h" +#include "misc.h" +#include "ks-engine.h" + +/* How many redirections do we allow. */ +#define MAX_REDIRECTS 2 + + +/* Get the key from URL which is expected to specify a http style + scheme. On success R_FP has an open stream to read the data. */ +gpg_error_t +ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) +{ + gpg_error_t err; + http_t http = NULL; + int redirects_left = MAX_REDIRECTS; + estream_t fp = NULL; + char *request_buffer = NULL; + + *r_fp = NULL; + once_more: + err = http_open (&http, + HTTP_REQ_GET, + url, + /* fixme: AUTH */ NULL, + 0, + /* fixme: proxy*/ NULL, + NULL, NULL, + /*FIXME curl->srvtag*/NULL); + if (!err) + { + fp = http_get_write_ptr (http); + /* Avoid caches to get the most recent copy of the key. We set + both the Pragma and Cache-Control versions of the header, so + we're good with both HTTP 1.0 and 1.1. */ + es_fputs ("Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n", fp); + http_start_data (http); + if (es_ferror (fp)) + err = gpg_error_from_syserror (); + } + if (err) + { + /* Fixme: After a redirection we show the old host name. */ + log_error (_("error connecting to `%s': %s\n"), + url, gpg_strerror (err)); + goto leave; + } + + /* Wait for the response. */ + dirmngr_tick (ctrl); + err = http_wait_response (http); + if (err) + { + log_error (_("error reading HTTP response for `%s': %s\n"), + url, gpg_strerror (err)); + goto leave; + } + + switch (http_get_status_code (http)) + { + case 200: + err = 0; + break; /* Success. */ + + case 301: + case 302: + { + const char *s = http_get_header (http, "Location"); + + log_info (_("URL `%s' redirected to `%s' (%u)\n"), + url, s?s:"[none]", http_get_status_code (http)); + if (s && *s && redirects_left-- ) + { + xfree (request_buffer); + request_buffer = xtrystrdup (s); + if (request_buffer) + { + url = request_buffer; + http_close (http, 0); + http = NULL; + goto once_more; + } + err = gpg_error_from_syserror (); + } + else + err = gpg_error (GPG_ERR_NO_DATA); + log_error (_("too many redirections\n")); + } + goto leave; + + default: + log_error (_("error accessing `%s': http status %u\n"), + url, http_get_status_code (http)); + err = gpg_error (GPG_ERR_NO_DATA); + goto leave; + } + + fp = http_get_read_ptr (http); + if (!fp) + { + err = gpg_error (GPG_ERR_BUG); + goto leave; + } + + /* Return the read stream and close the HTTP context. */ + *r_fp = fp; + http_close (http, 1); + http = NULL; + + leave: + http_close (http, 0); + xfree (request_buffer); + return err; +} diff --git a/dirmngr/ks-engine.h b/dirmngr/ks-engine.h index 50f42be4b..9d2afdf85 100644 --- a/dirmngr/ks-engine.h +++ b/dirmngr/ks-engine.h @@ -31,8 +31,12 @@ gpg_error_t ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, gpg_error_t ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen); +/*-- ks-engine-http.c --*/ +gpg_error_t ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp); + + /*-- ks-engine-finger.c --*/ -gpg_error_t ks_finger_get (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp); +gpg_error_t ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp);