gemini_server 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29f2c81f5db11cffa8974cf4a1a48654ac00565b66f2ce306086f900246b34f9
4
- data.tar.gz: 842fee3d9d59845cc851b65c2dc918a4ee850e5ffd6f27e4b1c09131a1181659
3
+ metadata.gz: e067f64e27db63e071c57585ae24b7ae0cca9b4c408d0c18acf4b99b6e7ddc57
4
+ data.tar.gz: 30ab2fec9b37e2316dc9b96a9ff18cfe88a892a9d97c5fbbc40ede5336aaba30
5
5
  SHA512:
6
- metadata.gz: 62be452faaec4d6c4b59a15f3847f6776f795a57d7037ec7ff54452ba15ec1ad3410e645e0c595c2358dd53ff0da54410765be27e6448f3519cc5c0ebb857edb
7
- data.tar.gz: 1cce37852838f92ced3fb4e504ff4356d0d098ef27a47d6638d6cb0123b4d2b8c8a63a0412260c15c71da9c78ab37df8f267328e9c331c3d5643614e95510cbe
6
+ metadata.gz: 34222c9438fda88020863ebf5c05dc454a43b02334fec1fe63af28594c418dc01d1024829ddbf275597af6fe72f196dd854e7b35932934e8805c411bfb5ed354
7
+ data.tar.gz: cd906abfa205f29f7470c7844043c266655c35d63da00aa95bcc27e9a2c418aced3f537ea2b44707d0353ff41dded57edb5c0e0c249f6f9bdba0583ffc5b00db
data/README.md CHANGED
@@ -4,6 +4,23 @@ A simple server for the Gemini protocol, with an API inspired by Sinatra.
4
4
 
5
5
  ## Usage
6
6
 
7
+ Use the built-in executable to serve the current directory.
8
+
9
+ ```
10
+ $ gem install gemini_server
11
+ Successfully installed gemini_server-0.1.0
12
+ 1 gem installed
13
+ $ gemini_server -h
14
+ Usage: gemini_server [options]
15
+ -p, --port PORT Port to listen on
16
+ --cert-path PATH Path to cert file
17
+ --key-path PATH Path to key file
18
+ --charset CHARSET Charset of text/* files
19
+ --lang LANG Language of text/* files
20
+ ```
21
+
22
+ Or require the library to declare custom routes in Ruby.
23
+
7
24
  ```ruby
8
25
  require "gemini_server"
9
26
 
@@ -1,3 +1,3 @@
1
1
  module GeminiServer
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/gemini_server.rb CHANGED
@@ -17,7 +17,7 @@ class GeminiServer
17
17
  @views_folder = File.expand_path(options[:views_folder] || ".")
18
18
  @charset = options[:charset]
19
19
  @lang = options[:lang]
20
- @ssl_cert, @ssl_key = self.load_cert_and_key(options)
20
+ @ssl_cert, @ssl_key, @ssl_chain = self.load_cert_and_key(options)
21
21
  end
22
22
 
23
23
  def route r, &blk
@@ -28,7 +28,7 @@ class GeminiServer
28
28
  def listen host, port
29
29
  Async do
30
30
  endpoint = Async::IO::Endpoint.tcp(host, port)
31
- endpoint = Async::IO::SSLEndpoint.new(endpoint, ssl_context: self.ssl_context(@ssl_cert, @ssl_key))
31
+ endpoint = Async::IO::SSLEndpoint.new(endpoint, ssl_context: self.ssl_context(@ssl_cert, @ssl_key, @ssl_chain))
32
32
 
33
33
  ["INT", "TERM"].each do |signal|
34
34
  old_handler = Signal.trap(signal) do
@@ -151,6 +151,26 @@ class GeminiServer
151
151
  LOG_FORMAT % [ip, username || '-', Time.now.strftime("%d/%b/%Y:%H:%M:%S %z"), path, status.to_s, body_size.to_s || '-', clock_time - start_time]
152
152
  end
153
153
 
154
+ def parse_cert_and_chain input_text
155
+ # Only works in Ruby 3+
156
+ if OpenSSL::X509::Certificate.respond_to?(:load)
157
+ certs = OpenSSL::X509::Certificate.load(input_text)
158
+ return [certs.shift, certs]
159
+ end
160
+
161
+ # Fallback behavior for .pem certificates
162
+ certificate_pattern = /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
163
+ certs = input_text.scan(certificate_pattern).collect do |text|
164
+ OpenSSL::X509::Certificate.new(text)
165
+ end
166
+
167
+ # Fallback behavior if above regex yields 0 certs. E.g. with .der certs
168
+ # This won't parse any chain certs that might be present
169
+ certs = [OpenSSL::X509::Certificate.new(input_text)] if certs.empty?
170
+
171
+ [certs.shift, certs]
172
+ end
173
+
154
174
  def load_cert_and_key options
155
175
  found_cert = options[:cert] || if options[:cert_path]
156
176
  File.open(options[:cert_path]) rescue nil
@@ -167,15 +187,24 @@ class GeminiServer
167
187
  raise "SSL certificate not found" unless found_cert
168
188
  raise "SSL key not found" unless found_key
169
189
 
190
+ if found_cert.is_a?(OpenSSL::X509::Certificate)
191
+ main_cert = found_cert
192
+ chain_list = []
193
+ else
194
+ main_cert, chain_list = parse_cert_and_chain found_cert.read
195
+ end
196
+
170
197
  [
171
- found_cert.is_a?(OpenSSL::X509::Certificate) ? found_cert : OpenSSL::X509::Certificate.new(found_cert),
198
+ main_cert,
172
199
  found_key.is_a?(OpenSSL::PKey::PKey) ? found_key : OpenSSL::PKey.read(found_key),
200
+ chain_list
173
201
  ]
174
202
  end
175
203
 
176
- def ssl_context cert, key
204
+ def ssl_context cert, key, chain
177
205
  OpenSSL::SSL::SSLContext.new.tap do |context|
178
206
  context.add_certificate(cert, key)
207
+ context.extra_chain_cert = chain
179
208
  context.session_id_context = "gemini_server"
180
209
  context.min_version = OpenSSL::SSL::TLS1_2_VERSION
181
210
  context.max_version = OpenSSL::SSL::TLS1_3_VERSION
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemini_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jess Bees
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  - !ruby/object:Gem::Version
120
120
  version: '0'
121
121
  requirements: []
122
- rubygems_version: 3.1.4
122
+ rubygems_version: 3.2.32
123
123
  signing_key:
124
124
  specification_version: 4
125
125
  summary: Simple server for the Gemini protocol