Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Extract user names
  • Loading branch information
Stephen Clayton committed May 10, 2017
1 parent 88c4e9b commit 4fb20a7
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 56 deletions.
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -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)

103 changes: 47 additions & 56 deletions src/main/clojure/de/mpg/shh/util_ldap/ldap.clj
Expand Up @@ -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))))

0 comments on commit 4fb20a7

Please sign in to comment.