OLD | NEW |
1 From 6b594dc531e7a1d1d5bca2f0f78e7bc0ac3ff937 Mon Sep 17 00:00:00 2001 | 1 From 3caa0f573d2637bfed99dcc0e5887fe3a52462ba Mon Sep 17 00:00:00 2001 |
2 From: Adam Langley <agl@chromium.org> | 2 From: Adam Langley <agl@chromium.org> |
3 Date: Mon, 3 Oct 2011 12:19:28 -0400 | 3 Date: Mon, 3 Oct 2011 12:19:28 -0400 |
4 Subject: [PATCH] nextproto.patch | 4 Subject: [PATCH 01/15] nextproto.patch |
5 | 5 |
6 --- | 6 --- |
7 mozilla/security/nss/cmd/tstclnt/tstclnt.c | 6 ++ | 7 mozilla/security/nss/lib/ssl/ssl.def | 6 ++ |
8 mozilla/security/nss/lib/ssl/ssl.def | 7 ++ | 8 mozilla/security/nss/lib/ssl/ssl.h | 51 ++++++++++++ |
9 mozilla/security/nss/lib/ssl/ssl.h | 12 +++ | 9 mozilla/security/nss/lib/ssl/ssl3con.c | 54 +++++++++++++ |
10 mozilla/security/nss/lib/ssl/ssl3con.c | 54 ++++++++++++ | 10 mozilla/security/nss/lib/ssl/ssl3ext.c | 104 ++++++++++++++++++++++++- |
11 mozilla/security/nss/lib/ssl/ssl3ext.c | 122 +++++++++++++++++++++++++++- | 11 mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +- |
12 mozilla/security/nss/lib/ssl/ssl3prot.h | 3 +- | 12 mozilla/security/nss/lib/ssl/sslerr.h | 2 + |
13 mozilla/security/nss/lib/ssl/sslimpl.h | 24 ++++++ | 13 mozilla/security/nss/lib/ssl/sslimpl.h | 21 +++++ |
14 mozilla/security/nss/lib/ssl/sslsock.c | 74 +++++++++++++++++ | 14 mozilla/security/nss/lib/ssl/sslsock.c | 131 +++++++++++++++++++++++++++++++ |
15 mozilla/security/nss/lib/ssl/sslt.h | 3 +- | 15 mozilla/security/nss/lib/ssl/sslt.h | 3 +- |
16 9 files changed, 302 insertions(+), 3 deletions(-) | 16 9 files changed, 372 insertions(+), 3 deletions(-) |
17 | 17 |
18 diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/c
md/tstclnt/tstclnt.c | |
19 index 55684e6..d209a33 100644 | |
20 --- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c | |
21 +++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c | |
22 @@ -868,6 +868,12 @@ int main(int argc, char **argv) | |
23 return 1; | |
24 } | |
25 | |
26 + rv = SSL_SetNextProtoNego(s, "\004flip\004http1.1", 10); | |
27 + if (rv != SECSuccess) { | |
28 + SECU_PrintError(progName, "error enabling next protocol negotiation"); | |
29 + return 1; | |
30 + } | |
31 + | |
32 /* enable false start. */ | |
33 rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart); | |
34 if (rv != SECSuccess) { | |
35 diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl
/ssl.def | 18 diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl
/ssl.def |
36 index d3f455c..a1f4b51 100644 | 19 index d3f455c..5256ae2 100644 |
37 --- a/mozilla/security/nss/lib/ssl/ssl.def | 20 --- a/mozilla/security/nss/lib/ssl/ssl.def |
38 +++ b/mozilla/security/nss/lib/ssl/ssl.def | 21 +++ b/mozilla/security/nss/lib/ssl/ssl.def |
39 @@ -152,3 +152,10 @@ SSL_SNISocketConfigHook; | 22 @@ -152,3 +152,9 @@ SSL_SNISocketConfigHook; |
40 ;+ local: | 23 ;+ local: |
41 ;+*; | 24 ;+*; |
42 ;+}; | 25 ;+}; |
43 +;+NSS_CHROMIUM { | 26 +;+NSS_CHROMIUM { |
44 +;+ global: | 27 +;+ global: |
45 +SSL_GetNextProto; | 28 +SSL_SetNextProtoCallback; |
46 +SSL_SetNextProtoNego; | |
47 +;+ local: | 29 +;+ local: |
48 +;+*; | 30 +;+*; |
49 +;+}; | 31 +;+}; |
50 diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/s
sl.h | 32 diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/s
sl.h |
51 index 4a9e89d..ffa973c 100644 | 33 index 4a9e89d..2cf777d 100644 |
52 --- a/mozilla/security/nss/lib/ssl/ssl.h | 34 --- a/mozilla/security/nss/lib/ssl/ssl.h |
53 +++ b/mozilla/security/nss/lib/ssl/ssl.h | 35 +++ b/mozilla/security/nss/lib/ssl/ssl.h |
54 @@ -153,6 +153,18 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, P
RBool on); | 36 @@ -153,6 +153,57 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, P
RBool on); |
55 SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on); | 37 SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on); |
56 SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHa
ndle); | 38 SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHa
ndle); |
57 | 39 |
| 40 +/* SSLNextProtoCallback is called, during the handshake, when the server has |
| 41 + * sent a Next Protocol Negotiation extension. |protos| and |protosLen| define |
| 42 + * a buffer which contains the server's advertisement. This data is guaranteed |
| 43 + * to be well formed per the NPN spec. |protoOut| is a buffer provided by the |
| 44 + * caller, of length 255 (the maximum allowed by the protocol). |
| 45 + * On successful return, the protocol to be announced to the server will be in |
| 46 + * |protoOut| and its length in |protoOutLen|. */ |
| 47 +typedef SECStatus (PR_CALLBACK *SSLNextProtoCallback)( |
| 48 + void *arg, |
| 49 + PRFileDesc *fd, |
| 50 + const unsigned char* protos, |
| 51 + unsigned int protosLen, |
| 52 + unsigned char* protoOut, |
| 53 + unsigned int* protoOutLen); |
| 54 + |
| 55 +/* SSL_SetNextProtoCallback sets a callback function to handle Next Protocol |
| 56 + * Negotiation. It causes a client to advertise NPN. */ |
| 57 +SSL_IMPORT SECStatus SSL_SetNextProtoCallback(PRFileDesc *fd, |
| 58 + SSLNextProtoCallback callback, |
| 59 + void *arg); |
| 60 + |
| 61 +/* SSL_SetNextProtoNego can be used as an alternative to |
| 62 + * SSL_SetNextProtoCallback. It also causes a client to advertise NPN and |
| 63 + * installs a default callback function which selects the first supported |
| 64 + * protocol in server-preference order. If no matching protocol is found it |
| 65 + * selects the first supported protocol. |
| 66 + * |
| 67 + * The supported protocols are specified in |data| in wire-format (8-bit |
| 68 + * length-prefixed). For example: "\010http/1.1\006spdy/2". */ |
58 +SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, | 69 +SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, |
59 + const unsigned char *data, | 70 + const unsigned char *data, |
60 +» » » » » unsigned short length); | 71 +» » » » » unsigned int length); |
| 72 +/* SSL_GetNextProto can be used after a handshake on a socket where |
| 73 + * SSL_SetNextProtoNego was called to retrieve the result of the Next Protocol |
| 74 + * negotiation. |
| 75 + * |
| 76 + * state is set to one of the SSL_NEXT_PROTO_* constants. The negotiated |
| 77 + * protocol, if any, is written into buf, which must be at least buf_len bytes |
| 78 + * long. If the negotiated protocol is longer than this, it is truncated. The |
| 79 + * number of bytes copied is written into *length. */ |
61 +SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd, | 80 +SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd, |
62 + int *state, | 81 + int *state, |
63 + unsigned char *buf, | 82 + unsigned char *buf, |
64 +» » » » unsigned *length, | 83 +» » » » unsigned int *length, |
65 +» » » » unsigned buf_len); | 84 +» » » » unsigned int buf_len); |
| 85 + |
| 86 +// TODO(wtc): it may be a good idea to define these as an enum type. |
66 +#define SSL_NEXT_PROTO_NO_SUPPORT 0 /* No peer support */ | 87 +#define SSL_NEXT_PROTO_NO_SUPPORT 0 /* No peer support */ |
67 +#define SSL_NEXT_PROTO_NEGOTIATED 1 /* Mutual agreement */ | 88 +#define SSL_NEXT_PROTO_NEGOTIATED 1 /* Mutual agreement */ |
68 +#define SSL_NEXT_PROTO_NO_OVERLAP 2 /* No protocol overlap found */ | 89 +#define SSL_NEXT_PROTO_NO_OVERLAP 2 /* No protocol overlap found */ |
69 + | 90 + |
70 /* | 91 /* |
71 ** Control ciphers that SSL uses. If on is non-zero then the named cipher | 92 ** Control ciphers that SSL uses. If on is non-zero then the named cipher |
72 ** is enabled, otherwise it is disabled. | 93 ** is enabled, otherwise it is disabled. |
73 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c | 94 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c |
74 index 8048913..e0cb4e9 100644 | 95 index 8048913..8f860a9 100644 |
75 --- a/mozilla/security/nss/lib/ssl/ssl3con.c | 96 --- a/mozilla/security/nss/lib/ssl/ssl3con.c |
76 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c | 97 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c |
77 @@ -81,6 +81,7 @@ static SECStatus ssl3_InitState( sslSocket *ss); | 98 @@ -81,6 +81,7 @@ static SECStatus ssl3_InitState( sslSocket *ss); |
78 static SECStatus ssl3_SendCertificate( sslSocket *ss); | 99 static SECStatus ssl3_SendCertificate( sslSocket *ss); |
79 static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); | 100 static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); |
80 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); | 101 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); |
81 +static SECStatus ssl3_SendNextProto( sslSocket *ss); | 102 +static SECStatus ssl3_SendNextProto( sslSocket *ss); |
82 static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); | 103 static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); |
83 static SECStatus ssl3_SendServerHello( sslSocket *ss); | 104 static SECStatus ssl3_SendServerHello( sslSocket *ss); |
84 static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); | 105 static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); |
(...skipping 15 matching lines...) Expand all Loading... |
100 | 121 |
101 /* called from ssl3_HandleServerHelloDone | 122 /* called from ssl3_HandleServerHelloDone |
102 + */ | 123 + */ |
103 +static SECStatus | 124 +static SECStatus |
104 +ssl3_SendNextProto(sslSocket *ss) | 125 +ssl3_SendNextProto(sslSocket *ss) |
105 +{ | 126 +{ |
106 + SECStatus rv; | 127 + SECStatus rv; |
107 + int padding_len; | 128 + int padding_len; |
108 + static const unsigned char padding[32] = {0}; | 129 + static const unsigned char padding[32] = {0}; |
109 + | 130 + |
110 + if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) | 131 + if (ss->ssl3.nextProto.len == 0) |
111 + return SECSuccess; | 132 + return SECSuccess; |
112 + | 133 + |
113 + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | 134 + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
114 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | 135 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
115 + | 136 + |
116 + padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32); | 137 + padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32); |
117 + | 138 + |
118 + rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len + | 139 + rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len + |
119 + 2 + padding_len); | 140 + 2 + padding_len); |
120 + if (rv != SECSuccess) { | 141 + if (rv != SECSuccess) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 ss->ssl3.initialized = PR_FALSE; | 178 ss->ssl3.initialized = PR_FALSE; |
158 + | 179 + |
159 + if (ss->ssl3.nextProto.data) { | 180 + if (ss->ssl3.nextProto.data) { |
160 + PORT_Free(ss->ssl3.nextProto.data); | 181 + PORT_Free(ss->ssl3.nextProto.data); |
161 + ss->ssl3.nextProto.data = NULL; | 182 + ss->ssl3.nextProto.data = NULL; |
162 + } | 183 + } |
163 } | 184 } |
164 | 185 |
165 /* End of ssl3con.c */ | 186 /* End of ssl3con.c */ |
166 diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/s
sl/ssl3ext.c | 187 diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/s
sl/ssl3ext.c |
167 index becbfe9..fbd5a91 100644 | 188 index becbfe9..36ac4de 100644 |
168 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c | 189 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c |
169 +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c | 190 +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c |
170 @@ -235,6 +235,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[]
= { | 191 @@ -235,6 +235,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[]
= { |
171 #endif | 192 #endif |
172 { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, | 193 { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, |
173 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | 194 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
174 + { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, | 195 + { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
175 { -1, NULL } | 196 { -1, NULL } |
176 }; | 197 }; |
177 | 198 |
178 @@ -245,6 +246,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { | 199 @@ -245,6 +246,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { |
179 /* TODO: add a handler for ssl_ec_point_formats_xtn */ | 200 /* TODO: add a handler for ssl_ec_point_formats_xtn */ |
180 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, | 201 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
181 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | 202 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
182 + { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | 203 + { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
183 { -1, NULL } | 204 { -1, NULL } |
184 }; | 205 }; |
185 | 206 |
186 @@ -267,7 +269,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { | 207 @@ -267,7 +269,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { |
187 { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, | 208 { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
188 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, | 209 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
189 #endif | 210 #endif |
190 - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn } | 211 - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn } |
191 + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | 212 + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
192 + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn } | 213 + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn } |
193 /* any extra entries will appear as { 0, NULL } */ | 214 /* any extra entries will appear as { 0, NULL } */ |
194 }; | 215 }; |
195 | 216 |
196 @@ -534,6 +537,123 @@ ssl3_SendSessionTicketXtn( | 217 @@ -534,6 +537,105 @@ ssl3_SendSessionTicketXtn( |
197 return -1; | 218 return -1; |
198 } | 219 } |
199 | 220 |
200 +/* handle an incoming Next Protocol Negotiation extension. */ | 221 +/* handle an incoming Next Protocol Negotiation extension. */ |
201 +SECStatus | 222 +SECStatus |
202 +ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *da
ta) | 223 +ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *da
ta) |
203 +{ | 224 +{ |
204 + if (data->len != 0) { | 225 + if (data->len != 0) { |
205 + /* Clients MUST send an empty NPN extension, if any. */ | 226 + /* Clients MUST send an empty NPN extension, if any. */ |
206 + return SECFailure; | 227 + return SECFailure; |
207 + } | 228 + } |
208 + | 229 + |
209 + ss->ssl3.hs.nextProtoNego = PR_TRUE; | |
210 + return SECSuccess; | 230 + return SECSuccess; |
211 +} | 231 +} |
212 + | 232 + |
213 +/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: non
e | 233 +/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: non
e |
214 + * of the length may be 0 and the sum of the lengths must equal the length of | 234 + * of the lengths may be 0 and the sum of the lengths must equal the length of |
215 + * the block. */ | 235 + * the block. */ |
216 +SECStatus | 236 +SECStatus |
217 +ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) | 237 +ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) |
218 +{ | 238 +{ |
219 + unsigned int offset = 0; | 239 + unsigned int offset = 0; |
220 + | 240 + |
221 + while (offset < length) { | 241 + while (offset < length) { |
222 + if (data[offset] == 0) { | 242 + if (data[offset] == 0) { |
| 243 + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
223 + return SECFailure; | 244 + return SECFailure; |
224 + } | 245 + } |
225 + offset += (unsigned int)data[offset] + 1; | 246 + offset += (unsigned int)data[offset] + 1; |
226 + } | 247 + } |
227 + | 248 + |
228 + if (offset > length) | 249 + if (offset > length) { |
| 250 +» PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
229 + return SECFailure; | 251 + return SECFailure; |
| 252 + } |
230 + | 253 + |
231 + return SECSuccess; | 254 + return SECSuccess; |
232 +} | 255 +} |
233 + | 256 + |
234 +SECStatus | 257 +SECStatus |
235 +ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, | 258 +ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, |
236 + SECItem *data) | 259 + SECItem *data) |
237 +{ | 260 +{ |
238 + unsigned int i, j; | |
239 + SECStatus rv; | 261 + SECStatus rv; |
240 + unsigned char *result; | 262 + unsigned char result[255]; |
241 + | 263 + unsigned int result_len; |
242 + if (data->len == 0) { | |
243 +» /* The server supports the extension, but doesn't have any | |
244 +» * protocols configured. In this case we request our favoured | |
245 +» * protocol. */ | |
246 +» goto pick_first; | |
247 + } | |
248 + | 264 + |
249 + rv = ssl3_ValidateNextProtoNego(data->data, data->len); | 265 + rv = ssl3_ValidateNextProtoNego(data->data, data->len); |
250 + if (rv != SECSuccess) | 266 + if (rv != SECSuccess) |
251 + return rv; | 267 + return rv; |
252 + | 268 + |
253 + /* For each protocol in server preference order, see if we support it. */ | 269 + rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, |
254 + for (i = 0; i < data->len; ) { | 270 + data->data, data->len, |
255 +» for (j = 0; j < ss->opt.nextProtoNego.len; ) { | 271 + result, &result_len); |
256 +» if (data->data[i] == ss->opt.nextProtoNego.data[j] && | 272 + if (rv != SECSuccess) |
257 +» » memcmp(&data->data[i+1], &ss->opt.nextProtoNego.data[j+1], | 273 +» return rv; |
258 +» » data->data[i]) == 0) { | 274 + // If the callback wrote more than allowed to |result| it has corrupted our |
259 +» » /* We found a match */ | 275 + // stack. |
260 +» » ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; | 276 + PORT_Assert(result_len <= sizeof(result)); |
261 +» » result = &data->data[i]; | |
262 +» » goto found; | |
263 +» } | |
264 +» j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1; | |
265 +» } | |
266 + | 277 + |
267 + i += (unsigned int)data->data[i] + 1; | |
268 + } | |
269 + | |
270 + pick_first: | |
271 + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; | |
272 + result = ss->opt.nextProtoNego.data; | |
273 + | |
274 + found: | |
275 + if (ss->ssl3.nextProto.data) | 278 + if (ss->ssl3.nextProto.data) |
276 + PORT_Free(ss->ssl3.nextProto.data); | 279 + PORT_Free(ss->ssl3.nextProto.data); |
277 + ss->ssl3.nextProto.data = PORT_Alloc(result[0]); | 280 + ss->ssl3.nextProto.data = PORT_Alloc(result_len); |
278 + PORT_Memcpy(ss->ssl3.nextProto.data, result + 1, result[0]); | 281 + PORT_Memcpy(ss->ssl3.nextProto.data, result, result_len); |
279 + ss->ssl3.nextProto.len = result[0]; | 282 + ss->ssl3.nextProto.len = result_len; |
280 + return SECSuccess; | 283 + return SECSuccess; |
281 +} | 284 +} |
282 + | 285 + |
283 +PRInt32 | 286 +PRInt32 |
284 +ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, | 287 +ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, |
285 + PRBool append, | 288 + PRBool append, |
286 + PRUint32 maxBytes) | 289 + PRUint32 maxBytes) |
287 +{ | 290 +{ |
288 + PRInt32 extension_length; | 291 + PRInt32 extension_length; |
289 + | 292 + |
290 + /* Renegotiations do not send this extension. */ | 293 + /* Renegotiations do not send this extension. */ |
291 + if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) { | 294 + if (!ss->nextProtoCallback || ss->firstHsDone) { |
292 + return 0; | 295 + return 0; |
293 + } | 296 + } |
294 + | 297 + |
295 + extension_length = 4; | 298 + extension_length = 4; |
296 + | 299 + |
297 + if (append && maxBytes >= extension_length) { | 300 + if (append && maxBytes >= extension_length) { |
298 + SECStatus rv; | 301 + SECStatus rv; |
299 + rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2); | 302 + rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2); |
300 + if (rv != SECSuccess) | 303 + if (rv != SECSuccess) |
301 + goto loser; | 304 + goto loser; |
(...skipping 22 matching lines...) Expand all Loading... |
324 @@ -157,7 +157,8 @@ typedef enum { | 327 @@ -157,7 +157,8 @@ typedef enum { |
325 server_hello_done = 14, | 328 server_hello_done = 14, |
326 certificate_verify = 15, | 329 certificate_verify = 15, |
327 client_key_exchange = 16, | 330 client_key_exchange = 16, |
328 - finished = 20 | 331 - finished = 20 |
329 + finished = 20, | 332 + finished = 20, |
330 + next_proto = 67 | 333 + next_proto = 67 |
331 } SSL3HandshakeType; | 334 } SSL3HandshakeType; |
332 | 335 |
333 typedef struct { | 336 typedef struct { |
| 337 diff --git a/mozilla/security/nss/lib/ssl/sslerr.h b/mozilla/security/nss/lib/ss
l/sslerr.h |
| 338 index a2f6524..c76ffa9 100644 |
| 339 --- a/mozilla/security/nss/lib/ssl/sslerr.h |
| 340 +++ b/mozilla/security/nss/lib/ssl/sslerr.h |
| 341 @@ -203,6 +203,8 @@ SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BAS
E + 114), |
| 342 |
| 343 SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY = (SSL_ERROR_BASE + 115), |
| 344 |
| 345 +SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID = (SSL_ERROR_BASE + 117), |
| 346 + |
| 347 SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ |
| 348 } SSLErrorCodes; |
| 349 #endif /* NO_SECURITY_ERROR_ENUM */ |
334 diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/s
sl/sslimpl.h | 350 diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/s
sl/sslimpl.h |
335 index 9af471d..d1c1181 100644 | 351 index 9af471d..199c573 100644 |
336 --- a/mozilla/security/nss/lib/ssl/sslimpl.h | 352 --- a/mozilla/security/nss/lib/ssl/sslimpl.h |
337 +++ b/mozilla/security/nss/lib/ssl/sslimpl.h | 353 +++ b/mozilla/security/nss/lib/ssl/sslimpl.h |
338 @@ -313,6 +313,11 @@ typedef struct { | 354 @@ -313,6 +313,10 @@ typedef struct { |
339 #endif /* NSS_ENABLE_ECC */ | 355 #endif /* NSS_ENABLE_ECC */ |
340 | 356 |
341 typedef struct sslOptionsStr { | 357 typedef struct sslOptionsStr { |
342 + /* For clients, this is a validated list of protocols in preference order | 358 + /* If SSL_SetNextProtoNego has been called, then this contains the |
343 + * and wire format. For servers, this is the list of support protocols, | 359 + * list of supported protocols. */ |
344 + * also in wire format. */ | |
345 + SECItem nextProtoNego; | 360 + SECItem nextProtoNego; |
346 + | 361 + |
347 unsigned int useSecurity : 1; /* 1 */ | 362 unsigned int useSecurity : 1; /* 1 */ |
348 unsigned int useSocks : 1; /* 2 */ | 363 unsigned int useSocks : 1; /* 2 */ |
349 unsigned int requestCertificate : 1; /* 3 */ | 364 unsigned int requestCertificate : 1; /* 3 */ |
350 @@ -786,6 +791,7 @@ const ssl3CipherSuiteDef *suite_def; | 365 @@ -827,6 +831,13 @@ struct ssl3StateStr { |
351 #ifdef NSS_ENABLE_ECC | |
352 PRUint32 negotiatedECCurves; /* bit mask */ | |
353 #endif /* NSS_ENABLE_ECC */ | |
354 + PRBool nextProtoNego;/* Our peer has sent this extension */ | |
355 } SSL3HandshakeState; | |
356 | |
357 | |
358 @@ -827,6 +833,16 @@ struct ssl3StateStr { | |
359 PRBool initialized; | 366 PRBool initialized; |
360 SSL3HandshakeState hs; | 367 SSL3HandshakeState hs; |
361 ssl3CipherSpec specs[2]; /* one is current, one is pending. */ | 368 ssl3CipherSpec specs[2]; /* one is current, one is pending. */ |
362 + | 369 + |
363 + /* In a client: if the server supports Next Protocol Negotiation, then | 370 + /* In a client: if the server supports Next Protocol Negotiation, then |
364 + * this is the protocol that was requested. | 371 + * this is the protocol that was negotiated. |
365 + * In a server: this is the protocol that the client requested via Next | |
366 + * Protocol Negotiation. | |
367 + * | 372 + * |
368 + * In either case, if the data pointer is non-NULL, then it is malloced | 373 + * If the data pointer is non-NULL, then it is malloced data. */ |
369 + * data. */ | |
370 + SECItem nextProto; | 374 + SECItem nextProto; |
371 + int» » » nextProtoState;»/* See SSL_NEXT_PROTO_* defines
*/ | 375 + int» » » nextProtoState; /* See NEXT_PROTO_* defines */ |
372 }; | 376 }; |
373 | 377 |
374 typedef struct { | 378 typedef struct { |
375 @@ -1494,8 +1510,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslS
ocket * ss, | 379 @@ -1058,6 +1069,8 @@ const unsigned char * preferredCipher; |
| 380 SSLHandshakeCallback handshakeCallback; |
| 381 void *handshakeCallbackData; |
| 382 void *pkcs11PinArg; |
| 383 + SSLNextProtoCallback nextProtoCallback; |
| 384 + void *nextProtoArg; |
| 385 |
| 386 PRIntervalTime rTimeout; /* timeout for NSPR I/O */ |
| 387 PRIntervalTime wTimeout; /* timeout for NSPR I/O */ |
| 388 @@ -1494,8 +1507,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslS
ocket * ss, |
376 PRUint16 ex_type, SECItem *data); | 389 PRUint16 ex_type, SECItem *data); |
377 extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, | 390 extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, |
378 PRUint16 ex_type, SECItem *data); | 391 PRUint16 ex_type, SECItem *data); |
379 +extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, | 392 +extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, |
380 + PRUint16 ex_type, SECItem *data); | 393 + PRUint16 ex_type, SECItem *data); |
381 extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, | 394 extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, |
382 PRUint16 ex_type, SECItem *data); | 395 PRUint16 ex_type, SECItem *data); |
383 +extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, | 396 +extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, |
384 + PRUint16 ex_type, SECItem *data); | 397 + PRUint16 ex_type, SECItem *data); |
385 | 398 |
386 /* ClientHello and ServerHello extension senders. | 399 /* ClientHello and ServerHello extension senders. |
387 * Note that not all extension senders are exposed here; only those that | 400 * Note that not all extension senders are exposed here; only those that |
388 @@ -1526,6 +1546,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, | 401 @@ -1526,6 +1543,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, |
389 extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss, | 402 extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss, |
390 PRBool append, PRUint32 maxBytes); | 403 PRBool append, PRUint32 maxBytes); |
391 #endif | 404 #endif |
392 +extern PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, | 405 +extern PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, |
393 + PRUint32 maxBytes); | 406 + PRUint32 maxBytes); |
394 +extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, | 407 +extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data, |
395 + unsigned short length); | 408 + unsigned short length); |
396 | 409 |
397 /* call the registered extension handlers. */ | 410 /* call the registered extension handlers. */ |
398 extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss, | 411 extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss, |
399 diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/s
sl/sslsock.c | 412 diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/s
sl/sslsock.c |
400 index bc770a1..4c8fbfd 100644 | 413 index bc770a1..769ea0a 100644 |
401 --- a/mozilla/security/nss/lib/ssl/sslsock.c | 414 --- a/mozilla/security/nss/lib/ssl/sslsock.c |
402 +++ b/mozilla/security/nss/lib/ssl/sslsock.c | 415 +++ b/mozilla/security/nss/lib/ssl/sslsock.c |
403 @@ -163,6 +163,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL.
*/ | 416 @@ -163,6 +163,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL.
*/ |
404 ** default settings for socket enables | 417 ** default settings for socket enables |
405 */ | 418 */ |
406 static sslOptions ssl_defaults = { | 419 static sslOptions ssl_defaults = { |
407 + { siBuffer, NULL, 0 }, /* nextProtoNego */ | 420 + { siBuffer, NULL, 0 }, /* nextProtoNego */ |
408 PR_TRUE, /* useSecurity */ | 421 PR_TRUE, /* useSecurity */ |
409 PR_FALSE, /* useSocks */ | 422 PR_FALSE, /* useSocks */ |
410 PR_FALSE, /* requestCertificate */ | 423 PR_FALSE, /* requestCertificate */ |
411 @@ -438,6 +439,10 @@ ssl_DestroySocketContents(sslSocket *ss) | 424 @@ -438,6 +439,10 @@ ssl_DestroySocketContents(sslSocket *ss) |
412 ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); | 425 ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); |
413 ss->ephemeralECDHKeyPair = NULL; | 426 ss->ephemeralECDHKeyPair = NULL; |
414 } | 427 } |
415 + if (ss->opt.nextProtoNego.data) { | 428 + if (ss->opt.nextProtoNego.data) { |
416 + PORT_Free(ss->opt.nextProtoNego.data); | 429 + PORT_Free(ss->opt.nextProtoNego.data); |
417 + ss->opt.nextProtoNego.data = NULL; | 430 + ss->opt.nextProtoNego.data = NULL; |
418 + } | 431 + } |
419 PORT_Assert(!ss->xtnData.sniNameArr); | 432 PORT_Assert(!ss->xtnData.sniNameArr); |
420 if (ss->xtnData.sniNameArr) { | 433 if (ss->xtnData.sniNameArr) { |
421 PORT_Free(ss->xtnData.sniNameArr); | 434 PORT_Free(ss->xtnData.sniNameArr); |
422 @@ -1266,6 +1271,75 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) | 435 @@ -1266,6 +1271,132 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) |
423 return fd; | 436 return fd; |
424 } | 437 } |
425 | 438 |
426 +/* SSL_SetNextProtoNego sets the list of supported protocols for the given | |
427 + * socket. The list is a series of 8-bit, length prefixed strings. */ | |
428 +SECStatus | 439 +SECStatus |
429 +SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, | 440 +SSL_SetNextProtoCallback(PRFileDesc *fd, |
430 +» » unsigned short length) | 441 + SSLNextProtoCallback callback, |
431 +{ | 442 + void *arg) { |
432 + sslSocket *ss = ssl_FindSocket(fd); | 443 + sslSocket *ss = ssl_FindSocket(fd); |
433 + | 444 + |
434 + if (!ss) { | 445 + if (!ss) { |
435 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID()
, | 446 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID()
, |
436 + fd)); | 447 + fd)); |
437 + return SECFailure; | 448 + return SECFailure; |
438 + } | 449 + } |
439 + | 450 + |
| 451 + ssl_GetSSL3HandshakeLock(ss); |
| 452 + ss->nextProtoCallback = callback; |
| 453 + ss->nextProtoArg = arg; |
| 454 + ssl_ReleaseSSL3HandshakeLock(ss); |
| 455 +} |
| 456 + |
| 457 +/* NextProtoStandardCallback is set as an NPN callback for the case when the |
| 458 + * user of the sockets wants the standard selection algorithm. */ |
| 459 +static SECStatus |
| 460 +NextProtoStandardCallback(void *arg, |
| 461 + PRFileDesc *fd, |
| 462 + const unsigned char *protos, |
| 463 + unsigned int protos_len, |
| 464 + unsigned char *protoOut, |
| 465 + unsigned int *protoOutLen) |
| 466 +{ |
| 467 + unsigned int i, j; |
| 468 + const unsigned char *result; |
| 469 + |
| 470 + sslSocket *ss = ssl_FindSocket(fd); |
| 471 + PORT_Assert(ss); |
| 472 + |
| 473 + if (protos_len == 0) { |
| 474 + /* The server supports the extension, but doesn't have any protocols |
| 475 + * configured. In this case we request our favoured protocol. */ |
| 476 + goto pick_first; |
| 477 + } |
| 478 + |
| 479 + /* For each protocol in server preference, see if we support it. */ |
| 480 + for (i = 0; i < protos_len; ) { |
| 481 + for (j = 0; j < ss->opt.nextProtoNego.len; ) { |
| 482 + if (protos[i] == ss->opt.nextProtoNego.data[j] && |
| 483 + memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1], |
| 484 + protos[i]) == 0) { |
| 485 + /* We found a match. */ |
| 486 + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; |
| 487 + result = &protos[i]; |
| 488 + goto found; |
| 489 + } |
| 490 + j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1; |
| 491 + } |
| 492 + i += (unsigned int)protos[i] + 1; |
| 493 + } |
| 494 + |
| 495 +pick_first: |
| 496 + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; |
| 497 + result = ss->opt.nextProtoNego.data; |
| 498 + |
| 499 +found: |
| 500 + memcpy(protoOut, result + 1, result[0]); |
| 501 + *protoOutLen = result[0]; |
| 502 + return SECSuccess; |
| 503 +} |
| 504 + |
| 505 +SECStatus |
| 506 +SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, |
| 507 + unsigned int length) |
| 508 +{ |
| 509 + SECStatus rv; |
| 510 + |
| 511 + sslSocket *ss = ssl_FindSocket(fd); |
| 512 + |
| 513 + if (!ss) { |
| 514 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", |
| 515 + SSL_GETPID(), fd)); |
| 516 + return SECFailure; |
| 517 + } |
| 518 + |
440 + if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess) | 519 + if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess) |
441 + return SECFailure; | 520 + return SECFailure; |
442 + | 521 + |
443 + ssl_GetSSL3HandshakeLock(ss); | 522 + ssl_GetSSL3HandshakeLock(ss); |
444 + if (ss->opt.nextProtoNego.data) | 523 + if (ss->opt.nextProtoNego.data) |
445 + PORT_Free(ss->opt.nextProtoNego.data); | 524 + PORT_Free(ss->opt.nextProtoNego.data); |
446 + ss->opt.nextProtoNego.data = PORT_Alloc(length); | 525 + ss->opt.nextProtoNego.data = PORT_Alloc(length); |
447 + if (!ss->opt.nextProtoNego.data) { | 526 + if (!ss->opt.nextProtoNego.data) { |
448 + ssl_ReleaseSSL3HandshakeLock(ss); | 527 + ssl_ReleaseSSL3HandshakeLock(ss); |
449 + return SECFailure; | 528 + return SECFailure; |
450 + } | 529 + } |
451 + memcpy(ss->opt.nextProtoNego.data, data, length); | 530 + memcpy(ss->opt.nextProtoNego.data, data, length); |
452 + ss->opt.nextProtoNego.len = length; | 531 + ss->opt.nextProtoNego.len = length; |
453 + ss->opt.nextProtoNego.type = siBuffer; | 532 + ss->opt.nextProtoNego.type = siBuffer; |
454 + ssl_ReleaseSSL3HandshakeLock(ss); | 533 + ssl_ReleaseSSL3HandshakeLock(ss); |
455 + | 534 + |
456 + return SECSuccess; | 535 + return SSL_SetNextProtoCallback(fd, NextProtoStandardCallback, NULL); |
457 +} | 536 +} |
458 + | 537 + |
459 +/* SSL_GetNextProto reads the resulting Next Protocol Negotiation result for | |
460 + * the given socket. It's only valid to call this once the handshake has | |
461 + * completed. | |
462 + * | |
463 + * state is set to one of the SSL_NEXT_PROTO_* constants. The negotiated | |
464 + * protocol, if any, is written into buf, which must be at least buf_len | |
465 + * bytes long. If the negotiated protocol is longer than this, it is truncated. | |
466 + * The number of bytes copied is written into length. | |
467 + */ | |
468 +SECStatus | 538 +SECStatus |
469 +SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf, | 539 +SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf, |
470 + unsigned int *length, unsigned int buf_len) | 540 + unsigned int *length, unsigned int buf_len) |
471 +{ | 541 +{ |
472 + sslSocket *ss = ssl_FindSocket(fd); | 542 + sslSocket *ss = ssl_FindSocket(fd); |
473 + | 543 + |
474 + if (!ss) { | 544 + if (!ss) { |
475 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(), | 545 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(), |
476 + fd)); | 546 + fd)); |
477 + return SECFailure; | 547 + return SECFailure; |
(...skipping 26 matching lines...) Expand all Loading... |
504 #endif | 574 #endif |
505 ssl_session_ticket_xtn = 35, | 575 ssl_session_ticket_xtn = 35, |
506 + ssl_next_proto_neg_xtn = 13172, | 576 + ssl_next_proto_neg_xtn = 13172, |
507 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ | 577 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ |
508 } SSLExtensionType; | 578 } SSLExtensionType; |
509 | 579 |
510 -#define SSL_MAX_EXTENSIONS 5 | 580 -#define SSL_MAX_EXTENSIONS 5 |
511 +#define SSL_MAX_EXTENSIONS 6 | 581 +#define SSL_MAX_EXTENSIONS 6 |
512 | 582 |
513 #endif /* __sslt_h_ */ | 583 #endif /* __sslt_h_ */ |
OLD | NEW |