Chromium Code Reviews| Index: net/third_party/nss/ssl/sslsock.c |
| diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c |
| index 8cc57add741cd8bf13ea38b9b76f80f5acff1241..6f870f92e5b6316fe4b90240c24f6823b677f04e 100644 |
| --- a/net/third_party/nss/ssl/sslsock.c |
| +++ b/net/third_party/nss/ssl/sslsock.c |
| @@ -1310,12 +1310,10 @@ 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) { |
| @@ -1324,6 +1322,74 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, |
| return SECFailure; |
| } |
| + ssl_GetSSL3HandshakeLock(ss); |
| + ss->nextProtoCallback = callback; |
| + ss->nextProtoArg = arg; |
| + ssl_ReleaseSSL3HandshakeLock(ss); |
|
wtc
2011/10/28 02:06:26
BUG: we need to return SECSuccess at the end of th
|
| +} |
| + |
| +/* 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; |
| @@ -1340,18 +1406,9 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, |
| 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) |