added ssl-set-verify-hostname!
This commit is contained in:
parent
1c0e08f0a6
commit
5cdb967251
|
@ -41,6 +41,7 @@
|
|||
|
||||
ssl-set-verify!
|
||||
ssl-try-verify!
|
||||
ssl-set-verify-hostname!
|
||||
|
||||
ssl-peer-verified?
|
||||
ssl-peer-certificate-hostnames
|
||||
|
@ -300,7 +301,7 @@
|
|||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Structs
|
||||
|
||||
(define-struct ssl-context (ctx))
|
||||
(define-struct ssl-context (ctx [verify-hostname? #:mutable]))
|
||||
(define-struct (ssl-client-context ssl-context) ())
|
||||
(define-struct (ssl-server-context ssl-context) ())
|
||||
|
||||
|
@ -391,7 +392,7 @@
|
|||
(SSL_CTX_set_mode ctx (bitwise-ior SSL_MODE_ENABLE_PARTIAL_WRITE
|
||||
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
|
||||
(register-finalizer ctx (lambda (v) (SSL_CTX_free v)))
|
||||
((if client? make-ssl-client-context make-ssl-server-context) ctx)))))
|
||||
((if client? make-ssl-client-context make-ssl-server-context) ctx #f)))))
|
||||
|
||||
(define (ssl-make-client-context [protocol-symbol default-encrypt])
|
||||
(make-context 'ssl-make-client-context protocol-symbol "" #t))
|
||||
|
@ -469,6 +470,13 @@
|
|||
(if asn1? SSL_FILETYPE_ASN1 SSL_FILETYPE_PEM)))
|
||||
ssl-context-or-listener pathname))
|
||||
|
||||
(define (ssl-set-verify-hostname! ssl-context on?)
|
||||
(unless (ssl-context? ssl-context)
|
||||
(raise-argument-error 'ssl-set-verify-hostname!
|
||||
"(or/c ssl-client-context? ssl-server-context?)"
|
||||
ssl-context))
|
||||
(set-ssl-context-verify-hostname?! ssl-context (and on? #t)))
|
||||
|
||||
(define (ssl-try-verify! ssl-context-or-listener-or-port on?)
|
||||
(do-ssl-set-verify! ssl-context-or-listener-or-port on?
|
||||
'ssl-try-verify!
|
||||
|
@ -965,8 +973,11 @@
|
|||
#:mode [mode 'connect]
|
||||
#:close-original? [close-original? #f]
|
||||
#:shutdown-on-close? [shutdown-on-close? #f]
|
||||
#:error/ssl [error/ssl error])
|
||||
(wrap-ports 'port->ssl-ports i o (or context encrypt) mode close-original? shutdown-on-close? error/ssl))
|
||||
#:error/ssl [error/ssl error]
|
||||
#:hostname [hostname #f])
|
||||
(wrap-ports 'port->ssl-ports i o (or context encrypt) mode
|
||||
close-original? shutdown-on-close? error/ssl
|
||||
hostname))
|
||||
|
||||
(define (create-ssl who context-or-encrypt-method connect/accept error/ssl)
|
||||
(atomically ; so we register the finalizer (and it's ok since everything is non-blocking)
|
||||
|
@ -1023,14 +1034,22 @@
|
|||
;; Return SSL and the cancel boxL:
|
||||
(values ssl cancel r-bio w-bio connect?)))))))))
|
||||
|
||||
(define (wrap-ports who i o context-or-encrypt-method connect/accept close? shutdown-on-close? error/ssl)
|
||||
(define (wrap-ports who i o context-or-encrypt-method connect/accept
|
||||
close? shutdown-on-close? error/ssl
|
||||
hostname)
|
||||
(unless (input-port? i)
|
||||
(raise-argument-error who "input-port?" i))
|
||||
(unless (output-port? o)
|
||||
(raise-argument-error who "output-port?" o))
|
||||
(unless (or (string? hostname) (eq? hostname #f))
|
||||
(raise-argument-error who "(or/c string? #f)" hostname))
|
||||
;; Create the SSL connection:
|
||||
(let-values ([(ssl cancel r-bio w-bio connect?)
|
||||
(create-ssl who context-or-encrypt-method connect/accept error/ssl)])
|
||||
(create-ssl who context-or-encrypt-method connect/accept error/ssl)]
|
||||
[(verify-hostname?)
|
||||
(cond [(ssl-context? context-or-encrypt-method)
|
||||
(ssl-context-verify-hostname? context-or-encrypt-method)]
|
||||
[else #f])])
|
||||
;; connect/accept:
|
||||
(let-values ([(buffer) (make-bytes BUFFER-SIZE)]
|
||||
[(pipe-r pipe-w) (make-pipe)]
|
||||
|
@ -1064,6 +1083,13 @@
|
|||
(error/ssl who "~a failed ~a"
|
||||
(if connect? "connect" "accept")
|
||||
estr)]))))))
|
||||
(when verify-hostname?
|
||||
(unless hostname
|
||||
(error/ssl who "~a failed (hostname not provided for verification)"
|
||||
(if connect? "connect" "accept")))
|
||||
(unless (hostname-in-cert? (SSL_get_peer_certificate ssl))
|
||||
(error/ssl who "~a failed (certificate not valid for hostname)"
|
||||
(if connect? "connect" "accept"))))
|
||||
;; Connection complete; make ports
|
||||
(values (register (make-ssl-input-port mzssl) mzssl #t)
|
||||
(register (make-ssl-output-port mzssl) mzssl #f))))))
|
||||
|
@ -1243,7 +1269,7 @@
|
|||
(close-input-port i)
|
||||
(close-output-port o)
|
||||
(raise exn))])
|
||||
(wrap-ports who i o (ssl-listener-mzctx ssl-listener) 'accept #t #f error/network))))
|
||||
(wrap-ports who i o (ssl-listener-mzctx ssl-listener) 'accept #t #f error/network #f))))
|
||||
|
||||
(define (ssl-accept ssl-listener)
|
||||
(do-ssl-accept 'ssl-accept tcp-accept ssl-listener))
|
||||
|
@ -1261,7 +1287,8 @@
|
|||
(close-input-port i)
|
||||
(close-output-port o)
|
||||
(raise exn))])
|
||||
(wrap-ports who i o client-context-or-protocol-symbol 'connect #t #f error/network))))
|
||||
(wrap-ports who i o client-context-or-protocol-symbol 'connect #t #f error/network
|
||||
hostname))))
|
||||
|
||||
(define (ssl-connect
|
||||
hostname port-k
|
||||
|
|
|
@ -68,6 +68,10 @@ details (including the meanings of the protocol symbols).
|
|||
Closing the resulting output port does not send a shutdown message to
|
||||
the server. See also @racket[ports->ssl-ports].
|
||||
|
||||
If hostname verification is enabled (see
|
||||
@racket[ssl-set-verify-hostname!]), the peer's certificate is checked
|
||||
against @racket[hostname].
|
||||
|
||||
@;{
|
||||
See `enforce-retry?' in "mzssl.rkt", currently set to #f so that this
|
||||
paragraph does not apply:
|
||||
|
@ -230,7 +234,8 @@ Returns @racket[#t] if @racket[v] is a value produced by
|
|||
[#:encrypt protocol symbol? 'sslv2-or-v3]
|
||||
[#:close-original? close-original? boolean? #f]
|
||||
[#:shutdown-on-close? shutdown-on-close? boolean? #f]
|
||||
[#:error/ssl error procedure? error])
|
||||
[#:error/ssl error procedure? error]
|
||||
[#:hostname hostname (or/c string? #f) #f])
|
||||
(values input-port? output-port?)]{
|
||||
|
||||
Returns two values---an input port and an output port---that
|
||||
|
@ -275,7 +280,12 @@ communication errors. The default is @racket[error], which raises
|
|||
@racket[exn:fail:network].
|
||||
|
||||
See also @racket[ssl-connect] about the limitations of reading and
|
||||
writing to an SSL connection (i.e., one direction at a time).}
|
||||
writing to an SSL connection (i.e., one direction at a time).
|
||||
|
||||
If hostname verification is enabled (see
|
||||
@racket[ssl-set-verify-hostname!]), the peer's certificate is checked
|
||||
against @racket[hostname].
|
||||
}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
|
@ -360,7 +370,7 @@ collection for testing purposes where the peer identifies itself using
|
|||
@defproc[(ssl-set-verify! [clp (or/c ssl-client-context? ssl-server-context?
|
||||
ssl-listener?
|
||||
ssl-port?)]
|
||||
[on? any/c]) void]{
|
||||
[on? any/c]) void?]{
|
||||
|
||||
Requires certificate verification on the peer SSL connection when
|
||||
@racket[on?] is @racket[#t]. If @racket[clp] is an SSL port, then the
|
||||
|
@ -371,13 +381,19 @@ subsequent connection using the context or listener.
|
|||
|
||||
Enabling verification also requires, at a minimum, designating trusted
|
||||
certificate authorities with
|
||||
@racket[ssl-load-verify-root-certificates!].}
|
||||
@racket[ssl-load-verify-root-certificates!].
|
||||
|
||||
Verifying the certificate is not sufficient to prevent attacks by
|
||||
active adversaries, such as
|
||||
@hyperlink["http://en.wikipedia.org/wiki/Man-in-the-middle_attack"]{man-in-the-middle
|
||||
attacks}. See also @racket[ssl-set-verify-hostname!].
|
||||
}
|
||||
|
||||
|
||||
@defproc[(ssl-try-verify! [clp (or/c ssl-client-context? ssl-server-context?
|
||||
ssl-listener?
|
||||
ssl-port?)]
|
||||
[on? any/c]) void]{
|
||||
[on? any/c]) void?]{
|
||||
|
||||
Like @racket[ssl-set-verify!], but when peer certificate verification fails,
|
||||
then connection continues to work. Use @racket[ssl-peer-verified?] to determine
|
||||
|
@ -389,6 +405,23 @@ whether verification succeeded.}
|
|||
Returns @racket[#t] if the peer of SSL port @racket[p] has presented a
|
||||
valid and verified certificate, @racket[#f] otherwise.}
|
||||
|
||||
@defproc[(ssl-set-verify-hostname! [ctx (or/c ssl-client-context? ssl-server-context?)]
|
||||
[on? any/c])
|
||||
void?]{
|
||||
|
||||
Requires hostname verification of SSL peers of connections made using
|
||||
@racket[ctx] when @racket[on?] is @racket[#t]. When hostname
|
||||
verification is enabled, the hostname associated with a connection
|
||||
(see @racket[ssl-connect] or @racket[ports->ssl-ports]) is checked
|
||||
against the hostnames listed in the peer's certificate. If the peer
|
||||
certificate does not contain an entry matching the hostname, or if the
|
||||
peer does not present a certificate, the connection is rejected and an
|
||||
exception is raised.
|
||||
|
||||
Hostname verification does not imply certificate verification. To
|
||||
verify the certificate itself, also call @racket[ssl-set-verify!].
|
||||
}
|
||||
|
||||
@defproc[(ssl-peer-certificate-hostnames [p ssl-port?])
|
||||
(listof string?)]{
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user