(2nd round) Proposed API Changes for JEP 114: TLS Server Name Indication (SNI) Extension

Xuelei Fan xuelei.fan at oracle.com
Wed Aug 15 07:03:03 UTC 2012


On 8/15/2012 2:10 PM, Bradford Wetmore wrote:
> 
> 
> On 8/14/2012 7:45 PM, Xuelei Fan wrote:
> 
>>>>> 197:  You're not planning to process (e.g.
>>>>> ServerHandshaker/ClientHandshaker.process_message) the consumed
>>>>> handshaking bytes immediately during the createSocket call, are
>>>>> you? You
>>>>> still need to allow the user time to set the socket
>>>>> options/SSLParameters/etc.  I was expecting in this method you'd just
>>>>> suck in the consumed bytes into temporary storage, then create/return
>>>>> the socket, and then when the handshaking is started, you then read
>>>>> out
>>>>> from the temporary storage until you run out, then you switch to the
>>>>> Socket's InputStream.
>>>>>
>>>> You're right. It is allowed to set more options in the returned socket
>>>> before kick off handshake.
>>>>
>>>>> 197:  This needs some wordsmithing here.  This method will produce the
>>>>> SSLSocket that will be consuming this data, so of course it has to be
>>>>> called first.
>>>>>
>>>> I'm not sure I understand your point. Please comment it again with the
>>>> revised APIs if you still have concerns.
>>>
>>> I just didn't understand much of this paragraph.
>>>
>>> 1. You have to call this method, then set up your parameters, then start
>>> your handshaking.  So the first half of this sentence doesn't apply.
>>>
>> Oh, I know your concerns. What I want to express is that before the
>> calling to method, the caller should not do real handshaking. The logic
>> I concerned looks like:
>>      // 1. accept a socket
>>      // 2. read ClientHello and reply ServerHello to output stream.
>>      // 3. call this method
>>      SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(
>>                      socke, inputStream, true);
>>
>> because the handshaking has started in step 2, then in step 3, we cannot
>> get a proper SSLSocket.
> 
> How would the ServerHello be generated until you call this method and
> then start the handshaking on the returned SSLSocket?
One can use SSLEngine.wrap()/unwrap() to generate handshaking messages
from socket I/O stream.
    // accept a socket
    // read/write the I/O with SSLEngine
    // call this method

Xuelei

> You said in a
> previous internal conversation that SSLExplore would not generate any
> ServerHello, so this can't be what you mean.  Are you talking about
> layering another SSLSocket over a already layered SSLSocket?
> 
>>> 2. "consumed network data is resumable" wasn't clear either.  To me this
>>> should mean that you can obtain the data which has already been read
>>> from "s".
>>>
>> Yes, need wordsmithing here.
>>
>>> 3. "Otherwise, the behavior of the return socket is not defined" lost
>>> me.  Does this mean that that SSLParameters and assorted settings are
>>> not otherwise defined?
>>>
>> See above example.
> 
> I think I need the above answered before I can comment further here.
> 
>>> I think you could delete this paragraph.
>>>
>>>  From your second email:
>>>
>>>> Thought more about the design, I would have to say that we cannot
>>>> return
>>>> the default value in sslParameters.getServerNames().  Otherwise, the
>>>> following two block of codes look very weird to me:
>>>>       // case one:
>>>> 1   SSLparameters sslParameters = sslSocket.getSSLParameters();
>>>> 2   sslParameters.clearServerName("host_name");
>>>> 3   Map<String, String> names = sslParameters.getServerNames();
>>>> 4   sslSocket.setSSLParameters(sslParameters);
>>>> 5   sslParameters = sslSocket.getSSLParameters();
>>>> 6   names = sslParameters.getServerNames();
>>>>
>>>> In line 3, the returned map does not contain "host_name" entry. But in
>>>> line 6, it may be expected that no "host_name" in the returned map. But
>>>> if we want to return default values, line 6 do need to return a map
>>>> containing "host_name".  The behavior is pretty confusing. We may want
>>>> to try avoid the confusion.
>>>
>>> I'm not following your confusion, it seemed pretty straightforward to
>>> me, it works much like CipherSuites.  We have a set of ciphersuites
>>> which are enabled by default.  We can turn some off by using
>>> SSLParameters.  Expanding a bit on your example here, I'll describe what
>>> I think would happen internally/externally:
>>>
>>> 1    SSLSocket sslSocket = mySSLSocketFactory.createSocket(
>>>          "www.example.com", 443);
>>>
>>> mySSLSocketFactory sets any initial parameters as usual.  SSLSocketImpl
>>> knows it's connecting to www.example.com and automatically stores
>>> "host_name" -> "www.example.com" in its local host data (map or separate
>>> variables).
>>>
>>> 2   SSLparameters sslParameters = sslSocket.getSSLParameters();
>>>
>>> SSLSocketImpl.getSSLParameters() creates a SSLParameters, and sets the
>>> hostmap to the one value "host_name" -> "www.example.com"
>>>
>>> If the application want to get the "default values", they just pull them
>>> out of the SSLParameters here
>>>
>>> 3   sslParameters.clearServerName("host_name");
>>>
>>> Or sslParameters.setServerName("host_name", null)?
>>>
>>> User just decided to clear it.  Ok, that's what we do.  It becomes an
>>> empty map in SSLParameters.
>>>
>>> 4   Map<String, String> names = sslParameters.getServerNames();
>>>
>>> Returns empty Map.
>>>
>> As far as good.
>>
>>> 5   sslSocket.setSSLParameters(sslParameters);
>>>
>>> SSLSocketImpl.setSSLParameters is empty, so SSLSocketImpl takes this
>>> SSLParameters and as a result, clears it's internal "host_name" map to
>>> null, and thus won't send anything out since it's empty.
>>>
>> We have problems here.  We need to support that if an application does
>> not specified host_name value, we should use default values.
>>    I.   SSLParameters sslParameters = new SSLParameters();
>>    II.  sslParameters.setCipherSuites(...);
>>    III. SSLSocket sslSocket =
>>            sslSocketFactory.createSocket("www.example.com", 443)
>>    IV.  sslSocket.setSSLParameters(sslParameters);
>>
>> Before line IV and after line II, the sslParameters.getServerNames() are
>> empty. In line IV, we need to make sure the internal "host_name",
>> "www.example.com" is used as default value, and send it to server in
>> SNI.  That's the default behaviors in JDK 7.  We cannot break it without
>> strong desires.
>>
>> I think it means that we cannot clear the internal "host_name" when the
>> sslParameters.getServerNames() return empty.
>>
>> Does it make sense to you?
> 
> Ok, that's an issue, I was assuming people would generally get a
> SSLParameters from the SSLSocket/SSLEngine, which would have
> prepopulated values such as CipherSuites/Protocols and SNI values. Now I
> hear what you're saying.
> 
> So in SSLSocket/SSLEngine, we have a very similar situation with the
> CipherSuites/Protocols.  The way we did it there was if
> SSLParameters.getCipherSuites() is null (that is, has not been set in
> this instance), we let the default values stand (that is we did not call
> SSLSocket.setEnabledCipherSuites()).  You could do something like that
> with the SNI info.  I've always felt the setServerName/getServerName
> should take/return the same Map<String,String> value, but you felt
> strongly about a setServerName(String, String) so I didn't push it.  If
> we didn't set this value, then the original value could stand.
> 
> Maybe your current design addresses this in a better way, I'll have to
> look at this in the morning, I still have a couple hours of home stuff
> to do before I can go to bed.
> 
> Brad
> 
>> Thanks,
>> Xuelei
>>
>>> 6   sslParameters = sslSocket.getSSLParameters();
>>>
>>> SSLSocketImpl.getSSLParameters() creates a SSLParameters, which sees
>>> that there's no name indication, so it creates an empty name map and
>>> stores in SSLParameters.
>>>
>>> 7   names = sslParameters.getServerNames();
>>>
>>> returns empty.
>>>
>>> It's no longer the default value, because they have specifically set the
>>> value.
>>>
>>> HTH,
>>>
>>> Brad
>>
> 




More information about the security-dev mailing list