Nmap Development mailing list archives

[PATCH] Extended SSL support in Nmap


From: Kristof Boeynaems <kristof.boeynaems () gmail com>
Date: Sat, 21 Feb 2009 20:01:33 +0100

Hi All,

I wrote a patch for the issue described at length in http://seclists.org/nmap-dev/2009/q1/0330.html.

In short, I added support for SSLv3-only and TLSv1-only SSL servers. That is, servers that do not accept the backward compatible SSLv2 ClientHello that the OpenSSL method SSLv23_client_method() implements (and which is used by Nmap).

See attachment.

This patch changes quite some code in quite some different places, so please test carefully.

Remarks:

- Instead of trying to implement the SSL 'change' method discussed in http://seclists.org/nmap-dev/2009/q1/0430.html, I decided to create separate objects for SSLv3 and TLSv1 connections, as this is less likely to break existing code.

- The code relies on version probing to detect the right SSL version. See http://seclists.org/nmap-dev/2009/q1/0330.html for an extensive discussion on this. For backward compatibility reasons, I kept the existing SSL probe (only renamed it for clarity), and added an extra probe for SSLv2 detection.

- The current SSL version probe matches should be reviewed to check which SSL version they actually check. This is easily done based on existing probes, but I did not do this yet. Because the existing matches all carry the label "ssl", which is translated in the code to the "SSLv23" method, it is possible that the wrong SSL connection is selected in case of existing matches (that is, in cases where the match actually matches a SSLv3-only or TLSv1-only server).

- The only change I applied to the current version probe file (apart from adding the extra probe described above), is the commenting out of a few existing matches that were a bit too generic in my opinion, and would interfere with the SSL detection. This is described in http://seclists.org/nmap-dev/2009/q1/0357.html.

- The current SSL version probes have the disadvantage that they will default to SSLv3 connections, even if a SSLv23 connection would be possible. Not sure whether this has any performance drawbacks, but this is because of backwards compatibility reasons. In case of considerable performance drawback, it should be considered to replace the existing SSL probes with a better selection; but this will most likely break backward compatibility with the existing SSL matches. See above referenced discussion for more info on alternative probe solutions.

- I did not migrate the SSL session re-use code to SSLv3 and TLSv1 (yet). Doing so likely will improve performance.

- Currently the output simply shows "ssl". I decided not to show the version detected during probing and used for connecting, as this version is simply *a* supported version.

- I did not look into the 'sslports' code in service_scan.cc yet, which currently labels certain ports as probable SSL ports. Probably here some changes to incorporate the new SSL versions is necessary as well.

- I also did not look into calling the new code from within Ncat yet (to add this kind of SSL support there as well); although this should be straightforward.

- I think it would be better to group all SSL versions under SERVICE_TUNNEL_SSL. But for now, I defined two extra variables for SSLv3 (SERVICE_TUNNEL_SSL3) and TLSv1 (SERVICE_TUNNEL_TLS1) connections, as to minimize the risk of breaking existing code. In practice this means that I had to do a lot of (inelegant) replacements of "SERVICE_TUNNEL_SSL" by "SERVICE_TUNNEL_SSL || SERVICE_TUNNEL_SSL3 || SERVICE_TUNNEL_TLS1".

- There is still a 'bug', where all detected SSL information will be thrown away in case the SSL server does not respond at all, beyond the SSL handshake. However, because the SSL connections succeeded, Nmap should list these situations as 'ssl/unknown'. This can be very easily reproduced by setting up your own OpenSSL server as follows: openssl s_server -cert /usr/share/doc/libssl-dev/demos/sign/cert.pem -key /usr/share/doc/libssl-dev/demos/sign/key.pem This OpenSSL server will listen at 4433 by default, and will not return anything beyond an SSL connection. This bug was not introduced by this patch, but was already part of the original code.

- I did some performance testing with 1000 random SSL servers with various ports open (443,465,636,990,995,993). I compared three instances of Nmap:
1. Nmap-4.85BETA3
2. Nmap-4.85BETA3 with the new nmap-services-probes file provided in the patch. Note that for this test, I had to slightly change the nmap-services-probes file, replacing all "ssl3" and "tls1" detections with "ssl", as Nmap-4.85BETA3 does not know these other versions.
3. A patched version of Nmap-4.85BETA3

I used the following command: nmap -T4 -v -n -PN -sV -p443,465,636,990,995,993 -iL <list of 100 random SSL servers collected earlier via an iR scan> -d -oA <filename>

Below the results:
1.
- Nmap done: 100 IP addresses (100 hosts up) scanned in 525.38 seconds
          Raw packets sent: 1002 (44.088KB) | Rcvd: 311 (13.676KB)
- Number of open SSL ports detected and successfully investigated (' ssl/something'): 36 - Number of open SSL ports detected and not successfully investigated ('ssl/unknown'): 8
- Number of the open 'ssl/unknown' ports that returned a new fingerprint: 2

2.
- Nmap done: 100 IP addresses (100 hosts up) scanned in 534.91 seconds
          Raw packets sent: 1005 (44.220KB) | Rcvd: 320 (14.044KB)
- Number of open SSL ports detected and successfully investigated (' ssl/something'): 37 - Number of open SSL ports detected and not successfully investigated ('ssl/unknown'): 7
- Number of the open 'ssl/unknown' ports that returned a new fingerprint: 2

3.
- Nmap done: 100 IP addresses (100 hosts up) scanned in 517.12 seconds
          Raw packets sent: 1000 (44.000KB) | Rcvd: 306 (13.436KB)
- Number of open SSL ports detected and succesfully investigated (' ssl/something'): 35 - Number of open SSL ports detected and not successfully investigated ('ssl/unknown'): 8
- Number of the open 'ssl/unknown' ports that returned a new fingerprint: 2

Based on these results, it seems that the patches version is more performant (faster, and generating less packets), while also giving much more information (less 'ssl/unknown's). Also the quality of the information seems better. Note that the difference in detected ssl ports is due to the fact that 1. and 2. detect a certain services as "ssl/unknown", while 3. detects this same service as "imaps?". Not sure why this happens.

Of course a lot more performance (and functional) testing is necessary; I am executing some more extensive tests (more hosts) myself.

All comments/test results welcome!

Thanks,

Kristof



diff -urNb nmap-4.85BETA3/nmap-service-probes nmap-ssl/nmap-service-probes
--- nmap-4.85BETA3/nmap-service-probes  2009-01-31 22:55:20.000000000 +0100
+++ nmap-ssl/nmap-service-probes        2009-02-21 17:29:02.000000000 +0100
@@ -6053,7 +6053,9 @@
 match webster m/^DICTIONARY server protocol:\r\n\r\nContact name is/ p/Webster dictionary server/
 
 ##############################NEXT PROBE##############################
-Probe TCP SSLSessionReq 
q|\x16\x03\0\0S\x01\0\0O\x03\0?G\xd7\xf7\xba,\xee\xea\xb2`~\xf3\0\xfd\x82{\xb9\xd5\x96\xc8w\x9b\xe6\xc4\xdb<=\xdbo\xef\x10n\0\0(\0\x16\0\x13\0\x0a\0f\0\x05\0\x04\0e\0d\0c\0b\0a\0`\0\x15\0\x12\0\x09\0\x14\0\x11\0\x08\0\x06\0\x03\x01\0|
+#SSLv3 ClientHello probe. Will be able to reliably identify the SSL version used, unless the server is running SSLv2 
only. Note that it will also detect TLSv1 servers, based on a fail handshake alert.
+#Note that all signatures below should be investigated, and converted to 'ssl3' or 'tls1' where necessary
+Probe TCP SSLv3SessionReq 
q|\x16\x03\0\0S\x01\0\0O\x03\0?G\xd7\xf7\xba,\xee\xea\xb2`~\xf3\0\xfd\x82{\xb9\xd5\x96\xc8w\x9b\xe6\xc4\xdb<=\xdbo\xef\x10n\0\0(\0\x16\0\x13\0\x0a\0f\0\x05\0\x04\0e\0d\0c\0b\0a\0`\0\x15\0\x12\0\x09\0\x14\0\x11\0\x08\0\x06\0\x03\x01\0|
 
 rarity 3
 ports 443,444,548,636,993,1241,1311,2000,4444,5550,7210,7272,8009,8194,9001
@@ -6072,24 +6074,24 @@
 match maxdb m|^.Rejected bad connect packet\0$|s p/SAP MaxDB/
 
 # OpenSSL/0.9.7aa
-match ssl m|^\x16\x03\0\0J\x02\0\0F\x03\0| p/OpenSSL/
+#Too generic#match ssl m|^\x16\x03\0\0J\x02\0\0F\x03\0| p/OpenSSL/
 
 # Don't think these 2 are correct:
 #match ssl m|^\x16\x03\0\x04#\x02\0\0F\x03\0| p/Apache Tomcat SSL/
 #match ssl m|^\x16\x03\0\0\*\x02\0\0&\x03\0| p/Apache mod_ssl/
 
 # Microsoft-IIS/5.0 - note that OpenSSL must go above this one because this is more general
-match ssl m|^\x16\x03\0..\x02\0\0F\x03\0|s p/Microsoft IIS SSL/ o/Windows/
+#Too generic#match ssl m|^\x16\x03\0..\x02\0\0F\x03\0|s p/Microsoft IIS SSL/ o/Windows/
 # Novell Netware 6 Enterprise Web server 5.1 https
 # Novell Netware Ldap over SSL or enterprise web server 5.1 over SSL
 match ssl m|^\x16\x03\0\0:\x02\0\x006\x03\0| p/Novell Netware SSL/ o/NetWare/
 # Very generic:
-match ssl m|^\x16\x03\0\0\*\x02\0\0&\x03\0|
+#Too generic#match ssl m|^\x16\x03\0\0\*\x02\0\0&\x03\0|
 # Cisco IDS 4.1 Appliance
 match ssl 
m|^\x16\x03\0\0\*\x02\0\0&\x03\0\xd10:\xbd\\\x8e\xe3\x15\x1c\x0fZ\xe4\x04\x87\x07\xc0\x82\xa9\xd4\x0e\x9c1LXk\xd1\xd2\x0b\x1a\xc6/p\0\0\n\0\x16\x03\0\x026\x0b\0\x022\0|
 p/Cisco IDS SSL/ d/firewall/
 # These Nessus match lines might be problematic:
-match ssl m|^\x15\x03\0\0\x02\x02\($| p/Nessus security scanner/ 
-match ssl m|^\x16\x03\x01\0J\x02\0\0F\x03\x01| p/Nessus security scanner/
+#Too generic#match ssl m|^\x15\x03\0\0\x02\x02\($| p/Nessus security scanner/ 
+#Too generic#match ssl m|^\x16\x03\x01\0J\x02\0\0F\x03\x01| p/Nessus security scanner/
 # PGP Corporation Keyserver Web Console 7.0 - custom Apache 1.3
 # PGP LDAPS Keyserver 8.X
 match ssl m|^\x16\x03\0\0\+\x02\0\0'\x03\0...\?|s p/PGP Corporation product SSL/
@@ -6115,6 +6117,29 @@
 match ssl/sophos m|^\x16\x03\0.*Router\$([a-zA-Z0-9_-]+).*Sophos EM Certification Manager|s p/Sophos Message Router/ 
h/$1/
 match ssl/sophos m|^\x16\x03\0.*Sophos EM Certification Manager|s p/Sophos Message Router/
 
+# Generic: TLSv1 Handshake error:
+match tls1 m|^\x15\x03\0\0\x02\x02\($|
+
+# Generic: SSLv3 ServerHello:
+match ssl3 m|^\x16\x03\0..\x02...\x03\0|
+
+##############################NEXT PROBE##############################
+#SSLv2-compatible ClientHello, 39 ciphers offered.
+#Will sollicit a ServerHello from most SSL implementations, apart from the ones that are TLSv1-only or SSLv3-only. As 
it comes after the SSLv3 probe, so its only added value is the detection of SSLv2-only servers
+Probe TCP SSLv23SessionReq q|\x80\x9e\x01\x03\x01\x00u\x00\x00\x00 
\x00\x00f\x00\x00e\x00\x00d\x00\x00c\x00\x00b\x00\x00:\x00\x009\x00\x008\x00\x005\x00\x004\x00\x003\x00\x002\x00\x00/\x00\x00\x1b\x00\x00\x1a\x00\x00\x19\x00\x00\x18\x00\x00\x17\x00\x00\x16\x00\x00\x15\x00\x00\x14\x00\x00\x13\x00\x00\x12\x00\x00\x11\x00\x00\n\x00\x00\t\x00\x00\x08\x00\x00\x06\x00\x00\x05\x00\x00\x04\x00\x00\x03\x07\x00\xc0\x06\x00@\x04\x00\x80\x03\x00\x80\x02\x00\x80\x01\x00\x80\x00\x00\x02\x00\x00\x01\xe4i<+\xf6\xd6\x9b\xbb\xd3\x81\x9f\xbf\x15\xc1@\xa5o\x14,M
 \xc4\xc7\xe0\xb6\xb0\xb2\x1f\xf9)\xe8\x98|
+
+rarity 3
+ports 443,444,548,636,993,1241,1311,2000,4444,5550,7210,7272,8009,8194,9001
+fallback GetRequest
+
+# SSLv2 ServerHello
+match ssl m|^..\x04\0.\0\x02|
+
+# TLSv1 ServerHello, compatible with SSLv2:
+match ss1 m|^\x16\x03\x01..\x02...\x03\x01|
+
+# SSLv3 ServerHello, compatible with SSLv2:
+match ssl m|^\x16\x03\0..\x02...\x03\0|
 
 # SMB Negotiate Protocol
 ##############################NEXT PROBE##############################
diff -urNb nmap-4.85BETA3/nse_nmaplib.cc nmap-ssl/nse_nmaplib.cc
--- nmap-4.85BETA3/nse_nmaplib.cc       2008-12-30 07:56:44.000000000 +0100
+++ nmap-ssl/nse_nmaplib.cc     2009-02-21 18:48:13.000000000 +0100
@@ -41,6 +41,8 @@
       SCRIPT_ENGINE_PUSHSTRING_NOTNULL("none", "service_tunnel");
       break;
     case(SERVICE_TUNNEL_SSL):
+    case(SERVICE_TUNNEL_SSL3):
+    case(SERVICE_TUNNEL_TLS1):
       SCRIPT_ENGINE_PUSHSTRING_NOTNULL("ssl", "service_tunnel");
       break;
     default:
@@ -418,6 +420,10 @@
     tunnel = SERVICE_TUNNEL_NONE;
   else if (strcmp(service_tunnel, "ssl") == 0)
     tunnel = SERVICE_TUNNEL_SSL;
+  else if (strcmp(service_tunnel, "ssl3") == 0)
+    tunnel = SERVICE_TUNNEL_SSL3;
+  else if (strcmp(service_tunnel, "tls1") == 0)
+    tunnel = SERVICE_TUNNEL_TLS1;
   else
     luaL_argerror(L, 2, "invalid value for port.version.service_tunnel");
 
diff -urNb nmap-4.85BETA3/nsock/include/nsock.h nmap-ssl/nsock/include/nsock.h
--- nmap-4.85BETA3/nsock/include/nsock.h        2009-01-08 03:12:35.000000000 +0100
+++ nmap-ssl/nsock/include/nsock.h      2009-02-21 16:50:02.000000000 +0100
@@ -135,6 +135,13 @@
 enum nsock_loopstatus { NSOCK_LOOP_NOEVENTS = 2, NSOCK_LOOP_TIMEOUT, NSOCK_LOOP_ERROR };
 enum nsock_loopstatus nsock_loop(nsock_pool nsp, int msec_timeout);
 
+/* Used in Nsock to differentiate between different SSL connection requirements. 
+ * NSOCK_SSL requires SSLv23_client_method
+ * NSOCK_SSL requires SSLv3_client_method
+ * NSOCK_SSL requires TLSv1_client_method
+ * */
+enum nsock_ssl { NSOCK_SSL, NSOCK_SSL3, NSOCK_TLS1 };
+
 /* This next function returns the errno style error code -- which is only
    valid if the status is NSOCK_LOOP_ERROR was returned by nsock_loop() */
 int nsp_geterrorcode(nsock_pool nsp);
@@ -186,7 +193,7 @@
    the event is created, and the event itself is included in callbacks */
 /* IF YOU ADD NEW NSE_TYPES YOU MUST INCREASE TYPE_CODE_NUM_BITS SO THAT
    IT IS ALWAYS log2(maximum_nse_type_value + 1) */
-#define TYPE_CODE_NUM_BITS 3
+#define TYPE_CODE_NUM_BITS 4
 enum nse_type { 
        NSE_TYPE_CONNECT=0,
        NSE_TYPE_CONNECT_SSL=1,
@@ -194,7 +201,9 @@
        NSE_TYPE_WRITE=3, 
        NSE_TYPE_TIMER=4,
        NSE_TYPE_PCAP_READ=5,
-       NSE_TYPE_MAX=6,
+       NSE_TYPE_CONNECT_SSL3=6,
+       NSE_TYPE_CONNECT_TLS1=7,
+       NSE_TYPE_MAX=8
 };  /* At some point I was considering a NSE_TYPE_START and NSE_TYPE_CUSTOM */
 
 /* Find the type of an event that spawned a callback */
@@ -410,7 +419,17 @@
                                 struct sockaddr *ss, size_t sslen,
                                 unsigned short port);
 
-/* Request an SSL over TCP connection to another system (by IP
+/* Should normally not be called externally, this is an internal function that
+ * takes care of the actual SSL logic of the nsock_connect_ssl_* functions 
+ * defined below. It uses a version field of type nsock_ssl to define the
+ * required SSL connection type */
+nsock_event_id nsock_connect_ssl_all(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *ss, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session, enum nsock_ssl version);
+
+/* Request an SSL (SSLv23) over TCP connection to another system (by IP
    address).  The in_addr is normal network byte order, but the port
    number should be given in HOST BYTE ORDER.  This function will call
    back only after it has made the TCP connection AND done the initial
@@ -425,6 +444,22 @@
                                 size_t sslen, unsigned short port,
                                 nsock_ssl_session ssl_session);
 
+/* Request an SSL3 over TCP connection to another system (by IP
+   address). All parameters have the same meaning as in nsock_connect_ssl */
+nsock_event_id nsock_connect_ssl3(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *ss, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session);
+
+/* Request an TLS1 over TCP connection to another system (by IP
+   address). All parameters have the same meaning as in nsock_connect_ssl */
+nsock_event_id nsock_connect_tls1(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *ss, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session);
+
 /* Request ssl connection over already established TCP connection.
    nsiod must be socket that is already connected to target
    using nsock_connect_tcp.
diff -urNb nmap-4.85BETA3/nsock/src/nsock_connect.c nmap-ssl/nsock/src/nsock_connect.c
--- nmap-4.85BETA3/nsock/src/nsock_connect.c    2009-01-08 03:12:35.000000000 +0100
+++ nmap-ssl/nsock/src/nsock_connect.c  2009-02-21 16:55:32.000000000 +0100
@@ -173,7 +173,7 @@
   return nse->id;
 }
 
-/* Request an SSL over TCP connection to another system (by IP
+/* Request an SSL (SSLv23) over TCP connection to another system (by IP
    address).  The in_addr is normal network byte order, but the port
    number should be given in HOST BYTE ORDER.  This function will call
    back only after it has made the TCP connection AND done the initial
@@ -187,6 +187,38 @@
                                 void *userdata, struct sockaddr *saddr, 
                                 size_t sslen, unsigned short port,
                                 nsock_ssl_session ssl_session) {
+       return nsock_connect_ssl_all(nsp,nsiod,handler,timeout_msecs,userdata,saddr,sslen,port,ssl_session,NSOCK_SSL);
+}
+
+/* Request an SSL3 over TCP connection to another system (by IP
+ *    address). All parameters have the same meaning as in nsock_connect_ssl */
+nsock_event_id nsock_connect_ssl3(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *saddr, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session) {
+       return nsock_connect_ssl_all(nsp,nsiod,handler,timeout_msecs,userdata,saddr,sslen,port,ssl_session,NSOCK_SSL3);
+}
+
+/* Request an TLS1 over TCP connection to another system (by IP
+ *    address). All parameters have the same meaning as in nsock_connect_ssl */
+nsock_event_id nsock_connect_tls1(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *saddr, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session) {
+       return nsock_connect_ssl_all(nsp,nsiod,handler,timeout_msecs,userdata,saddr,sslen,port,ssl_session,NSOCK_TLS1);
+}
+
+/* Should normally not be called externally, this is an internal function that
+ * takes care of the actual SSL logic of the nsock_connect_ssl_* functions
+ * defined below. It uses a version field of type nsock_ssl to define the
+ * required SSL connection type */
+nsock_event_id nsock_connect_ssl_all(nsock_pool nsp, nsock_iod nsiod, 
+                                nsock_ev_handler handler, int timeout_msecs, 
+                                void *userdata, struct sockaddr *saddr, 
+                                size_t sslen, unsigned short port,
+                                nsock_ssl_session ssl_session, enum nsock_ssl version) {
 
 #ifndef HAVE_OPENSSL
   fatal("nsock_connect_ssl called - but nsock was built w/o SSL support.  QUITTING");
@@ -197,19 +229,37 @@
   mspool *ms = (mspool *) nsp;
   msevent *nse;
   static int ssl_initialized = 0;
-
+  static int ssl3_initialized = 0;
+  static int tls1_initialized = 0;
   /* Just in case someone waits a long time and then does a new connect */
   gettimeofday(&nsock_tod, NULL);
 
+  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);
+  
+  //Change SSL session version if necessary
+  if (version == NSOCK_SSL3){
+       if (!ssl3_initialized) {  
+               Nsock_SSL3_Init();
+               ssl3_initialized = 1;
+       }
+       nse = msevent_new(ms, NSE_TYPE_CONNECT_SSL3, nsi, timeout_msecs, handler, 
+                   userdata);
+  }else if (version == NSOCK_TLS1){
+       if (!tls1_initialized) {  
+               Nsock_TLS1_Init();
+               tls1_initialized = 1;
+       }
+       nse = msevent_new(ms, NSE_TYPE_CONNECT_TLS1, nsi, timeout_msecs, handler, 
+                   userdata);
+  }else{
   if (!ssl_initialized) {  
     Nsock_SSL_Init();
     ssl_initialized = 1;
   }
- 
-  assert(nsi->state == NSIOD_STATE_INITIAL || nsi->state == NSIOD_STATE_UNKNOWN);
-  
   nse = msevent_new(ms, NSE_TYPE_CONNECT_SSL, nsi, timeout_msecs, handler, 
                    userdata);
+  } 
+  
   assert(nse);
   
   /* Set our SSL_SESSION so we can benefit from session-id reuse. */
