What's new in NSS 3.12.\* - Server Name Indication (SNI) callback

What's new in NSS 3.12.\* - Server Name Indication (SNI) callback

When a request comes in to a web server, it sends the domain name in the Host header.

"GET /test.html HTTP/1.0

Host: abc.com"

by the time any web server parses it, its too late to send the appropriate certificate as it was already sent in the SSL Handshake. As per RFC4366, we now have a new extension in Handshake with which client can tell server the required domain. So the server can send appropriate certificate in the handshake.

In a Web Server, we can configure only one certificate of a type (ECC/RSA etc.) per HTTP listener using SSL_ConfigureSecureServer(fd...) call. If the server has to be used for one more domain, we need to regenerate the certificate with that domain in Subject Alternate Names. But with Server Name Indication (SNI) extension, we can register, more than one certificates (of a particular type) per HTTP listener.

In NSS 3.12.6 a new SNI callback was added as a part of bug 360421. Any Server which uses NSS can set this callback function (similar to what is shown in selfserv.c#1709) and write its implementation to send appropriate SNI certificate at runtime.

I used two binaries bundled with NSS selfserv and tstclnt to see what is happening. (I have used NSS 3.12.8)

Create two server certificates "www.foo.com" and "www.bar.com"

$certutil -N -d .
$certutil -S -x -n www.foo.com -s "CN=www.foo.com" -t CTu,u,u -d .
$certutil -S -x -n www.bar.com -s "CN=www.bar.com" -t CTu,u,u -d .

start the server

$selfserv -D -B -s -p 4443  -n www.foo.com  -r -a www.bar.com -d .

Where
-D => disable Nagle delays in TCP
-B => bypasses the PKCS11 layer
-s => disable SSL socket locking
-n  rsa_cert_nickname
-a is used to configure server for SNI. [-a sni_cert_nickname]
-r => request, not require, cert on initial handshake.

create sslreq.cat

$cat > req.dat  
GET /test.html HTTP/1.0

 


Now send a request asking for domain "www.bar.com"

$tstclnt -p 4443 -h www.foo.com -f -d  . -n www.foo.com  -2 -a www.bar.com  < sslreq.dat

where
-n => Nickname of key & cert for client auth (use www.foo.com  for now)
-a => Send different SNI name. [-a 1st_handshake_sni_cert_name]

We get : 

subject DN: CN=www.bar.com
issuer  DN: CN=www.bar.com
0 cache hits; 1 cache misses, 0 cache not reusable
0 stateless resumes
HTTP/1.0 200 OK
Server: Generic Web Server
Date: Tue, 26 Aug 1997 22:10:05 GMT
Content-type: text/plain
GET /test.html HTTP/1.0
EOF

As you can see, the server returned the certificate for "www.bar.com"

To know what's happening look at the ssltap output (use -c z in selfserv and tstclnt both):

$ssltap -l -s -p 1925 foo:4443
Connection #1 [Mon Jan 17 14:51:12 2011]
Connected to foo:4443
--> [
(74 bytes of 69)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 69 (0x45)
   handshake {
      type = 1 (client_hello)
      length = 65 (0x000041)
         ClientHelloV3 {
            client_version = {3, 1}
            random = {...}
            session ID = {
                length = 0
                contents = {...}
            }
            cipher_suites[2] = {
                (0x00ff) ????/????????/?????????/???
                (0x0002) SSL3/RSA/NULL/SHA
            }
            compression[1] = {
                (00) NULL
            }
  extensions[20] = {
  extension type server_name, length [16] = {
   0: 00 0e 00 00  0b 77 77 77  2e 62 61 72  2e 63 6f 6d  | .....www.bar.com
              }
            }
         }
   }
}
]
<-- [
(590 bytes of 585)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 585 (0x249)
   handshake {
      type = 2 (server_hello)
      length = 81 (0x000051)
         ServerHello {
            server_version = {3, 1}
            random = {...}
            session ID = {
                length = 32
                contents = {...}
            }
            cipher_suite = (0x0002) SSL3/RSA/NULL/SHA
            compression method = (00) NULL
            extensions[9] = {
              extension type 65281, length [1] = {
   0: 00                    | .
              }
              extension type server_name, length [0]
            }
         }
      type = 11 (certificate)
      length = 430 (0x0001ae)
         CertificateChain {
            chainlength = 427 (0x01ab)
            Certificate {
               size = 424 (0x01a8)
               data = { saved in file 'cert.001' }
            }
         }
      type = 13 (certificate_request)
      length = 58 (0x00003a)
         CertificateRequest {
            certificate types[3] = { 01 02 40 }
            certificate_authorities[52] = {
CN=www.bar.com
   CN=www.foo.com
            }
         }
      type = 14 (server_hello_done)
      length = 0 (0x000000)
   }
}
]
--> [
(754 bytes of 702, with 47 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 702 (0x2be)
   handshake {
      type = 11 (certificate)
      length = 430 (0x0001ae)
         CertificateChain {
            chainlength = 427 (0x01ab)
            Certificate {
               size = 424 (0x01a8)
               data = { saved in file 'cert.002' }
            }
         }
      type = 16 (client_key_exchange)
      length = 130 (0x000082)
         ClientKeyExchange {
            message = {...}
         }
      type = 15 (certificate_verify)
      length = 130 (0x000082)
   }
}
(754 bytes of 1, with 41 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 20 (change_cipher_spec)
   version = { 3,1 }
   length  = 1 (0x1)
}
(754 bytes of 36)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 36 (0x24)
   handshake {
      type = 20 (finished)
      length = 12 (0x00000c)
         Finished {
            verify_data = {...}
         }
   }
      MAC = {...}
}
]
<-- [
(47 bytes of 1, with 41 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 20 (change_cipher_spec)
   version = { 3,1 }
   length  = 1 (0x1)
}
(47 bytes of 36)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 36 (0x24)
   handshake {
      type = 20 (finished)
      length = 12 (0x00000c)
         Finished {
            verify_data = {...}
         }
   }
      MAC = {...}
}
]
--> [
(50 bytes of 45)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 23 (application_data)
   version = { 3,1 }
   length  = 45 (0x2d)
   0: 47 45 54 20  2f 74 65 73  74 2e 68 74  6d 6c 20 48  | GET /test.html H
  10: 54 54 50 2f  31 2e 30 0a  0a                        | TTP/1.0..
      MAC = {...}
}
]
<-- [
(196 bytes of 164, with 27 left over)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 23 (application_data)
   version = { 3,1 }
   length  = 164 (0xa4)
   0: 48 54 54 50  2f 31 2e 30  20 32 30 30  20 4f 4b 0d  | HTTP/1.0 200 OK.
  10: 0a 53 65 72  76 65 72 3a  20 47 65 6e  65 72 69 63  | .Server: Generic
  20: 20 57 65 62  20 53 65 72  76 65 72 0d  0a 44 61 74  |  Web Server..Dat
  30: 65 3a 20 54  75 65 2c 20  32 36 20 41  75 67 20 31  | e: Tue, 26 Aug 1
  40: 39 39 37 20  32 32 3a 31  30 3a 30 35  20 47 4d 54  | 997 22:10:05 GMT
  50: 0d 0a 43 6f  6e 74 65 6e  74 2d 74 79  70 65 3a 20  | ..Content-type:
  60: 74 65 78 74  2f 70 6c 61  69 6e 0d 0a  0d 0a 47 45  | text/plain....GE
  70: 54 20 2f 74  65 73 74 2e  68 74 6d 6c  20 48 54 54  | T /test.html HTT
  80: 50 2f 31 2e  30 0a 0a 45  4f 46 0d 0a  0d 0a 0d 0a  | P/1.0..EOF......
      MAC = {...}
}
(196 bytes of 22)
SSLRecord { [Mon Jan 17 14:51:12 2011]
   type    = 21 (alert)
   version = { 3,1 }
   length  = 22 (0x16)
   warning: close_notify
      MAC = {...}
}
]

 Note that the client sent "www.bar.com" to the server in the extension.

