>From 25d06e1338ad6d3ec874146e719670424f5b6b74 Mon Sep 17 00:00:00 2001
From: Markus Klinik <markus.klinik () gmx de>
Date: Fri, 26 Feb 2010 20:15:55 +0100
Subject: [PATCH 4/8] ncat_proxy: SSL support for http CONNECT method


diff --git a/ncat_proxy.c b/ncat_proxy.c
index 35d1136..b3caa06 100644
--- a/ncat_proxy.c
+++ b/ncat_proxy.c
@@ -106,9 +106,9 @@ static void proxyreaper(int signo)
 #endif
 
 /* send a '\0'-terminated string. */
-static int send_string(int sock, const char *s)
+static int send_string(struct fdinfo* fdi, const char *s)
 {
-    return send(sock, s, strlen(s), 0);
+    return ncat_send(fdi, s, strlen(s));
 }
 
 static void http_server_handler(int c);
@@ -163,6 +163,11 @@ int ncat_http_server(void)
     http_digest_init_secret();
 #endif
 
+#ifdef HAVE_OPENSSL
+    if(o.ssl)
+        setup_ssl_listen();
+#endif
+
     s = do_listen(SOCK_STREAM, IPPROTO_TCP);
 
     for (;;) {
@@ -251,18 +256,30 @@ static int method_is_known(const char *method)
 static void http_server_handler(int c)
 {
     int code;
+    struct fdinfo client_fdi;
     struct socket_buffer sock;
     struct http_request request;
     char *buf;
 
-    socket_buffer_init(&sock, c);
+    fdinfo_init(&client_fdi);
+    client_fdi.fd = c;
+
+#if HAVE_OPENSSL
+    if(o.ssl)
+    {
+        client_fdi.ssl = new_ssl(client_fdi.fd);
+        SSL_set_accept_state(client_fdi.ssl);
+    }
+#endif
+
+    socket_buffer_init(&sock, &client_fdi);
 
     code = http_read_request_line(&sock, &buf);
     if (code != 0) {
         if (o.verbose)
             logdebug("Error reading Request-Line.\n");
-        send_string(c, http_code2str(code));
-        Close(c);
+        send_string(&client_fdi, http_code2str(code));
+        fdinfo_close(&client_fdi);
         return;
     }
     if (o.debug > 1)
@@ -272,8 +289,8 @@ static void http_server_handler(int c)
     if (code != 0) {
         if (o.verbose)
             logdebug("Error parsing Request-Line.\n");
-        send_string(c, http_code2str(code));
-        Close(c);
+        send_string(&client_fdi, http_code2str(code));
+        fdinfo_close(&client_fdi);
         return;
     }
 
@@ -281,8 +298,8 @@ static void http_server_handler(int c)
         if (o.debug > 1)
             logdebug("Bad method: %s.\n", request.method);
         http_request_free(&request);
-        send_string(c, http_code2str(405));
-        Close(c);
+        send_string(&client_fdi, http_code2str(405));
+        fdinfo_close(&client_fdi);
         return;
     }
 
@@ -291,8 +308,8 @@ static void http_server_handler(int c)
         if (o.verbose)
             logdebug("Error reading header.\n");
         http_request_free(&request);
-        send_string(c, http_code2str(code));
-        Close(c);
+        send_string(&client_fdi, http_code2str(code));
+        fdinfo_close(&client_fdi);
         return;
     }
     if (o.debug > 1)
@@ -303,12 +320,14 @@ static void http_server_handler(int c)
         if (o.verbose)
             logdebug("Error parsing header.\n");
         http_request_free(&request);
-        send_string(c, http_code2str(code));
-        Close(c);
+        send_string(&client_fdi, http_code2str(code));
+        fdinfo_close(&client_fdi);
         return;
     }
 
     /* Check authentication. */
+    /*TODO: SSL support*/
+#if 0
     if (o.proxy_auth) {
         struct http_credentials credentials;
         int ret, stale;
@@ -317,7 +336,7 @@ static void http_server_handler(int c)
             /* No credentials or a parsing error. */
             send_proxy_authenticate(c, 0);
             http_request_free(&request);
-            Close(c);
+            fdinfo_close(&client_fdi);
             return;
         }
             
@@ -330,10 +349,11 @@ static void http_server_handler(int c)
                Authentication Required). */
             send_proxy_authenticate(c, stale);
             http_request_free(&request);
-            Close(c);
+            fdinfo_close(&client_fdi);
             return;
         }
     }
+#endif
 
     if (strcmp(request.method, "CONNECT") == 0) {
         code = handle_connect(&sock, &request);
@@ -347,12 +367,12 @@ static void http_server_handler(int c)
     http_request_free(&request);
 
     if (code != 0) {
-        send_string(c, http_code2str(code));
-        Close(c);
+        send_string(&client_fdi, http_code2str(code));
+        fdinfo_close(&client_fdi);
         return;
     }
 
-    Close(c);
+    fdinfo_close(&client_fdi);
 }
 
 static int handle_connect(struct socket_buffer *client_sock,
@@ -388,7 +408,7 @@ static int handle_connect(struct socket_buffer *client_sock,
         return 504;
     }
 
-    send_string(client_sock->sd, http_code2str(200));
+    send_string(client_sock->fdi, http_code2str(200));
 
     /* Clear out whatever is left in the socket buffer. The client may have
        already sent the first part of its request to the origin server. */
@@ -400,9 +420,9 @@ static int handle_connect(struct socket_buffer *client_sock,
         return 0;
     }
 
-    maxfd = client_sock->sd < s ? s : client_sock->sd;
+    maxfd = client_sock->fdi->fd < s ? s : client_sock->fdi->fd;
     FD_ZERO(&m);
-    FD_SET(client_sock->sd, &m);
+    FD_SET(client_sock->fdi->fd, &m);
     FD_SET(s, &m);
 
     errno = 0;
@@ -417,25 +437,31 @@ static int handle_connect(struct socket_buffer *client_sock,
 
         zmem(buf, sizeof(buf));
 
-        if (FD_ISSET(client_sock->sd, &r)) {
-            if ((len = recv(client_sock->sd, buf, sizeof(buf), 0)) < 0)
-                continue;
+        if (FD_ISSET(client_sock->fdi->fd, &r)) {
+            int pending = 1;
 
-            if (!len)
-                break;
+            while( 1 == pending ) {
+                /* receive from the client and forward to the server */
+                if ((len = ncat_recv(client_sock->fdi, buf, sizeof(buf), &pending)) < 0)
+                    continue;
 
-            if (send(s, buf, len, 0) < 0)
-                continue;
+                if (!len)
+                    break;
+
+                if (send(s, buf, len, 0) < 0)
+                    continue;
+            }
         }
 
         if (FD_ISSET(s, &r)) {
+            /* receive from the server and forward to the client */
             if ((len = recv(s, buf, sizeof(buf), 0)) < 0)
                 continue;
 
             if (!len)
                 break;
 
-            if (send(client_sock->sd, buf, len, 0) < 0)
+            if (ncat_send(client_sock->fdi, buf, len) < 0)
                 continue;
         }
     }
-- 
1.6.6.1

