-
Notifications
You must be signed in to change notification settings - Fork 844
Fix support for openssl async engine #6910
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,6 +72,15 @@ static int async_rsa_finish(RSA *rsa); | |
|
|
||
| static RSA_METHOD *async_rsa_method = NULL; | ||
|
|
||
| EVP_PKEY *async_load_privkey(ENGINE *e, const char *s_key_id, UI_METHOD *ui_method, void *callback_data) | ||
| { | ||
| printf("Loading key %s\n", s_key_id); | ||
| FILE *f = fopen(s_key_id, "r"); | ||
| EVP_PKEY *key = PEM_read_PrivateKey(f, NULL, NULL, NULL); | ||
| fclose(f); | ||
| return key; | ||
| } | ||
|
|
||
| static int bind_async(ENGINE *e) | ||
| { | ||
| /* Setup RSA_METHOD */ | ||
|
|
@@ -96,7 +105,8 @@ static int bind_async(ENGINE *e) | |
| || !ENGINE_set_RSA(e, async_rsa_method) | ||
| || !ENGINE_set_destroy_function(e, async_destroy) | ||
| || !ENGINE_set_init_function(e, engine_async_init) | ||
| || !ENGINE_set_finish_function(e, async_finish)) { | ||
| || !ENGINE_set_finish_function(e, async_finish) | ||
| || !ENGINE_set_load_privkey_function(e, async_load_privkey)) { | ||
| fprintf(stderr, "Failed to initialize\n"); | ||
| return 0; | ||
| } | ||
|
|
@@ -176,14 +186,17 @@ static void async_pause_job(void) { | |
| OSSL_ASYNC_FD *writefd; | ||
| char buf = DUMMY_CHAR; | ||
|
|
||
| if ((job = ASYNC_get_current_job()) == NULL) | ||
| if ((job = ASYNC_get_current_job()) == NULL) { | ||
| printf("No job\n"); | ||
| return; | ||
| } | ||
|
|
||
| waitctx = ASYNC_get_wait_ctx(job); | ||
|
|
||
| if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_id, &pipefds[0], | ||
| (void **)&writefd)) { | ||
| pipefds[1] = *writefd; | ||
| printf("Existing wait ctx\n"); | ||
| return; | ||
| } else { | ||
| writefd = (OSSL_ASYNC_FD *)OPENSSL_malloc(sizeof(*writefd)); | ||
| if (writefd == NULL) | ||
|
|
@@ -194,6 +207,8 @@ static void async_pause_job(void) { | |
| } | ||
| *writefd = pipefds[1]; | ||
|
|
||
| printf("New wait ctx %d %d\n", pipefds[0], pipefds[1]); | ||
|
|
||
| if(!ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_id, pipefds[0], | ||
| writefd, wait_cleanup)) { | ||
| wait_cleanup(waitctx, engine_id, pipefds[0], writefd); | ||
|
|
@@ -213,35 +228,39 @@ void * | |
| delay_method(void *arg) | ||
| { | ||
| int signal_fd = (intptr_t)arg; | ||
| sleep(5); | ||
| uint64_t buf = 1; | ||
| sleep(2); | ||
| char buf = DUMMY_CHAR; | ||
| write(signal_fd, &buf, sizeof(buf)); | ||
| printf("Send signal to %d\n", signal_fd); | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
||
| void | ||
| spawn_delay_thread() | ||
| { | ||
| pthread_t thread_id; | ||
| OSSL_ASYNC_FD signal_fd; | ||
| OSSL_ASYNC_FD pipefds[2] = {0, 0}; | ||
| ASYNC_JOB *job; | ||
| if ((job = ASYNC_get_current_job()) == NULL) | ||
| if ((job = ASYNC_get_current_job()) == NULL) { | ||
| printf("Spawn no job\n"); | ||
| return; | ||
| } | ||
|
|
||
| ASYNC_WAIT_CTX *waitctx = ASYNC_get_wait_ctx(job); | ||
|
|
||
| size_t numfds; | ||
| if (ASYNC_WAIT_CTX_get_all_fds(waitctx, &signal_fd, &numfds) && numfds > 0) { | ||
| if (ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds) && numfds > 0) { | ||
| printf("Spawn, wait_ctx exists. Go away, something else is using this job\n"); | ||
| } else { | ||
| OSSL_ASYNC_FD signal_fd; | ||
| OSSL_ASYNC_FD pipefds[2] = {0,0}; | ||
| OSSL_ASYNC_FD *writefd = OPENSSL_malloc(sizeof(*writefd)); | ||
| pipe(pipefds); | ||
| signal_fd = *writefd = pipefds[1]; | ||
| ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_id, pipefds[0], writefd, wait_cleanup); | ||
| printf("Spawn, create wait_ctx %d %d\n", pipefds[0], pipefds[1]); | ||
| pthread_create(&thread_id, NULL, delay_method, (void *)((intptr_t)signal_fd)); | ||
| } | ||
|
|
||
| pthread_create(&thread_id, NULL, delay_method, (void *)((intptr_t)signal_fd)); | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -264,7 +283,7 @@ static int async_pub_dec(int flen, const unsigned char *from, | |
| static int async_rsa_priv_enc(int flen, const unsigned char *from, | ||
| unsigned char *to, RSA *rsa, int padding) | ||
| { | ||
| //printf("async_priv_enc\n"); | ||
| printf("async_priv_enc\n"); | ||
| spawn_delay_thread(); | ||
| async_pause_job(); | ||
| return RSA_meth_get_priv_enc(RSA_PKCS1_OpenSSL()) | ||
|
|
@@ -274,7 +293,7 @@ static int async_rsa_priv_enc(int flen, const unsigned char *from, | |
| static int async_rsa_priv_dec(int flen, const unsigned char *from, | ||
| unsigned char *to, RSA *rsa, int padding) | ||
| { | ||
| //printf("async_priv_dec\n"); | ||
| printf("async_priv_dec\n"); | ||
| spawn_delay_thread(); | ||
| async_pause_job(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is required to clear the wake signal by
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That clearing is actually done within the async_pause_job function. Rather after the return from the openssl function ASYNC_pause_job
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I confused async_pause_job with ASYNC_pause_job. |
||
| return RSA_meth_get_priv_dec(RSA_PKCS1_OpenSSL()) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| ''' | ||
| ''' | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
|
|
||
| import os | ||
|
|
||
|
|
||
| # Someday should add client cert to origin to exercise the | ||
| # engine interface on the other side | ||
|
|
||
| Test.Summary = ''' | ||
| Test tls via the async interface with the sample async_engine | ||
| ''' | ||
|
|
||
| Test.SkipUnless(Condition.HasOpenSSLVersion('1.1.1')) | ||
|
|
||
| # Define default ATS | ||
| ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True) | ||
| server = Test.MakeOriginServer("server") | ||
|
|
||
| # Compile with tsxs. That should bring in the consisten versions of openssl | ||
| ts.Setup.Copy(os.path.join(Test.Variables.AtsTestToolsDir, '../../contrib/openssl', 'async_engine.c'), Test.RunDirectory) | ||
| ts.Setup.RunCommand("tsxs -o async_engine.so async_engine.c") | ||
|
|
||
| # Add info the origin server responses | ||
| server.addResponse("sessionlog.json", | ||
| {"headers": "GET / HTTP/1.1\r\nuuid: basic\r\n\r\n", "timestamp": "1469733493.993", "body": ""}, | ||
| {"headers": "HTTP/1.1 200 OK\r\nServer: microserver\r\nConnection: close\r\nCache-Control: max-age=3600\r\nContent-Length: 2\r\n\r\n", "timestamp": "1469733493.993", "body": "ok"}) | ||
|
|
||
| # add ssl materials like key, certificates for the server | ||
| ts.addSSLfile("ssl/server.pem") | ||
| ts.addSSLfile("ssl/server.key") | ||
|
|
||
| ts.Disk.remap_config.AddLine( | ||
| 'map / http://127.0.0.1:{0}'.format(server.Variables.Port) | ||
| ) | ||
|
|
||
| ts.Disk.ssl_multicert_config.AddLine( | ||
| 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' | ||
| ) | ||
| ts.Disk.records_config.update({ | ||
| 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), | ||
| 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), | ||
| 'proxy.config.ssl.client.verify.server': 0, | ||
| 'proxy.config.exec_thread.autoconfig.scale': 1.0, | ||
| 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', | ||
| 'proxy.config.ssl.engine.conf_file': '{0}/ts/config/load_engine.cnf'.format(Test.RunDirectory), | ||
| 'proxy.config.ssl.async.handshake.enabled': 1, | ||
| 'proxy.config.diags.debug.enabled': 0, | ||
| 'proxy.config.diags.debug.tags': 'ssl' | ||
| }) | ||
|
|
||
| ts.Disk.MakeConfigFile('load_engine.cnf').AddLines([ | ||
| 'openssl_conf = openssl_init', | ||
| '', | ||
| '[openssl_init]', | ||
| '', | ||
| 'engines = engine_section', | ||
| '', | ||
| '[engine_section]', | ||
| '', | ||
| 'async = async_section', | ||
| '', | ||
| '[async_section]', | ||
| '', | ||
| 'dynamic_path = {0}/async_engine.so'.format(Test.RunDirectory), | ||
| '', | ||
| 'engine_id = async-test', | ||
| '', | ||
| 'default_algorithms = RSA', | ||
| '', | ||
| 'init = 1']) | ||
|
|
||
| # Make a basic request. Hopefully it goes through | ||
| tr = Test.AddTestRun("Run-Test") | ||
| tr.Processes.Default.Command = "curl -k -v -H uuid:basic -H host:example.com https://127.0.0.1:{0}/".format(ts.Variables.ssl_port) | ||
| tr.ReturnCode = 0 | ||
| tr.Processes.Default.StartBefore(server) | ||
| tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.ssl_port)) | ||
| tr.Processes.Default.Streams.All = Testers.ContainsExpression("HTTP/(2|1\.1) 200", "Request succeeds") | ||
| tr.StillRunningAfter = server | ||
|
|
||
| ts.Streams.All += Testers.ContainsExpression("Send signal to ", "The Async engine triggers") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we got an existed
fdfromwaitctx, it means there is an async job still in progress. It should return immediately.