]> Pileus Git - ~andy/fetchmail/blobdiff - socket.c
Reinstate SSLv2 support on legacy_63 branch.
[~andy/fetchmail] / socket.c
index 91ca662b00e537335c685b3500930abdfa23688e..f513d9ffdd3db4b1691a7beabecfa0fde715c8a9 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -179,7 +179,7 @@ static int handle_plugin(const char *host,
                (void) close(fds[1]);
                if ( (dup2(fds[0],0) == -1) || (dup2(fds[0],1) == -1) ) {
                        report(stderr, GT_("dup2 failed\n"));
-                       exit(1);
+                       _exit(EXIT_FAILURE);
                }
                /* fds[0] is now connected to 0 and 1; close it */
                (void) close(fds[0]);
@@ -188,7 +188,7 @@ static int handle_plugin(const char *host,
                argvec = parse_plugin(plugin,host,service);
                execvp(*argvec, argvec);
                report(stderr, GT_("execvp(%s) failed\n"), *argvec);
-               exit(0);
+               _exit(EXIT_FAILURE);
                break;
        default:        /* parent */
                /* NOP */
@@ -200,6 +200,37 @@ static int handle_plugin(const char *host,
 }
 #endif /* HAVE_SOCKETPAIR */
 
+static int setsocktimeout(int sock, int which, int timeout) {
+    struct timeval tv;
+    int rc;
+
+    tv.tv_sec = timeout;
+    tv.tv_usec = 0;
+    rc = setsockopt(sock, SOL_SOCKET, which, &tv, sizeof(tv));
+    if (rc) {
+       report(stderr, GT_("setsockopt(%d, SOL_SOCKET) failed: %s"), sock, strerror(errno));
+    }
+    return rc;
+}
+
+/** Configure socket options such as send/receive timeout at the socket
+ * level, to avoid network-induced stalls.
+ */
+int SockTimeout(int sock, int timeout)
+{
+    int err = 0;
+
+    if (setsocktimeout(sock, SO_RCVTIMEO, timeout)) err = 1;
+    if (setsocktimeout(sock, SO_SNDTIMEO, timeout)) err = 1;
+    return err;
+}
+
+/** Set socket to SO_KEEPALIVE. \return 0 for success. */
+int SockKeepalive(int sock) {
+    int keepalive = 1;
+    return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof keepalive);
+}
+
 int UnixOpen(const char *path)
 {
     int sock = -1;
@@ -294,6 +325,9 @@ int SockOpen(const char *host, const char *service,
            continue;
        }
 
+       SockTimeout(i, mytimeout);
+       SockKeepalive(i);
+
        /* Save socket descriptor.
         * Used to close the socket after connect timeout. */
        mailserver_socket_temp = i;
@@ -865,14 +899,16 @@ int SSLOpen(int sock, char *mycert, char *mykey, const char *myproto, int certck
        /* Make sure a connection referring to an older context is not left */
        _ssl_context[sock] = NULL;
        if(myproto) {
-               if(!strcasecmp("ssl3",myproto)) {
+               if(!strcasecmp("ssl2",myproto)) {
+                       _ctx[sock] = SSL_CTX_new(SSLv2_client_method());
+               } else if(!strcasecmp("ssl3",myproto)) {
                        _ctx[sock] = SSL_CTX_new(SSLv3_client_method());
                } else if(!strcasecmp("tls1",myproto)) {
                        _ctx[sock] = SSL_CTX_new(TLSv1_client_method());
                } else if (!strcasecmp("ssl23",myproto)) {
                        myproto = NULL;
                } else {
-                       fprintf(stderr,GT_("Invalid SSL protocol '%s' specified, using default (SSL23).\n"), myproto);
+                       fprintf(stderr,GT_("Invalid SSL protocol '%s' specified, using default (SSLv23).\n"), myproto);
                        myproto = NULL;
                }
        }
@@ -884,7 +920,7 @@ int SSLOpen(int sock, char *mycert, char *mykey, const char *myproto, int certck
                return(-1);
        }
 
-       SSL_CTX_set_options(_ctx[sock], SSL_OP_ALL | SSL_OP_NO_SSLv2);
+       SSL_CTX_set_options(_ctx[sock], SSL_OP_ALL);
 
        if (certck) {
                SSL_CTX_set_verify(_ctx[sock], SSL_VERIFY_PEER, SSL_ck_verify_callback);
@@ -1035,21 +1071,3 @@ static ssize_t cygwin_read(int sock, void *buf, size_t count)
     return count;
 }
 #endif /* __CYGWIN__ */
-
-#ifdef MAIN
-/*
- * Use the chargen service to test input buffering directly.
- * You may have to uncomment the `chargen' service description in your
- * inetd.conf (and then SIGHUP inetd) for this to work.  */
-main()
-{
-    int                sock = SockOpen("localhost", "chargen", NULL);
-    char       buf[80];
-
-    while (SockRead(sock, buf, sizeof(buf)-1))
-       SockWrite(1, buf, strlen(buf));
-    SockClose(sock);
-}
-#endif /* MAIN */
-
-/* socket.c ends here */