X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fhttp.c;h=71706e1d1f4babe2657703721de46f2968adfef2;hp=b487cbc4ba229cdb7c4362b8a588ac66e89fc30f;hb=7828e81c7905a8e9b864c7e386c9ebadcb474b82;hpb=dc78acde56045fa55f3ea73be696d5e936500e06 diff --git a/src/http.c b/src/http.c index b487cbc4..71706e1d 100644 --- a/src/http.c +++ b/src/http.c @@ -44,6 +44,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # endif #endif +#ifdef HAVE_SSL +#include "gen_sslfunc.h" +#endif /* HAVE_SSL */ + #ifdef WINDOWS # include #endif @@ -269,7 +273,6 @@ http_process_connection (const char *hdr, void *arg) /* Whether a persistent connection is active. */ static int pc_active_p; - /* Host and port of currently active persistent connection. */ static unsigned char pc_last_host[4]; static unsigned short pc_last_port; @@ -277,6 +280,13 @@ static unsigned short pc_last_port; /* File descriptor of the currently active persistent connection. */ static int pc_last_fd; +#ifdef HAVE_SSL +/* Whether a ssl handshake has occoured on this connection */ +static int pc_active_ssl; +/* SSL connection of the currently active persistent connection. */ +static SSL *pc_last_ssl; +#endif /* HAVE_SSL */ + /* Mark the persistent connection as invalid. This is used by the CLOSE_* macros after they forcefully close a registered persistent connection. This does not close the file descriptor -- it is left @@ -286,6 +296,9 @@ static void invalidate_persistent (void) { pc_active_p = 0; +#ifdef HAVE_SSL + pc_active_ssl = 0; +#endif /* HAVE_SSL */ DEBUGP (("Invalidating fd %d from further reuse.\n", pc_last_fd)); } @@ -298,7 +311,11 @@ invalidate_persistent (void) If a previous connection was persistent, it is closed. */ static void +#ifndef HAVE_SSL register_persistent (const char *host, unsigned short port, int fd) +#else +register_persistent (const char *host, unsigned short port, int fd, SSL* ssl) +#endif /* HAVE_SSL */ { int success; @@ -317,6 +334,10 @@ register_persistent (const char *host, unsigned short port, int fd) persistent connection exists, but we then connect to a different host, and try to register a persistent connection to that one. */ +#ifdef HAVE_SSL + /* the ssl disconnect has to take place before the closing of pc_last_fd */ + if (pc_last_ssl) shutdown_ssl(pc_last_ssl); +#endif /* HAVE_SSL */ CLOSE (pc_last_fd); invalidate_persistent (); } @@ -329,6 +350,10 @@ register_persistent (const char *host, unsigned short port, int fd) pc_last_port = port; pc_last_fd = fd; pc_active_p = 1; +#ifdef HAVE_SSL + pc_last_ssl=ssl; + pc_active_ssl= ssl ? 1 : 0; +#endif /* HAVE_SSL */ DEBUGP (("Registered fd %d for persistent reuse.\n", fd)); } @@ -336,7 +361,11 @@ register_persistent (const char *host, unsigned short port, int fd) connecting to HOST:PORT. */ static int +#ifndef HAVE_SSL persistent_available_p (const char *host, unsigned short port) +#else +persistent_available_p (const char *host, unsigned short port,int ssl) +#endif /* HAVE_SSL */ { unsigned char this_host[4]; /* First, check whether a persistent connection is active at all. */ @@ -365,6 +394,15 @@ persistent_available_p (const char *host, unsigned short port) invalidate_persistent (); return 0; } +#ifdef HAVE_SSL + /* Fourth: check if current connection is (not) ssl, too. + This test is unlikely to fail because HTTP and HTTPS + typicaly use different ports. Yet it is possible (or so + I have been told) to run HTTPS and HTTP simultaneus on + the same port. */ + if (ssl!=pc_active_ssl) + return 0; +#endif /* HAVE_SSL */ return 1; } @@ -383,6 +421,7 @@ persistent_available_p (const char *host, unsigned short port) `pc_active_p && (fd) == pc_last_fd' is "we're *now* using an active, registered connection". */ +#ifndef HAVE_SSL #define CLOSE_FINISH(fd) do { \ if (!keep_alive) \ { \ @@ -398,6 +437,25 @@ persistent_available_p (const char *host, unsigned short port) invalidate_persistent (); \ } while (0) +#else + +#define CLOSE_FINISH(fd,ssl) do { \ + if (!keep_alive) \ + { \ + if (ssl) shutdown_ssl(ssl); \ + CLOSE (fd); \ + if (pc_active_p && (fd) == pc_last_fd) \ + invalidate_persistent (); \ + } \ +} while (0) + +#define CLOSE_INVALIDATE(fd,ssl) do { \ + if (ssl) shutdown_ssl(ssl); \ + CLOSE (fd); \ + if (pc_active_p && (fd) == pc_last_fd) \ + invalidate_persistent (); \ +} while (0) +#endif /* HAVE_SSL */ struct http_stat { @@ -466,6 +524,10 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) FILE *fp; int auth_tried_already; struct rbuf rbuf; +#ifdef HAVE_SSL + static SSL_CTX *ssl_ctx=NULL; + SSL *ssl=NULL; +#endif /* HAVE_SSL */ /* Whether this connection will be kept alive after the HTTP request is done. */ @@ -478,6 +540,11 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) /* Whether keep-alive should be inhibited. */ int inhibit_keep_alive; +#ifdef HAVE_SSL +/* initialize ssl_ctx on first run */ + if (!ssl_ctx) init_ssl(&ssl_ctx); +#endif /* HAVE_SSL */ + if (!(*dt & HEAD_ONLY)) /* If we're doing a GET on the URL, as opposed to just a HEAD, we need to know the local filename so we can save to it. */ @@ -512,11 +579,15 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) /* First: establish the connection. */ if (inhibit_keep_alive +#ifndef HAVE_SSL || !persistent_available_p (u->host, u->port)) +#else + || !persistent_available_p (u->host, u->port, (u->proto==URLHTTPS ? 1 : 0))) +#endif /* HAVE_SSL */ { logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port); err = make_connection (&sock, u->host, u->port); - switch (err) + switch (err) { case HOSTERR: logputs (LOG_VERBOSE, "\n"); @@ -548,6 +619,14 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) abort (); break; } +#ifdef HAVE_SSL + if (u->proto==URLHTTPS) if (connect_ssl(&ssl,ssl_ctx,sock)!=0) { + logputs (LOG_VERBOSE, "\n"); + logprintf (LOG_NOTQUIET, _("Unable to establish SSL connection.\n")); + CLOSE (sock); + return CONSSLERR; + } +#endif /* HAVE_SSL */ } else { @@ -555,6 +634,9 @@ gethttp (struct urlinfo *u, struct http_stat *hs, int *dt) /* #### pc_last_fd should be accessed through an accessor function. */ sock = pc_last_fd; +#ifdef HAVE_SSL + ssl = pc_last_ssl; +#endif /* HAVE_SSL */ DEBUGP (("Reusing fd %d.\n", sock)); } @@ -715,12 +797,24 @@ Accept: %s\r\n\ FREE_MAYBE (proxyauth); /* Send the request to server. */ +#ifdef HAVE_SSL + if (u->proto==URLHTTPS) { + num_written = ssl_iwrite (ssl, request, strlen (request)); + } else { +#endif /* HAVE_SSL */ num_written = iwrite (sock, request, strlen (request)); +#ifdef HAVE_SSL + } +#endif /* HAVE_SSL */ if (num_written < 0) { logprintf (LOG_VERBOSE, _("Failed writing HTTP request: %s.\n"), strerror (errno)); - CLOSE_INVALIDATE (sock); +#ifndef HAVE_SSL + CLOSE_INVALIDATE (sock); +#else + CLOSE_INVALIDATE (sock,ssl); +#endif /* HAVE_SSL */ return WRITEFAILED; } logprintf (LOG_VERBOSE, _("%s request sent, awaiting response... "), @@ -732,7 +826,11 @@ Accept: %s\r\n\ /* Before reading anything, initialize the rbuf. */ rbuf_initialize (&rbuf, sock); - +#ifdef HAVE_SSL + if (u->proto == URLHTTPS) { + rbuf.ssl=ssl; + } else { rbuf.ssl=NULL; } +#endif /* HAVE_SSL */ all_headers = NULL; all_length = 0; /* Header-fetching loop. */ @@ -767,7 +865,11 @@ Accept: %s\r\n\ FREE_MAYBE (type); FREE_MAYBE (hs->newloc); FREE_MAYBE (all_headers); - CLOSE_INVALIDATE (sock); +#ifndef HAVE_SSL + CLOSE_INVALIDATE (sock); +#else + CLOSE_INVALIDATE (sock,ssl); +#endif /* HAVE_SSL */ return HEOF; } else if (status == HG_ERROR) @@ -779,7 +881,11 @@ Accept: %s\r\n\ FREE_MAYBE (type); FREE_MAYBE (hs->newloc); FREE_MAYBE (all_headers); - CLOSE_INVALIDATE (sock); +#ifndef HAVE_SSL + CLOSE_INVALIDATE (sock); +#else + CLOSE_INVALIDATE (sock,ssl); +#endif /* HAVE_SSL */ return HERR; } @@ -919,7 +1025,11 @@ Accept: %s\r\n\ if (keep_alive) /* The server has promised that it will not close the connection when we're done. This means that we can register it. */ +#ifndef HAVE_SSL register_persistent (u->host, u->port, sock); +#else + register_persistent (u->host, u->port, sock, ssl); +#endif /* HAVE_SSL */ if ((statcode == HTTP_STATUS_UNAUTHORIZED) && authenticate_h) @@ -928,7 +1038,11 @@ Accept: %s\r\n\ FREE_MAYBE (type); type = NULL; FREEHSTAT (*hs); - CLOSE_FINISH (sock); +#ifndef HAVE_SSL + CLOSE_FINISH (sock); +#else + CLOSE_FINISH (sock,ssl); +#endif /* HAVE_SSL */ if (auth_tried_already) { /* If we have tried it already, then there is not point @@ -1004,7 +1118,11 @@ Accept: %s\r\n\ FREE_MAYBE (type); FREE_MAYBE (hs->newloc); FREE_MAYBE (all_headers); - CLOSE_INVALIDATE (sock); +#ifndef HAVE_SSL + CLOSE_INVALIDATE (sock); +#else + CLOSE_INVALIDATE (sock,ssl); +#endif /* HAVE_SSL */ return RANGEERR; } @@ -1034,7 +1152,11 @@ Accept: %s\r\n\ _("Location: %s%s\n"), hs->newloc ? hs->newloc : _("unspecified"), hs->newloc ? _(" [following]") : ""); - CLOSE_FINISH (sock); +#ifndef HAVE_SSL + CLOSE_FINISH (sock); +#else + CLOSE_FINISH (sock,ssl); +#endif /* HAVE_SSL */ FREE_MAYBE (type); FREE_MAYBE (all_headers); return NEWLOCATION; @@ -1075,7 +1197,11 @@ Accept: %s\r\n\ hs->res = 0; FREE_MAYBE (type); FREE_MAYBE (all_headers); - CLOSE_FINISH (sock); +#ifndef HAVE_SSL + CLOSE_FINISH (sock); +#else + CLOSE_FINISH (sock,ssl); +#endif /* HAVE_SSL */ return RETRFINISHED; } @@ -1089,7 +1215,11 @@ Accept: %s\r\n\ if (!fp) { logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno)); - CLOSE_FINISH (sock); +#ifndef HAVE_SSL + CLOSE_FINISH (sock); +#else + CLOSE_FINISH (sock,ssl); +#endif /* HAVE_SSL */ FREE_MAYBE (all_headers); return FOPENERR; } @@ -1129,7 +1259,11 @@ Accept: %s\r\n\ hs->res = -2; } FREE_MAYBE (all_headers); - CLOSE_FINISH (sock); +#ifndef HAVE_SSL + CLOSE_FINISH (sock); +#else + CLOSE_FINISH (sock,ssl); +#endif /* HAVE_SSL */ if (hs->res == -2) return FWRITEERR; return RETRFINISHED; @@ -1350,6 +1484,13 @@ File `%s' already there, will not retrieve.\n"), u->local); logprintf (LOG_NOTQUIET, _("Cannot write to `%s' (%s).\n"), u->local, strerror (errno)); FREEHSTAT (hstat); + return err; + break; + case CONSSLERR: + /* Another fatal error. */ + logputs (LOG_VERBOSE, "\n"); + logprintf (LOG_NOTQUIET, _("Unable to establish SSL connection.\n")); + FREEHSTAT (hstat); xfree (filename_plus_orig_suffix); /* must precede every return! */ return err; break;