diff -urNb nmap-4.85BETA3/nsock/src/nsock_core.c nmap-ssl/nsock/src/nsock_core.c
--- nmap-4.85BETA3/nsock/src/nsock_core.c       2009-01-14 21:16:25.000000000 +0100
+++ nmap-ssl/nsock/src/nsock_core.c     2009-02-21 17:00:12.000000000 +0100
@@ -232,7 +232,8 @@
 #if HAVE_OPENSSL
   struct NsockSSLInfo *sslnfo;
   int sslerr;
-  int sslconnect_inprogress = nse->type == NSE_TYPE_CONNECT_SSL && iod->ssl;
+  int sslconnect_inprogress = (nse->type == NSE_TYPE_CONNECT_SSL ||
+       nse->type == NSE_TYPE_CONNECT_SSL3 || nse->type == NSE_TYPE_CONNECT_TLS1) && iod->ssl;
 #else
   int sslconnect_inprogress = 0;
 #endif
@@ -294,12 +295,24 @@
       break;
     }
 
-
     /* Now special code for the SSL case where the TCP connection was successful. */
-    if (nse->type == NSE_TYPE_CONNECT_SSL && 
-       nse->status == NSE_STATUS_SUCCESS) {
+    if ((nse->type == NSE_TYPE_CONNECT_SSL||nse->type==NSE_TYPE_CONNECT_SSL3||
+       nse->type==NSE_TYPE_CONNECT_TLS1) && nse->status == NSE_STATUS_SUCCESS) {
 #if HAVE_OPENSSL
+      switch (nse->type){
+       case NSE_TYPE_CONNECT_SSL:
       sslnfo = Nsock_SSLGetInfo();
+               break;
+       case NSE_TYPE_CONNECT_SSL3:
+               sslnfo = Nsock_SSL3GetInfo();
+               break;
+       case NSE_TYPE_CONNECT_TLS1:
+               sslnfo = Nsock_TLS1GetInfo();
+               break;
+       default:
+               assert(0); /* We should never arrive here */
+               break;
+      }
       iod->ssl = SSL_new(sslnfo->ctx);
       if (!iod->ssl)
        fatal("SSL_new failed: %s", ERR_error_string(ERR_get_error(), NULL));
@@ -337,7 +350,8 @@
   }
 
 #if HAVE_OPENSSL
-  if (nse->type == NSE_TYPE_CONNECT_SSL && !nse->event_done) {
+  if ((nse->type == NSE_TYPE_CONNECT_SSL || nse->type==NSE_TYPE_CONNECT_SSL3 ||
+       nse->type==NSE_TYPE_CONNECT_TLS1) && !nse->event_done) {
     /* Lets now start/continue/finish the connect! */
     if (iod->ssl_session) {    
      rc = SSL_set_session(iod->ssl, iod->ssl_session);
@@ -799,6 +813,8 @@
          switch(nse->type) {
          case NSE_TYPE_CONNECT:
          case NSE_TYPE_CONNECT_SSL:
+         case NSE_TYPE_CONNECT_SSL3:
+         case NSE_TYPE_CONNECT_TLS1:
            if (FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_r) ||
                FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_w) ||
                FD_ISSET(nse->iod->sd, &nsp->mioi.fds_results_x)) {
@@ -1036,6 +1052,8 @@
   switch(nse->type) {
   case NSE_TYPE_CONNECT:
   case NSE_TYPE_CONNECT_SSL:
+  case NSE_TYPE_CONNECT_SSL3:
+  case NSE_TYPE_CONNECT_TLS1:
     if (!nse->event_done) {
       assert(nse->iod->sd >= 0);
       FD_SET( nse->iod->sd, &nsp->mioi.fds_master_r);
@@ -1148,6 +1166,8 @@
   switch(nse->type) {
   case NSE_TYPE_CONNECT:
   case NSE_TYPE_CONNECT_SSL:
+  case NSE_TYPE_CONNECT_SSL3:
+  case NSE_TYPE_CONNECT_TLS1:
     nsock_trace(ms, "Callback: %s %s %sfor EID %li [%s:%hu]",  
                nse_type2str(nse->type), nse_status2str(nse->status), errstr, 
                nse->id, inet_ntop_ez(&nsi->peer, nsi->peerlen), nsi_peerport(nsi));
diff -urNb nmap-4.85BETA3/nsock/src/nsock_event.c nmap-ssl/nsock/src/nsock_event.c
--- nmap-4.85BETA3/nsock/src/nsock_event.c      2008-05-05 06:10:20.000000000 +0200
+++ nmap-ssl/nsock/src/nsock_event.c    2009-02-21 16:03:47.000000000 +0100
@@ -439,6 +439,8 @@
   case NSE_TYPE_WRITE: return "WRITE";
   case NSE_TYPE_TIMER: return "TIMER";
   case NSE_TYPE_PCAP_READ: return "READ-PCAP";
+  case NSE_TYPE_CONNECT_SSL3: return "SSL3-CONNECT";
+  case NSE_TYPE_CONNECT_TLS1: return "TLS1-CONNECT";
   default:
     return "UNKNOWN!";
   }
diff -urNb nmap-4.85BETA3/nsock/src/nsock_ssl.c nmap-ssl/nsock/src/nsock_ssl.c
--- nmap-4.85BETA3/nsock/src/nsock_ssl.c        2008-07-20 22:02:39.000000000 +0200
+++ nmap-ssl/nsock/src/nsock_ssl.c      2009-02-21 17:03:01.000000000 +0100
@@ -69,6 +69,8 @@
 extern struct timeval nsock_tod;
 
 static struct NsockSSLInfo *sslnfo = NULL;
+static struct NsockSSLInfo *ssl3nfo = NULL;
+static struct NsockSSLInfo *tls1nfo = NULL;
 
 /* Initializes Nsock for low security (fast) SSL connections.
  Eventually it will probably have arguments for various attributes
@@ -124,6 +126,114 @@
 
 }
 
+/* Initializes Nsock for low security (fast) SSL3 connections.
+ Eventually it will probably have arguments for various attributes
+ (such as whether you want the connection to be fast or secure).  It is
+ OK to call it multiple times - only the first one will count.  
+ This is a copy of Nsock_SSL_Init(), can probably be optimalized for the SSLv3 case */
+void Nsock_SSL3_Init() {
+  char rndbuf[128];
+
+  if (ssl3nfo)
+    return; /* Already done */
+
+  ssl3nfo = (struct NsockSSLInfo *) safe_zalloc(sizeof(*ssl3nfo));
+
+  SSL_load_error_strings();
+  SSL_library_init();
+  
+  /* Note that we are assuming the SSL connections don't have to
+     be high security */
+  get_random_bytes(rndbuf, sizeof(rndbuf));
+  RAND_seed(rndbuf, sizeof(rndbuf));
+
+  ssl3nfo->ctx = SSL_CTX_new( SSLv3_client_method() );
+  if ( ! ssl3nfo->ctx ) {
+    fatal("OpenSSL failed to create a new SSL_CTX: %s", 
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  
+  /* set us to ignore cert entirely */
+  SSL_CTX_set_verify( ssl3nfo->ctx, SSL_VERIFY_NONE, NULL );   
+
+  /* set bug-compatibility for pretty much everything. */
+  SSL_CTX_set_options( ssl3nfo->ctx, SSL_OP_ALL );
+
+  /* Accept any and all ciphers, including none.  Since speed, not security, is
+     our goal, the list below is sorted by speed, based on Brian Hatch's (bri () ifokr org)
+     tests on an Pentium 686 against the ciphers listed.  Nmap's typical
+     version scanning connections are short and sweet, so the actual speed
+     difference isn't terribly great anyway. */
+  if (!SSL_CTX_set_cipher_list( ssl3nfo->ctx, 
+                               
"RC4-SHA:RC4-MD5:NULL-SHA:EXP-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-RC4-MD5:NULL-MD5:EDH-RSA-DES-CBC-SHA:EXP-RC2-CBC-MD5:EDH-RSA-DES-CBC3-SHA:EXP-ADH-RC4-MD5:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:EXP-ADH-DES-CBC-SHA:ADH-AES256-SHA:ADH-DES-CBC-SHA:ADH-RC4-MD5:AES256-SHA:DES-CBC-SHA:DES-CBC3-SHA:ADH-DES-CBC3-SHA:AES128-SHA:ADH-AES128-SHA:eNULL:ALL"))
 {
+    fatal("Unable to set OpenSSL cipher list: %s", 
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+
+
+  /* Our SSL* will always have the SSL_SESSION* inside it, so we neither
+     need to use nor waste memory for the session cache.
+     (Use '1' because '0' means 'infinite'.)   */
+  SSL_CTX_set_session_cache_mode(
+     ssl3nfo->ctx,  SSL_SESS_CACHE_OFF | SSL_SESS_CACHE_NO_AUTO_CLEAR );
+  SSL_CTX_sess_set_cache_size( ssl3nfo->ctx, 1 ); 
+  SSL_CTX_set_timeout( ssl3nfo->ctx, 3600); /* pretty unnecessary */
+}
+
+/* Initializes Nsock for low security (fast) TLS1 connections.
+ Eventually it will probably have arguments for various attributes
+ (such as whether you want the connection to be fast or secure).  It is
+ OK to call it multiple times - only the first one will count.  
+ This is a copy of Nsock_SSL_Init. Can probablyl be optimized for TLSv1 */
+void Nsock_TLS1_Init() {
+  char rndbuf[128];
+
+  if (tls1nfo)
+    return; /* Already done */
+
+  tls1nfo = (struct NsockSSLInfo *) safe_zalloc(sizeof(*tls1nfo));
+
+  SSL_load_error_strings();
+  SSL_library_init();
+  
+  /* Note that we are assuming the SSL connections don't have to
+     be high security */
+  get_random_bytes(rndbuf, sizeof(rndbuf));
+  RAND_seed(rndbuf, sizeof(rndbuf));
+
+  tls1nfo->ctx = SSL_CTX_new( TLSv1_client_method() );
+  if ( ! tls1nfo->ctx ) {
+    fatal("OpenSSL failed to create a new SSL_CTX: %s", 
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+  
+  /* set us to ignore cert entirely */
+  SSL_CTX_set_verify( tls1nfo->ctx, SSL_VERIFY_NONE, NULL );   
+
+  /* set bug-compatibility for pretty much everything. */
+  SSL_CTX_set_options( tls1nfo->ctx, SSL_OP_ALL );
+
+  /* Accept any and all ciphers, including none.  Since speed, not security, is
+     our goal, the list below is sorted by speed, based on Brian Hatch's (bri () ifokr org)
+     tests on an Pentium 686 against the ciphers listed.  Nmap's typical
+     version scanning connections are short and sweet, so the actual speed
+     difference isn't terribly great anyway. */
+  if (!SSL_CTX_set_cipher_list( tls1nfo->ctx, 
+                               
"RC4-SHA:RC4-MD5:NULL-SHA:EXP-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-RC4-MD5:NULL-MD5:EDH-RSA-DES-CBC-SHA:EXP-RC2-CBC-MD5:EDH-RSA-DES-CBC3-SHA:EXP-ADH-RC4-MD5:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:EXP-ADH-DES-CBC-SHA:ADH-AES256-SHA:ADH-DES-CBC-SHA:ADH-RC4-MD5:AES256-SHA:DES-CBC-SHA:DES-CBC3-SHA:ADH-DES-CBC3-SHA:AES128-SHA:ADH-AES128-SHA:eNULL:ALL"))
 {
+    fatal("Unable to set OpenSSL cipher list: %s", 
+         ERR_error_string(ERR_get_error(), NULL));
+  }
+
+
+  /* Our SSL* will always have the SSL_SESSION* inside it, so we neither
+     need to use nor waste memory for the session cache.
+     (Use '1' because '0' means 'infinite'.)   */
+  SSL_CTX_set_session_cache_mode(
+     tls1nfo->ctx,  SSL_SESS_CACHE_OFF | SSL_SESS_CACHE_NO_AUTO_CLEAR );
+  SSL_CTX_sess_set_cache_size( tls1nfo->ctx, 1 ); 
+  SSL_CTX_set_timeout( tls1nfo->ctx, 3600); /* pretty unnecessary */
+}
+
 /* This function returns the Nsock Global SSL information.  You should
    have called Nsock_SSL_Init once before, but this function will take
    care of it if you haven't. */
@@ -134,4 +244,25 @@
 
   return sslnfo;
 }
+
+/* This function returns the Nsock Global SSL information.  You should
+   have called Nsock_SSL_Init once before, but this function will take
+   care of it if you haven't. */
+struct NsockSSLInfo *Nsock_SSL3GetInfo() {
+
+  if (!ssl3nfo)
+    Nsock_SSL3_Init();
+
+  return ssl3nfo;
+}
+/* This function returns the Nsock Global SSL information.  You should
+   have called Nsock_SSL_Init once before, but this function will take
+   care of it if you haven't. */
+struct NsockSSLInfo *Nsock_TLS1GetInfo() {
+
+  if (!tls1nfo)
+    Nsock_TLS1_Init();
+
+  return tls1nfo;
+}
 #endif /* HAVE_OPENSSL */
diff -urNb nmap-4.85BETA3/nsock/src/nsock_ssl.h nmap-ssl/nsock/src/nsock_ssl.h
--- nmap-4.85BETA3/nsock/src/nsock_ssl.h        2008-05-05 06:10:20.000000000 +0200
+++ nmap-ssl/nsock/src/nsock_ssl.h      2009-02-21 16:03:47.000000000 +0100
@@ -88,10 +88,15 @@
  (such as whether you want the connection to be fast or secure).  It is
  OK to call it multiple times - only the first one will count.  */
 void Nsock_SSL_Init();
+void Nsock_SSL3_Init();
+void Nsock_TLS1_Init();
 
 /* This function returns the Nsock Global SSL information.  You should
    have called Nsock_SSL_Init once before, but this function will take
    care of it if you haven't. */
 struct NsockSSLInfo *Nsock_SSLGetInfo();
+struct NsockSSLInfo *Nsock_SSL3GetInfo();
+struct NsockSSLInfo *Nsock_TLS1GetInfo();
+
 #endif /* HAVE_OPENSSL */
 #endif /* NSOCK_SSL_H */
diff -urNb nmap-4.85BETA3/output.cc nmap-ssl/output.cc
--- nmap-4.85BETA3/output.cc    2009-02-01 22:08:39.000000000 +0100
+++ nmap-ssl/output.cc  2009-02-21 17:07:57.000000000 +0100
@@ -285,6 +285,11 @@
 
   versionxmlstring += " ";
   versionxmlstring += (sd->service_tunnel == SERVICE_TUNNEL_SSL)? "tunnel=\"ssl\" " : "";
+  /* Do not differentiate between different SSL versions in the output, as this is just
+ * 'a' supported version, and by no means a statement about the highest/lowest supported 
+ * SSL version */
+  versionxmlstring += (sd->service_tunnel == SERVICE_TUNNEL_SSL3)? "tunnel=\"ssl\" " : "";
+  versionxmlstring += (sd->service_tunnel == SERVICE_TUNNEL_TLS1)? "tunnel=\"ssl\" " : "";
   versionxmlstring += "method=\"";
   versionxmlstring += (sd->dtype == SERVICE_DETECTION_TABLE)? "table" : "probed";
   versionxmlstring += "\" conf=\"";
@@ -460,14 +465,19 @@
   int len;
   if (buflen < 1) return;
 
-  if (sd->service_tunnel == SERVICE_TUNNEL_SSL) {
+ /* Do not differentiate between different SSL versions in the output, as this is just
+ *   'a' supported version, and by no means a statement about the highest/lowest supported
+ *   SSL version */
+  if (sd->service_tunnel == SERVICE_TUNNEL_SSL || sd->service_tunnel == SERVICE_TUNNEL_SSL3 ||
+       sd->service_tunnel == SERVICE_TUNNEL_TLS1) {
     if (lenremaining < 5) goto overflow;
     strncpy(dst, "ssl/", lenremaining);
     dst += 4;
     lenremaining -= 4;
   } 
 
-  if (sd->name && (sd->service_tunnel != SERVICE_TUNNEL_SSL || 
+  if (sd->name && ((sd->service_tunnel != SERVICE_TUNNEL_SSL &&
+       sd->service_tunnel != SERVICE_TUNNEL_SSL3 && sd->service_tunnel != SERVICE_TUNNEL_TLS1) ||
                   sd->dtype == SERVICE_DETECTION_PROBED)) {
     if (o.servicescan && state == PORT_OPEN && sd->name_confidence <= 5) 
       len = Snprintf(dst, lenremaining, "%s?", sd->name);
diff -urNb nmap-4.85BETA3/portlist.h nmap-ssl/portlist.h
--- nmap-4.85BETA3/portlist.h   2008-10-25 02:24:32.000000000 +0200
+++ nmap-ssl/portlist.h 2009-02-21 16:03:47.000000000 +0100
@@ -143,7 +143,7 @@
 
 enum service_detection_type { SERVICE_DETECTION_TABLE, SERVICE_DETECTION_PROBED };
 
-enum service_tunnel_type { SERVICE_TUNNEL_NONE, SERVICE_TUNNEL_SSL };
+enum service_tunnel_type { SERVICE_TUNNEL_NONE, SERVICE_TUNNEL_SSL, SERVICE_TUNNEL_SSL3, SERVICE_TUNNEL_TLS1 };
 
 // Move some popular TCP ports to the beginning of the portlist, because
 // that can speed up certain scans.  You should have already done any port
diff -urNb nmap-4.85BETA3/service_scan.cc nmap-ssl/service_scan.cc
--- nmap-4.85BETA3/service_scan.cc      2008-12-04 18:04:48.000000000 +0100
+++ nmap-ssl/service_scan.cc    2009-02-21 17:10:43.000000000 +0100
@@ -1779,11 +1779,24 @@
                            (struct sockaddr *) &ss, ss_len,
                            svc->portno);
        } else {
-         assert(svc->tunnel == SERVICE_TUNNEL_SSL);
+         assert(svc->tunnel == SERVICE_TUNNEL_SSL || svc->tunnel == SERVICE_TUNNEL_SSL3 || svc->tunnel == 
SERVICE_TUNNEL_TLS1);
+         if (svc->tunnel == SERVICE_TUNNEL_SSL) {
          nsock_connect_ssl(nsp, svc->niod, servicescan_connect_handler, 
                            DEFAULT_CONNECT_SSL_TIMEOUT, svc, 
                            (struct sockaddr *) &ss,
                            ss_len, svc->portno, svc->ssl_session);
+         }else if (svc->tunnel == SERVICE_TUNNEL_SSL3) {
+               nsock_connect_ssl3(nsp, svc->niod, servicescan_connect_handler,
+                            DEFAULT_CONNECT_SSL_TIMEOUT, svc,
+                            (struct sockaddr *) &ss,
+                            ss_len, svc->portno, svc->ssl_session);    
+         }else{
+               assert(svc->tunnel == SERVICE_TUNNEL_TLS1);
+               nsock_connect_tls1(nsp, svc->niod, servicescan_connect_handler,
+                            DEFAULT_CONNECT_SSL_TIMEOUT, svc,
+                            (struct sockaddr *) &ss,
+                            ss_len, svc->portno, svc->ssl_session);
+         }
        }
       } else {
        assert(svc->proto == IPPROTO_UDP);
@@ -1833,13 +1846,24 @@
     return 0;
   }
 
-  if (svc->proto != IPPROTO_TCP || 
-      !svc->probe_matched || strcmp(svc->probe_matched, "ssl") != 0)
+  if ((svc->proto != IPPROTO_TCP || !svc->probe_matched) != 0)
     return 0; // Not SSL
 
+  //Which SSL version should we use to connect?
+  if (strncmp(svc->probe_matched, "ssl", 4) == 0) {
+       //SSLv3
+       svc->tunnel = SERVICE_TUNNEL_SSL;
+  } else if (strncmp(svc->probe_matched, "ssl3", 4) == 0) {
+       //TLSv1
+       svc->tunnel = SERVICE_TUNNEL_SSL3;
+  } else if (strncmp(svc->probe_matched, "tls1", 4) == 0) {
+       svc->tunnel = SERVICE_TUNNEL_TLS1;
+  }else{
+       return 0; //Not SSL
+  }
+
   // Alright!  We are going to start the tests over using SSL
   // printf("DBG: Found SSL service on %s:%hu - starting SSL scan\n", svc->target->NameIP(), svc->portno);
-  svc->tunnel = SERVICE_TUNNEL_SSL;
   svc->probe_matched = NULL;
   svc->product_matched[0] = svc->version_matched[0] = svc->extrainfo_matched[0] = '\0';
   svc->hostname_matched[0] = svc->ostype_matched[0] = svc->devicetype_matched[0] = '\0';
@@ -2005,7 +2029,8 @@
   ServiceProbe *probe = svc->currentProbe();
   ServiceGroup *SG = (ServiceGroup *) nsp_getud(nsp);
 
-  assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL);
+  assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL ||
+        type == NSE_TYPE_CONNECT_SSL3 || type == NSE_TYPE_CONNECT_TLS1);
 
   if (svc->target->timedOut(nsock_gettimeofday())) {
     end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi);

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

Current thread: