Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1057)

Unified Diff: net/third_party/nss/ssl/ssl3ext.c

Issue 415005: Linux: add next-protocol-negotiation to libssl. (Closed)
Patch Set: Addressing wtc's comments. Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/third_party/nss/ssl/ssl3ext.c
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
index 21bb818598cdc55c84f34e1aa7a3b58e1967a4e1..0365d5aa8457c5b224e25babe19335155a77940f 100644
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ b/net/third_party/nss/ssl/ssl3ext.c
@@ -229,6 +229,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
{ ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
#endif
{ session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
+ { next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
{ -1, NULL }
};
@@ -236,6 +237,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlers[] = {
{ server_name_xtn, &ssl3_HandleServerNameXtn },
/* TODO: add a handler for ec_point_formats_xtn */
{ session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
+ { next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
{ -1, NULL }
};
@@ -254,7 +256,8 @@ ssl3HelloExtensionSender clientHelloSenders[MAX_EXTENSIONS] = {
{ -1, NULL },
{ -1, NULL },
#endif
- { session_ticket_xtn, ssl3_SendSessionTicketXtn }
+ { session_ticket_xtn, ssl3_SendSessionTicketXtn },
+ { next_proto_neg_xtn, ssl3_ClientSendNextProtoNegoXtn }
};
static PRBool
@@ -412,6 +415,123 @@ 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;
+ }
+
+ 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
+ * the block. */
+SECStatus
+ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length)
+{
+ unsigned int offset = 0;
+
+ while (offset < length) {
+ if (data[offset] == 0) {
+ return SECFailure;
+ }
+ offset += data[offset] + 1;
+ }
+
+ if (offset > length)
+ return SECFailure;
+
+ return SECSuccess;
+}
+
+SECStatus
+ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
+ 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;
+ }
+
+ 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 += ss->opt.nextProtoNego.data[j] + 1;
+ }
+
+ i += data->data[i] + 1;
+ }
+
+ pick_first:
+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
+ result = ss->opt.nextProtoNego.data;
+
+ 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];
+ return SECSuccess;
+}
+
+PRInt32
+ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss,
+ PRBool append,
+ PRUint32 maxBytes)
+{
+ PRInt32 extension_length;
+
+ /* Renegotiations do not send this extension. */
+ if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) {
+ return 0;
+ }
+
+ extension_length = 4;
+
+ if (append && maxBytes >= extension_length) {
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, next_proto_neg_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ TLSExtensionData *xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] = next_proto_neg_xtn;
+ } else if (maxBytes < extension_length) {
+ return 0;
+ }
+
+ return extension_length;
+
+ loser:
+ return -1;
+}
+
/*
* NewSessionTicket
* Called from ssl3_HandleFinished

Powered by Google App Engine
This is Rietveld 408576698