Nmap Development mailing list archives

Re: Ncat and windows line endings


From: jah <jah () zadkiel plus com>
Date: Thu, 04 Jun 2009 16:25:11 +0100

On 04/06/2009 02:30, David Fifield wrote:
Here is the patch. It sets _O_TEXT mode on stdin when the input is from
the console (checked using the _isatty function), and _O_BINARY
otherwise. It sets _O_BINARY on stdout. So the terminal sends \n for
line endings, and no newline translation is done anywhere else, just
like on Unix.

The only problem I can envision is if it's somehow possible to fool
_isatty. I can confirm that it returns true for
      ncat target
and false for
      ncat target < infile
      cat infile | ncat target
but there might be other cases. Documentation is here:
http://msdn.microsoft.com/en-us/library/f4s0ddew(VS.80).aspx

Setting _O_BINARY on stdout fixes another bug that was not discovered
until now. Ncat on Windows was doing newline translation on output as
well, breaking binary transfers.
      unix$ md5sum /etc/services
      aca587f0966a6f14536dae8fa15f095a  /etc/services
      C:\> ncat.exe -l > services
      unix$ ncat win --send-only < /etc/services
      C:\> C:\cygwin\bin\md5sum.exe services
      4458bb84b47c93cfa7f5e2432f21ca68 *services

What do you think?
This sounds like a good idea and it certainly would dispense with the
need for an -L option which should be a good thing.
I've attached the half of the patch I previously [1] posted that
converts LF to CRLF throughout the buffer.  Thanks a bug report from
Venkat Sanaka I've fixed an error I made in the original patch too.

jah

[1] http://seclists.org/nmap-dev/2009/q2/0370.html
diff -urNb r13551/ncat/ncat_broker.c r13551_crlf/ncat/ncat_broker.c
--- r13551/ncat/ncat_broker.c   2009-06-04 13:54:58.640625000 +0100
+++ r13551_crlf/ncat/ncat_broker.c      2009-06-04 03:43:25.031250000 +0100
@@ -195,6 +195,7 @@
 {
     char buf[DEFAULT_TCP_BUF_LEN];
     char *chatbuf, *outbuf;
+    char *tempbuf = NULL;
     struct fdinfo *fdn = get_fdinfo(&fdlist, recv_fd);
     ssize_t nbytes;
     fd_set fds;
@@ -209,7 +210,7 @@
 #endif
     if (recv_fd == STDIN_FILENO) {
         /* Behavior differs depending on whether this is stdin or a socket. */
-        nbytes = read(recv_fd, buf, sizeof(buf) - o.crlf);
+        nbytes = read(recv_fd, buf, sizeof(buf));
         if (nbytes <= 0) {
             if (nbytes < 0 && o.verbose)
                 logdebug("Error reading from stdin: %s\n", strerror(errno));
@@ -225,11 +226,8 @@
             return;
         }
 
-        /* We gave ourselves extra room in our special-case stdin read above */
-        if (o.crlf && buf[nbytes - 1] == '\n' && buf[nbytes - 2] != '\r') {
-            memcpy(&buf[nbytes - 1], "\r\n", 2);
-            nbytes++;
-        }
+        if (o.crlf)
+            fix_line_endings((char *) buf, &nbytes, &tempbuf);
     } else {
         /* From a connected socket, not stdin. */
         nbytes = recv(recv_fd, buf, sizeof(buf), 0);
@@ -270,10 +268,14 @@
         logdebug("Handling data from client %d.\n", recv_fd);
 
     chatbuf = NULL;
+    /* tempbuf is in use if we read from STDIN and fixed CRLF */
+    if (tempbuf == NULL)
     outbuf = buf;
+    else
+        outbuf = tempbuf;
 
     if (o.chat) {
-        chatbuf = chat_filter(buf, nbytes, recv_fd, &nbytes);
+        chatbuf = chat_filter(outbuf, nbytes, recv_fd, &nbytes);
         if (chatbuf == NULL) {
             if (o.verbose)
                 logdebug("Error formatting chat message from fd %d\n", recv_fd);
@@ -291,6 +293,8 @@
     broadcast(&fds, &fdlist, outbuf, nbytes);
 
     free(chatbuf);
+    free(tempbuf);
+    tempbuf = NULL;
 
 #ifdef HAVE_OPENSSL
     /* SSL can buffer our input, so doing another select()
diff -urNb r13551/ncat/ncat_connect.c r13551_crlf/ncat/ncat_connect.c
--- r13551/ncat/ncat_connect.c  2009-06-04 13:54:58.312500000 +0100
+++ r13551_crlf/ncat/ncat_connect.c     2009-06-04 03:56:31.875000000 +0100
@@ -386,12 +386,9 @@
                     if (o.recvonly == 0) {
                         char *tmp = NULL;
 
-                        if (o.crlf && buf[nbytes - 1] == '\n' && buf[nbytes - 2] != '\r') {
-                            tmp = (char *) safe_malloc(nbytes + 1);
-                            memcpy(tmp, buf, nbytes - 1);
-                            memcpy(tmp + nbytes - 1, "\r\n", 2);
+                        if (o.crlf) {
+                            if (fix_line_endings(buf, &nbytes, &tmp))
                             buf = tmp;
-                            nbytes++;
                         }
 
                         nsock_write(nsp, cs->sock_nsi, connect_evt_handler,
diff -urNb r13551/ncat/ncat_listen.c r13551_crlf/ncat/ncat_listen.c
--- r13551/ncat/ncat_listen.c   2009-06-04 13:54:58.421875000 +0100
+++ r13551_crlf/ncat/ncat_listen.c      2009-06-04 14:30:39.718750000 +0100
@@ -207,9 +207,10 @@
 {
     int nbytes;
     char buf[DEFAULT_TCP_BUF_LEN];
+    char* write_buf;
     fd_set fds;
 
-    nbytes = read(STDIN_FILENO, buf, sizeof(buf) - o.crlf);
+    nbytes = read(STDIN_FILENO, buf, sizeof(buf));
     if (nbytes <= 0) {
         if (nbytes < 0 && o.verbose)
             logdebug("Error reading from stdin: %s\n", strerror(errno));
@@ -225,10 +226,9 @@
         return;
     }
 
-    /* We gave ourselves extra room in our special-case stdin read above */
-    if (o.crlf && buf[nbytes - 1] == '\n' && buf[nbytes - 2] != '\r') {
-        memcpy(&buf[nbytes - 1], "\r\n", 2);
-        nbytes++;
+    if (!o.crlf || !fix_line_endings((char *) buf, &nbytes, &write_buf)) {
+        write_buf = (char *) safe_malloc(sizeof(buf));
+        memcpy(write_buf, &buf, sizeof(buf));
     }
 
     if(o.linedelay)
@@ -239,7 +239,9 @@
     fds = master;
     FD_CLR(STDIN_FILENO, &fds);
     FD_CLR(listen_socket, &fds);
-    broadcast(&fds, &fdlist, buf, nbytes);
+    broadcast(&fds, &fdlist, write_buf, nbytes);
+    if (write_buf)
+        free(write_buf);
 }
 
 /* Read from a client socket and write to stdout. */
diff -urNb r13551/ncat/util.c r13551_crlf/ncat/util.c
--- r13551/ncat/util.c  2009-06-04 13:54:58.546875000 +0100
+++ r13551_crlf/ncat/util.c     2009-06-04 15:13:47.890625000 +0100
@@ -442,3 +442,42 @@
     fdl->nfds = 0;
     fdl->fdmax = -1;
 }
+
+
+/*  If any changes need to be made to EOL sequences to comply with --crlf
+ *  then dst will be populated with the modified src, len will be adjusted
+ *  accordingly and the return will be non-zero.
+ *  Returns 0 if changes were not made and len and dst will remain untouched.
+ */
+int fix_line_endings(char *src, int *len, char **dst)
+{
+    char *tmp = NULL;
+    int fix_count;
+    int i,j;
+    int num_bytes = *len;
+
+    /* get count of \n without matching \r */
+    fix_count = 0;
+    for (i = 0; i < num_bytes; i++) {
+        if (src[i] == '\n' && (i == 0 || src[i-1] != '\r'))
+            fix_count++;
+    }
+    if (fix_count <= 0 ) return 0;
+
+    /* now insert matching \r */
+    *dst = (char *) safe_malloc(num_bytes + fix_count);
+    j=0;
+
+    for (i = 0; i < num_bytes; i++) {
+        if (src[i] == '\n' && (i == 0 || src[i-1] != '\r')) {
+            memcpy(*dst+j, "\r\n", 2);
+            j += 2;
+        } else {
+            memcpy(*dst+j, src+i, 1);
+            j++;
+        }
+    }
+    *len += fix_count;
+
+    return 1;
+}
diff -urNb r13551/ncat/util.h r13551_crlf/ncat/util.h
--- r13551/ncat/util.h  2009-06-04 13:54:58.562500000 +0100
+++ r13551_crlf/ncat/util.h     2009-05-15 01:37:32.171875000 +0100
@@ -85,3 +85,5 @@
 struct fdinfo *get_fdinfo(const fd_list_t *, int);
 
 #endif
+
+int fix_line_endings(char *src, int *len, char **dst);

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: