OLD | NEW |
1 /* | 1 /* |
2 * SSL3 Protocol | 2 * SSL3 Protocol |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 4 * This Source Code Form is subject to the terms of the Mozilla Public |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | 5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 /* TLS extension code moved here from ssl3ecc.c */ | 8 /* TLS extension code moved here from ssl3ecc.c */ |
9 | 9 |
10 #include "nssrenam.h" | 10 #include "nssrenam.h" |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 return extension_length; | 717 return extension_length; |
718 | 718 |
719 loser: | 719 loser: |
720 return -1; | 720 return -1; |
721 } | 721 } |
722 | 722 |
723 static PRInt32 | 723 static PRInt32 |
724 ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) | 724 ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) |
725 { | 725 { |
726 PRInt32 extension_length; | 726 PRInt32 extension_length; |
| 727 unsigned char *alpn_protos = NULL; |
727 | 728 |
728 /* Renegotiations do not send this extension. */ | 729 /* Renegotiations do not send this extension. */ |
729 if (!ss->opt.nextProtoNego.data || ss->firstHsDone) { | 730 if (!ss->opt.nextProtoNego.data || ss->firstHsDone) { |
730 return 0; | 731 return 0; |
731 } | 732 } |
732 | 733 |
733 extension_length = 2 /* extension type */ + 2 /* extension length */ + | 734 extension_length = 2 /* extension type */ + 2 /* extension length */ + |
734 2 /* protocol name list length */ + | 735 2 /* protocol name list length */ + |
735 ss->opt.nextProtoNego.len; | 736 ss->opt.nextProtoNego.len; |
736 | 737 |
737 if (append && maxBytes >= extension_length) { | 738 if (append && maxBytes >= extension_length) { |
| 739 /* NPN requires that the client's fallback protocol is first in the |
| 740 * list. However, ALPN sends protocols in preference order. So we |
| 741 * allocate a buffer and move the first protocol to the end of the |
| 742 * list. */ |
738 SECStatus rv; | 743 SECStatus rv; |
| 744 const unsigned int len = ss->opt.nextProtoNego.len; |
| 745 |
| 746 alpn_protos = PORT_Alloc(len); |
| 747 if (alpn_protos == NULL) { |
| 748 return SECFailure; |
| 749 } |
| 750 if (len > 0) { |
| 751 /* Each protocol string is prefixed with a single byte length. */ |
| 752 unsigned int i = ss->opt.nextProtoNego.data[0] + 1; |
| 753 if (i <= len) { |
| 754 memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i); |
| 755 memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i); |
| 756 } else { |
| 757 /* This seems to be invalid data so we'll send as-is. */ |
| 758 memcpy(alpn_protos, ss->opt.nextProtoNego.data, len); |
| 759 } |
| 760 } |
| 761 |
739 rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); | 762 rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); |
740 if (rv != SECSuccess) | 763 if (rv != SECSuccess) |
741 goto loser; | 764 goto loser; |
742 rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); | 765 rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
743 if (rv != SECSuccess) | 766 if (rv != SECSuccess) |
744 goto loser; | 767 goto loser; |
745 » rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data, | 768 » rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2); |
746 » » » » » ss->opt.nextProtoNego.len, 2); | 769 » PORT_Free(alpn_protos); |
| 770 » alpn_protos = NULL; |
747 if (rv != SECSuccess) | 771 if (rv != SECSuccess) |
748 goto loser; | 772 goto loser; |
749 ss->xtnData.advertised[ss->xtnData.numAdvertised++] = | 773 ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
750 ssl_app_layer_protocol_xtn; | 774 ssl_app_layer_protocol_xtn; |
751 } else if (maxBytes < extension_length) { | 775 } else if (maxBytes < extension_length) { |
752 return 0; | 776 return 0; |
753 } | 777 } |
754 | 778 |
755 return extension_length; | 779 return extension_length; |
756 | 780 |
757 loser: | 781 loser: |
| 782 if (alpn_protos) |
| 783 PORT_Free(alpn_protos); |
758 return -1; | 784 return -1; |
759 } | 785 } |
760 | 786 |
761 static SECStatus | 787 static SECStatus |
762 ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type, | 788 ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type, |
763 SECItem *data) | 789 SECItem *data) |
764 { | 790 { |
765 PORT_Assert(ss->getChannelID != NULL); | 791 PORT_Assert(ss->getChannelID != NULL); |
766 | 792 |
767 if (data->len) { | 793 if (data->len) { |
(...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2264 } else if (maxBytes < extension_length) { | 2290 } else if (maxBytes < extension_length) { |
2265 PORT_Assert(0); | 2291 PORT_Assert(0); |
2266 return 0; | 2292 return 0; |
2267 } | 2293 } |
2268 | 2294 |
2269 return extension_length; | 2295 return extension_length; |
2270 | 2296 |
2271 loser: | 2297 loser: |
2272 return -1; | 2298 return -1; |
2273 } | 2299 } |
OLD | NEW |