Skip to content
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

Make-context #24

Merged
merged 22 commits into from
Dec 6, 2015
Merged

Make-context #24

merged 22 commits into from
Dec 6, 2015

Conversation

deadtrickster
Copy link
Contributor

Provides with-global-context macro and make-context function

Can help with problems like described here:
edicl/drakma#50

Examples:

(cl+ssl:with-global-context 
    ((cl+ssl:make-context :verify-location "/etc/ssl/certs"))
  (drakma:http-request "https://google.com" :force-ssl t))
(cl+ssl:with-global-context 
    ((cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-none+))
  (drakma:http-request "https://incomplete-chain.badssl.com/"))
(cl+ssl:with-global-context 
    ((cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-peer+))
  (drakma:http-request "https://incomplete-chain.badssl.com/"))

SSL verify error: 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
(cl+ssl:with-context 
    ((cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-peer+ :verify-callback nil))
  (drakma:http-request "https://incomplete-chain.badssl.com/"))

A failure in the SSL library occurred on handle #.(SB-SYS:INT-SAP #X7FFE6825EC40) (return code: 1).
SSL error queue:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

X509_STORE_CTX_get_error
SSL_CTX_set_default_verify_dir
SSL_CTX_set_default_verify_file
SSL_VERIFY_* constants
SSL_CTX_SET_VERIFY
SSL_SESS_CACHE_* constants
@avodonosov
Copy link
Member

After a very superficial look: I think better name instead of make-global-context would be make-context or new-context or even context

(cl+ssl:with-global-context 
    (cl+ssl:new-context :verify-mode cl+ssl::+ssl-verify-peer+ :verify-callback nil)

  ...
  )

;; or something like

(cl+ssl:with-global-context 
    (cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-peer+ :verify-callback nil)

  ...
  )

(cl+ssl:with-global-context 
    (cl+ssl:build-context :verify-mode cl+ssl::+ssl-verify-peer+ :verify-callback nil)

  ...
  )

(cl+ssl:with-global-context 
    (cl+ssl:context :verify-mode cl+ssl::+ssl-verify-peer+ :verify-callback nil)

  ...
  )

@deadtrickster
Copy link
Contributor Author

Actually it was make-context. I changed it just before creating pull request. Why?
Because *ssl-global-context* -> with-global-context -> make-global-context.

I don't think cl+ssl:(make-)context is a good name for this particular function since there is always two contexts (SSL_CTX_new and SSL_ctx). And this naming can be confusing.

@avodonosov
Copy link
Member

No no, I think you probably forgetting (due to late hour?) your original, correct, reasoning.

SSL_CTX_new and SSL_ctx are not two context. SSL_CTX_new creates new context, it can create one, two or as many contexts as we want. SSL_ctx is a slot of ssl session storing a context earlier created by SSL_CTX_new.

make-context is just a convenience wrapper around SSL_CTX_new, that's all.

@deadtrickster
Copy link
Contributor Author

yeah you are right, any other thoughts? I'll change the name right now

@deadtrickster
Copy link
Contributor Author

done!

@deadtrickster deadtrickster changed the title Make-global-context Make-context Dec 5, 2015
#:+ssl-verify-none+
#:+ssl-verify-peer+
#:+ssl-verify-fail-if-no-peer-cert+
#:+ssl-verify--client-once+
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two dashes - is it typo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@avodonosov
Copy link
Member

We will also need to document new public API in the doc (index.html)

@avodonosov
Copy link
Member

Makes sense to add ssl-ctx-free to the public API - the users who call make-context will want to free the context.

@avodonosov
Copy link
Member

@deadtrickster do you think it would be convenient to have a auto-free option in the with-global-context macro?

@deadtrickster
Copy link
Contributor Author

@avodonosov
maybe not ssl-ctx-free but

(declaim (inline free-context))
(defun free-context (context)
  (ssl-ctx-free context))

?

auto-free - why not? but only if it set to nil by default

documentation - news section is extremely outdated, as well as copyright years and holders btw :-)
I will add doc entry after ensure-initialized.

