Comments (5)
Currently, SSLSocket passes the file descriptor to OpenSSL and doesn't use Ruby's IO interface.
openssl/ext/openssl/ossl_ssl.c
Lines 1688 to 1689 in 45c731c
OpenSSL uses an abstraction layer called BIO to interact with the underlying socket. Here is the default implementation (a "BIO method" - SSL_set_fd()
will set up the BIO_s_socket()
): https://github.com/openssl/openssl/blob/master/crypto/bio/bss_sock.c
It's more work than just removing a check, but it should be possible to define a custom BIO method that wraps an IO-ish object (as long as it supports non-blocking IO methods).
from openssl.
I was anticipating it to be much harder than just removing the check, no worries.
To better illustrate what I'm looking for, here's a practical example using docker: I've just pushed the "infra setup" changes to this MR branch. Once you download the repo and switch to the "https-proxy" branch:
- run
docker-compose -f docker-compose -f docker-compose-ruby-{MAJOR}-{MINOR}.yml run --entrypoint bash httpx
to open a shell - run these and these commands
And you should be in a position to replicate the issue. You can run:
> curl -x https://proxyuser:password@httpsproxy:9080 \
--proxy-cacert test/support/ci/certs/ca.crt \
https://nghttp2/get -v
to verify what/how curl does it. To replicate what at least I'd expect to work in ruby, you can run this script:
require "socket"
require "openssl"
require "base64"
AUTH = Base64.strict_encode64("proxyuser:password")
CONNECT_REQ = <<-CONNECT.gsub("\n", "\r\n")
CONNECT nghttp2:443 HTTP/1.1
Host: nghttp2
Proxy-Authorization: Basic #{AUTH}
CONNECT
REQ = <<-REQ.gsub("\n", "\r\n")
GET /get HTTP/1.1
User-Agent: smth
Accept: */*
Connection: close
Host: nghttp2
REQ
tcp = TCPSocket.new("httpsproxy", 9080)
ctx = OpenSSL::SSL::SSLContext.new
ssl = OpenSSL::SSL::SSLSocket.new(tcp, ctx)
ssl.hostname = "httpsproxy"
ssl.sync_close = true
ssl.connect
ssl.post_connection_check("httpsproxy")
ssl.write(CONNECT_REQ)
response = ssl.readpartial(2048)
puts "response from proxy connect"
puts response.inspect
raise unless response.start_with?("HTTP/1.1 200")
ssl.write(REQ)
puts ssl.readpartial(2048)
which currently breaks on the last line with ...openssl/buffering.rb:157:in
sysread': end of file reached (EOFError)`
from openssl.
@rhenium just opened an MR to explore a possible approach to solving this. LMK what you think, and whether you think there are other alternatives worth pursuing.
from openssl.
I was exploring the approach to implement a BIO_METHOD
that simply translates those Ruby IO methods. It's not reviewed carefully, but here is a WIP PR: #736
Thanks for the pointer to usage of the memory BIO in Python's ssl library. I didn't know about it, and that approach is interesting. While it is slightly inefficient due to one additional data copy, if I understand it right, it would let us interact with the IO-like object outside of SSL_{read,write,..}()
and reduce the amount of rb_protect()
state variables churn. It's quite a mess in my WIP PR.
from openssl.
hey @rhenium , after a bit of back-and-forth with my approach, and hitting some limitations of my openssl C API expertise, and also researching other implementations, I'm leaning towards your approach of BIO_METHOD as being the most viable.
To begin with, it works! I've tested it with the script pasted above against a server behind-a-squid-behind-stunnel, and even if still a rough patch, it worked the first time. So that's something I haven't been able to produce.
I've also been looking at how curl works on top of openssl, and it seems that it also ships with its own BIO_METHOD. The main advantage seems to be that SSL_connect usage seems to "just work", whereas you'd have to "drop down" a layer of abstraction if maintaining bio-mems around (ssl connect was the hurdle I was never to pass from in my attempt). This sees to be how cpython works with openssl, where different APIs are used (SSL_write_ex instead of SSL_write, and SSL_do_handshake instead of SSL_connect, just to name a couple).
I also find that approach to be a better template to implement on top of openssl QUIC connections; not sure how much you've considered introducing them at this point though.
About rb_protect usage, I'm not sure if you really need it, considering you're using the "exception: false" variants of the non-blocking APIs? Moreover (and a bit tangential), having researched the cpython implementation (a bit superficially, I admit), I was wondering why can't the gem release the GVL more often, for example when calling the SSL_* family of APIs (python examples here and here), as I believe roughly the same constraints apply?
Thx for the help sofar, and LMK how I can help move this forward! 🙏
from openssl.
Related Issues (20)
- macos-latest truffeeruby-head: test_basic_response_response_operations failing HOT 3
- truffleruby-head 24.0.0-dev: Failing to compile dependant stringio gem. HOT 14
- OpenSSL::PKey::EC.new(nil).generate_key fails with OpenSSL::PKey::PKeyError HOT 6
- OpenSSL 3.2.0 - sessions, time, signed vs unsigned, failure with negative session timeout values HOT 6
- OpenSSL::SSL::SSLContext.new returns SSL_CTX_new: library has no ciphers HOT 6
- Respect system wide minimum TLS version HOT 2
- windows-latest 3.3 case failing with "OpenSSL::Provider::ProviderError: Failed to load legacy provider: (null) (name=legacy)" HOT 8
- OpenSSL::PKey::PKey subclass for EVP_PKEY_RSA_PSS HOT 4
- Error "Failed to build gem native extension." when running "gem install openssl" in Fedora HOT 4
- OpenSSL udate 3.2.1 for CVE-2023-6129 HOT 3
- OpenSSL 3 | Providers | Support broader range of URI schemes for loading keys HOT 3
- OpenSSL 3 support for loading engine keys HOT 3
- OpenSSL version 3.3.0-dev: OpenSSL::ASN1::ASN1Error: utctime/generalizedtime is too short HOT 7
- OpenSSL::ASN1.decode doesn't correctly parse UTCTime or GeneralizedTime with fractional seconds or a timezone
- When decrypted with a different private key, `OpenSSL::PKey::RSAError` does not occur HOT 2
- Upcoming OpenSSL Webinar: Writing Your First OpenSSL Application
- Invalid CSR versions set in regress tests HOT 2
- OpenSSL::SSL::SSLError: SSL_write: unsupported method HOT 4
- Can we please cut a 3.3.0 release? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from openssl.