diff --git a/project.clj b/project.clj index 487b7efe..7606e4f6 100644 --- a/project.clj +++ b/project.clj @@ -18,4 +18,6 @@ :integration :integration :all (constantly true)} :aliases {"all" ["with-profile" "dev,1.2:dev,1.3:dev:1.5,dev"]} - :checksum-deps true) + :checksum-deps true + :aot [clj-http.lite.NoDHSocketFactory] + ) diff --git a/src/clj_http/lite/NoDHSocketFactory.clj b/src/clj_http/lite/NoDHSocketFactory.clj new file mode 100644 index 00000000..63ce1b78 --- /dev/null +++ b/src/clj_http/lite/NoDHSocketFactory.clj @@ -0,0 +1,35 @@ +(ns clj-http.lite.NoDHSocketFactory + (:import (javax.net.ssl SSLSocket SSLSocketFactory) + (java.net Socket)) + (:gen-class + :name clj-http.lite.NoDHSocketFactory + :extends javax.net.ssl.SSLSocketFactory + :init init + :state state + :constructors {[javax.net.ssl.SSLSocketFactory] []})) + +(defn strip-dh-suites + "Remove cipher suites containing 'DH'" + [suites] + (into-array String (filter #(not (or (re-find #"_DHE_" %) + (re-find #"_DH_" %) + (re-find #"_ECDH_" %) + (re-find #"_ECDHE_" %))) suites))) + +(defn -init + [^SSLSocketFactory f] + (let [state {:factory f + :enabled-ciphers (strip-dh-suites (.getSupportedCipherSuites f))}] + + [[] (atom state)])) + +(defn -createSocket [this & args] + (doto + (apply (partial (memfn createSocket) (:factory @(.state this))) args) + (.setEnabledCipherSuites (:enabled-ciphers @(.state this))))) + +(defn -getDefaultCipherSuites [this] + (strip-dh-suites (.getDefaultCipherSuites (:factory @(.state this))))) + +(defn -getSupportedCipherSuites [this] + (strip-dh-suites (.getSupportedCipherSuites (:factory @(.state this))))) diff --git a/src/clj_http/lite/core.clj b/src/clj_http/lite/core.clj index b0c73b42..4fa06222 100644 --- a/src/clj_http/lite/core.clj +++ b/src/clj_http/lite/core.clj @@ -2,7 +2,9 @@ "Core HTTP request/response implementation." (:require [clojure.java.io :as io]) (:import (java.io ByteArrayOutputStream InputStream IOException) - (java.net URI URL HttpURLConnection))) + (java.net URI URL HttpURLConnection) + (javax.net.ssl HttpsURLConnection) + (clj-http.lite NoDHSocketFactory))) (defn parse-headers "Takes a URLConnection and returns a map of names to values. @@ -39,6 +41,17 @@ (.flush baos) (.toByteArray baos))))) +(defn- get-connection [^URL url] + "Wrap .openConnection to " + (let [conn (.openConnection url)] + (if (instance? HttpsURLConnection conn) + (doto conn + (.setSSLSocketFactory + (NoDHSocketFactory. + (.getSSLSocketFactory conn)))) + conn))) + + (defn request "Executes the HTTP request corresponding to the given Ring request map and returns the Ring response map corresponding to the resulting HTTP response. @@ -52,7 +65,7 @@ (when server-port (str ":" server-port)) uri (when query-string (str "?" query-string))) - conn (.openConnection ^URL (URL. http-url))] + conn (get-connection ^URL (URL. http-url))] (when (and content-type character-encoding) (.setRequestProperty conn "Content-Type" (str content-type "; charset="