lassik / scheme-gemini

Scheme library for the Gemini network protocol
ISC License
3 stars 2 forks source link

Buggy addresses #1

Open snan opened 2 years ago

snan commented 2 years ago
(gemini-get "gemini://clemat.is/gemlog/[2022-04-25]..macOS.10.yr.later..gmi" identity)                                             

Error: (URI-scheme) bad argument type - not a structure of the required type                                                             
#f                                                                                                                                       
uri-generic#<URI>   

(gemini-get "gemini://gemini.ucant.org" identity)                                                                                  

Error: (ssl-do-handshake) syscall: library=<unknown>, function=<unknown>, reason=<unknown> 
wasamasa commented 2 years ago

The first URL needs percent encoding of the square brackets. They are not permitted characters in the query part, therefore uri-generic fails to return a URI object.

The second URL points to a server only supporting TLSv1.3, whereas this library defaults to TLSv1.2. According to the Gemini spec, the library should try both TLSv1.2 and TLSv1.3. Since TLSv1.3 support cannot be assumed in OpenSSL, the library needs to be amended as follows:

For example a sensible logic would be to raise an error if TLSv1.2 is not supported, try connecting with both TLSv1.2 and TLSv1.3 if TLSv1.3 is supported and otherwise connect with TLSv1.3. A more implicit approach would be assuming that OpenSSL always supports TLSv1.2 and specifying (cons 'tlsv1.2 ssl-max-protocol).

Alternatively the library could ignore this since the spec mandates TLSv1.2 support.

lassik commented 2 years ago

Thanks for looking into this.

With the following standalone script test.scm:

(import (only (scheme base) read-line write-string)
        (chicken condition)
        (chicken process-context)
        (openssl)
        (uri-generic))

(define (disp . args) (for-each display args) (newline))

(define read-response read-line)

(define (write-request to-server uri-string)
  (write-string (string-append uri-string "\r\n")
                to-server))

(define (try-using protocol uri)
  (let* ((uri-object (uri-reference uri))
         (uri-string (if (string? uri) uri (uri->string uri-object))))
    (disp "Trying " protocol " on " uri)
    (handle-exceptions err (disp "Error: " err)
      (receive (from-server to-server)
          (ssl-connect* hostname: (uri-host uri-object)
                        port: (or (uri-port uri-object) 1965)
                        protocol: (cons protocol
                                        protocol)
                        verify?: #f)
        (dynamic-wind (lambda () #f)
                      (lambda ()
                        (write-request to-server uri-string)
                        (read-response from-server))
                      (lambda ()
                        (close-input-port from-server)
                        (close-output-port to-server)))
        (disp "OK")))
    (disp)))

(define (try uri)
  (try-using 'tlsv12 uri)
  (try-using ssl-max-protocol uri))

(for-each try (command-line-arguments))

I get:

$ csi -script test.scm gemini://jsreed5.org/log/2022/202204/20220426-twitter-a-few-unsorted-thoughts.gmi
Trying tlsv12 on gemini://jsreed5.org/log/2022/202204/20220426-twitter-a-few-unsorted-thoughts.gmi
OK

Trying tlsv13 on gemini://jsreed5.org/log/2022/202204/20220426-twitter-a-few-unsorted-thoughts.gmi
OK
$ csi -script test.scm gemini://gemini.ucant.org
Trying tlsv12 on gemini://gemini.ucant.org
Error: #<condition: (exn i/o net openssl)>

Trying tlsv13 on gemini://gemini.ucant.org
OK
$ csi -script test.scm gemini://clemat.is/gemlog/%5b2022-04-25%5d..macOS.10.yr.later..gmi
Trying tlsv12 on gemini://clemat.is/gemlog/%5b2022-04-25%5d..macOS.10.yr.later..gmi
Error: #<condition: (exn i/o net)>

Trying tlsv13 on gemini://clemat.is/gemlog/%5b2022-04-25%5d..macOS.10.yr.later..gmi
Error: #<condition: (exn i/o net)>

The last of the above URLs timeouts.