Chromium Code Reviews| 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 c0ce548d086840c042c9e21398b51b6e85cfc0b6..140838b84c8d36d3c43dc94e0106b274f8360163 100644 |
| --- a/net/third_party/nss/ssl/ssl3ext.c |
| +++ b/net/third_party/nss/ssl/ssl3ext.c |
| @@ -53,8 +53,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, |
| PRUint16 ex_type, SECItem *data); |
| static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, |
| PRUint16 ex_type, SECItem *data); |
| +static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss, |
| + PRUint16 ex_type, SECItem *data); |
| static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, |
| PRUint16 ex_type, SECItem *data); |
| +static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, |
| + PRUint32 maxBytes); |
| static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, |
| PRUint32 maxBytes); |
| static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, |
| @@ -247,14 +251,15 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = { |
| /* These two tables are used by the client, to handle server hello |
| * extensions. */ |
| static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { |
| - { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
| + { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
| /* 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_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
| - { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
| - { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, |
| - { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
| + { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
| + { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| + { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
| + { ssl_application_layer_protocol, &ssl3_ClientHandleAppProtoXtn }, |
| + { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
| + { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, |
| + { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
| { -1, NULL } |
| }; |
| @@ -271,17 +276,18 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { |
| */ |
| static const |
| ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { |
| - { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, |
| - { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
| + { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, |
| + { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
| #ifdef NSS_ENABLE_ECC |
| - { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
| - { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
| + { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
| + { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
| #endif |
| - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
| - { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| - { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, |
| - { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, |
| - { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
| + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
| + { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| + { ssl_application_layer_protocol, &ssl3_ClientSendAppProtoXtn }, |
| + { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, |
| + { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, |
| + { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
| { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } |
| /* any extra entries will appear as { 0, NULL } */ |
| }; |
| @@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, |
| PORT_Assert(!ss->firstHsDone); |
| + if (ssl3_ExtensionNegotiated(ss, ssl_application_layer_protocol)) { |
| + PORT_SetError(SSL_ERROR_BOTH_NPN_AND_ALPN); |
| + return SECFailure; |
| + } |
| + |
| rv = ssl3_ValidateNextProtoNego(data->data, data->len); |
| if (rv != SECSuccess) |
| return rv; |
| @@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, |
| return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result); |
| } |
| +static SECStatus |
| +ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) |
| +{ |
| + const unsigned char* d = data->data; |
| + PRUint16 name_list_len; |
| + SECItem protocol_name; |
| + |
| + if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) { |
| + PORT_SetError(SSL_ERROR_BOTH_NPN_AND_ALPN); |
| + return SECFailure; |
|
Ryan Sleevi
2013/07/02 18:36:48
This won't actually abort the connection - it will
agl
2013/07/02 18:42:22
Hmm, I was planning on aborting the connection but
|
| + } |
| + |
| + /* The extension data from the server has the following format: |
| + * uint16 name_list_len; |
| + * uint8 len; |
| + * uint8 protocol_name[len]; */ |
| + if (data->len < 4 || data->len > 2 + 1 + 255) { |
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
| + return SECFailure; |
| + } |
| + |
| + name_list_len = ((PRUint16) d[0]) << 8 | |
| + ((PRUint16) d[1]); |
| + if (name_list_len != data->len - 2 || |
| + d[2] != data->len - 3) { |
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
| + return SECFailure; |
| + } |
| + |
| + protocol_name.data = data->data + 3; |
| + protocol_name.len = data->len - 3; |
| + |
| + SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
| + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED; |
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
| + return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name); |
| +} |
| + |
| static PRInt32 |
| ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append, |
| PRUint32 maxBytes) |
| @@ -672,6 +721,44 @@ loser: |
| return -1; |
| } |
| +static PRInt32 |
| +ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) |
| +{ |
| + PRInt32 extension_length; |
| + |
| + /* Renegotiations do not send this extension. */ |
| + if (!ss->opt.nextProtoNego.data || ss->firstHsDone) { |
| + return 0; |
| + } |
| + |
| + extension_length = 2 /* extension type */ + 2 /* extension length */ + |
| + 2 /* protocol name list length */ + |
| + ss->opt.nextProtoNego.len; |
| + |
| + if (append && maxBytes >= extension_length) { |
| + SECStatus rv; |
| + rv = ssl3_AppendHandshakeNumber(ss, ssl_application_layer_protocol, 2); |
| + if (rv != SECSuccess) |
| + goto loser; |
| + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
| + if (rv != SECSuccess) |
| + goto loser; |
| + rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data, |
| + ss->opt.nextProtoNego.len, 2); |
| + if (rv != SECSuccess) |
| + goto loser; |
| + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
| + ssl_application_layer_protocol; |
| + } else if (maxBytes < extension_length) { |
| + return 0; |
| + } |
| + |
| + return extension_length; |
| + |
| +loser: |
| + return -1; |
| +} |
| + |
| static SECStatus |
| ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type, |
| SECItem *data) |