From 4fb20a74bd7506b80af48842a8d07cedc181a499 Mon Sep 17 00:00:00 2001 From: Stephen Clayton Date: Wed, 10 May 2017 11:33:47 +0200 Subject: [PATCH] Extract user names --- README.md | 5 + .../clojure/de/mpg/shh/util_ldap/ldap.clj | 103 ++++++++---------- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index e22574f..523cb1a 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,8 @@ cat dev-resources/shh-auth.properties ldap.host = myserver.mpg.de ldap.port = 389 ``` + +This uses the java library: + +[[com.novell.ldap/jldap "2009-10-07"]](https://www.novell.com/documentation/developer/jldap/jldapenu/api/com/novell/ldap/package-summary.html) + diff --git a/src/main/clojure/de/mpg/shh/util_ldap/ldap.clj b/src/main/clojure/de/mpg/shh/util_ldap/ldap.clj index 2215391..078d21c 100644 --- a/src/main/clojure/de/mpg/shh/util_ldap/ldap.clj +++ b/src/main/clojure/de/mpg/shh/util_ldap/ldap.clj @@ -46,75 +46,66 @@ (error e "Failed to authenticate" username) false)))) -(defn url->connection - [^Hashtable connections url] - (let [ldap-url (LDAPUrl. url) - conn-id (str/join ":" [(.getHost ldap-url) (.getPort ldap-url)])] - (when (.containsKey connections conn-id) - (.get connections conn-id)))) - -(defn connect - [conn constraints username password ldap-url old-conn] - (try - (let [_ (println "connect using ldap-url: " ldap-url) - _ (.connect conn (.getHost ldap-url) (.getPort ldap-url)) - _ (when (.isTLS old-conn) (.startTLS conn)) - _ (when (.isBound old-conn) (.bind conn (.getProtocolVersion old-conn) username (.getBytes password) constraints))] - (println "bound new conn") - conn) - (catch Exception e - (println "exception on rebind:" (stack-trace-to-string e))))) - -;; https://www.novell.com/documentation/developer/samplecode/jldap_sample/ -(defn ldap-bind-handler - [username password] - (let [connections (Hashtable.)] - (reify LDAPBindHandler - (^LDAPConnection bind [this #^"[Ljava.lang.String;" urls ^LDAPConnection conn] - (let [_ (println "called ldap-bind-handler") - conn-id (str/join ":" [(.getHost conn) (.getPort conn)]) - _ (println "conn-id: " conn-id) - _ (when (nil? (.get connections conn-id)) - (.put connections conn-id conn))] - (if-let [existing-conn (first (remove nil? (map (partial url->connection connections) (seq urls))))] - (println "found existing conn") - (let [_ (println "no existing conn found") - new-constraints (doto (.getSearchConstraints conn) - (.setReferralFollowing false)) - new-conn (doto (LDAPConnection. (.getSocketFactory conn)) - (.setConstraints new-constraints))] - (loop [ldap-urls (map #(LDAPUrl. %) urls)] - (if (empty? ldap-urls) - (throw (LDAPException.)) - (if-let [bound-conn (connect new-conn new-constraints username password (first ldap-urls) conn)] - bound-conn - (recur (rest ldap-urls)))))))))))) - (defn ldap-entry-iterator [ldap-result] (reify java.util.Iterator (hasNext [this] (.hasMore ldap-result)) (next [this] (.next ldap-result)))) -(defn users - "Attempt to retrieve Active Directory users" +(defn ldap-entry->map + [ldap-entry] + {:name (.getName ldap-entry) + :values (vec (.getStringValueArray ldap-entry))}) + +(defn filter-user + [maybe-user-entry] + (when-let [m (re-matches #"^(.*),ou=dag,dc=shh,dc=mpg,dc=de$" (str/lower-case (:dn maybe-user-entry)))] + (and (not (empty? (->> (:attrs maybe-user-entry) + (filter (comp #(= % "sn") :name)) + (remove (comp #(= (str/lower-case %) "dag") first :values))))) + (= (count m) 2) + (empty? (filter #(str/starts-with? % "ou=") (-> m second str/lower-case (str/split #","))))))) + +(defn extract-user + [user-entry] + (let [full-name (->> (:attrs user-entry) + (filter (comp #(= % "cn") :name)) + (map :values) + ffirst) + name-parts (str/split full-name #" ") + short-name (->> (:attrs user-entry) + (filter (comp #(= % "sn") :name)) + (map :values) + ffirst)] + {:full-name full-name + :first-name (first name-parts) + :last-name (str/join " " (rest name-parts)) + :short-name short-name})) + +(defn user-entries + "Get user ldap entries" [username password] (let [ldap-conn (LDAPConnection. (LDAPJSSEStartTLSFactory.)) - ldap-bind (ldap-bind-handler username password) - search-constraints (doto (LDAPConstraints.) (.setReferralFollowing true) (.setReferralHandler ldap-bind))] + search-constraints (LDAPConstraints.)] (try (let [ldap-result (-> (doto ldap-conn (.setConstraints search-constraints) (.connect ldap-host ldap-port) (.startTLS) (.bind LDAPConnection/LDAP_V3 username (.getBytes password))) - (.search "dc=shh,dc=mpg,dc=de" LDAPConnection/SCOPE_SUB "(objectclass=user)" user-attributes false))] - ;;(for [ldap-entry (iterator-seq (ldap-entry-iterator ldap-result))] - ;;{:dn ldap-entry;;(.getDN ldap-entry) - ;; :attrs :foo;;(.getAttributeSet ldap-entry) - ;; }) - ;;ldap-result - (first (iterator-seq (ldap-entry-iterator ldap-result))) - ) + (.search "ou=dag,dc=shh,dc=mpg,dc=de" LDAPConnection/SCOPE_SUB "(objectclass=user)" user-attributes false))] + (for [ldap-entry (iterator-seq (ldap-entry-iterator ldap-result))] + (let [attributes (-> ldap-entry + (.getAttributeSet) + (.iterator) + (iterator-seq))] + {:dn (.getDN ldap-entry) + :attrs (vec (map ldap-entry->map attributes))}))) (catch Exception e (error e "Failed to authenticate" username))))) + +(defn users + "Attempt to retrieve Active Directory users" + [username password] + (map extract-user (filter filter-user (user-entries username password)))) +