Also that server sends the certificate (cert.001) i.e. "www.bar.com"  to the client.  

$openssl x509  -in cert.001 -text -inform DER

Certificate:

    Data:

        Version: 3 (0x2)

        Issuer: CN=www.bar.com

        Subject: CN=www.bar.com

And the client sends the certificate (cert.002) i.e. "www.foo.com"  to the server.

$openssl x509  -in cert.002 -text -inform DER

Certificate:

    Data:

        Version: 3 (0x2)

        Issuer: CN=www.foo.com

        Subject: CN=www.foo.com

Now send a request asking for domain "www.domain-not-found.com", the server is unable to find a certificate registered for such a domain and hence returns error. This behavior will vary from server to server depending on the implementation. 

$tstclnt -p 4443 -h www.foo.com -f -d  . -n www.foo.com  -2 -a "www.domain-not-found.com"  < sslreq.dat

 We get the error :

 tstclnt: write to SSL socket failed: SSL peer has no certificate for the requested DNS name

For this case, ssltap output shows an "unrecognize_name" alert (use -c z in selfserv and tstclnt):

$ssltap -l -s -p 1925 foo:4443
Connection #1 [Mon Jan 17 14:49:28 2011]
Connected to foo:4443
--> [
(87 bytes of 82)
SSLRecord { [Mon Jan 17 14:49:28 2011]
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 82 (0x52)
   handshake {
      type = 1 (client_hello)
      length = 78 (0x00004e)
         ClientHelloV3 {
            client_version = {3, 1}
            random = {...}
            session ID = {
                length = 0
                contents = {...}
            }
            cipher_suites[2] = {
                (0x00ff) ????/????????/?????????/???
                (0x0002) SSL3/RSA/NULL/SHA
            }
            compression[1] = {
                (00) NULL
            }
            extensions[33] = {
              extension type server_name, length [29] = {
  0: 00 1b 00 00  18 77 77 77  2e 64 6f 6d  61 69 6e 2d| .....www.domain-
 10: 6e 6f 74 2d  66 6f 75 6e  64 2e 63 6f  6d  | not-found.com
              }
            }
         }
   }
}
]
<-- [
(7 bytes of 2)
SSLRecord { [Mon Jan 17 14:49:28 2011]
   type    = 21 (alert)
   version = { 3,1 }
   length  = 2 (0x2)
   fatal: unrecognized_name
}
]
 
  

Looks like j2SE SNI client side support was integrated in J2SE 7 b118 CR6985179 To support Server Name Indication extension for JSSE client.

 Browsers that support TLS SNI

Refer http://en.wikipedia.org/wiki/Server_Name_Indication#Support for a full list. Some of these browsers are :

  • Internet Explorer 7 or later, on Windows Vista or higher. Does not work on Windows XP, even Internet Explorer 8.
  • Mozilla Firefox 2.0 or later
  • Google Chrome (Vista or higher. XP on Chrome 6 or newer. OS X 10.5.7 or higher on Chrome 5.0.342.1 or newer)
  • Safari 2.1 or later (Mac OS X 10.5.6 or higher and Windows Vista or higher)

References

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Meena Vyas

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today