Skip to content

Instantly share code, notes, and snippets.

@rdp
Created December 13, 2019 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rdp/2b867a5b9e3c0a56368833f2b95878bd to your computer and use it in GitHub Desktop.
Save rdp/2b867a5b9e3c0a56368833f2b95878bd to your computer and use it in GitHub Desktop.
diff --git a/spec/std/openssl/ssl/socket_spec.cr b/spec/std/openssl/ssl/socket_spec.cr
index df3a34a61..b1d931c34 100644
--- a/spec/std/openssl/ssl/socket_spec.cr
+++ b/spec/std/openssl/ssl/socket_spec.cr
@@ -42,7 +42,7 @@ describe OpenSSL::SSL::Socket do
# in tls 1.3, if clients don't read anything and close the connection
# the server still try and write to it a ticket, resulting in a "pipe failure"
# this context method disables the tickets which allows the behavior:
- server_context.disable_session_resume_tickets
+ #server_context.disable_session_resume_tickets
OpenSSL::SSL::Server.open(tcp_server, server_context) do |server|
spawn do
@@ -61,7 +61,7 @@ describe OpenSSL::SSL::Socket do
it "closes connection to server that doesn't properly terminate SSL session" do
tcp_server = TCPServer.new(0)
server_context, client_context = ssl_context_pair
- server_context.disable_session_resume_tickets # avoid Broken pipe
+ #server_context.disable_session_resume_tickets # avoid Broken pipe
client_successfully_closed_socket = Channel(Nil).new
spawn do
@@ -77,4 +77,24 @@ describe OpenSSL::SSL::Socket do
socket.close
client_successfully_closed_socket.send(nil)
end
+
+ it "interprets graceful EOF of underlying socket as SSL termination" do
+ tcp_server = TCPServer.new(0)
+ server_context, client_context = ssl_context_pair
+
+ server_finished_reading = Channel(String).new
+ spawn do
+ OpenSSL::SSL::Server.open(tcp_server, server_context, sync_close: true) do |server|
+ server_socket = server.accept
+ received = server_socket.gets_to_end # interprets underlying socket close as a graceful EOF
+ server_finished_reading.send(received)
+ end
+ end
+ socket = TCPSocket.new(tcp_server.local_address.address, tcp_server.local_address.port)
+ socket_ssl = OpenSSL::SSL::Socket::Client.new(socket, client_context, hostname: "example.com", sync_close: true)
+ socket_ssl.print "hello"
+ socket_ssl.flush # needed today see #5375
+ socket.close # close underlying socket without gracefully shutting down SSL at all
+ server_finished_reading.receive().should eq("hello")
+ end
end
diff --git a/src/openssl.cr b/src/openssl.cr
index 93b676f6a..307f7ce4c 100644
--- a/src/openssl.cr
+++ b/src/openssl.cr
@@ -96,6 +96,7 @@ module OpenSSL
class Error < OpenSSL::Error
getter error : ErrorType
+ getter? underlying_eof : Bool = false
def initialize(ssl : LibSSL::SSL, return_code : LibSSL::Int, func = nil)
@error = LibSSL.ssl_get_error(ssl, return_code)
@@ -109,6 +110,7 @@ module OpenSSL
case return_code
when 0
message = "Unexpected EOF"
+ @underlying_eof = true
when -1
cause = Errno.new(func || "OpenSSL")
message = "I/O error"
diff --git a/src/openssl/ssl/socket.cr b/src/openssl/ssl/socket.cr
index f3557f2a3..3ab50a8db 100644
--- a/src/openssl/ssl/socket.cr
+++ b/src/openssl/ssl/socket.cr
@@ -115,7 +115,13 @@ abstract class OpenSSL::SSL::Socket < IO
LibSSL.ssl_read(@ssl, slice.to_unsafe, count).tap do |bytes|
if bytes <= 0 && !LibSSL.ssl_get_error(@ssl, bytes).zero_return?
- raise OpenSSL::SSL::Error.new(@ssl, bytes, "SSL_read")
+ ex = OpenSSL::SSL::Error.new(@ssl, bytes, "SSL_read")
+ if ex.underlying_eof?
+ # underlying BIO termianted gracefully, without terminating SSL aspect gracefully first
+ # some misbehaving servers "do this" so treat as EOF even though it's a protocol error
+ return 0
+ end
+ raise ex
end
end
end
@@ -155,7 +161,10 @@ abstract class OpenSSL::SSL::Socket < IO
begin
ret = LibSSL.ssl_shutdown(@ssl)
break if ret == 1 # done bidirectional
- break if ret == 0 && sync_close? # done unidirectional, "this first successful call to SSL_shutdown() is sufficient"
+ if ret == 0 && sync_close? # done unidirectional, "this first successful call to SSL_shutdown() is sufficient"
+ #unbuffered_read(Bytes.new(0))
+ break
+ end
raise OpenSSL::SSL::Error.new(@ssl, ret, "SSL_shutdown") if ret < 0
rescue e : OpenSSL::SSL::Error
case e.error
@majat
Copy link

majat commented Dec 13, 2019

Dear gentlemen of evolvingweb.ca I am new to Drupal and even more so in Acquia Dev Desktop, I made all steps written on your website (https://evolvingweb.ca/blog/installing-drupal-console-windows) for the installation of Drupal Console, the problem I have is that it did not install all the dependencies that Drupal has. To verify that not all dependencies were installed, run "$ drupal" and display only the following commands:

C:\Users\HP\Sites\devdesktop\drupal878>drupal
Drupal Console version 1.9.4

Usage:
command [options] [arguments]

Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-e, --env[=ENV] The Environment name [default: "prod"]
--root[=ROOT] Define the Drupal root to be used in command execution
--debug Switches on debug mode
--learning Generate a verbose code output
-c, --generate-chain Shows command options and arguments as yaml output to be used in chain command
-i, --generate-inline Shows command options and arguments as inline command
-d, --generate-doc Shows command options and arguments as markdown
-t, --target[=TARGET] Site name you want to interact with (for local or remote sites)
-l, --uri=URI URI of the Drupal site to use (for multi-site environments or when running on an alternate port)
-y, --yes Skip confirmation and proceed
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
about Displays basic information about Drupal Console project
chain Chain command execution
check System requirement checker
exec Execute an external command.
help Displays help for a command
init Copy configuration files.
list Lists all available commands
server (serve,rs) Runs PHP built-in web server
database
database:add (dba) Add a database to settings.php
database:client (dbc) Launch a DB client if it's available
database:connect (dbco,sqlc) Shows DB connection
database:query (dbq,sqlq) Executes a SQL statement directly as argument
database:restore (dbr) Restore structure and contents of a database.
debug
debug:chain (dch) List available chain files.
debug:dotenv Debug Dotenv debug values.
debug:settings (dse) List user Drupal Console settings.
debug:site (dsi) List all known local and remote sites.
debug:update:composer (duc) Displays current updates available from the composer file
develop
develop:contribute Download Drupal + Drupal Console to contribute.
docker
docker:init Create a docker-compose.yml file
dotenv
dotenv:init Add support and required config to work with an .env file
generate
generate:site:alias (gsa) Generates a site alias.
quick
quick:start Download, install and serve a new Drupal project
settings
settings:set Change a specific setting value in DrupalConsole config file
site
site:install (si) Install a Drupal project
site:new Download a new Drupal project

Please I need your help, thanks in advance.

Sincerely Bladimir

@rdp
Copy link
Author

rdp commented Dec 13, 2019

comment on wrong gist?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment