aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/IO/IO.c10
-rw-r--r--src/IO/Makefile.am4
-rw-r--r--src/IO/http.c217
-rw-r--r--src/IO/ssl.h47
-rw-r--r--src/IO/tls.c (renamed from src/IO/ssl.c)431
-rw-r--r--src/IO/tls.h47
-rw-r--r--src/cache.c16
-rw-r--r--src/dialog.cc20
-rw-r--r--src/dillo.cc6
-rw-r--r--src/html.cc2
-rw-r--r--src/url.c25
-rw-r--r--src/url.h10
12 files changed, 478 insertions, 357 deletions
diff --git a/src/IO/IO.c b/src/IO/IO.c
index e5c5fc79..0cdb9499 100644
--- a/src/IO/IO.c
+++ b/src/IO/IO.c
@@ -21,7 +21,7 @@
#include "../klist.h"
#include "IO.h"
#include "iowatch.hh"
-#include "ssl.h"
+#include "tls.h"
/*
* Symbolic defines for shutdown() function
@@ -163,7 +163,7 @@ static bool_t IO_read(IOData_t *io)
ssize_t St;
bool_t ret = FALSE;
int io_key = io->Key;
- void *conn = a_Ssl_connection(io->FD);
+ void *conn = a_Tls_connection(io->FD);
_MSG(" IO_read\n");
@@ -172,7 +172,7 @@ static bool_t IO_read(IOData_t *io)
io->Status = 0;
while (1) {
- St = conn ? a_Ssl_read(conn, Buf, IOBufLen)
+ St = conn ? a_Tls_read(conn, Buf, IOBufLen)
: read(io->FD, Buf, IOBufLen);
if (St > 0) {
dStr_append_l(io->Buf, Buf, St);
@@ -217,13 +217,13 @@ static bool_t IO_write(IOData_t *io)
{
ssize_t St;
bool_t ret = FALSE;
- void *conn = a_Ssl_connection(io->FD);
+ void *conn = a_Tls_connection(io->FD);
_MSG(" IO_write\n");
io->Status = 0;
while (1) {
- St = conn ? a_Ssl_write(conn, io->Buf->str, io->Buf->len)
+ St = conn ? a_Tls_write(conn, io->Buf->str, io->Buf->len)
: write(io->FD, io->Buf->str, io->Buf->len);
if (St < 0) {
/* Error */
diff --git a/src/IO/Makefile.am b/src/IO/Makefile.am
index ff600521..d8fed40a 100644
--- a/src/IO/Makefile.am
+++ b/src/IO/Makefile.am
@@ -15,8 +15,8 @@ libDiof_a_SOURCES = \
about.c \
Url.h \
http.c \
- ssl.h \
- ssl.c \
+ tls.h \
+ tls.c \
dpi.c \
IO.c \
iowatch.cc \
diff --git a/src/IO/http.c b/src/IO/http.c
index e5c459ee..379d51c1 100644
--- a/src/IO/http.c
+++ b/src/IO/http.c
@@ -27,7 +27,7 @@
#include <arpa/inet.h> /* for inet_ntop */
#include "IO.h"
-#include "ssl.h"
+#include "tls.h"
#include "Url.h"
#include "../msg.h"
#include "../klist.h"
@@ -52,18 +52,18 @@ D_STMT_START { \
static const int HTTP_SOCKET_USE_PROXY = 0x1;
static const int HTTP_SOCKET_QUEUED = 0x2;
static const int HTTP_SOCKET_TO_BE_FREED = 0x4;
-static const int HTTP_SOCKET_SSL = 0x8;
+static const int HTTP_SOCKET_TLS = 0x8;
/* 'web' is just a reference (no need to deallocate it here). */
typedef struct {
int SockFD;
- uint_t connect_port;
uint_t flags;
DilloWeb *web; /* reference to client's web structure */
DilloUrl *url;
Dlist *addr_list; /* Holds the DNS answer */
ChainLink *Info; /* Used for CCC asynchronous operations */
- char *connected_to; /* Used for per-host connection limit */
+ char *connected_to; /* Used for per-server connection limit */
+ uint_t connect_port;
Dstr *https_proxy_reply;
} SocketData_t;
@@ -72,19 +72,23 @@ typedef struct {
*/
typedef struct {
char *host;
+ uint_t port;
+ bool_t https;
+
int active_conns;
+ int running_the_queue;
Dlist *queue;
-} HostConnection_t;
+} Server_t;
typedef struct {
int fd;
int skey;
} FdMapEntry_t;
-static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock);
-static HostConnection_t *Http_host_connection_get(const char *host);
-static void Http_host_connection_remove(HostConnection_t *hc);
-static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc);
+static void Http_socket_enqueue(Server_t *srv, SocketData_t* sock);
+static Server_t *Http_server_get(const char *host, uint_t port, bool_t https);
+static void Http_server_remove(Server_t *srv);
+static void Http_connect_socket(ChainLink *Info);
static char *Http_get_connect_str(const DilloUrl *url);
static void Http_send_query(SocketData_t *S);
static void Http_socket_free(int SKey);
@@ -97,7 +101,7 @@ static Klist_t *ValidSocks = NULL; /* Active sockets list. It holds pointers to
static DilloUrl *HTTP_Proxy = NULL;
static char *HTTP_Proxy_Auth_base64 = NULL;
static char *HTTP_Language_hdr = NULL;
-static Dlist *host_connections;
+static Dlist *servers;
/* TODO: If fd_map will stick around in its present form (FDs and SocketData_t)
* then consider whether having both this and ValidSocks is necessary.
@@ -127,7 +131,7 @@ int a_Http_init(void)
HTTP_Proxy_Auth_base64 = a_Misc_encode_base64(prefs.http_proxyuser);
*/
- host_connections = dList_new(5);
+ servers = dList_new(5);
fd_map = dList_new(20);
return 0;
@@ -211,12 +215,14 @@ void a_Http_connect_done(int fd, bool_t success)
if (fme && (sd = a_Klist_get_data(ValidSocks, fme->skey))) {
ChainLink *info = sd->Info;
+ bool_t valid_web = a_Web_valid(sd->web);
- if (success) {
+ if (success && valid_web) {
a_Chain_bfcb(OpSend, info, &sd->SockFD, "FD");
Http_send_query(sd);
} else {
- MSG_BW(sd->web, 1, "Could not establish connection.");
+ if (valid_web)
+ MSG_BW(sd->web, 1, "Could not establish connection.");
MSG("fd %d is done and failed\n", sd->SockFD);
dClose(fd);
Http_socket_free(VOIDP2INT(info->LocalKey)); /* free sd */
@@ -228,48 +234,56 @@ void a_Http_connect_done(int fd, bool_t success)
}
}
-static void Http_socket_activate(HostConnection_t *hc, SocketData_t *sd)
+static void Http_socket_activate(Server_t *srv, SocketData_t *sd)
{
- dList_remove(hc->queue, sd);
+ dList_remove(srv->queue, sd);
sd->flags &= ~HTTP_SOCKET_QUEUED;
- hc->active_conns++;
- sd->connected_to = hc->host;
+ srv->active_conns++;
+ sd->connected_to = srv->host;
}
-static void Http_connect_queued_sockets(HostConnection_t *hc)
+static void Http_connect_queued_sockets(Server_t *srv)
{
SocketData_t *sd;
int i;
+ srv->running_the_queue++;
+
for (i = 0;
- i < dList_length(hc->queue) && hc->active_conns < prefs.http_max_conns;
+ (i < dList_length(srv->queue) &&
+ srv->active_conns < prefs.http_max_conns);
i++) {
- sd = dList_nth_data(hc->queue, i);
+ sd = dList_nth_data(srv->queue, i);
- if (!(sd->flags & HTTP_SOCKET_TO_BE_FREED)) {
- int connect_ready = SSL_CONNECT_READY;
+ if (sd->flags & HTTP_SOCKET_TO_BE_FREED) {
+ dList_remove(srv->queue, sd);
+ dFree(sd);
+ i--;
+ } else {
+ int connect_ready = TLS_CONNECT_READY;
- if (sd->flags & HTTP_SOCKET_SSL)
- connect_ready = a_Ssl_connect_ready(sd->url);
+ if (sd->flags & HTTP_SOCKET_TLS)
+ connect_ready = a_Tls_connect_ready(sd->url);
- if (connect_ready == SSL_CONNECT_NEVER || !a_Web_valid(sd->web)) {
+ if (connect_ready == TLS_CONNECT_NEVER || !a_Web_valid(sd->web)) {
int SKey = VOIDP2INT(sd->Info->LocalKey);
Http_socket_free(SKey);
- } else if (connect_ready == SSL_CONNECT_READY) {
+ } else if (connect_ready == TLS_CONNECT_READY) {
i--;
- Http_socket_activate(hc, sd);
- Http_connect_socket(sd->Info, hc);
+ Http_socket_activate(srv, sd);
+ Http_connect_socket(sd->Info);
}
}
- if (sd->flags & HTTP_SOCKET_TO_BE_FREED) {
- dList_remove(hc->queue, sd);
- dFree(sd);
- i--;
- }
}
- _MSG("Queue %s len %d\n", hc->host, dList_length(hc->queue));
+ _MSG("Queue http%s://%s:%u len %d\n", srv->https ? "s" : "", srv->host,
+ srv->port, dList_length(srv->queue));
+
+ if (--srv->running_the_queue == 0) {
+ if (srv->active_conns == 0)
+ Http_server_remove(srv);
+ }
}
/*
@@ -290,15 +304,14 @@ static void Http_socket_free(int SKey)
} else {
if (S->SockFD != -1)
Http_fd_map_remove_entry(S->SockFD);
- a_Ssl_reset_server_state(S->url);
+ a_Tls_reset_server_state(S->url);
if (S->connected_to) {
- a_Ssl_close_by_fd(S->SockFD);
+ a_Tls_close_by_fd(S->SockFD);
- HostConnection_t *hc = Http_host_connection_get(S->connected_to);
- hc->active_conns--;
- Http_connect_queued_sockets(hc);
- if (hc->active_conns == 0)
- Http_host_connection_remove(hc);
+ Server_t *srv = Http_server_get(S->connected_to, S->connect_port,
+ (S->flags & HTTP_SOCKET_TLS));
+ srv->active_conns--;
+ Http_connect_queued_sockets(srv);
}
a_Url_free(S->url);
dFree(S);
@@ -478,9 +491,9 @@ static void Http_send_query(SocketData_t *S)
/*
* Prepare an HTTPS connection. If necessary, tunnel it through a proxy.
- * Then perform the SSL handshake.
+ * Then perform the TLS handshake.
*/
-static void Http_connect_ssl(ChainLink *info)
+static void Http_connect_tls(ChainLink *info)
{
int SKey = VOIDP2INT(info->LocalKey);
SocketData_t *S = a_Klist_get_data(ValidSocks, SKey);
@@ -496,7 +509,7 @@ static void Http_connect_ssl(ChainLink *info)
dFree(dbuf);
dFree(connect_str);
} else {
- a_Ssl_handshake(S->SockFD, S->url);
+ a_Tls_handshake(S->SockFD, S->url);
}
}
@@ -504,7 +517,7 @@ static void Http_connect_ssl(ChainLink *info)
* This function is called after the DNS succeeds in solving a hostname.
* Task: Finish socket setup and start connecting the socket.
*/
-static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc)
+static void Http_connect_socket(ChainLink *Info)
{
int i, status;
SocketData_t *S;
@@ -542,7 +555,7 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc)
sin->sin_port = htons(S->connect_port);
memcpy(&sin->sin_addr, dh->data, (size_t)dh->alen);
if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl))
- MSG("Connecting to %s:%d\n", inet_ntoa(sin->sin_addr),
+ MSG("Connecting to %s:%u\n", inet_ntoa(sin->sin_addr),
S->connect_port);
break;
}
@@ -557,7 +570,7 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc)
memcpy(&sin6->sin6_addr, dh->data, dh->alen);
inet_ntop(dh->af, dh->data, buf, sizeof(buf));
if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl))
- MSG("Connecting to %s:%d\n", buf, S->connect_port);
+ MSG("Connecting to %s:%u\n", buf, S->connect_port);
break;
}
#endif
@@ -567,8 +580,8 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc)
if (status == -1 && errno != EINPROGRESS) {
MSG("Http_connect_socket ERROR: %s\n", dStrerror(errno));
a_Http_connect_done(S->SockFD, FALSE);
- } else if (S->flags & HTTP_SOCKET_SSL) {
- Http_connect_ssl(Info);
+ } else if (S->flags & HTTP_SOCKET_TLS) {
+ Http_connect_tls(Info);
} else {
a_Http_connect_done(S->SockFD, TRUE);
}
@@ -658,7 +671,7 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data)
int SKey = VOIDP2INT(data);
bool_t clean_up = TRUE;
SocketData_t *S;
- HostConnection_t *hc;
+ Server_t *srv;
S = a_Klist_get_data(ValidSocks, SKey);
if (S) {
@@ -670,9 +683,10 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data)
/* Successful DNS answer; save the IP */
S->addr_list = addr_list;
clean_up = FALSE;
- hc = Http_host_connection_get(host);
- Http_socket_enqueue(hc, S);
- Http_connect_queued_sockets(hc);
+ srv = Http_server_get(host, S->connect_port,
+ (S->flags & HTTP_SOCKET_TLS));
+ Http_socket_enqueue(srv, S);
+ Http_connect_queued_sockets(srv);
} else {
/* DNS wasn't able to resolve the hostname */
MSG_BW(S->web, 0, "ERROR: DNS can't resolve %s", host);
@@ -718,7 +732,7 @@ static int Http_get(ChainLink *Info, void *Data1)
S->connect_port = URL_PORT(url);
S->url = a_Url_dup(S->web->url);
if (!dStrAsciiCasecmp(URL_SCHEME(S->url), "https"))
- S->flags |= HTTP_SOCKET_SSL;
+ S->flags |= HTTP_SOCKET_TLS;
/* Let the user know what we'll do */
MSG_BW(S->web, 1, "DNS resolving %s", hostname);
@@ -734,16 +748,18 @@ static int Http_get(ChainLink *Info, void *Data1)
/*
* Can the old socket's fd be reused for the new socket?
*
- * NOTE: old and new must come from the same HostConnection_t.
+ * NOTE: old and new must come from the same Server_t.
* This is not built to accept arbitrary sockets.
*/
static bool_t Http_socket_reuse_compatible(SocketData_t *old,
SocketData_t *new)
{
+ /*
+ * If we are using TLS through a proxy, we need to ensure that old and new
+ * are going through to the same host:port.
+ */
if (a_Web_valid(new->web) &&
- old->connect_port == new->connect_port &&
- ((old->flags & HTTP_SOCKET_SSL) == (new->flags & HTTP_SOCKET_SSL)) &&
- ((old->flags & HTTP_SOCKET_SSL) == 0 ||
+ ((old->flags & HTTP_SOCKET_TLS) == 0 ||
(old->flags & HTTP_SOCKET_USE_PROXY) == 0 ||
((URL_PORT(old->url) == URL_PORT(new->url)) &&
!dStrAsciiCasecmp(URL_HOST(old->url), URL_HOST(new->url)))))
@@ -760,11 +776,13 @@ static void Http_socket_reuse(int SKey)
SocketData_t *new_sd, *old_sd = a_Klist_get_data(ValidSocks, SKey);
if (old_sd) {
- HostConnection_t *hc = Http_host_connection_get(old_sd->connected_to);
- int i, n = dList_length(hc->queue);
+ Server_t *srv = Http_server_get(old_sd->connected_to,
+ old_sd->connect_port,
+ (old_sd->flags & HTTP_SOCKET_TLS));
+ int i, n = dList_length(srv->queue);
for (i = 0; i < n; i++) {
- new_sd = dList_nth_data(hc->queue, i);
+ new_sd = dList_nth_data(srv->queue, i);
if (!(new_sd->flags & HTTP_SOCKET_TO_BE_FREED) &&
Http_socket_reuse_compatible(old_sd, new_sd)) {
@@ -773,11 +791,11 @@ static void Http_socket_reuse(int SKey)
new_sd->SockFD = old_sd->SockFD;
old_sd->connected_to = NULL;
- hc->active_conns--;
+ srv->active_conns--;
Http_socket_free(SKey);
MSG("Reusing fd %d for %s\n", new_sd->SockFD,URL_STR(new_sd->url));
- Http_socket_activate(hc, new_sd);
+ Http_socket_activate(srv, new_sd);
Http_fd_map_add_entry(new_sd);
a_Http_connect_done(new_sd->SockFD, success);
return;
@@ -863,7 +881,7 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info,
sd->https_proxy_reply->str);
dStr_free(sd->https_proxy_reply, 1);
sd->https_proxy_reply = NULL;
- a_Ssl_handshake(sd->SockFD, sd->url);
+ a_Tls_handshake(sd->SockFD, sd->url);
} else {
MSG_BW(sd->web, 1, "Can't connect through proxy to %s",
URL_HOST(sd->url));
@@ -935,68 +953,77 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info,
* Add socket data to the queue. Pages/stylesheets/etc. have higher priority
* than images.
*/
-static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock)
+static void Http_socket_enqueue(Server_t *srv, SocketData_t* sock)
{
sock->flags |= HTTP_SOCKET_QUEUED;
if ((sock->web->flags & WEB_Image) == 0) {
- int i, n = dList_length(hc->queue);
+ int i, n = dList_length(srv->queue);
for (i = 0; i < n; i++) {
- SocketData_t *curr = dList_nth_data(hc->queue, i);
+ SocketData_t *curr = dList_nth_data(srv->queue, i);
if (a_Web_valid(curr->web) && (curr->web->flags & WEB_Image)) {
- dList_insert_pos(hc->queue, sock, i);
+ dList_insert_pos(srv->queue, sock, i);
return;
}
}
}
- dList_append(hc->queue, sock);
+ dList_append(srv->queue, sock);
}
-static HostConnection_t *Http_host_connection_get(const char *host)
+static Server_t *Http_server_get(const char *host, uint_t port, bool_t https)
{
int i;
- HostConnection_t *hc;
+ Server_t *srv;
- for (i = 0; i < dList_length(host_connections); i++) {
- hc = (HostConnection_t*) dList_nth_data(host_connections, i);
+ for (i = 0; i < dList_length(servers); i++) {
+ srv = (Server_t*) dList_nth_data(servers, i);
- if (dStrAsciiCasecmp(host, hc->host) == 0)
- return hc;
+ if (port == srv->port && https == srv->https &&
+ !dStrAsciiCasecmp(host, srv->host))
+ return srv;
}
- hc = dNew0(HostConnection_t, 1);
- hc->queue = dList_new(10);
- hc->host = dStrdup(host);
- dList_append(host_connections, hc);
+ srv = dNew0(Server_t, 1);
+ srv->queue = dList_new(10);
+ srv->running_the_queue = 0;
+ srv->host = dStrdup(host);
+ srv->port = port;
+ srv->https = https;
+ dList_append(servers, srv);
- return hc;
+ return srv;
}
-static void Http_host_connection_remove(HostConnection_t *hc)
+static void Http_server_remove(Server_t *srv)
{
- assert(dList_length(hc->queue) == 0);
- dList_free(hc->queue);
- dList_remove_fast(host_connections, hc);
- dFree(hc->host);
- dFree(hc);
+ SocketData_t *sd;
+
+ while ((sd = dList_nth_data(srv->queue, 0))) {
+ dList_remove_fast(srv->queue, sd);
+ dFree(sd);
+ }
+ dList_free(srv->queue);
+ dList_remove_fast(servers, srv);
+ dFree(srv->host);
+ dFree(srv);
}
-static void Http_host_connection_remove_all()
+static void Http_servers_remove_all()
{
- HostConnection_t *hc;
+ Server_t *srv;
SocketData_t *sd;
- while (dList_length(host_connections) > 0) {
- hc = (HostConnection_t*) dList_nth_data(host_connections, 0);
- while ((sd = dList_nth_data(hc->queue, 0))) {
- dList_remove(hc->queue, sd);
+ while (dList_length(servers) > 0) {
+ srv = (Server_t*) dList_nth_data(servers, 0);
+ while ((sd = dList_nth_data(srv->queue, 0))) {
+ dList_remove(srv->queue, sd);
dFree(sd);
}
- Http_host_connection_remove(hc);
+ Http_server_remove(srv);
}
- dList_free(host_connections);
+ dList_free(servers);
}
static void Http_fd_map_remove_all()
@@ -1017,7 +1044,7 @@ static void Http_fd_map_remove_all()
*/
void a_Http_freeall(void)
{
- Http_host_connection_remove_all();
+ Http_servers_remove_all();
Http_fd_map_remove_all();
a_Klist_free(&ValidSocks);
a_Url_free(HTTP_Proxy);
diff --git a/src/IO/ssl.h b/src/IO/ssl.h
deleted file mode 100644
index f55479b2..00000000
--- a/src/IO/ssl.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __SSL_H__
-#define __SSL_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "../url.h"
-
-#define SSL_CONNECT_NEVER -1
-#define SSL_CONNECT_NOT_YET 0
-#define SSL_CONNECT_READY 1
-
-void a_Ssl_init();
-
-
-#ifdef ENABLE_SSL
-int a_Ssl_connect_ready(const DilloUrl *url);
-void a_Ssl_reset_server_state(const DilloUrl *url);
-
-/* Use to initiate a SSL connection. */
-void a_Ssl_handshake(int fd, const DilloUrl *url);
-
-void *a_Ssl_connection(int fd);
-
-void a_Ssl_freeall();
-
-void a_Ssl_close_by_fd(int fd);
-int a_Ssl_read(void *conn, void *buf, size_t len);
-int a_Ssl_write(void *conn, void *buf, size_t len);
-#else
-
-#define a_Ssl_connect_ready(url) SSL_CONNECT_NEVER
-#define a_Ssl_reset_server_state(url) ;
-#define a_Ssl_handshake(fd, url) ;
-#define a_Ssl_connection(fd) NULL
-#define a_Ssl_freeall() ;
-#define a_Ssl_close_by_fd(fd) ;
-#define a_Ssl_read(conn, buf, len) 0
-#define a_Ssl_write(conn, buf, len) 0
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __SSL_H__ */
-
diff --git a/src/IO/ssl.c b/src/IO/tls.c
index 856d94b5..f0f33215 100644
--- a/src/IO/ssl.c
+++ b/src/IO/tls.c
@@ -1,5 +1,5 @@
/*
- * File: ssl.c
+ * File: tls.c
*
* Copyright 2004 Garrett Kajmowicz <gkajmowi@tbaytel.net>
* (for some bits derived from the https dpi, e.g., certificate handling)
@@ -33,9 +33,9 @@
#ifndef ENABLE_SSL
-void a_Ssl_init()
+void a_Tls_init()
{
- MSG("SSL: Disabled at compilation time.\n");
+ MSG("TLS: Disabled at compilation time.\n");
}
#else
@@ -52,7 +52,7 @@ void a_Ssl_init()
#include "../dialog.hh"
#include "../klist.h"
#include "iowatch.hh"
-#include "ssl.h"
+#include "tls.h"
#include "Url.h"
#include <openssl/ssl.h>
@@ -78,7 +78,7 @@ typedef struct {
} FdMapEntry_t;
/*
- * Data type for SSL connection information
+ * Data type for TLS connection information
*/
typedef struct {
int fd;
@@ -87,22 +87,22 @@ typedef struct {
bool_t connecting;
} Conn_t;
-/* List of active SSL connections */
+/* List of active TLS connections */
static Klist_t *conn_list = NULL;
/*
- * If ssl_context is still NULL, this corresponds to SSL being disabled.
+ * If ssl_context is still NULL, this corresponds to TLS being disabled.
*/
static SSL_CTX *ssl_context;
static Dlist *servers;
static Dlist *fd_map;
-static void Ssl_connect_cb(int fd, void *vssl);
+static void Tls_connect_cb(int fd, void *vconnkey);
/*
* Compare by FD.
*/
-static int Ssl_fd_map_cmp(const void *v1, const void *v2)
+static int Tls_fd_map_cmp(const void *v1, const void *v2)
{
int fd = VOIDP2INT(v2);
const FdMapEntry_t *e = v1;
@@ -110,14 +110,14 @@ static int Ssl_fd_map_cmp(const void *v1, const void *v2)
return (fd != e->fd);
}
-static void Ssl_fd_map_add_entry(int fd, int connkey)
+static void Tls_fd_map_add_entry(int fd, int connkey)
{
FdMapEntry_t *e = dNew0(FdMapEntry_t, 1);
e->fd = fd;
e->connkey = connkey;
- if (dList_find_custom(fd_map, INT2VOIDP(e->fd), Ssl_fd_map_cmp)) {
- MSG_ERR("SSL FD ENTRY ALREADY FOUND FOR %d\n", e->fd);
+ if (dList_find_custom(fd_map, INT2VOIDP(e->fd), Tls_fd_map_cmp)) {
+ MSG_ERR("TLS FD ENTRY ALREADY FOUND FOR %d\n", e->fd);
assert(0);
}
@@ -128,30 +128,30 @@ static void Ssl_fd_map_add_entry(int fd, int connkey)
/*
* Remove and free entry from fd_map.
*/
-static void Ssl_fd_map_remove_entry(int fd)
+static void Tls_fd_map_remove_entry(int fd)
{
- void *data = dList_find_custom(fd_map, INT2VOIDP(fd), Ssl_fd_map_cmp);
+ void *data = dList_find_custom(fd_map, INT2VOIDP(fd), Tls_fd_map_cmp);
//MSG("REMOVE ENTRY %d\n", fd);
if (data) {
dList_remove_fast(fd_map, data);
dFree(data);
} else {
- MSG("SSL FD ENTRY NOT FOUND FOR %d\n", fd);
+ MSG("TLS FD ENTRY NOT FOUND FOR %d\n", fd);
}
}
/*
- * Return SSL connection information for a given file
- * descriptor, or NULL if no SSL connection was found.
+ * Return TLS connection information for a given file
+ * descriptor, or NULL if no TLS connection was found.
*/
-void *a_Ssl_connection(int fd)
+void *a_Tls_connection(int fd)
{
Conn_t *conn;
if (fd_map) {
FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd),
- Ssl_fd_map_cmp);
+ Tls_fd_map_cmp);
if (fme && (conn = a_Klist_get_data(conn_list, fme->connkey)))
return conn;
@@ -160,9 +160,9 @@ void *a_Ssl_connection(int fd)
}
/*
- * Add a new SSL connection information node.
+ * Add a new TLS connection information node.
*/
-static int Ssl_conn_new(int fd, const DilloUrl *url, SSL *ssl)
+static int Tls_conn_new(int fd, const DilloUrl *url, SSL *ssl)
{
int key;
@@ -174,19 +174,22 @@ static int Ssl_conn_new(int fd, const DilloUrl *url, SSL *ssl)
key = a_Klist_insert(&conn_list, conn);
- Ssl_fd_map_add_entry(fd, key);
+ Tls_fd_map_add_entry(fd, key);
return key;
}
/*
- * Let's monitor for ssl alerts.
+ * Let's monitor for TLS alerts.
*/
-static void Ssl_info_cb(const SSL *ssl, int where, int ret)
+static void Tls_info_cb(const SSL *ssl, int where, int ret)
{
if (where & SSL_CB_ALERT) {
- MSG("SSL ALERT on %s: %s\n", (where & SSL_CB_READ) ? "read" : "write",
- SSL_alert_desc_string_long(ret));
+ const char *str = SSL_alert_desc_string_long(ret);
+
+ if (strcmp(str, "close notify"))
+ MSG("TLS ALERT on %s: %s\n", (where & SSL_CB_READ) ? "read" : "write",
+ str);
}
}
@@ -197,7 +200,7 @@ static void Ssl_info_cb(const SSL *ssl, int where, int ret)
* abysmal openssl documentation, this was worked out from reading discussion
* on the web and then reading openssl source to see what it normally does.
*/
-static void Ssl_load_certificates()
+static void Tls_load_certificates()
{
/* curl-7.37.1 says that the following bundle locations are used on "Debian
* systems", "Redhat and Mandriva", "old(er) Redhat", "FreeBSD", and
@@ -207,7 +210,7 @@ static void Ssl_load_certificates()
*/
uint_t u;
char *userpath;
- static const char *ca_files[] = {
+ static const char *const ca_files[] = {
"/etc/ssl/certs/ca-certificates.crt",
"/etc/pki/tls/certs/ca-bundle.crt",
"/usr/share/ssl/certs/ca-bundle.crt",
@@ -216,7 +219,7 @@ static void Ssl_load_certificates()
CA_CERTS_FILE
};
- static const char *ca_paths[] = {
+ static const char *const ca_paths[] = {
"/etc/ssl/certs/",
CA_CERTS_DIR
};
@@ -247,7 +250,7 @@ static void Ssl_load_certificates()
/*
* Initialize the OpenSSL library.
*/
-void a_Ssl_init(void)
+void a_Tls_init(void)
{
SSL_library_init();
SSL_load_error_strings();
@@ -266,7 +269,7 @@ void a_Ssl_init(void)
return;
}
- SSL_CTX_set_info_callback(ssl_context, Ssl_info_cb);
+ SSL_CTX_set_info_callback(ssl_context, Tls_info_cb);
/* Don't want: eNULL, which has no encryption; aNULL, which has no
* authentication; LOW, which as of 2014 use 64 or 56-bit encryption;
@@ -285,7 +288,7 @@ void a_Ssl_init(void)
/* This lets us deal with self-signed certificates */
SSL_CTX_set_verify(ssl_context, SSL_VERIFY_NONE, NULL);
- Ssl_load_certificates();
+ Tls_load_certificates();
fd_map = dList_new(20);
servers = dList_new(8);
@@ -295,7 +298,7 @@ void a_Ssl_init(void)
* Save certificate with a hashed filename.
* Return: 0 on success, 1 on failure.
*/
-static int Ssl_save_certificate_home(X509 * cert)
+static int Tls_save_certificate_home(X509 * cert)
{
char buf[4096];
@@ -338,16 +341,30 @@ static int Ssl_save_certificate_home(X509 * cert)
}
/*
- * Test whether a URL corresponds to a server.
+ * Ordered comparison of servers.
*/
-static int Ssl_servers_cmp(const void *v1, const void *v2)
+static int Tls_servers_cmp(const void *v1, const void *v2)
{
- Server_t *s = (Server_t *)v1;
+ const Server_t *s1 = (const Server_t *)v1, *s2 = (const Server_t *)v2;
+ int cmp = dStrAsciiCasecmp(s1->hostname, s2->hostname);
+
+ if (!cmp)
+ cmp = s1->port - s2->port;
+ return cmp;
+}
+/*
+ * Ordered comparison of server with URL.
+ */
+static int Tls_servers_by_url_cmp(const void *v1, const void *v2)
+{
+ const Server_t *s = (const Server_t *)v1;
const DilloUrl *url = (const DilloUrl *)v2;
- const char *host = URL_HOST(url);
- int port = URL_PORT(url);
- return (dStrAsciiCasecmp(s->hostname, host) || (port != s->port));
+ int cmp = dStrAsciiCasecmp(s->hostname, URL_HOST(url));
+
+ if (!cmp)
+ cmp = s->port - URL_PORT(url);
+ return cmp;
}
/*
@@ -355,41 +372,31 @@ static int Ssl_servers_cmp(const void *v1, const void *v2)
* Once we have the certificate, know whether we like it -- and whether the
* user accepts it -- HTTP can run through queued sockets as normal.
*
- * Return: 1 means yes, 0 means not yet, -1 means never.
- * TODO: Something clearer or different.
+ * Return: TLS_CONNECT_READY or TLS_CONNECT_NOT_YET or TLS_CONNECT_NEVER.
*/
-int a_Ssl_connect_ready(const DilloUrl *url)
+int a_Tls_connect_ready(const DilloUrl *url)
{
Server_t *s;
- int i, len;
- const char *host = URL_HOST(url);
- const int port = URL_PORT(url);
- int ret = SSL_CONNECT_READY;
+ int ret = TLS_CONNECT_READY;
- dReturn_val_if_fail(ssl_context, SSL_CONNECT_NEVER);
+ dReturn_val_if_fail(ssl_context, TLS_CONNECT_NEVER);
- len = dList_length(servers);
+ if ((s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp))) {
+ if (s->cert_status == CERT_STATUS_RECEIVING)
+ ret = TLS_CONNECT_NOT_YET;
+ else if (s->cert_status == CERT_STATUS_BAD)
+ ret = TLS_CONNECT_NEVER;
- for (i = 0; i < len; i++) {
- s = dList_nth_data(servers, i);
-
- if (!dStrAsciiCasecmp(s->hostname, host) && (port == s->port)) {
- if (s->cert_status == CERT_STATUS_RECEIVING)
- ret = SSL_CONNECT_NOT_YET;
- else if (s->cert_status == CERT_STATUS_BAD)
- ret = SSL_CONNECT_NEVER;
+ if (s->cert_status == CERT_STATUS_NONE)
+ s->cert_status = CERT_STATUS_RECEIVING;
+ } else {
+ s = dNew(Server_t, 1);
- if (s->cert_status == CERT_STATUS_NONE)
- s->cert_status = CERT_STATUS_RECEIVING;
- return ret;
- }
+ s->hostname = dStrdup(URL_HOST(url));
+ s->port = URL_PORT(url);
+ s->cert_status = CERT_STATUS_RECEIVING;
+ dList_insert_sorted(servers, s, Tls_servers_cmp);
}
- s = dNew(Server_t, 1);
-
- s->port = port;
- s->hostname = dStrdup(host);
- s->cert_status = CERT_STATUS_RECEIVING;
- dList_append(servers, s);
return ret;
}
@@ -397,9 +404,9 @@ int a_Ssl_connect_ready(const DilloUrl *url)
* Did we find problems with the certificate, and did the user proceed to
* reject the connection?
*/
-static int Ssl_user_said_no(const DilloUrl *url)
+static int Tls_user_said_no(const DilloUrl *url)
{
- Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp);
+ Server_t *s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp);
if (!s)
return FALSE;
@@ -407,20 +414,6 @@ static int Ssl_user_said_no(const DilloUrl *url)
return s->cert_status == CERT_STATUS_BAD;
}
-/*
- * Did we find problems with the certificate, and did the user proceed to
- * accept the connection anyway?
- */
-static int Ssl_user_said_yes(const DilloUrl *url)
-{
- Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp);
-
- if (!s)
- return FALSE;
-
- return s->cert_status == CERT_STATUS_USER_ACCEPTED;
-}
-
/******************** BEGINNING OF STUFF DERIVED FROM wget-1.16.3 */
#define ASTERISK_EXCLUDES_DOT /* mandated by rfc2818 */
@@ -466,13 +459,18 @@ static bool_t pattern_match (const char *pattern, const char *string)
return *n == '\0';
}
-static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
+/*
+ * Check that the certificate corresponds to the site it's presented for.
+ *
+ * Return TRUE if the hostname matched or the user indicated acceptance.
+ * FALSE on failure.
+ */
+static bool_t Tls_check_cert_hostname(X509 *cert, const char *host,
int *choice)
{
- dReturn_val_if_fail(cert && url, -1);
+ dReturn_val_if_fail(cert && host, FALSE);
char *msg;
- const char *host = URL_HOST(url);
GENERAL_NAMES *subjectAltNames;
bool_t success = TRUE, alt_name_checked = FALSE;;
char common_name[256];
@@ -493,6 +491,10 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
{
/* Test subject alternative names */
+ Dstr *err = dStr_new("");
+ dStr_sprintf(err, "Hostname %s does not match any of certificate's "
+ "Subject Alternative Names: ", host);
+
/* Do we want to check for dNSNAmes or ipAddresses (see RFC 2818)?
* Signal it by host_in_octet_string. */
ASN1_OCTET_STRING *host_in_octet_string = a2i_IPADDRESS (host);
@@ -516,6 +518,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
if (!ASN1_STRING_cmp (host_in_octet_string,
name->d.iPAddress))
break;
+ dStr_sprintfa(err, "%s ", name->d.iPAddress);
}
}
else if (name->type == GEN_DNS)
@@ -537,6 +540,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
OPENSSL_free (name_in_utf8);
break;
}
+ dStr_sprintfa(err, "%s ", name_in_utf8);
OPENSSL_free (name_in_utf8);
}
}
@@ -549,11 +553,8 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
if (alt_name_checked == TRUE && i >= numaltnames)
{
success = FALSE;
- msg = dStrconcat("No certificate subject alternative name matches"
- " requested host name \n", host, NULL);
- *choice = a_Dialog_choice("Dillo SSL security warning",
- msg, "Continue", "Cancel", NULL);
- dFree(msg);
+ *choice = a_Dialog_choice("Dillo TLS security warning",
+ err->str, "Continue", "Cancel", NULL);
switch (*choice){
case 1:
@@ -565,6 +566,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
break;
}
}
+ dStr_free(err, 1);
}
if (alt_name_checked == FALSE)
@@ -580,7 +582,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
success = FALSE;
msg = dStrconcat("Certificate common name ", common_name,
" doesn't match requested host name ", host, NULL);
- *choice = a_Dialog_choice("Dillo SSL security warning",
+ *choice = a_Dialog_choice("Dillo TLS security warning",
msg, "Continue", "Cancel", NULL);
dFree(msg);
@@ -626,7 +628,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
"character). This may be an indication that the "
"host is not who it claims to be -- that is, not "
"the real ", host, NULL);
- *choice = a_Dialog_choice("Dillo SSL security warning",
+ *choice = a_Dialog_choice("Dillo TLS security warning",
msg, "Continue", "Cancel", NULL);
dFree(msg);
@@ -648,18 +650,58 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url,
/******************** END OF STUFF DERIVED FROM wget-1.16.3 */
/*
+ * Get the certificate at the end of the chain, or NULL on failure.
+ *
+ * Rumor has it that the stack can be NULL if a connection has been reused
+ * and that the stack can then be reconstructed if necessary, but it doesn't
+ * sound like a case we'll encounter.
+ */
+static X509 *Tls_get_end_of_chain(SSL *ssl)
+{
+ STACK_OF(X509) *sk = SSL_get_peer_cert_chain(ssl);
+
+ return sk ? sk_X509_value(sk, sk_X509_num(sk) - 1) : NULL;
+}
+
+static void Tls_get_issuer_name(X509 *cert, char *buf, uint_t buflen)
+{
+ if (cert) {
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf, buflen);
+ } else {
+ strncpy(buf, "(unknown)", buflen);
+ buf[buflen-1] = '\0';
+ }
+}
+
+static void Tls_get_expiration_str(X509 *cert, char *buf, uint_t buflen)
+{
+ ASN1_TIME *exp_date = X509_get_notAfter(cert);
+ BIO *b = BIO_new(BIO_s_mem());
+ int rc = ASN1_TIME_print(b, exp_date);
+
+ if (rc > 0) {
+ rc = BIO_gets(b, buf, buflen);
+ }
+ if (rc <= 0) {
+ strncpy(buf, "(unknown)", buflen);
+ buf[buflen-1] = '\0';
+ }
+ BIO_free(b);
+}
+
+/*
* Examine the certificate, and, if problems are detected, ask the user what
* to do.
* Return: -1 if connection should be canceled, or 0 if it should continue.
*/
-static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
+static int Tls_examine_certificate(SSL *ssl, Server_t *srv,const char *host)
{
X509 *remote_cert;
long st;
- char buf[4096], *cn, *msg;
+ const uint_t buflen = 4096;
+ char buf[buflen], *cn, *msg;
int choice = -1, ret = -1;
- char *title = dStrconcat("Dillo SSL security warning: ",URL_HOST(url),NULL);
- Server_t *srv = dList_find_custom(servers, url, Ssl_servers_cmp);
+ char *title = dStrconcat("Dillo TLS security warning: ", host, NULL);
remote_cert = SSL_get_peer_certificate(ssl);
if (remote_cert == NULL){
@@ -674,7 +716,7 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
ret = 0;
}
- } else if (Ssl_check_cert_hostname(remote_cert, url, &choice)) {
+ } else if (Tls_check_cert_hostname(remote_cert, host, &choice)) {
/* Figure out if (and why) the remote system can't be trusted */
st = SSL_get_verify_result(ssl);
switch (st) {
@@ -713,7 +755,7 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
/* Save certificate to a file here and recheck the chain */
/* Potential security problems because we are writing
* to the filesystem */
- Ssl_save_certificate_home(remote_cert);
+ Tls_save_certificate_home(remote_cert);
ret = 1;
break;
default:
@@ -761,14 +803,15 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_CRL_HAS_EXPIRED:
- choice = a_Dialog_choice(title,
- "The remote certificate has expired. The certificate "
- "wasn't designed to last this long. You should avoid "
- "this site.",
- "Continue", "Cancel", NULL);
+ Tls_get_expiration_str(remote_cert, buf, buflen);
+ msg = dStrconcat("The remote certificate expired on: ", buf,
+ ". This site can no longer be trusted.", NULL);
+
+ choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL);
if (choice == 1) {
ret = 0;
}
+ dFree(msg);
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
@@ -812,23 +855,24 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
}
break;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- choice = a_Dialog_choice(title,
- "Self signed certificate in certificate chain. The certificate "
- "chain could be built up using the untrusted certificates but the "
- "root could not be found locally.",
- "Continue", "Cancel", NULL);
+ Tls_get_issuer_name(Tls_get_end_of_chain(ssl), buf, buflen);
+ msg = dStrconcat("Certificate chain led to a self-signed certificate "
+ "instead of a trusted root. Name: ", buf , NULL);
+ choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL);
if (choice == 1) {
ret = 0;
}
+ dFree(msg);
break;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- choice = a_Dialog_choice(title,
- "Unable to get local issuer certificate. The issuer certificate "
- "of an untrusted certificate cannot be found.",
- "Continue", "Cancel", NULL);
+ Tls_get_issuer_name(Tls_get_end_of_chain(ssl), buf, buflen);
+ msg = dStrconcat("The issuer certificate of an untrusted certificate "
+ "cannot be found. Issuer: ", buf, NULL);
+ choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL);
if (choice == 1) {
ret = 0;
}
+ dFree(msg);
break;
default: /* Need to add more options later */
snprintf(buf, 80,
@@ -859,10 +903,10 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url)
* If the connection was closed before we got the certificate, we need to
* reset state so that we'll try again.
*/
-void a_Ssl_reset_server_state(const DilloUrl *url)
+void a_Tls_reset_server_state(const DilloUrl *url)
{
if (servers) {
- Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp);
+ Server_t *s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp);
if (s && s->cert_status == CERT_STATUS_RECEIVING)
s->cert_status = CERT_STATUS_NONE;
@@ -870,14 +914,14 @@ void a_Ssl_reset_server_state(const DilloUrl *url)
}
/*
- * Close an open SSL connection.
+ * Close an open TLS connection.
*/
-static void Ssl_close_by_key(int connkey)
+static void Tls_close_by_key(int connkey)
{
Conn_t *c;
if ((c = a_Klist_get_data(conn_list, connkey))) {
- a_Ssl_reset_server_state(c->url);
+ a_Tls_reset_server_state(c->url);
if (c->connecting) {
a_IOwatch_remove_fd(c->fd, -1);
dClose(c->fd);
@@ -886,24 +930,100 @@ static void Ssl_close_by_key(int connkey)
SSL_free(c->ssl);
a_Url_free(c->url);
- Ssl_fd_map_remove_entry(c->fd);
+ Tls_fd_map_remove_entry(c->fd);
a_Klist_remove(conn_list, connkey);
dFree(c);
}
}
+static void Tls_print_cert_chain(SSL *ssl)
+{
+ STACK_OF(X509) *sk = SSL_get_peer_cert_chain(ssl);
+
+ if (sk) {
+ const uint_t buflen = 4096;
+ char buf[buflen];
+ int rc, i, n = sk_X509_num(sk);
+ X509 *cert = NULL;
+ EVP_PKEY *public_key;
+ int key_type, key_bits;
+ const char *type_str;
+ BIO *b;
+
+ for (i = 0; i < n; i++) {
+ cert = sk_X509_value(sk, i);
+ public_key = X509_get_pubkey(cert);
+
+ /* We are trying to find a way to get the hash function used
+ * with a certificate. This way, which is not very pleasant, puts
+ * a string such as "sha256WithRSAEncryption" in our buffer and we
+ * then trim off the "With..." part.
+ */
+ b = BIO_new(BIO_s_mem());
+ rc = i2a_ASN1_OBJECT(b, cert->sig_alg->algorithm);
+
+ if (rc > 0) {
+ rc = BIO_gets(b, buf, buflen);
+ }
+ if (rc <= 0) {
+ strcpy(buf, "(unknown)");
+ buf[buflen-1] = '\0';
+ } else {
+ char *s = strstr(buf, "With");
+
+ if (s) {
+ *s = '\0';
+ if (!strcmp(buf, "sha1")) {
+ MSG_WARN("In 2015, browsers have begun to deprecate SHA1 "
+ "certificates.\n");
+ } else if (!strncmp(buf, "md", 2)) {
+ MSG_ERR("Browsers stopped accepting MD5 certificates around "
+ "2012.\n");
+ }
+ }
+ }
+ BIO_free(b);
+ MSG("%s ", buf);
+
+
+ key_type = EVP_PKEY_type(public_key->type);
+ type_str = key_type == EVP_PKEY_RSA ? "RSA" :
+ key_type == EVP_PKEY_DSA ? "DSA" :
+ key_type == EVP_PKEY_DH ? "DH" :
+ key_type == EVP_PKEY_EC ? "EC" : "???";
+ key_bits = EVP_PKEY_bits(public_key);
+ X509_NAME_oneline(X509_get_subject_name(cert), buf, buflen);
+ buf[buflen-1] = '\0';
+ MSG("%d-bit %s: %s\n", key_bits, type_str, buf);
+ EVP_PKEY_free(public_key);
+
+ if (key_type == EVP_PKEY_RSA && key_bits <= 1024) {
+ /* TODO: Gather warnings into one popup. */
+ MSG_WARN("In 2014/5, browsers have been deprecating 1024-bit RSA "
+ "keys.\n");
+ }
+ }
+
+ if (cert) {
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf, buflen);
+ buf[buflen-1] = '\0';
+ MSG("root: %s\n", buf);
+ }
+ }
+}
+
/*
* Connect, set a callback if it's still not completed. If completed, check
* the certificate and report back to http.
*/
-static void Ssl_connect(int fd, int connkey)
+static void Tls_connect(int fd, int connkey)
{
int ret;
bool_t ongoing = FALSE, failed = TRUE;
Conn_t *conn;
if (!(conn = a_Klist_get_data(conn_list, connkey))) {
- MSG("Ssl_connect: conn for fd %d not valid\n", fd);
+ MSG("Tls_connect: conn for fd %d not valid\n", fd);
return;
}
@@ -917,10 +1037,10 @@ static void Ssl_connect(int fd, int connkey)
err1_ret == SSL_ERROR_WANT_WRITE) {
int want = err1_ret == SSL_ERROR_WANT_READ ? DIO_READ : DIO_WRITE;
- _MSG("iowatching fd %d for ssl -- want %s\n", fd,
+ _MSG("iowatching fd %d for tls -- want %s\n", fd,
err1_ret == SSL_ERROR_WANT_READ ? "read" : "write");
a_IOwatch_remove_fd(fd, -1);
- a_IOwatch_add_fd(fd, want, Ssl_connect_cb, INT2VOIDP(connkey));
+ a_IOwatch_add_fd(fd, want, Tls_connect_cb, INT2VOIDP(connkey));
ongoing = TRUE;
failed = FALSE;
} else if (err1_ret == SSL_ERROR_SYSCALL || err1_ret == SSL_ERROR_SSL) {
@@ -934,14 +1054,14 @@ static void Ssl_connect(int fd, int connkey)
} else {
/* nothing in the error queue */
if (ret == 0) {
- MSG("SSL connect error: \"an EOF was observed that violates "
+ MSG("TLS connect error: \"an EOF was observed that violates "
"the protocol\"\n");
/*
* I presume we took too long on our side and the server grew
* impatient.
*/
} else if (ret == -1) {
- MSG("SSL connect error: %s\n", dStrerror(errno));
+ MSG("TLS connect error: %s\n", dStrerror(errno));
/* If the following can happen, I'll add code to handle it, but
* I don't want to add code blindly if it isn't getting used
@@ -956,9 +1076,24 @@ static void Ssl_connect(int fd, int connkey)
MSG("SSL_get_error() returned %d on a connect.\n", err1_ret);
}
} else {
- if (Ssl_user_said_yes(conn->url) ||
- (Ssl_examine_certificate(conn->ssl, conn->url) != -1))
+ Server_t *srv = dList_find_sorted(servers, conn->url,
+ Tls_servers_by_url_cmp);
+
+ if (srv->cert_status == CERT_STATUS_RECEIVING) {
+ /* Making first connection with the server. Show some information. */
+ SSL *ssl = conn->ssl;
+ const char *version = SSL_get_version(ssl);
+ const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
+
+ MSG("%s: %s, cipher %s\n", URL_AUTHORITY(conn->url), version,
+ SSL_CIPHER_get_name(cipher));
+ Tls_print_cert_chain(ssl);
+ }
+
+ if (srv->cert_status == CERT_STATUS_USER_ACCEPTED ||
+ (Tls_examine_certificate(conn->ssl, srv, URL_HOST(conn->url))!=-1)) {
failed = FALSE;
+ }
}
/*
@@ -970,7 +1105,7 @@ static void Ssl_connect(int fd, int connkey)
if (a_Klist_get_data(conn_list, connkey)) {
conn->connecting = FALSE;
if (failed) {
- Ssl_close_by_key(connkey);
+ Tls_close_by_key(connkey);
}
a_IOwatch_remove_fd(fd, DIO_READ|DIO_WRITE);
a_Http_connect_done(fd, failed ? FALSE : TRUE);
@@ -980,15 +1115,15 @@ static void Ssl_connect(int fd, int connkey)
}
}
-static void Ssl_connect_cb(int fd, void *vconnkey)
+static void Tls_connect_cb(int fd, void *vconnkey)
{
- Ssl_connect(fd, VOIDP2INT(vconnkey));
+ Tls_connect(fd, VOIDP2INT(vconnkey));
}
/*
- * Perform the SSL handshake on an open socket.
+ * Perform the TLS handshake on an open socket.
*/
-void a_Ssl_handshake(int fd, const DilloUrl *url)
+void a_Tls_handshake(int fd, const DilloUrl *url)
{
SSL *ssl;
bool_t success = TRUE;
@@ -997,7 +1132,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url)
if (!ssl_context)
success = FALSE;
- if (success && Ssl_user_said_no(url)) {
+ if (success && Tls_user_said_no(url)) {
success = FALSE;
}
@@ -1011,7 +1146,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url)
success = FALSE;
}
- /* assign SSL connection to this file descriptor */
+ /* assign TLS connection to this file descriptor */
if (success && !SSL_set_fd(ssl, fd)) {
unsigned long err_ret = ERR_get_error();
do {
@@ -1021,7 +1156,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url)
}
if (success)
- connkey = Ssl_conn_new(fd, url, ssl);
+ connkey = Tls_conn_new(fd, url, ssl);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
/* Server Name Indication. From the openssl changelog, it looks like this
@@ -1032,42 +1167,42 @@ void a_Ssl_handshake(int fd, const DilloUrl *url)
#endif
if (!success) {
- a_Ssl_reset_server_state(url);
+ a_Tls_reset_server_state(url);
a_Http_connect_done(fd, success);
} else {
- Ssl_connect(fd, connkey);
+ Tls_connect(fd, connkey);
}
}
/*
- * Read data from an open SSL connection.
+ * Read data from an open TLS connection.
*/
-int a_Ssl_read(void *conn, void *buf, size_t len)
+int a_Tls_read(void *conn, void *buf, size_t len)
{
Conn_t *c = (Conn_t*)conn;
return SSL_read(c->ssl, buf, len);
}
/*
- * Write data to an open SSL connection.
+ * Write data to an open TLS connection.
*/
-int a_Ssl_write(void *conn, void *buf, size_t len)
+int a_Tls_write(void *conn, void *buf, size_t len)
{
Conn_t *c = (Conn_t*)conn;
return SSL_write(c->ssl, buf, len);
}
-void a_Ssl_close_by_fd(int fd)
+void a_Tls_close_by_fd(int fd)
{
FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd),
- Ssl_fd_map_cmp);
+ Tls_fd_map_cmp);
if (fme) {
- Ssl_close_by_key(fme->connkey);
+ Tls_close_by_key(fme->connkey);
}
}
-static void Ssl_servers_freeall()
+static void Tls_servers_freeall()
{
if (servers) {
Server_t *s;
@@ -1082,7 +1217,7 @@ static void Ssl_servers_freeall()
}
}
-static void Ssl_fd_map_remove_all()
+static void Tls_fd_map_remove_all()
{
if (fd_map) {
FdMapEntry_t *fme;
@@ -1099,12 +1234,12 @@ static void Ssl_fd_map_remove_all()
/*
* Clean up the OpenSSL library
*/
-void a_Ssl_freeall(void)
+void a_Tls_freeall(void)
{
if (ssl_context)
SSL_CTX_free(ssl_context);
- Ssl_fd_map_remove_all();
- Ssl_servers_freeall();
+ Tls_fd_map_remove_all();
+ Tls_servers_freeall();
}
#endif /* ENABLE_SSL */
diff --git a/src/IO/tls.h b/src/IO/tls.h
new file mode 100644
index 00000000..e3892cb2
--- /dev/null
+++ b/src/IO/tls.h
@@ -0,0 +1,47 @@
+#ifndef __TLS_H__
+#define __TLS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../url.h"
+
+#define TLS_CONNECT_NEVER -1
+#define TLS_CONNECT_NOT_YET 0
+#define TLS_CONNECT_READY 1
+
+void a_Tls_init();
+
+
+#ifdef ENABLE_SSL
+int a_Tls_connect_ready(const DilloUrl *url);
+void a_Tls_reset_server_state(const DilloUrl *url);
+
+/* Use to initiate a TLS connection. */
+void a_Tls_handshake(int fd, const DilloUrl *url);
+
+void *a_Tls_connection(int fd);
+
+void a_Tls_freeall();
+
+void a_Tls_close_by_fd(int fd);
+int a_Tls_read(void *conn, void *buf, size_t len);
+int a_Tls_write(void *conn, void *buf, size_t len);
+#else
+
+#define a_Tls_connect_ready(url) TLS_CONNECT_NEVER
+#define a_Tls_reset_server_state(url) ;
+#define a_Tls_handshake(fd, url) ;
+#define a_Tls_connection(fd) NULL
+#define a_Tls_freeall() ;
+#define a_Tls_close_by_fd(fd) ;
+#define a_Tls_read(conn, buf, len) 0
+#define a_Tls_write(conn, buf, len) 0
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TLS_H__ */
+
diff --git a/src/cache.c b/src/cache.c
index 2cc8c0aa..d8f1a123 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -756,6 +756,7 @@ static void Cache_parse_header(CacheEntry_t *entry)
if (!web->requester ||
a_Url_same_organization(entry->Url, web->requester)) {
+ /* If cookies are third party, don't even consider them. */
char *server_date = Cache_parse_field(header, "Date");
a_Cookies_set(Cookies, entry->Url, server_date);
@@ -764,10 +765,6 @@ static void Cache_parse_header(CacheEntry_t *entry)
}
}
}
- if (i >= dList_length(ClientQueue)) {
- MSG("Cache: cookies not accepted from '%s'\n", URL_STR(entry->Url));
- }
-
for (i = 0; (data = dList_nth_data(Cookies, i)); ++i)
dFree(data);
dList_free(Cookies);
@@ -857,17 +854,6 @@ static void Cache_finish_msg(CacheEntry_t *entry)
MSG("Expected size: %d, Transfer size: %d\n",
entry->ExpectedSize, entry->TransferSize);
}
- if (!entry->TransferSize && !(entry->Flags & CA_Redirect) &&
- (entry->Flags & WEB_RootUrl)) {
- char *eol = strchr(entry->Header->str, '\n');
- if (eol) {
- char *status_line = dStrndup(entry->Header->str,
- eol - entry->Header->str);
- MSG_HTTP("Body of %s was empty. Server sent status: %s\n",
- URL_STR_(entry->Url), status_line);
- dFree(status_line);
- }
- }
entry->Flags |= CA_GotData;
entry->Flags &= ~CA_Stopped; /* it may catch up! */
if (entry->TransferDecoder) {
diff --git a/src/dialog.cc b/src/dialog.cc
index 10988c98..03949a1c 100644
--- a/src/dialog.cc
+++ b/src/dialog.cc
@@ -325,6 +325,7 @@ static void choice_cb(Fl_Widget *button, void *number)
{
choice_answer = VOIDP2INT(number);
_MSG("choice_cb: %d\n", choice_answer);
+
button->window()->hide();
}
@@ -358,16 +359,15 @@ int a_Dialog_choice(const char *title, const char *msg, ...)
Fl_Window *window = new Fl_Window(ww, wh, title);
window->set_modal();
window->begin();
- Fl_Group *ib = new Fl_Group(0, 0, window->w(), window->h());
- ib->begin();
- window->resizable(ib);
- if (msg != NULL){
- Fl_Box *box = new Fl_Box(0, 0, ww, wh - bh, msg);
- box->labelfont(FL_HELVETICA);
- box->labelsize(14);
- box->align(FL_ALIGN_WRAP);
- }
+ Fl_Text_Buffer *buf = new Fl_Text_Buffer();
+ buf->text(msg);
+ Fl_Text_Display *td = new Fl_Text_Display(0, 0, ww, wh - bh);
+ td->buffer(buf);
+ td->textsize((int) rint(14.0 * prefs.font_factor));
+ td->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0);
+
+ window->resizable(td);
int xpos = gap;
va_start(ap, msg);
@@ -386,6 +386,8 @@ int a_Dialog_choice(const char *title, const char *msg, ...)
while (window->shown())
Fl::wait();
_MSG("Dialog_choice answer = %d\n", answer);
+ td->buffer(NULL);
+ delete buf;
delete window;
return choice_answer;
diff --git a/src/dillo.cc b/src/dillo.cc
index 847c9d63..17747c59 100644
--- a/src/dillo.cc
+++ b/src/dillo.cc
@@ -45,7 +45,7 @@
#include "dns.h"
#include "web.hh"
-#include "IO/ssl.h"
+#include "IO/tls.h"
#include "IO/Url.h"
#include "IO/mime.h"
#include "capi.h"
@@ -477,7 +477,7 @@ int main(int argc, char **argv)
a_Dns_init();
a_Web_init();
a_Http_init();
- a_Ssl_init();
+ a_Tls_init();
a_Mime_init();
a_Capi_init();
a_Dicache_init();
@@ -599,7 +599,7 @@ int main(int argc, char **argv)
a_Cache_freeall();
a_Dicache_freeall();
a_Http_freeall();
- a_Ssl_freeall();
+ a_Tls_freeall();
a_Dns_freeall();
a_History_freeall();
a_Prefs_freeall();
diff --git a/src/html.cc b/src/html.cc
index 3e4f27a8..a92771d3 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -2514,8 +2514,6 @@ static void
if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) {
url = a_Html_url_new(html, attrbuf, NULL, 0);
dReturn_if_fail ( url != NULL );
- if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "alt")))
- a_Url_set_alt(url, attrbuf);
link = Html_set_new_link(html, &url);
}
diff --git a/src/url.c b/src/url.c
index aa211fb7..e2eac48a 100644
--- a/src/url.c
+++ b/src/url.c
@@ -204,7 +204,6 @@ void a_Url_free(DilloUrl *url)
dFree((char *)url->hostname);
dFree((char *)url->buffer);
dStr_free(url->data, 1);
- dFree((char *)url->alt);
dFree(url);
}
}
@@ -213,7 +212,6 @@ void a_Url_free(DilloUrl *url)
* Resolve the URL as RFC3986 suggests.
*/
static Dstr *Url_resolve_relative(const char *RelStr,
- DilloUrl *BaseUrlPar,
const char *BaseStr)
{
char *p, *s, *e;
@@ -224,9 +222,7 @@ static Dstr *Url_resolve_relative(const char *RelStr,
/* parse relative URL */
RelUrl = Url_object_new(RelStr);
- if (BaseUrlPar) {
- BaseUrl = BaseUrlPar;
- } else if (RelUrl->scheme == NULL) {
+ if (RelUrl->scheme == NULL) {
/* only required when there's no <scheme> in RelStr */
BaseUrl = Url_object_new(BaseStr);
}
@@ -336,8 +332,7 @@ static Dstr *Url_resolve_relative(const char *RelStr,
done:
dStr_free(Path, TRUE);
a_Url_free(RelUrl);
- if (BaseUrl != BaseUrlPar)
- a_Url_free(BaseUrl);
+ a_Url_free(BaseUrl);
return SolvedUrl;
}
@@ -356,7 +351,6 @@ done:
* port = 8080
* flags = URL_Get
* data = Dstr * ("")
- * alt = NULL
* ismap_url_len = 0
* }
*
@@ -406,7 +400,7 @@ DilloUrl* a_Url_new(const char *url_str, const char *base_url)
}
/* Resolve the URL */
- SolvedUrl = Url_resolve_relative(urlstr, NULL, base_url);
+ SolvedUrl = Url_resolve_relative(urlstr, base_url);
_MSG("SolvedUrl = %s\n", SolvedUrl->str);
/* Fill url data */
@@ -435,7 +429,6 @@ DilloUrl* a_Url_dup(const DilloUrl *ori)
url->url_string = dStr_new(URL_STR(ori));
url->port = ori->port;
url->flags = ori->flags;
- url->alt = dStrdup(ori->alt);
url->ismap_url_len = ori->ismap_url_len;
url->illegal_chars = ori->illegal_chars;
url->illegal_chars_spc = ori->illegal_chars_spc;
@@ -495,17 +488,6 @@ void a_Url_set_data(DilloUrl *u, Dstr **data)
}
/*
- * Set DilloUrl alt (alternate text to the URL. Used by image maps)
- */
-void a_Url_set_alt(DilloUrl *u, const char *alt)
-{
- if (u) {
- dFree((char *)u->alt);
- u->alt = dStrdup(alt);
- }
-}
-
-/*
* Set DilloUrl ismap coordinates
* (this is optimized for not hogging the CPU)
*/
@@ -516,7 +498,6 @@ void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str)
if (!u->ismap_url_len) {
/* Save base-url length (without coords) */
u->ismap_url_len = URL_STR_(u) ? u->url_string->len : 0;
- a_Url_set_flags(u, URL_FLAGS(u) | URL_Ismap);
}
if (u->url_string) {
dStr_truncate(u->url_string, u->ismap_url_len);
diff --git a/src/url.h b/src/url.h
index 6920f769..93d198f8 100644
--- a/src/url.h
+++ b/src/url.h
@@ -22,12 +22,8 @@
*/
#define URL_Get (1 << 0)
#define URL_Post (1 << 1)
-#define URL_ISindex (1 << 2)
-#define URL_Ismap (1 << 3)
-#define URL_RealmAccess (1 << 4)
#define URL_E2EQuery (1 << 5)
-#define URL_ReloadImages (1 << 6)
#define URL_ReloadPage (1 << 7)
#define URL_ReloadFromCache (1 << 8)
@@ -47,7 +43,6 @@
#define URL_QUERY_(u) (u)->query
#define URL_FRAGMENT_(u) (u)->fragment
#define URL_HOST_(u) a_Url_hostname(u)
-#define URL_ALT_(u) (u)->alt
#define URL_STR_(u) a_Url_str(u)
/* this returns a Dstr* */
#define URL_DATA_(u) (u)->data
@@ -69,9 +64,8 @@
#define URL_QUERY(u) NPTR2STR(URL_QUERY_(u))
#define URL_FRAGMENT(u) NPTR2STR(URL_FRAGMENT_(u))
#define URL_HOST(u) NPTR2STR(URL_HOST_(u))
-#define URL_DATA(u) URL_DATA_(u)
-#define URL_ALT(u) NPTR2STR(URL_ALT_(u))
#define URL_STR(u) NPTR2STR(URL_STR_(u))
+#define URL_DATA(u) URL_DATA_(u)
#define URL_PORT(u) URL_PORT_(u)
#define URL_FLAGS(u) URL_FLAGS_(u)
#define URL_ILLEGAL_CHARS(u) URL_ILLEGAL_CHARS_(u)
@@ -94,7 +88,6 @@ typedef struct {
int port;
int flags;
Dstr *data; /* POST */
- const char *alt; /* "alt" text (used by image maps) */
int ismap_url_len; /* Used by server side image maps */
int illegal_chars; /* number of illegal chars */
int illegal_chars_spc; /* number of illegal space chars */
@@ -109,7 +102,6 @@ DilloUrl* a_Url_dup(const DilloUrl *u);
int a_Url_cmp(const DilloUrl *A, const DilloUrl *B);
void a_Url_set_flags(DilloUrl *u, int flags);
void a_Url_set_data(DilloUrl *u, Dstr **data);
-void a_Url_set_alt(DilloUrl *u, const char *alt);
void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str);
char *a_Url_decode_hex_str(const char *str);
char *a_Url_encode_hex_str(const char *str);