Blame SOURCES/nmap-6.40-ncat_memleak.patch

41d651
diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c
41d651
index d8c73ab1b..5695800a3 100644
41d651
--- a/ncat/ncat_connect.c
41d651
+++ b/ncat/ncat_connect.c
41d651
@@ -1049,7 +1049,10 @@ int ncat_connect(void)
41d651
         }
41d651
 
41d651
         if (connect_socket == -1)
41d651
+        {
41d651
+            nsp_delete(mypool);
41d651
             return 1;
41d651
+        }
41d651
         /* Clear out whatever is left in the socket buffer which may be
41d651
            already sent by proxy server along with http response headers. */
41d651
         //line = socket_buffer_remainder(&stateful_buf, &n);
41d651
--- a/ncat/ncat.h
41d651
+++ b/ncat/ncat.h
41d651
@@ -177,13 +177,13 @@
41d651
 
41d651
 struct socks5_connect {
41d651
     char ver;
41d651
-    char nmethods;
41d651
+    unsigned char nmethods;
41d651
     char methods[3];
41d651
 } __attribute__((packed));
41d651
 
41d651
 struct socks5_auth {
41d651
-  char ver; // must be always 1
41d651
-  char data[SOCKS_BUFF_SIZE];
41d651
+    char ver; // must be always 1
41d651
+    unsigned char data[SOCKS_BUFF_SIZE];
41d651
 } __attribute__((packed));
41d651
 