@deadtrickster deadtrickster force-pushed the make-context branch 3 times, most recently from 87a3079 to 3d37dfa Compare December 6, 2015 11:14
+ssl-verify-none+
+ssl-verify-peer+
+ssl-verify-fail-if-no-peer-cert+
:+ssl-verify-client-once+
@avodonosov
Copy link
Member

maybe not ssl-ctx-free but

(declaim (inline free-context))
(defun free-context (context)
(ssl-ctx-free context))
?

It's too much IMO.

I don't wan't to hide real OpenSSL API, and introduce our different API. I think it's better to think of cl+ssl as a plain ffi bindings to OpenSSL + some helpers.

auto-free - why not? but only if it set to nil by default

nil by default, or course, I fully agree.

I wasn't sure about auto-free because it will complicate the invocation format of with-global-context; if the cases when auto-free is used are rare - probably most users will reuse their context more than once - then the majority of cases will suffer from complicated with-global-context while not having benefits of auto-free.

documentation - news section is extremely outdated, as well as copyright years and holders btw :-)
I will add doc entry after ensure-initialized.

Thanks.

Yes, there are outdated parts, in particular I am considering to remove the news section to avoid maintenance. But not now.

@deadtrickster
Copy link
Contributor Author

I think it's better to think of cl+ssl as a plain ffi bindings to OpenSSL + some helpers.

Well given that cl+ssl implements gray streams I don't think it is plain ffi + some helpers
I'm sure coherent naming (esp without performance penalty) is way more important. If you call make-context why you should call ssl-ctx-free but not free-context?

auto-free

I played with it and you know what? It can kill you if you'll try to reuse freed context (basically on sbcl at least you are done and have to restart sbcl)! And as you rightly assume contexts indeed intended to be long-lived
Btw this is closely related to previous citation: should cl+ssl really punish its users that hard if they are trying to reuse freed contexts?

I remember when we met last time on #lisp we agreed that cl+ssl actually has two parts - plain ffi bindings and a lot of helpers ;-). Or I misunderstood something? Lets make it clear now since next step I plan is actually introduce wrapper around ssl-ctx structure with which I can at least test if it was freed, initialized or not (as I said earlier it just kills entire lisp instance in case of an error). If you think it is too much then I'll continue to contribute ffi related-stuff (there is so much to do too) but all these highlevel things will go to my separate repo.

@deadtrickster
Copy link
Contributor Author

Changed some defaults, added documentation

@deadtrickster
Copy link
Contributor Author

About #-asdf - I just googled how others do it.
I don't want to fight with you over free-context mostly because reevaluating my own use cases I returned :auto-free.

@deadtrickster
Copy link
Contributor Author

added (hopefully concise) documentation entry for with-global-context

avodonosov added a commit that referenced this pull request Dec 6, 2015
@avodonosov avodonosov merged commit 93fcdf9 into cl-plus-ssl:master Dec 6, 2015
@avodonosov
Copy link
Member

Thank you very much for new features and for being so responsive during the review.

It's a great contribution - enables many convenient use cases, while preserving backward compatibility.

@avodonosov
Copy link
Member

BTW, I forgot one important thing: do we use any new OpenSSL functions which present only in new versions of OpenSSL? (As I learned from your pull request #8, some features like verifying host/email/ip were absent in old OpenSSL and people needed to implement it themselves; later these features were added to OpenSSL). Do we now depend on some similar, newly introduced OpenSSL API?

@deadtrickster
Copy link
Contributor Author

good question. recently a lot of stuff was deprecated and unfortunately openssl usually shipped very outdated. For example tls_method introduced that effectively replaces ssl_v23_method and no_sslv2|no_sslv3 flags i.e. it allows TLS only. rsa_callback deprecated too.

Now I don't think hostname verification should rely on openssl implementation. At least until we implement reliable openssl-version dependent switches. But even with these switches there is a great possibility of subtle difference between old-lisp and new-openssl implementations.

I have battle-tested erlang implementation, I'll just backport it and cover with tests.

@avodonosov
Copy link
Member

I mean in this pull request, new functions we use, like SSL_CTX_set_verify, or the ciphers used in +default-cipher-list+ - are they backwards compatible, or they are only work with new OpenSSL? (I think unlikely, but just to check).

I have battle-tested erlang implementation [of hostname verfication], I'll just backport it and cover with tests.

Doesn't your pull request #8 provide this?

@deadtrickster
Copy link
Contributor Author

SSL_CTX_set_verify is backwards compatible. +default-cipher-list+ should be too unless openssl EXTREMELY outdated.

Yep my pull request provide this however it was tested and used by me only. While https://github.com/deadtrickster/ssl_verify_hostname.erl is widely used and therefore I can be sure in its algorithm and tests.

@avodonosov
Copy link
Member

Listen, I can't reproduce the verify-peer failure from examples in the description. Instead of the error I get normal HTTP reply:

(cl+ssl:with-global-context 
    ((cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-peer+))
  (drakma:http-request "https://incomplete-chain.badssl.com/"))

=>
"<!DOCTYPE html>
<html>
<head>
  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
  <link rel=\"shortcut icon\" href=\"/icons/favicon-orange.ico\"/>
  <link rel=\"apple-touch-icon\" href=\"/icons/icon-orange.png\"/>
  <title>incomplete-chain.badssl.com</title>
  <link rel=\"stylesheet\" href=\"/style.css\">
  <style>body { background: rgb(243, 121, 46); }</style>
</head>
<body>
<div id=\"content\">
  <h1 style=\"font-size: 8vw;\">
    incomplete-chain.<br>badssl.com
  </h1>
</div>

</body>
</html>
"
200
((:SERVER . "nginx/1.6.2 (Ubuntu)") (:DATE . "Sun, 06 Dec 2015 23:43:37 GMT") (:CONTENT-TYPE . "text/html") (:CONTENT-LENGTH . "506") (:LAST-MODIFIED . "Fri, 04 Dec 2015 02:46:28 GMT") (:CONNECTION . "close") (:ETAG . "\"5660fe84-1fa\"") (:CACHE-CONTROL . "no-store") (:ACCEPT-RANGES . "bytes"))
#<URI https://incomplete-chain.badssl.com/>
#<FLEXI-STREAMS:FLEXI-IO-STREAM #x302002FCD07D>
T
"OK"

@avodonosov
Copy link
Member

I am trying on quicklisp 2015-09-24, CCL 1.9 on linux.

@deadtrickster
Copy link
Contributor Author

Hmm at first I was thinking about my drakma patches, but:

(cl+ssl:with-global-context 
 ((cl+ssl:make-context :verify-mode cl+ssl::+ssl-verify-peer+))
 (usocket:with-client-socket (socket stream "incomplete-chain.badssl.com" 443
                                     :element-type '(unsigned-byte 8))
                             (let* ((ssl-stream (cl+ssl:make-ssl-client-stream stream
                                                                               :hostname  "incomplete-chain.badssl.com"))
                                    (char-stream (flexi-streams:make-flexi-stream ssl-stream
                                                                                  :external-format '(:utf-8 :eol-style :crlf)))
                                    (reply-buf (make-string 1000)))
                               (unwind-protect
                                   (progn
                                     (format char-stream "GET / HTTP/1.1~%")
                                     (format char-stream "Host: incomplete-chain.badssl.com~%~%")
                                     (finish-output char-stream)
                                     (read-sequence reply-buf char-stream)
                                     reply-buf)
                                 (close ssl-stream)))))

also signals

SSL verify error: 20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

sbcl 1.3.1 on linux too

@avodonosov
Copy link
Member

This usocket example behaves the same for me

@deadtrickster
Copy link
Contributor Author

ok let me install ccl too

@avodonosov
Copy link
Member

By "the same" I mean signals failre - "the same" as your result

@avodonosov
Copy link
Member

Only the drakma example differs - doesn't fail

@deadtrickster
Copy link
Contributor Author

oh thank you :-) so looks like drakma issue. lets dive deeper into this when hostname verification merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants