(2nd round) Proposed API Changes for JEP 114: TLS Server Name Indication (SNI) Extension
Xuelei Fan
xuelei.fan at oracle.com
Wed Aug 15 02:45:48 UTC 2012
I only reply on the items that I may need more review.
On 8/15/2012 7:54 AM, Brad Wetmore wrote:
>>> SSLParameters.java
>>> ==================
>>> 76: Not sure why you want/need a LinkedHashMap with only one currently
>>> defined NameType. Even if there were multiple types, I don't think that
>>> SNI requires an ordering. You also mention this in
>>> setAccessibleServerName, but not sure what purpose this serves. I'm not
>>> strongly against it, just wondering.
>>>
>> I am also not sure about the strong desire that the SNI should be
>> ordered. But Weijun prefers it to be ordered because he think the SNI in
>> RFC6066 is defined as an ordered sequence.
>>
>> struct {
>> ServerName server_name_list<1..2^16-1>
>> } ServerNameList;
>
> I've gone through RFC6066 pretty carefully, and I'm not seeing any
> indication that this should be ordered.
>
> In RFC 2246, if there is an ordering required, such as
> cipher_suites/compression/certs/cert_requests, it's specifically called
> out. For any other "lists", it is not specified.
>
> Section 7.4.1.2
>
> The CipherSuite list, passed from the client to the server in the
> client hello message, contains the combinations of cryptographic
> algorithms supported by the client in order of the client's
> preference (favorite choice first).
>
> ...deleted...
>
> The client hello includes a list of compression algorithms supported
> by the client, ordered according to the client's preference.
>
> ...deleted...
>
> cipher_suites
> This is a list of the cryptographic options supported by the
> client, with the client's first preference first.
>
> ...deleted...
>
> compression_methods
> This is a list of the compression methods supported by the
> client, sorted by client preference.
>
> Section 7.4.2
>
> certificate_list
> This is a sequence (chain) of X.509v3 certificates. The sender's
> certificate must come first in the list.
>
> Section 7.4.4
>
> certificate_types
> This field is a list of the types of certificates requested,
> sorted in order of the server's preference.
>
> Weijun, did you see something else in your read of the spec that
> indicates an ordering? If not, maybe we should not put in the order
> wording now. If it turns out we do need it, we can always add that
> wording later in a later release, but it will be impossible to remove it
> if we add it now.
>
I think you are right. If Weijun has no other concerns, I will remove
related description.
>> The SSLParameters will not check the validity of the value. The checking
>> will be checked later during handshaking. With the revised APIs, empty
>> string is not valid. An exception will be thrown during the preparing of
>> SNI extension.
>>
>>> 308: What kinds of things are you thinking of writing in the Additional
>>> Standard Names doc for "value"?
>>>
>> That was a hot discussion, I think we had talked about it a lot.
>
> You missed my original point, sorry for dragging you into that
> discussion. I was talking about the "value" field not the "name" field.
> In that section, you indicated that the "value" field was going to be
> talked about in the Standard Algorithm Name document. I was wondering
> what you were going to be talking about there, just that this needs to
> be an ASCII value of a DNS hostname if it's a host_name type? For
> example, a table with:
>
> type value
> ==== =====
> host_name ASCII representation of a DNS hostname
>
Sorry, I did misunderstand your point. Yes, the doc will looks like your
above example.
>>> SSLSocketFactory.java
>>> =====================
>>>
>>> Since you're leaving the door open for this socket being either client
>>> or server, shouldn't the API then be similar to the existing layered
>>> socket one, just including the additional InputStream here:
>>>
>>> public abstract Socket createSocket(Socket s, InputStream is,
>>> String host, int port, boolean autoClose)
>>>
>>> We might be able to glean SNI information from the host here.
>>>
>> To make it more straightforward, I closed the door for this socket being
>> in client mode in the revised APIs.
>
> As you like. I would think adding an InputStream to the existing API is
> just as straightforward also for learning the API, but since we would
> only expect this to be used in server mode, your point has merit.
>
>>> 171: Interesting, the existing layered createSocket doesn't mention
>>> anything about whether client or server mode, and that you must set the
>>> mode or suffer with the default. Might want to file a bug and CCC this
>>> also.
>>>
>> Not really need the description of the mode. The existing description
>> has already implied that the return socket must be in client mode.
>>
>> * @param host the server host
>> * @param port the server port
>> * @return a socket connected to the specified host and port
>
> You mean because it's a "named host"? I can kind of buy that. But
> currently it's kind of subtle that it will be in client mode. I was
> thinking we should make it more clear.
>
I mean the "host" param is the *server* host, and the "port" param is
the *server* port, and the returned value is connected to the server
"host" and server "port", so it should be a client. But, it is not
straightforward. I'm OK to make it more clear.
>>> 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.
> 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 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?
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