]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
gopher: Implement secure gopher protocol.
authorparazyd <parazyd@dyne.org>
Sun, 15 Nov 2020 17:46:06 +0000 (18:46 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 15 Dec 2020 11:58:12 +0000 (12:58 +0100)
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

configure.ac
lib/gopher.c
lib/gopher.h
lib/url.c
lib/version.c

index 39bdb5ef123499e486bc5c4d8d5462c04def07c6..733c3f973a16ab9b1bf322ad9b5b8b2560e23dcd 100755 (executable)
@@ -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"
index b101c0ab680ec3eb3398159b1aba414acedf788f..c02436d4a1fe9d7634328436b3d0cbe67ad0edd0 100644 (file)
@@ -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"
  */
 
 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);
index b35fa450965662ba4ca8a76733c8af74e97298a7..6b8bd554a668bd8513fafc847817b07c9302be50 100644 (file)
@@ -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 */
index 2b0ba87ba87576f0859122f444c0f3ac5cf8ffa9..a340213adcdc9c3a4d1c32ec2ed5f6b181a5f964 100644 (file)
--- 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
index 7064c20d2fde1869981737a65256cc5473c3c86f..ab2c0d812af8edd0c616aa7c616ec9ff1d30be2d 100644 (file)
@@ -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