41d651
 struct socks5_request {
41d651
@@ -263,6 +263,12 @@
41d651
 #define SOCKS5_ATYP_NAME        3
41d651
 #define SOCKS5_ATYP_IPv6        4
41d651
 
41d651
+#define SOCKS5_USR_MAXLEN       255
41d651
+#define SOCKS5_PWD_MAXLEN       255
41d651
+
41d651
+#if SOCKS_BUFF_SIZE < (1 + SOCKS5_USR_MAXLEN) + (1 + SOCKS5_PWD_MAXLEN)
41d651
+#error SOCKS_BUFF_SIZE is defined too small to handle SOCKS5 authentication
41d651
+#endif
41d651
 
41d651
 /* Length of IPv6 address */
41d651
 #ifndef INET6_ADDRSTRLEN
41d651
--- a/ncat/ncat_connect.c
41d651
+++ b/ncat/ncat_connect.c
41d651
@@ -664,9 +664,8 @@
41d651
     int sd,len,lenfqdn;
41d651
     struct socks5_request socks5msg2;
41d651
     struct socks5_auth socks5auth;
41d651
-    char *proxy_auth;
41d651
-    char *username;
41d651
-    char *password;
41d651
+    char *uptr, *pptr;
41d651
+    size_t authlen, ulen, plen;
41d651
 
41d651
     sd = do_connect(SOCK_STREAM);
41d651
     if (sd == -1) {
41d651
@@ -683,17 +682,13 @@
41d651
 
41d651
     zmem(&socks5msg,sizeof(socks5msg));
41d651
     socks5msg.ver = SOCKS5_VERSION;
41d651
-    socks5msg.nmethods = 1;
41d651
-    socks5msg.methods[0] = SOCKS5_AUTH_NONE;
41d651
-    len = 3;
41d651
+    socks5msg.nmethods = 0;
41d651
+    socks5msg.methods[socks5msg.nmethods++] = SOCKS5_AUTH_NONE;
41d651
 
41d651
-    if (o.proxy_auth){
41d651
-        socks5msg.nmethods ++;
41d651
-        socks5msg.methods[1] = SOCKS5_AUTH_USERPASS;
41d651
-        len ++;
41d651
-    }
41d651
+    if (o.proxy_auth)
41d651
+        socks5msg.methods[socks5msg.nmethods++] = SOCKS5_AUTH_USERPASS;
41d651
 
41d651
-    if (send(sd, (char *) &socks5msg, len, 0) < 0) {
41d651
+    if (send(sd, (char *)&socks5msg, offsetof(struct socks5_connect, methods) + socks5msg.nmethods, 0) < 0) {
41d651
         loguser("Error: proxy request: %s.\n", socket_strerror(socket_errno()));
41d651
         close(sd);
41d651
         return -1;
41d651
@@ -706,46 +701,47 @@
41d651
         return -1;
41d651
     }
41d651
 
41d651
-    if (socksbuf[0] != 5){
41d651
+    if (socksbuf[0] != SOCKS5_VERSION) {
41d651
         loguser("Error: got wrong server version in response.\n");
41d651
         close(sd);
41d651
         return -1;
41d651
     }
41d651
 
41d651
-    switch(socksbuf[1]) {
41d651
+    switch((unsigned char)socksbuf[1]) {
41d651
         case SOCKS5_AUTH_NONE:
41d651
             if (o.verbose)
41d651
                 loguser("No authentication needed.\n");
41d651
             break;
41d651
 
41d651
-        case SOCKS5_AUTH_GSSAPI:
41d651
-            loguser("GSSAPI authentication method not supported.\n");
41d651
-            close(sd);
41d651
-            return -1;
41d651
-
41d651
         case SOCKS5_AUTH_USERPASS:
41d651
             if (o.verbose)
41d651
                 loguser("Doing username and password authentication.\n");
41d651
 
41d651
             if(!o.proxy_auth){
41d651
-                loguser("Error: proxy requested to do authentication, but no credentials were provided.\n");
41d651
+                /* Proxy must not select a method not offered by the client */
41d651
+                loguser("Error: proxy selected invalid authentication method.\n");
41d651
                 close(sd);
41d651
                 return -1;
41d651
             }
41d651
 
41d651
-            if (strlen(o.proxy_auth) > SOCKS_BUFF_SIZE-2){
41d651
-                loguser("Error: username and password are too long to fit into buffer.\n");
41d651
+            /* Split up the proxy auth argument. */
41d651
+            uptr = o.proxy_auth;
41d651
+            pptr = strchr(o.proxy_auth, ':');
41d651
+            if (pptr == NULL) {
41d651
+                loguser("Error: invalid username:password combo.\n");
41d651
                 close(sd);
41d651
                 return -1;
41d651
             }
41d651
 
41d651
-            /* Split up the proxy auth argument. */
41d651
-            proxy_auth = Strdup(o.proxy_auth);
41d651
-            username = strtok(proxy_auth, ":");
41d651
-            password = strtok(NULL, ":");
41d651
-            if (password == NULL || username == NULL) {
41d651
-                free(proxy_auth);
41d651
-                loguser("Error: empty username or password.\n");
41d651
+            ulen = (pptr++) - uptr;
41d651
+            plen = strlen(pptr);
41d651
+            if (ulen > SOCKS5_USR_MAXLEN) {
41d651
+                loguser("Error: username length exceeds %d.\n", SOCKS5_USR_MAXLEN);
41d651
+                close(sd);
41d651
+                return -1;
41d651
+            }
41d651
+            if (plen > SOCKS5_PWD_MAXLEN) {
41d651
+                loguser("Error: password length exceeds %d.\n", SOCKS5_PWD_MAXLEN);
41d651
                 close(sd);
41d651
                 return -1;
41d651
             }
41d651
@@ -766,15 +762,16 @@
41d651
              */
41d651
 
41d651
             socks5auth.ver = 1;
41d651
-            socks5auth.data[0] = strlen(username);
41d651
-            memcpy(socks5auth.data+1,username,strlen(username));
41d651
-            len = 2 + strlen(username); // (version + strlen) + username
41d651
+            authlen = 0;
41d651
+            socks5auth.data[authlen++] = ulen;
41d651
+            memcpy(socks5auth.data + authlen, uptr, ulen);
41d651
+            authlen += ulen;
41d651
 
41d651
-            socks5auth.data[len-1]=strlen(password);
41d651
-            memcpy(socks5auth.data+len,password,strlen(password));
41d651
-            len += 1 + strlen(password);
41d651
+            socks5auth.data[authlen++] = plen;
41d651
+            memcpy(socks5auth.data + authlen, pptr, plen);
41d651
+            authlen += plen;
41d651
 
41d651
-            if (send(sd, (char *) &socks5auth, len, 0) < 0) {
41d651
+            if (send(sd, (char *) &socks5auth, offsetof(struct socks5_auth, data) + authlen, 0) < 0) {
41d651
                 loguser("Error: sending proxy authentication.\n");
41d651
                 close(sd);
41d651
                 return -1;
41d651
@@ -794,8 +791,14 @@
41d651
 
41d651
             break;
41d651
 
41d651
+        case SOCKS5_AUTH_FAILED:
41d651
+            loguser("Error: no acceptable authentication method proposed.\n");
41d651
+            close(sd);
41d651
+            return -1;
41d651
+
41d651
         default:
41d651
-            loguser("Error - can't choose any authentication method.\n");
41d651
+            /* Proxy must not select a method not offered by the client */
41d651
+            loguser("Error: proxy selected invalid authentication method.\n");
41d651
             close(sd);
41d651
             return -1;
41d651
     }
41d651
@@ -832,6 +835,10 @@
41d651
             socks5msg2.dst[0]=lenfqdn;
41d651
             memcpy(socks5msg2.dst+1,o.target,lenfqdn);
41d651
             len = 1 + lenfqdn;
41d651
+            break;
41d651
+
41d651
+        default: // this shall not happen
41d651
+            ncat_assert(0);
41d651
     }
41d651
 
41d651
     memcpy(socks5msg2.dst+len, &proxyport, sizeof(proxyport));