Index: net/third_party/nss/patches/nextproto.patch |
diff --git a/net/third_party/nss/patches/nextproto.patch b/net/third_party/nss/patches/nextproto.patch |
index a01f2404b15b992ae578bcd462e360ef5de5797a..46021b425f3cbed78b4aef4119069982274b9206 100644 |
--- a/net/third_party/nss/patches/nextproto.patch |
+++ b/net/third_party/nss/patches/nextproto.patch |
@@ -1,68 +1,89 @@ |
-From 6b594dc531e7a1d1d5bca2f0f78e7bc0ac3ff937 Mon Sep 17 00:00:00 2001 |
+From 3caa0f573d2637bfed99dcc0e5887fe3a52462ba Mon Sep 17 00:00:00 2001 |
From: Adam Langley <agl@chromium.org> |
Date: Mon, 3 Oct 2011 12:19:28 -0400 |
-Subject: [PATCH] nextproto.patch |
+Subject: [PATCH 01/15] nextproto.patch |
--- |
- mozilla/security/nss/cmd/tstclnt/tstclnt.c | 6 ++ |
- mozilla/security/nss/lib/ssl/ssl.def | 7 ++ |
- mozilla/security/nss/lib/ssl/ssl.h | 12 +++ |
- mozilla/security/nss/lib/ssl/ssl3con.c | 54 ++++++++++++ |
- mozilla/security/nss/lib/ssl/ssl3ext.c | 122 +++++++++++++++++++++++++++- |
- mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +- |
- mozilla/security/nss/lib/ssl/sslimpl.h | 24 ++++++ |
- mozilla/security/nss/lib/ssl/sslsock.c | 74 +++++++++++++++++ |
- mozilla/security/nss/lib/ssl/sslt.h | 3 +- |
- 9 files changed, 302 insertions(+), 3 deletions(-) |
+ mozilla/security/nss/lib/ssl/ssl.def | 6 ++ |
+ mozilla/security/nss/lib/ssl/ssl.h | 51 ++++++++++++ |
+ mozilla/security/nss/lib/ssl/ssl3con.c | 54 +++++++++++++ |
+ 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 | 131 +++++++++++++++++++++++++++++++ |
+ mozilla/security/nss/lib/ssl/sslt.h | 3 +- |
+ 9 files changed, 372 insertions(+), 3 deletions(-) |
-diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c |
-index 55684e6..d209a33 100644 |
---- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c |
-+++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c |
-@@ -868,6 +868,12 @@ int main(int argc, char **argv) |
- return 1; |
- } |
- |
-+ rv = SSL_SetNextProtoNego(s, "\004flip\004http1.1", 10); |
-+ if (rv != SECSuccess) { |
-+ SECU_PrintError(progName, "error enabling next protocol negotiation"); |
-+ return 1; |
-+ } |
-+ |
- /* enable false start. */ |
- rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart); |
- if (rv != SECSuccess) { |
diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def |
-index d3f455c..a1f4b51 100644 |
+index d3f455c..5256ae2 100644 |
--- a/mozilla/security/nss/lib/ssl/ssl.def |
+++ b/mozilla/security/nss/lib/ssl/ssl.def |
-@@ -152,3 +152,10 @@ SSL_SNISocketConfigHook; |
+@@ -152,3 +152,9 @@ SSL_SNISocketConfigHook; |
;+ local: |
;+*; |
;+}; |
+;+NSS_CHROMIUM { |
+;+ global: |
-+SSL_GetNextProto; |
-+SSL_SetNextProtoNego; |
++SSL_SetNextProtoCallback; |
+;+ local: |
+;+*; |
+;+}; |
diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h |
-index 4a9e89d..ffa973c 100644 |
+index 4a9e89d..2cf777d 100644 |
--- a/mozilla/security/nss/lib/ssl/ssl.h |
+++ b/mozilla/security/nss/lib/ssl/ssl.h |
-@@ -153,6 +153,18 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on); |
+@@ -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 short length); |
++ 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 *length, |
-+ unsigned buf_len); |
++ 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 */ |
@@ -71,7 +92,7 @@ index 4a9e89d..ffa973c 100644 |
** 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..e0cb4e9 100644 |
+index 8048913..8f860a9 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); |
@@ -107,7 +128,7 @@ index 8048913..e0cb4e9 100644 |
+ int padding_len; |
+ static const unsigned char padding[32] = {0}; |
+ |
-+ if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) |
++ if (ss->ssl3.nextProto.len == 0) |
+ return SECSuccess; |
+ |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
@@ -164,7 +185,7 @@ index 8048913..e0cb4e9 100644 |
/* End of ssl3con.c */ |
diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c |
-index becbfe9..fbd5a91 100644 |
+index becbfe9..36ac4de 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[] = { |
@@ -193,7 +214,7 @@ index becbfe9..fbd5a91 100644 |
/* any extra entries will appear as { 0, NULL } */ |
}; |
-@@ -534,6 +537,123 @@ ssl3_SendSessionTicketXtn( |
+@@ -534,6 +537,105 @@ ssl3_SendSessionTicketXtn( |
return -1; |
} |
@@ -206,12 +227,11 @@ index becbfe9..fbd5a91 100644 |
+ return SECFailure; |
+ } |
+ |
-+ ss->ssl3.hs.nextProtoNego = PR_TRUE; |
+ return SECSuccess; |
+} |
+ |
+/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none |
-+ * of the length may be 0 and the sum of the lengths must equal the length of |
++ * 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) |
@@ -220,63 +240,46 @@ index becbfe9..fbd5a91 100644 |
+ |
+ 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) |
++ 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) |
++ SECItem *data) |
+{ |
-+ unsigned int i, j; |
+ SECStatus rv; |
-+ unsigned char *result; |
-+ |
-+ if (data->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; |
-+ } |
++ unsigned char result[255]; |
++ unsigned int result_len; |
+ |
+ rv = ssl3_ValidateNextProtoNego(data->data, data->len); |
+ if (rv != SECSuccess) |
+ return rv; |
+ |
-+ /* For each protocol in server preference order, see if we support it. */ |
-+ for (i = 0; i < data->len; ) { |
-+ for (j = 0; j < ss->opt.nextProtoNego.len; ) { |
-+ if (data->data[i] == ss->opt.nextProtoNego.data[j] && |
-+ memcmp(&data->data[i+1], &ss->opt.nextProtoNego.data[j+1], |
-+ data->data[i]) == 0) { |
-+ /* We found a match */ |
-+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; |
-+ result = &data->data[i]; |
-+ goto found; |
-+ } |
-+ j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1; |
-+ } |
-+ |
-+ i += (unsigned int)data->data[i] + 1; |
-+ } |
-+ |
-+ pick_first: |
-+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; |
-+ result = ss->opt.nextProtoNego.data; |
++ 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)); |
+ |
-+ found: |
+ if (ss->ssl3.nextProto.data) |
+ PORT_Free(ss->ssl3.nextProto.data); |
-+ ss->ssl3.nextProto.data = PORT_Alloc(result[0]); |
-+ PORT_Memcpy(ss->ssl3.nextProto.data, result + 1, result[0]); |
-+ ss->ssl3.nextProto.len = result[0]; |
++ 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; |
+} |
+ |
@@ -288,7 +291,7 @@ index becbfe9..fbd5a91 100644 |
+ PRInt32 extension_length; |
+ |
+ /* Renegotiations do not send this extension. */ |
-+ if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) { |
++ if (!ss->nextProtoCallback || ss->firstHsDone) { |
+ return 0; |
+ } |
+ |
@@ -331,48 +334,58 @@ index 4702fcc..f3c950e 100644 |
} 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..d1c1181 100644 |
+index 9af471d..199c573 100644 |
--- a/mozilla/security/nss/lib/ssl/sslimpl.h |
+++ b/mozilla/security/nss/lib/ssl/sslimpl.h |
-@@ -313,6 +313,11 @@ typedef struct { |
+@@ -313,6 +313,10 @@ typedef struct { |
#endif /* NSS_ENABLE_ECC */ |
typedef struct sslOptionsStr { |
-+ /* For clients, this is a validated list of protocols in preference order |
-+ * and wire format. For servers, this is the list of support protocols, |
-+ * also in wire format. */ |
++ /* 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 */ |
-@@ -786,6 +791,7 @@ const ssl3CipherSuiteDef *suite_def; |
- #ifdef NSS_ENABLE_ECC |
- PRUint32 negotiatedECCurves; /* bit mask */ |
- #endif /* NSS_ENABLE_ECC */ |
-+ PRBool nextProtoNego;/* Our peer has sent this extension */ |
- } SSL3HandshakeState; |
- |
- |
-@@ -827,6 +833,16 @@ struct ssl3StateStr { |
+@@ -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 requested. |
-+ * In a server: this is the protocol that the client requested via Next |
-+ * Protocol Negotiation. |
++ * this is the protocol that was negotiated. |
+ * |
-+ * In either case, if the data pointer is non-NULL, then it is malloced |
-+ * data. */ |
++ * If the data pointer is non-NULL, then it is malloced data. */ |
+ SECItem nextProto; |
-+ int nextProtoState; /* See SSL_NEXT_PROTO_* defines */ |
++ int nextProtoState; /* See NEXT_PROTO_* defines */ |
}; |
typedef struct { |
-@@ -1494,8 +1510,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss, |
+@@ -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); |
@@ -385,7 +398,7 @@ index 9af471d..d1c1181 100644 |
/* ClientHello and ServerHello extension senders. |
* Note that not all extension senders are exposed here; only those that |
-@@ -1526,6 +1546,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, |
+@@ -1526,6 +1543,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, |
extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss, |
PRBool append, PRUint32 maxBytes); |
#endif |
@@ -397,7 +410,7 @@ index 9af471d..d1c1181 100644 |
/* 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..4c8fbfd 100644 |
+index bc770a1..769ea0a 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. */ |
@@ -419,16 +432,14 @@ index bc770a1..4c8fbfd 100644 |
PORT_Assert(!ss->xtnData.sniNameArr); |
if (ss->xtnData.sniNameArr) { |
PORT_Free(ss->xtnData.sniNameArr); |
-@@ -1266,6 +1271,75 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) |
+@@ -1266,6 +1271,132 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) |
return fd; |
} |
-+/* SSL_SetNextProtoNego sets the list of supported protocols for the given |
-+ * socket. The list is a series of 8-bit, length prefixed strings. */ |
+SECStatus |
-+SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, |
-+ unsigned short length) |
-+{ |
++SSL_SetNextProtoCallback(PRFileDesc *fd, |
++ SSLNextProtoCallback callback, |
++ void *arg) { |
+ sslSocket *ss = ssl_FindSocket(fd); |
+ |
+ if (!ss) { |
@@ -437,6 +448,74 @@ index bc770a1..4c8fbfd 100644 |
+ return SECFailure; |
+ } |
+ |
++ ssl_GetSSL3HandshakeLock(ss); |
++ ss->nextProtoCallback = callback; |
++ ss->nextProtoArg = arg; |
++ ssl_ReleaseSSL3HandshakeLock(ss); |
++} |
++ |
++/* 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)); |
++ return SECFailure; |
++ } |
++ |
+ if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess) |
+ return SECFailure; |
+ |
@@ -453,18 +532,9 @@ index bc770a1..4c8fbfd 100644 |
+ ss->opt.nextProtoNego.type = siBuffer; |
+ ssl_ReleaseSSL3HandshakeLock(ss); |
+ |
-+ return SECSuccess; |
++ return SSL_SetNextProtoCallback(fd, NextProtoStandardCallback, NULL); |
+} |
+ |
-+/* SSL_GetNextProto reads the resulting Next Protocol Negotiation result for |
-+ * the given socket. It's only valid to call this once the handshake has |
-+ * completed. |
-+ * |
-+ * 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. |
-+ */ |
+SECStatus |
+SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf, |
+ unsigned int *length, unsigned int buf_len) |