/* * With a NULL context, this function just checks that the serverinfo data * parses correctly. With a non-NULL context, it registers callbacks for * the included extensions. */ static int serverinfo_process_buffer(const unsigned char *serverinfo, size_t serverinfo_length, SSL_CTX *ctx) { if (serverinfo == NULL || serverinfo_length == 0) return 0; for (;;) { unsigned int ext_type = 0; size_t len = 0; /* end of serverinfo */ if (serverinfo_length == 0) return 1; /* read 2-byte type field */ if (serverinfo_length < 2) return 0; /* FIXME: check for types we understand explicitly? */ /* Register callbacks for extensions */ ext_type = (serverinfo[0] << 8) + serverinfo[1]; if (ctx) { int have_ext_cbs = 0; size_t i; custom_ext_methods *exts = &ctx->cert->srv_ext; custom_ext_method *meth = exts->meths; for (i = 0; i < exts->meths_count; i++, meth++) { if (ext_type == meth->ext_type) { have_ext_cbs = 1; break; } } if (!have_ext_cbs && !SSL_CTX_add_server_custom_ext(ctx, ext_type, serverinfo_srv_add_cb, NULL, NULL, serverinfo_srv_parse_cb, NULL)) return 0; } serverinfo += 2; serverinfo_length -= 2; /* read 2-byte len field */ if (serverinfo_length < 2) return 0; len = (serverinfo[0] << 8) + serverinfo[1]; serverinfo += 2; serverinfo_length -= 2; if (len > serverinfo_length) return 0; serverinfo += len; serverinfo_length -= len; } }
/* With a NULL context, this function just checks that the serverinfo data parses correctly. With a non-NULL context, it registers callbacks for the included extensions. */ static int serverinfo_process_buffer(const unsigned char *serverinfo, size_t serverinfo_length, SSL_CTX *ctx) { if (serverinfo == NULL || serverinfo_length == 0) return 0; for (;;) { unsigned int ext_type = 0; size_t len = 0; /* end of serverinfo */ if (serverinfo_length == 0) return 1; /* read 2-byte type field */ if (serverinfo_length < 2) return 0; /* FIXME: check for types we understand explicitly? */ /* Register callbacks for extensions */ ext_type = (serverinfo[0] << 8) + serverinfo[1]; if (ctx && !SSL_CTX_add_server_custom_ext(ctx, ext_type, serverinfo_srv_add_cb, NULL, NULL, serverinfo_srv_parse_cb, NULL)) return 0; serverinfo += 2; serverinfo_length -= 2; /* read 2-byte len field */ if (serverinfo_length < 2) return 0; len = (serverinfo[0] << 8) + serverinfo[1]; serverinfo += 2; serverinfo_length -= 2; if (len > serverinfo_length) return 0; serverinfo += len; serverinfo_length -= len; } }
/* * Custom call back tests. * Test 0: callbacks in TLSv1.2 * Test 1: callbacks in TLSv1.2 with SNI */ static int test_custom_exts(int tst) { SSL_CTX *cctx = NULL, *sctx = NULL, *sctx2 = NULL; SSL *clientssl = NULL, *serverssl = NULL; int testresult = 0; static int server = 1; static int client = 0; SSL_SESSION *sess = NULL; /* Reset callback counters */ clntaddcb = clntparsecb = srvaddcb = srvparsecb = 0; snicb = 0; if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx, &cctx, cert, privkey)) { printf("Unable to create SSL_CTX pair\n"); goto end; } if (tst == 1 && !create_ssl_ctx_pair(TLS_server_method(), NULL, &sctx2, NULL, cert, privkey)) { printf("Unable to create SSL_CTX pair (2)\n"); goto end; } /* Create a client side custom extension */ if (!SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1, add_cb, free_cb, &client, parse_cb, &client)) { printf("Unable to add client custom extension\n"); goto end; } /* Should not be able to add duplicates */ if (SSL_CTX_add_client_custom_ext(cctx, TEST_EXT_TYPE1, add_cb, free_cb, &client, parse_cb, &client)) { printf("Unexpected success adding duplicate extension\n"); goto end; } /* Create a server side custom extension */ if (!SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1, add_cb, free_cb, &server, parse_cb, &server)) { printf("Unable to add server custom extension\n"); goto end; } if (sctx2 != NULL && !SSL_CTX_add_server_custom_ext(sctx2, TEST_EXT_TYPE1, add_cb, free_cb, &server, parse_cb, &server)) { printf("Unable to add server custom extension for SNI\n"); goto end; } /* Should not be able to add duplicates */ if (SSL_CTX_add_server_custom_ext(sctx, TEST_EXT_TYPE1, add_cb, free_cb, &server, parse_cb, &server)) { printf("Unexpected success adding duplicate extension (2)\n"); goto end; } if (tst == 1) { /* Set up SNI */ if (!SSL_CTX_set_tlsext_servername_callback(sctx, sni_cb) || !SSL_CTX_set_tlsext_servername_arg(sctx, sctx2)) { printf("Cannot set SNI callbacks\n"); goto end; } } if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL) || !create_ssl_connection(serverssl, clientssl)) { printf("Cannot create SSL connection\n"); goto end; } if (clntaddcb != 1 || clntparsecb != 1 || srvaddcb != 1 || srvparsecb != 1 || (tst != 1 && snicb != 0) || (tst == 1 && snicb != 1)) { printf("Incorrect callback counts\n"); goto end; } sess = SSL_get1_session(clientssl); SSL_shutdown(clientssl); SSL_shutdown(serverssl); SSL_free(serverssl); SSL_free(clientssl); serverssl = clientssl = NULL; if (tst == 1) { /* We don't bother with the resumption aspects for this test */ testresult = 1; goto end; } if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL) || !SSL_set_session(clientssl, sess) || !create_ssl_connection(serverssl, clientssl)) { printf("Cannot create resumption connection\n"); goto end; } /* * For a resumed session we expect to add the ClientHello extension but we * should ignore it on the server side. */ if (clntaddcb != 2 || clntparsecb != 1 || srvaddcb != 1 || srvparsecb != 1) { printf("Incorrect resumption callback counts\n"); goto end; } testresult = 1; end: SSL_SESSION_free(sess); SSL_free(serverssl); SSL_free(clientssl); SSL_CTX_free(sctx2); SSL_CTX_free(sctx); SSL_CTX_free(cctx); return testresult; }
static char *ngx_http_ssl_ct_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) { /* merge config */ ngx_ssl_ct_srv_conf_t *prev = parent; ngx_ssl_ct_srv_conf_t *conf = child; ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_str_value(conf->sct, prev->sct, ""); /* validate config */ if (conf->enable) { if (conf->sct.len == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_ct_static_scts\" is defined for the \"ssl_ct\"" "directive"); return NGX_CONF_ERROR; } } else { return NGX_CONF_OK; } /* get ngx_http_ssl_module configuration and check if SSL is enabled */ ngx_http_ssl_srv_conf_t *ssl_conf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_ssl_module); if (!ssl_conf->ssl.ctx) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "\"ssl_ct\" can only be enabled if ssl is enabled"); return NGX_CONF_ERROR; } /* read .sct files */ ngx_ssl_ct_ext *sct_list = ngx_ssl_ct_read_static_scts(cf, &conf->sct); if (!sct_list) { /* ngx_ssl_ct_read_static_scts calls ngx_log_error */ return NGX_CONF_ERROR; } /* add OpenSSL TLS extension */ #ifndef OPENSSL_IS_BORINGSSL if (SSL_CTX_add_server_custom_ext(ssl_conf->ssl.ctx, NGX_SSL_CT_EXT, &ngx_ssl_ct_ext_cb, NULL, sct_list, NULL, NULL) == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_add_server_custom_ext failed"); ngx_pfree(cf->pool, sct_list); return NGX_CONF_ERROR; } #else if (SSL_CTX_set_signed_cert_timestamp_list(ssl_conf->ssl.ctx, sct_list->buf, sct_list->len) == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_signed_cert_timestamp_list failed"); ngx_pfree(cf->pool, sct_list); return NGX_CONF_ERROR; } #endif return NGX_CONF_OK; }