summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorparazyd <parazyd@dyne.org>2020-11-15 18:46:06 +0100
committerDaniel Stenberg <daniel@haxx.se>2020-12-15 12:58:12 +0100
commita1f06f32b8603427535fc21183a84ce92a9b96f7 (patch)
treef78431d8a63fc74f68216ba88600363ca421809b
parentbe8c94da781f2df2b8e424923581945195025db0 (diff)
downloadcurl-a1f06f32b8603427535fc21183a84ce92a9b96f7.tar.gz
gopher: Implement secure gopher protocol.
This commit introduces a "gophers" handler inside the gopher protocol if USE_SSL is defined. This protocol is no different than the usual gopher prococol, with the added TLS encapsulation upon connecting. The protocol has been adopted in the gopher community, and many people have enabled TLS in their gopher daemons like geomyidae(8), and clients, like clic(1) and hurl(1). I have not implemented test units for this protocol because my knowledge of Perl is sub-par. However, for someone more knowledgeable it might be fairly trivial, because the same test that tests the plain gopher protocol can be used for "gophers" just by adding a TLS listener. Signed-off-by: parazyd <parazyd@dyne.org> Closes #6208
-rwxr-xr-xconfigure.ac3
-rw-r--r--lib/gopher.c50
-rw-r--r--lib/gopher.h3
-rw-r--r--lib/url.c3
-rw-r--r--lib/version.c3
5 files changed, 62 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 39bdb5ef1..733c3f973 100755
--- a/configure.ac
+++ b/configure.ac
@@ -5111,6 +5111,9 @@ if test "x$CURL_DISABLE_TFTP" != "x1"; then
fi
if test "x$CURL_DISABLE_GOPHER" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER"
+ if test "x$SSL_ENABLED" = "x1"; then
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHERS"
+ fi
fi
if test "x$CURL_DISABLE_MQTT" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
diff --git a/lib/gopher.c b/lib/gopher.c
index b101c0ab6..c02436d4a 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -33,6 +33,7 @@
#include "gopher.h"
#include "select.h"
#include "strdup.h"
+#include "vtls/vtls.h"
#include "url.h"
#include "escape.h"
#include "warnless.h"
@@ -46,6 +47,10 @@
*/
static CURLcode gopher_do(struct connectdata *conn, bool *done);
+#ifdef USE_SSL
+static CURLcode gopher_connect(struct connectdata *conn, bool *done);
+static CURLcode gopher_connecting(struct connectdata *conn, bool *done);
+#endif
/*
* Gopher protocol handler.
@@ -75,6 +80,46 @@ const struct Curl_handler Curl_handler_gopher = {
PROTOPT_NONE /* flags */
};
+#ifdef USE_SSL
+const struct Curl_handler Curl_handler_gophers = {
+ "GOPHERS", /* scheme */
+ ZERO_NULL, /* setup_connection */
+ gopher_do, /* do_it */
+ ZERO_NULL, /* done */
+ ZERO_NULL, /* do_more */
+ gopher_connect, /* connect_it */
+ gopher_connecting, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* connection_check */
+ PORT_GOPHER, /* defport */
+ CURLPROTO_GOPHER, /* protocol */
+ CURLPROTO_GOPHER, /* family */
+ PROTOPT_SSL /* flags */
+};
+
+static CURLcode gopher_connect(struct connectdata *conn, bool *done)
+{
+ (void)conn;
+ (void)done;
+ return CURLE_OK;
+}
+
+static CURLcode gopher_connecting(struct connectdata *conn, bool *done)
+{
+ CURLcode result = Curl_ssl_connect(conn, FIRSTSOCKET);
+ if(result)
+ connclose(conn, "Failed TLS connection");
+ *done = TRUE;
+ return result;
+}
+#endif
+
static CURLcode gopher_do(struct connectdata *conn, bool *done)
{
CURLcode result = CURLE_OK;
@@ -127,6 +172,11 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
k = curlx_uztosz(len);
for(;;) {
+ /* Break out of the loop if the selector is empty because OpenSSL and/or
+ LibreSSL fail with errno 0 if this is the case. */
+ if(strlen(sel) < 1)
+ break;
+
result = Curl_write(conn, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
diff --git a/lib/gopher.h b/lib/gopher.h
index b35fa4509..6b8bd554a 100644
--- a/lib/gopher.h
+++ b/lib/gopher.h
@@ -24,6 +24,9 @@
#ifndef CURL_DISABLE_GOPHER
extern const struct Curl_handler Curl_handler_gopher;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_gophers;
+#endif
#endif
#endif /* HEADER_CURL_GOPHER_H */
diff --git a/lib/url.c b/lib/url.c
index 2b0ba87ba..a340213ad 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -251,6 +251,9 @@ static const struct Curl_handler * const protocols[] = {
#ifndef CURL_DISABLE_GOPHER
&Curl_handler_gopher,
+#ifdef USE_SSL
+ &Curl_handler_gophers,
+#endif
#endif
#ifdef USE_LIBRTMP
diff --git a/lib/version.c b/lib/version.c
index 7064c20d2..ab2c0d812 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -274,6 +274,9 @@ static const char * const protocols[] = {
#ifndef CURL_DISABLE_GOPHER
"gopher",
#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+ "gophers",
+#endif
#ifndef CURL_DISABLE_HTTP
"http",
#endif