Index: net/third_party/nss/patches/nextproto.patch |
=================================================================== |
--- net/third_party/nss/patches/nextproto.patch (revision 124804) |
+++ net/third_party/nss/patches/nextproto.patch (working copy) |
@@ -1,592 +0,0 @@ |
-From 0c2f72b38711abdd4ada08ae8d7e96dce79a672b Mon Sep 17 00:00:00 2001 |
-From: Adam Langley <agl@chromium.org> |
-Date: Mon, 3 Oct 2011 12:19:28 -0400 |
-Subject: [PATCH 01/15] nextproto.patch |
- |
---- |
- mozilla/security/nss/lib/ssl/ssl.def | 8 ++ |
- mozilla/security/nss/lib/ssl/ssl.h | 51 ++++++++++++ |
- mozilla/security/nss/lib/ssl/ssl3con.c | 58 +++++++++++++ |
- mozilla/security/nss/lib/ssl/ssl3ext.c | 104 ++++++++++++++++++++++++- |
- mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +- |
- mozilla/security/nss/lib/ssl/sslerr.h | 2 + |
- mozilla/security/nss/lib/ssl/sslimpl.h | 21 +++++ |
- mozilla/security/nss/lib/ssl/sslsock.c | 134 +++++++++++++++++++++++++++++++ |
- mozilla/security/nss/lib/ssl/sslt.h | 3 +- |
- 9 files changed, 381 insertions(+), 3 deletions(-) |
- |
-diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def |
-index d3f455c..6ea48c0 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl.def |
-+++ b/mozilla/security/nss/lib/ssl/ssl.def |
-@@ -152,3 +152,11 @@ SSL_SNISocketConfigHook; |
- ;+ local: |
- ;+*; |
- ;+}; |
-+;+NSS_CHROMIUM { |
-+;+ global: |
-+SSL_GetNextProto; |
-+SSL_SetNextProtoCallback; |
-+SSL_SetNextProtoNego; |
-+;+ local: |
-+;+*; |
-+;+}; |
-diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h |
-index 4a9e89d..f54eb09 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl.h |
-+++ b/mozilla/security/nss/lib/ssl/ssl.h |
-@@ -153,6 +153,57 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on); |
- SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on); |
- SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle); |
- |
-+/* SSLNextProtoCallback is called, during the handshake, when the server has |
-+ * sent a Next Protocol Negotiation extension. |protos| and |protosLen| define |
-+ * a buffer which contains the server's advertisement. This data is guaranteed |
-+ * to be well formed per the NPN spec. |protoOut| is a buffer provided by the |
-+ * caller, of length 255 (the maximum allowed by the protocol). |
-+ * On successful return, the protocol to be announced to the server will be in |
-+ * |protoOut| and its length in |*protoOutLen|. */ |
-+typedef SECStatus (PR_CALLBACK *SSLNextProtoCallback)( |
-+ void *arg, |
-+ PRFileDesc *fd, |
-+ const unsigned char* protos, |
-+ unsigned int protosLen, |
-+ unsigned char* protoOut, |
-+ unsigned int* protoOutLen); |
-+ |
-+/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol |
-+ * Negotiation. It causes a client to advertise NPN. */ |
-+SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd, |
-+ SSLNextProtoCallback callback, |
-+ void *arg); |
-+ |
-+/* SSL_SetNextProtoNego can be used as an alternative to |
-+ * SSL_SetNextProtoCallback. It also causes a client to advertise NPN and |
-+ * installs a default callback function which selects the first supported |
-+ * protocol in server-preference order. If no matching protocol is found it |
-+ * selects the first supported protocol. |
-+ * |
-+ * The supported protocols are specified in |data| in wire-format (8-bit |
-+ * length-prefixed). For example: "\010http/1.1\006spdy/2". */ |
-+SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, |
-+ const unsigned char *data, |
-+ unsigned int length); |
-+/* SSL_GetNextProto can be used after a handshake on a socket where |
-+ * SSL_SetNextProtoNego was called to retrieve the result of the Next Protocol |
-+ * negotiation. |
-+ * |
-+ * state is set to one of the SSL_NEXT_PROTO_* constants. The negotiated |
-+ * protocol, if any, is written into buf, which must be at least buf_len bytes |
-+ * long. If the negotiated protocol is longer than this, it is truncated. The |
-+ * number of bytes copied is written into *length. */ |
-+SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd, |
-+ int *state, |
-+ unsigned char *buf, |
-+ unsigned int *length, |
-+ unsigned int buf_len); |
-+ |
-+/* TODO(wtc): it may be a good idea to define these as an enum type. */ |
-+#define SSL_NEXT_PROTO_NO_SUPPORT 0 /* No peer support */ |
-+#define SSL_NEXT_PROTO_NEGOTIATED 1 /* Mutual agreement */ |
-+#define SSL_NEXT_PROTO_NO_OVERLAP 2 /* No protocol overlap found */ |
-+ |
- /* |
- ** Control ciphers that SSL uses. If on is non-zero then the named cipher |
- ** is enabled, otherwise it is disabled. |
-diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c |
-index 8048913..d2d4f91 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl3con.c |
-+++ b/mozilla/security/nss/lib/ssl/ssl3con.c |
-@@ -81,6 +81,7 @@ static SECStatus ssl3_InitState( sslSocket *ss); |
- static SECStatus ssl3_SendCertificate( sslSocket *ss); |
- static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); |
- static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); |
-+static SECStatus ssl3_SendNextProto( sslSocket *ss); |
- static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); |
- static SECStatus ssl3_SendServerHello( sslSocket *ss); |
- static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); |
-@@ -5742,6 +5743,16 @@ ssl3_HandleServerHelloDone(sslSocket *ss) |
- if (rv != SECSuccess) { |
- goto loser; /* err code was set. */ |
- } |
-+ |
-+ /* We don't send NPN in a renegotiation as it's explicitly disallowed by |
-+ * the spec. */ |
-+ if (!ss->firstHsDone) { |
-+ rv = ssl3_SendNextProto(ss); |
-+ if (rv != SECSuccess) { |
-+ goto loser; /* err code was set. */ |
-+ } |
-+ } |
-+ |
- rv = ssl3_SendFinished(ss, 0); |
- if (rv != SECSuccess) { |
- goto loser; /* err code was set. */ |
-@@ -8169,6 +8180,40 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, |
- } |
- |
- /* called from ssl3_HandleServerHelloDone |
-+ */ |
-+static SECStatus |
-+ssl3_SendNextProto(sslSocket *ss) |
-+{ |
-+ SECStatus rv; |
-+ int padding_len; |
-+ static const unsigned char padding[32] = {0}; |
-+ |
-+ if (ss->ssl3.nextProto.len == 0) |
-+ return SECSuccess; |
-+ |
-+ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
-+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
-+ |
-+ padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32); |
-+ |
-+ rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len + |
-+ 2 + padding_len); |
-+ if (rv != SECSuccess) { |
-+ return rv; /* error code set by AppendHandshakeHeader */ |
-+ } |
-+ rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data, |
-+ ss->ssl3.nextProto.len, 1); |
-+ if (rv != SECSuccess) { |
-+ return rv; /* error code set by AppendHandshake */ |
-+ } |
-+ rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1); |
-+ if (rv != SECSuccess) { |
-+ return rv; /* error code set by AppendHandshake */ |
-+ } |
-+ return rv; |
-+} |
-+ |
-+/* called from ssl3_HandleServerHelloDone |
- * ssl3_HandleClientHello |
- * ssl3_HandleFinished |
- */ |
-@@ -8421,6 +8466,14 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, |
- if (doStepUp || ss->writerThread == PR_GetCurrentThread()) { |
- flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER; |
- } |
-+ |
-+ if (!isServer && !ss->firstHsDone) { |
-+ rv = ssl3_SendNextProto(ss); |
-+ if (rv != SECSuccess) { |
-+ goto xmit_loser; /* err code was set. */ |
-+ } |
-+ } |
-+ |
- rv = ssl3_SendFinished(ss, flags); |
- if (rv != SECSuccess) { |
- goto xmit_loser; /* err is set. */ |
-@@ -9488,6 +9541,11 @@ ssl3_DestroySSL3Info(sslSocket *ss) |
- ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/); |
- |
- ss->ssl3.initialized = PR_FALSE; |
-+ |
-+ if (ss->ssl3.nextProto.data) { |
-+ PORT_Free(ss->ssl3.nextProto.data); |
-+ ss->ssl3.nextProto.data = NULL; |
-+ } |
- } |
- |
- /* End of ssl3con.c */ |
-diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c |
-index becbfe9..711cad0 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl3ext.c |
-+++ b/mozilla/security/nss/lib/ssl/ssl3ext.c |
-@@ -235,6 +235,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = { |
- #endif |
- { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, |
- { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
-+ { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
- { -1, NULL } |
- }; |
- |
-@@ -245,6 +246,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { |
- /* TODO: add a handler for ssl_ec_point_formats_xtn */ |
- { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
- { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
-+ { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
- { -1, NULL } |
- }; |
- |
-@@ -267,7 +269,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { |
- { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
- { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
- #endif |
-- { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn } |
-+ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
-+ { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn } |
- /* any extra entries will appear as { 0, NULL } */ |
- }; |
- |
-@@ -534,6 +537,105 @@ ssl3_SendSessionTicketXtn( |
- return -1; |
- } |
- |
-+/* handle an incoming Next Protocol Negotiation extension. */ |
-+SECStatus |
-+ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
-+{ |
-+ if (data->len != 0) { |
-+ /* Clients MUST send an empty NPN extension, if any. */ |
-+ return SECFailure; |
-+ } |
-+ |
-+ return SECSuccess; |
-+} |
-+ |
-+/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none |
-+ * of the lengths may be 0 and the sum of the lengths must equal the length of |
-+ * the block. */ |
-+SECStatus |
-+ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) |
-+{ |
-+ unsigned int offset = 0; |
-+ |
-+ while (offset < length) { |
-+ if (data[offset] == 0) { |
-+ PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
-+ return SECFailure; |
-+ } |
-+ offset += (unsigned int)data[offset] + 1; |
-+ } |
-+ |
-+ if (offset > length) { |
-+ PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
-+ return SECFailure; |
-+ } |
-+ |
-+ return SECSuccess; |
-+} |
-+ |
-+SECStatus |
-+ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, |
-+ SECItem *data) |
-+{ |
-+ SECStatus rv; |
-+ unsigned char result[255]; |
-+ unsigned int result_len; |
-+ |
-+ rv = ssl3_ValidateNextProtoNego(data->data, data->len); |
-+ if (rv != SECSuccess) |
-+ return rv; |
-+ |
-+ rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, |
-+ data->data, data->len, |
-+ result, &result_len); |
-+ if (rv != SECSuccess) |
-+ return rv; |
-+ /* If the callback wrote more than allowed to |result| it has corrupted our |
-+ * stack. */ |
-+ PORT_Assert(result_len <= sizeof(result)); |
-+ |
-+ if (ss->ssl3.nextProto.data) |
-+ PORT_Free(ss->ssl3.nextProto.data); |
-+ ss->ssl3.nextProto.data = PORT_Alloc(result_len); |
-+ PORT_Memcpy(ss->ssl3.nextProto.data, result, result_len); |
-+ ss->ssl3.nextProto.len = result_len; |
-+ return SECSuccess; |
-+} |
-+ |
-+PRInt32 |
-+ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, |
-+ PRBool append, |
-+ PRUint32 maxBytes) |
-+{ |
-+ PRInt32 extension_length; |
-+ |
-+ /* Renegotiations do not send this extension. */ |
-+ if (!ss->nextProtoCallback || ss->firstHsDone) { |
-+ return 0; |
-+ } |
-+ |
-+ extension_length = 4; |
-+ |
-+ if (append && maxBytes >= extension_length) { |
-+ SECStatus rv; |
-+ rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2); |
-+ if (rv != SECSuccess) |
-+ goto loser; |
-+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
-+ if (rv != SECSuccess) |
-+ goto loser; |
-+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
-+ ssl_next_proto_neg_xtn; |
-+ } else if (maxBytes < extension_length) { |
-+ return 0; |
-+ } |
-+ |
-+ return extension_length; |
-+ |
-+ loser: |
-+ return -1; |
-+} |
-+ |
- /* |
- * NewSessionTicket |
- * Called from ssl3_HandleFinished |
-diff --git a/mozilla/security/nss/lib/ssl/ssl3prot.h b/mozilla/security/nss/lib/ssl/ssl3prot.h |
-index 4702fcc..f3c950e 100644 |
---- a/mozilla/security/nss/lib/ssl/ssl3prot.h |
-+++ b/mozilla/security/nss/lib/ssl/ssl3prot.h |
-@@ -157,7 +157,8 @@ typedef enum { |
- server_hello_done = 14, |
- certificate_verify = 15, |
- client_key_exchange = 16, |
-- finished = 20 |
-+ finished = 20, |
-+ next_proto = 67 |
- } SSL3HandshakeType; |
- |
- typedef struct { |
-diff --git a/mozilla/security/nss/lib/ssl/sslerr.h b/mozilla/security/nss/lib/ssl/sslerr.h |
-index a2f6524..c76ffa9 100644 |
---- a/mozilla/security/nss/lib/ssl/sslerr.h |
-+++ b/mozilla/security/nss/lib/ssl/sslerr.h |
-@@ -203,6 +203,8 @@ SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114), |
- |
- SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115), |
- |
-+SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 117), |
-+ |
- SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ |
- } SSLErrorCodes; |
- #endif /* NO_SECURITY_ERROR_ENUM */ |
-diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h |
-index 9af471d..199c573 100644 |
---- a/mozilla/security/nss/lib/ssl/sslimpl.h |
-+++ b/mozilla/security/nss/lib/ssl/sslimpl.h |
-@@ -313,6 +313,10 @@ typedef struct { |
- #endif /* NSS_ENABLE_ECC */ |
- |
- typedef struct sslOptionsStr { |
-+ /* If SSL_SetNextProtoNego has been called, then this contains the |
-+ * list of supported protocols. */ |
-+ SECItem nextProtoNego; |
-+ |
- unsigned int useSecurity : 1; /* 1 */ |
- unsigned int useSocks : 1; /* 2 */ |
- unsigned int requestCertificate : 1; /* 3 */ |
-@@ -827,6 +831,13 @@ struct ssl3StateStr { |
- PRBool initialized; |
- SSL3HandshakeState hs; |
- ssl3CipherSpec specs[2]; /* one is current, one is pending. */ |
-+ |
-+ /* In a client: if the server supports Next Protocol Negotiation, then |
-+ * this is the protocol that was negotiated. |
-+ * |
-+ * If the data pointer is non-NULL, then it is malloced data. */ |
-+ SECItem nextProto; |
-+ int nextProtoState; /* See NEXT_PROTO_* defines */ |
- }; |
- |
- typedef struct { |
-@@ -1058,6 +1069,8 @@ const unsigned char * preferredCipher; |
- SSLHandshakeCallback handshakeCallback; |
- void *handshakeCallbackData; |
- void *pkcs11PinArg; |
-+ SSLNextProtoCallback nextProtoCallback; |
-+ void *nextProtoArg; |
- |
- PRIntervalTime rTimeout; /* timeout for NSPR I/O */ |
- PRIntervalTime wTimeout; /* timeout for NSPR I/O */ |
-@@ -1494,8 +1507,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss, |
- PRUint16 ex_type, SECItem *data); |
- extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, |
- PRUint16 ex_type, SECItem *data); |
-+extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, |
-+ PRUint16 ex_type, SECItem *data); |
- extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, |
- PRUint16 ex_type, SECItem *data); |
-+extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, |
-+ PRUint16 ex_type, SECItem *data); |
- |
- /* ClientHello and ServerHello extension senders. |
- * Note that not all extension senders are exposed here; only those that |
-@@ -1526,6 +1543,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, |
- extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss, |
- PRBool append, PRUint32 maxBytes); |
- #endif |
-+extern PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, |
-+ PRUint32 maxBytes); |
-+extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, |
-+ unsigned short length); |
- |
- /* call the registered extension handlers. */ |
- extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss, |
-diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c |
-index bc770a1..829103b 100644 |
---- a/mozilla/security/nss/lib/ssl/sslsock.c |
-+++ b/mozilla/security/nss/lib/ssl/sslsock.c |
-@@ -163,6 +163,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */ |
- ** default settings for socket enables |
- */ |
- static sslOptions ssl_defaults = { |
-+ { siBuffer, NULL, 0 }, /* nextProtoNego */ |
- PR_TRUE, /* useSecurity */ |
- PR_FALSE, /* useSocks */ |
- PR_FALSE, /* requestCertificate */ |
-@@ -438,6 +439,10 @@ ssl_DestroySocketContents(sslSocket *ss) |
- ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); |
- ss->ephemeralECDHKeyPair = NULL; |
- } |
-+ if (ss->opt.nextProtoNego.data) { |
-+ PORT_Free(ss->opt.nextProtoNego.data); |
-+ ss->opt.nextProtoNego.data = NULL; |
-+ } |
- PORT_Assert(!ss->xtnData.sniNameArr); |
- if (ss->xtnData.sniNameArr) { |
- PORT_Free(ss->xtnData.sniNameArr); |
-@@ -1266,6 +1271,135 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) |
- return fd; |
- } |
- |
-+SECStatus |
-+SSL_SetNextProtoCallback(PRFileDesc *fd, |
-+ SSLNextProtoCallback callback, |
-+ void *arg) { |
-+ sslSocket *ss = ssl_FindSocket(fd); |
-+ |
-+ if (!ss) { |
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID(), |
-+ fd)); |
-+ PORT_SetError(SEC_ERROR_INVALID_ARGS); |
-+ return SECFailure; |
-+ } |
-+ |
-+ ssl_GetSSL3HandshakeLock(ss); |
-+ ss->nextProtoCallback = callback; |
-+ ss->nextProtoArg = arg; |
-+ ssl_ReleaseSSL3HandshakeLock(ss); |
-+ return SECSuccess; |
-+} |
-+ |
-+/* NextProtoStandardCallback is set as an NPN callback for the case when the |
-+ * user of the sockets wants the standard selection algorithm. */ |
-+static SECStatus |
-+NextProtoStandardCallback(void *arg, |
-+ PRFileDesc *fd, |
-+ const unsigned char *protos, |
-+ unsigned int protos_len, |
-+ unsigned char *protoOut, |
-+ unsigned int *protoOutLen) |
-+{ |
-+ unsigned int i, j; |
-+ const unsigned char *result; |
-+ |
-+ sslSocket *ss = ssl_FindSocket(fd); |
-+ PORT_Assert(ss); |
-+ |
-+ if (protos_len == 0) { |
-+ /* The server supports the extension, but doesn't have any protocols |
-+ * configured. In this case we request our favoured protocol. */ |
-+ goto pick_first; |
-+ } |
-+ |
-+ /* For each protocol in server preference, see if we support it. */ |
-+ for (i = 0; i < protos_len; ) { |
-+ for (j = 0; j < ss->opt.nextProtoNego.len; ) { |
-+ if (protos[i] == ss->opt.nextProtoNego.data[j] && |
-+ memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1], |
-+ protos[i]) == 0) { |
-+ /* We found a match. */ |
-+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; |
-+ result = &protos[i]; |
-+ goto found; |
-+ } |
-+ j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1; |
-+ } |
-+ i += (unsigned int)protos[i] + 1; |
-+ } |
-+ |
-+pick_first: |
-+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; |
-+ result = ss->opt.nextProtoNego.data; |
-+ |
-+found: |
-+ memcpy(protoOut, result + 1, result[0]); |
-+ *protoOutLen = result[0]; |
-+ return SECSuccess; |
-+} |
-+ |
-+SECStatus |
-+SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, |
-+ unsigned int length) |
-+{ |
-+ SECStatus rv; |
-+ |
-+ sslSocket *ss = ssl_FindSocket(fd); |
-+ |
-+ if (!ss) { |
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", |
-+ SSL_GETPID(), fd)); |
-+ PORT_SetError(SEC_ERROR_INVALID_ARGS); |
-+ return SECFailure; |
-+ } |
-+ |
-+ if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess) |
-+ return SECFailure; |
-+ |
-+ ssl_GetSSL3HandshakeLock(ss); |
-+ if (ss->opt.nextProtoNego.data) |
-+ PORT_Free(ss->opt.nextProtoNego.data); |
-+ ss->opt.nextProtoNego.data = PORT_Alloc(length); |
-+ if (!ss->opt.nextProtoNego.data) { |
-+ ssl_ReleaseSSL3HandshakeLock(ss); |
-+ return SECFailure; |
-+ } |
-+ memcpy(ss->opt.nextProtoNego.data, data, length); |
-+ ss->opt.nextProtoNego.len = length; |
-+ ss->opt.nextProtoNego.type = siBuffer; |
-+ ssl_ReleaseSSL3HandshakeLock(ss); |
-+ |
-+ return SSL_SetNextProtoCallback(fd, NextProtoStandardCallback, NULL); |
-+} |
-+ |
-+SECStatus |
-+SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf, |
-+ unsigned int *length, unsigned int buf_len) |
-+{ |
-+ sslSocket *ss = ssl_FindSocket(fd); |
-+ |
-+ if (!ss) { |
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(), |
-+ fd)); |
-+ return SECFailure; |
-+ } |
-+ |
-+ *state = ss->ssl3.nextProtoState; |
-+ |
-+ if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && |
-+ ss->ssl3.nextProto.data) { |
-+ *length = ss->ssl3.nextProto.len; |
-+ if (*length > buf_len) |
-+ *length = buf_len; |
-+ PORT_Memcpy(buf, ss->ssl3.nextProto.data, *length); |
-+ } else { |
-+ *length = 0; |
-+ } |
-+ |
-+ return SECSuccess; |
-+} |
-+ |
- PRFileDesc * |
- SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) |
- { |
-diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h |
-index c7d4553..f6e0b62 100644 |
---- a/mozilla/security/nss/lib/ssl/sslt.h |
-+++ b/mozilla/security/nss/lib/ssl/sslt.h |
-@@ -203,9 +203,10 @@ typedef enum { |
- ssl_ec_point_formats_xtn = 11, |
- #endif |
- ssl_session_ticket_xtn = 35, |
-+ ssl_next_proto_neg_xtn = 13172, |
- ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ |
- } SSLExtensionType; |
- |
--#define SSL_MAX_EXTENSIONS 5 |
-+#define SSL_MAX_EXTENSIONS 6 |
- |
- #endif /* __sslt_h_ */ |