Mercurial > hg > nginx
comparison src/stream/ngx_stream_ssl_preread_module.c @ 7314:3dfc1584ad75
Stream ssl_preread: $ssl_preread_protocol variable.
The variable keeps the latest SSL protocol version supported by the client.
The variable has the same format as $ssl_protocol.
The version is read from the client_version field of ClientHello. If the
supported_versions extension is present in the ClientHello, then the version
is set to TLSv1.3.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 11 Jul 2018 17:56:51 +0300 |
parents | 0f811890f2f0 |
children | 6649d4433266 |
comparison
equal
deleted
inserted
replaced
7313:e45f09198dab | 7314:3dfc1584ad75 |
---|---|
19 size_t size; | 19 size_t size; |
20 size_t ext; | 20 size_t ext; |
21 u_char *pos; | 21 u_char *pos; |
22 u_char *dst; | 22 u_char *dst; |
23 u_char buf[4]; | 23 u_char buf[4]; |
24 u_char version[2]; | |
24 ngx_str_t host; | 25 ngx_str_t host; |
25 ngx_str_t alpn; | 26 ngx_str_t alpn; |
26 ngx_log_t *log; | 27 ngx_log_t *log; |
27 ngx_pool_t *pool; | 28 ngx_pool_t *pool; |
28 ngx_uint_t state; | 29 ngx_uint_t state; |
30 | 31 |
31 | 32 |
32 static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s); | 33 static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s); |
33 static ngx_int_t ngx_stream_ssl_preread_parse_record( | 34 static ngx_int_t ngx_stream_ssl_preread_parse_record( |
34 ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last); | 35 ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last); |
36 static ngx_int_t ngx_stream_ssl_preread_protocol_variable( | |
37 ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); | |
35 static ngx_int_t ngx_stream_ssl_preread_server_name_variable( | 38 static ngx_int_t ngx_stream_ssl_preread_server_name_variable( |
36 ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); | 39 ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); |
37 static ngx_int_t ngx_stream_ssl_preread_alpn_protocols_variable( | 40 static ngx_int_t ngx_stream_ssl_preread_alpn_protocols_variable( |
38 ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); | 41 ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); |
39 static ngx_int_t ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf); | 42 static ngx_int_t ngx_stream_ssl_preread_add_variables(ngx_conf_t *cf); |
84 }; | 87 }; |
85 | 88 |
86 | 89 |
87 static ngx_stream_variable_t ngx_stream_ssl_preread_vars[] = { | 90 static ngx_stream_variable_t ngx_stream_ssl_preread_vars[] = { |
88 | 91 |
92 { ngx_string("ssl_preread_protocol"), NULL, | |
93 ngx_stream_ssl_preread_protocol_variable, 0, 0, 0 }, | |
94 | |
89 { ngx_string("ssl_preread_server_name"), NULL, | 95 { ngx_string("ssl_preread_server_name"), NULL, |
90 ngx_stream_ssl_preread_server_name_variable, 0, 0, 0 }, | 96 ngx_stream_ssl_preread_server_name_variable, 0, 0, 0 }, |
91 | 97 |
92 { ngx_string("ssl_preread_alpn_protocols"), NULL, | 98 { ngx_string("ssl_preread_alpn_protocols"), NULL, |
93 ngx_stream_ssl_preread_alpn_protocols_variable, 0, 0, 0 }, | 99 ngx_stream_ssl_preread_alpn_protocols_variable, 0, 0, 0 }, |
194 u_char *dst, *p; | 200 u_char *dst, *p; |
195 | 201 |
196 enum { | 202 enum { |
197 sw_start = 0, | 203 sw_start = 0, |
198 sw_header, /* handshake msg_type, length */ | 204 sw_header, /* handshake msg_type, length */ |
199 sw_head_tail, /* version, random */ | 205 sw_version, /* client_version */ |
206 sw_random, /* random */ | |
200 sw_sid_len, /* session_id length */ | 207 sw_sid_len, /* session_id length */ |
201 sw_sid, /* session_id */ | 208 sw_sid, /* session_id */ |
202 sw_cs_len, /* cipher_suites length */ | 209 sw_cs_len, /* cipher_suites length */ |
203 sw_cs, /* cipher_suites */ | 210 sw_cs, /* cipher_suites */ |
204 sw_cm_len, /* compression_methods length */ | 211 sw_cm_len, /* compression_methods length */ |
208 sw_sni_len, /* SNI length */ | 215 sw_sni_len, /* SNI length */ |
209 sw_sni_host_head, /* SNI name_type, host_name length */ | 216 sw_sni_host_head, /* SNI name_type, host_name length */ |
210 sw_sni_host, /* SNI host_name */ | 217 sw_sni_host, /* SNI host_name */ |
211 sw_alpn_len, /* ALPN length */ | 218 sw_alpn_len, /* ALPN length */ |
212 sw_alpn_proto_len, /* ALPN protocol_name length */ | 219 sw_alpn_proto_len, /* ALPN protocol_name length */ |
213 sw_alpn_proto_data /* ALPN protocol_name */ | 220 sw_alpn_proto_data, /* ALPN protocol_name */ |
221 sw_supver_len /* supported_versions length */ | |
214 } state; | 222 } state; |
215 | 223 |
216 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, ctx->log, 0, | 224 ngx_log_debug2(NGX_LOG_DEBUG_STREAM, ctx->log, 0, |
217 "ssl preread: state %ui left %z", ctx->state, ctx->left); | 225 "ssl preread: state %ui left %z", ctx->state, ctx->left); |
218 | 226 |
252 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, | 260 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, |
253 "ssl preread: not a client hello"); | 261 "ssl preread: not a client hello"); |
254 return NGX_DECLINED; | 262 return NGX_DECLINED; |
255 } | 263 } |
256 | 264 |
257 state = sw_head_tail; | 265 state = sw_version; |
258 dst = NULL; | 266 dst = ctx->version; |
259 size = 34; | 267 size = 2; |
260 left = (p[1] << 16) + (p[2] << 8) + p[3]; | 268 left = (p[1] << 16) + (p[2] << 8) + p[3]; |
261 break; | 269 break; |
262 | 270 |
263 case sw_head_tail: | 271 case sw_version: |
272 state = sw_random; | |
273 dst = NULL; | |
274 size = 32; | |
275 break; | |
276 | |
277 case sw_random: | |
264 state = sw_sid_len; | 278 state = sw_sid_len; |
265 dst = p; | 279 dst = p; |
266 size = 1; | 280 size = 1; |
267 break; | 281 break; |
268 | 282 |
332 dst = p; | 346 dst = p; |
333 size = 2; | 347 size = 2; |
334 break; | 348 break; |
335 } | 349 } |
336 | 350 |
351 if (p[0] == 0 && p[1] == 43) { | |
352 /* supported_versions extension */ | |
353 state = sw_supver_len; | |
354 dst = p; | |
355 size = 1; | |
356 break; | |
357 } | |
358 | |
337 state = sw_ext; | 359 state = sw_ext; |
338 dst = NULL; | 360 dst = NULL; |
339 size = (p[2] << 8) + p[3]; | 361 size = (p[2] << 8) + p[3]; |
340 break; | 362 break; |
341 | 363 |
432 | 454 |
433 state = sw_ext; | 455 state = sw_ext; |
434 dst = NULL; | 456 dst = NULL; |
435 size = 0; | 457 size = 0; |
436 break; | 458 break; |
459 | |
460 case sw_supver_len: | |
461 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, | |
462 "ssl preread: supported_versions"); | |
463 | |
464 /* set TLSv1.3 */ | |
465 ctx->version[0] = 3; | |
466 ctx->version[1] = 4; | |
467 | |
468 state = sw_ext; | |
469 dst = NULL; | |
470 size = p[0]; | |
471 break; | |
437 } | 472 } |
438 | 473 |
439 if (left < size) { | 474 if (left < size) { |
440 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, | 475 ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, |
441 "ssl preread: failed to parse handshake"); | 476 "ssl preread: failed to parse handshake"); |
452 return NGX_AGAIN; | 487 return NGX_AGAIN; |
453 } | 488 } |
454 | 489 |
455 | 490 |
456 static ngx_int_t | 491 static ngx_int_t |
492 ngx_stream_ssl_preread_protocol_variable(ngx_stream_session_t *s, | |
493 ngx_variable_value_t *v, uintptr_t data) | |
494 { | |
495 ngx_str_t version; | |
496 ngx_stream_ssl_preread_ctx_t *ctx; | |
497 | |
498 ctx = ngx_stream_get_module_ctx(s, ngx_stream_ssl_preread_module); | |
499 | |
500 if (ctx == NULL) { | |
501 v->not_found = 1; | |
502 return NGX_OK; | |
503 } | |
504 | |
505 /* SSL_get_version() format */ | |
506 | |
507 ngx_str_null(&version); | |
508 | |
509 switch (ctx->version[0]) { | |
510 case 2: | |
511 ngx_str_set(&version, "SSLv2"); | |
512 break; | |
513 case 3: | |
514 switch (ctx->version[1]) { | |
515 case 0: | |
516 ngx_str_set(&version, "SSLv3"); | |
517 break; | |
518 case 1: | |
519 ngx_str_set(&version, "TLSv1"); | |
520 break; | |
521 case 2: | |
522 ngx_str_set(&version, "TLSv1.1"); | |
523 break; | |
524 case 3: | |
525 ngx_str_set(&version, "TLSv1.2"); | |
526 break; | |
527 case 4: | |
528 ngx_str_set(&version, "TLSv1.3"); | |
529 break; | |
530 } | |
531 } | |
532 | |
533 v->valid = 1; | |
534 v->no_cacheable = 0; | |
535 v->not_found = 0; | |
536 v->len = version.len; | |
537 v->data = version.data; | |
538 | |
539 return NGX_OK; | |
540 } | |
541 | |
542 | |
543 static ngx_int_t | |
457 ngx_stream_ssl_preread_server_name_variable(ngx_stream_session_t *s, | 544 ngx_stream_ssl_preread_server_name_variable(ngx_stream_session_t *s, |
458 ngx_variable_value_t *v, uintptr_t data) | 545 ngx_variable_value_t *v, uintptr_t data) |
459 { | 546 { |
460 ngx_stream_ssl_preread_ctx_t *ctx; | 547 ngx_stream_ssl_preread_ctx_t *ctx; |
461 | 548 |