-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ALPN support in SSLSocket #640
Conversation
Update the private native socketConnect method to receive optional ALPN data to include in handshake. The value is performatted per SSL_SetNextProtoNego(). Support for library users to supply the ALPN data will follow in subsequent commits.
Update the private SSLSocket constructor to accept a String[] of ALPN protocol names in preferred order. When given, it will prepare the ALPN extension data in the required format and pass it along to the socketConnect method. The change to publicly expose this capability will occur in a subsequent commit.
Add a method to retrieve the identifier of the negotiated protocol, if available.
Add a new SSLSocket constructor that allows the caller to specify ALPN protocols.
@cipherboy ahaha whups, I did not even see #526 :S |
@cipherboy ah, looks like #526 is about the server side anyway, whereas this PR is for the client side and is mostly orthogonal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is largely fine.
What's missing is a ALPN selection routine on the server. I'm not sure if you wanted to add that; this is purely client side support, as is mine in #526 (it doesn't do server selection at all--that requires a call to SSL_SetNextProtoCallback
).
My only thing is... this is the legacy SSLSocket
... We should really be adding features its replacement, org.mozilla.jss.ssl.javax.JSSSocket
.
I guess, what's the use case for still using this one? The other one is compliant with standard JDK interfaces and I'd prefer to push #526 (and then a later one adding server-side ALPN support) rather than continuing to add new features to the old one.
It is on my TODO list to rip out all of this old SSLSocket, including from PKI.
My 2c. I'll merge if there's a compelling reason to not use the new one for something.
* After the handshake, returns the negotiated protocol | ||
* or null (e.g. when the server does not support ALPN). | ||
*/ | ||
public native byte[] getNegotiatedProtocol() throws SocketException; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that we have any hope of making org.mozilla.jss.ssl.SSLSocket
comply with javax.net.ssl.SSLSocket
at this point in time (I've tried, twice!)... But how about we at least comply when the functions do the same thing? :-)
https://docs.oracle.com/javase/9/docs/api/javax/net/ssl/SSLSocket.html#getApplicationProtocol--
(return String
and getNegotiatedProtocol
-> getApplicationProtocol
since they do the same thing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change the name sure. Return String I am less sure about (discussed elsewhere).
*/ | ||
public SSLSocket( | ||
InetAddress address, int port, | ||
String hostname, byte[][]alpn, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your commit message you wrote:
Update the private SSLSocket constructor to accept a String[] of ALPN
But I only see byte[][]
of ALPNs. I'd prefer we stick with JCA-standard types here rather than introducing our own in general... But at minimum, the commit message should match the code. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it should be byte[]
- this is how ALPN protocol IDs are defined. See https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids and https://tools.ietf.org/html/rfc7301#section-6 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just saw your comment on the other PR. Bravo Java, bravo. What if the sequence of bytes is not valid UTF-8? What do you know, there are ALPN GREASE values that are not valid UTF-8 (see https://tools.ietf.org/html/rfc8701, e.g. {0xFA, 0xFA}
. If you want to set them, you cannot. If you want to read them, you cannot (the UTF-8 reader converts them to ��
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-)
if (alpn != NULL) { | ||
JSS_RefByteArray(env, alpn, (jbyte**)&alpnData, &alpnLength); | ||
if (alpnLength > 0) { | ||
SSL_SetNextProtoNego(sock->fd, alpnData, alpnLength); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ALPN data only really needs to be provided before the handshake is performed. Not that I mind the extra constructors, but should we add a separate setApplicationProtocols(...)
function to add this after construction? This would let us set it after construction from a JSSSocketFactory
(which I think we have in ldap-jdk and/or PKI).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(And IIRC, it can be used with TLSv1.2 and can be provided on later handshakes. Under TLSv1.3 there's only the initial one so I guess it doesn't matter too much.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to worry about the renegotiation use case. But if it does turn out to be important we could add the extra function then.
Or now... I do prefer supplying as much "config" in the constructor rather than afterwards. Having to call extra functions to do more setup is something I find distasteful (I use that word in acknowledgement that it is indeed a matter of taste ^_^). Ideally there would be a single configuration record type that can supply SNI, ALPN and be extensible as new knobs are needed, so that there is not a combinatorial explosion in the number of possible constructors :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also turns out (I had forgotten until I made changes in my other PR) -- NSS doesn't support changing ALPN values on renegotiation. Even 0RTT assumes (and validates!) ALPN doesn't change any.
"single configuration record type"
... So ... JSSParameters? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cipherboy yep :D
I'll have a closer review of #526. I don't mind to abandon this #526 satisfies the client side use case of ACME tls-alpn-01 challenge. |
Abandoning in favour of #526 . |
This is a prerequisite for ACME tls-alpn-01 challenge verification.
See https://gist.github.com/frasertweedale/dfac386579cb2d1fe892f39d22c2975d
for usage / testbed.