ldap-auth article patch

Tom Rhodes trhodes at FreeBSD.org
Tue Nov 10 00:39:57 UTC 2009


On Mon, 9 Nov 2009 13:43:26 -0500
Toby Burress <kurin at delete.org> wrote:

> Could I trouble someone to look at docs/132839?  It's just a patch
> to the ldap-auth article.  I don't think it's very contentious.
> 
> It fixes some misinformation that the OpenLDAP guys have emailed
> me about, and want to keep from spreading.

Patch modified, please verify the original meaning by giving
my version a once over.

--- article.sgml.old     2009-03-20 00:57:22.000000000 -0400
+++ article.sgml 2009-03-20 01:03:08.000000000 -0400
@@ -307,7 +307,6 @@
         organizational unit will look like:</para>
       <programlisting>dn: ou=people,dc=example,dc=org
-objectClass: top
 objectClass: organizationalUnit
 ou: people</programlisting>
@@ -336,7 +335,6 @@
 objectClass: person
 objectClass: posixAccount
 objectClass: shadowAccount
-objectClass: top
 uidNumber: 10000
 gidNumber: 10000
 homeDirectory: /home/tuser
@@ -352,13 +350,11 @@
         user entries, but we will use the defaults below:</para>
       <programlisting>dn: ou=groups,dc=example,dc=org
-objectClass: top
 objectClass: organizationalUnit
 ou: groups
 dn: cn=tuser,ou=groups,dc=example,dc=org
 objectClass: posixGroup
-objectClass: top
 gidNumber: 10000
 cn: tuser</programlisting>
@@ -604,51 +600,74 @@
         <screen>&prompt.root; <userinput>sysctl security.bsd.see_other_uids=0</userinput>.</screen>
       </caution>
-      <para>A more flexible (and probably more secure) approach can be
-        used by writing a custom program, or even a web interface.  The
-        following is part of a <application>Ruby</application> library
-        that can change LDAP passwords.  It sees use both on the command
-        line, and on the web.</para>
+  <para>A more flexible (and probably more secure) approach can be
+        used by writing a custom program, or even a web interface.
+        The following is modeled on a <application>Python</application>
+        library that can change LDAP passwords.  It may be used on both
+        on the command line, and on the web.</para>
-      <example id="chpw-ruby">
-        <title>Ruby script for changing passwords</title>
+      <example id="chpw-python">
+        <title>Python script for changing passwords</title>
-        <programlisting><![CDATA[require 'ldap'
-require 'base64'
-require 'digest'
-require 'password' # ruby-password
-
-ldap_server = "ldap.example.org"
-luser = "uid=#{ENV['USER']},ou=people,dc=example,dc=org"
-
-# get the new password, check it, and create a salted hash from it
-def get_password
-  pwd1 = Password.get("New Password: ")
-  pwd2 = Password.get("Retype New Password: ")
-
-  raise if pwd1 != pwd2
-  pwd1.check # check password strength
-
-  salt = rand.to_s.gsub(/0\./, '')
-  pass = pwd1.to_s
-  hash = "{SSHA}"+Base64.encode64(Digest::SHA1.digest("#{pass}#{salt}")+salt).chomp!
-  return hash
-end
-
-oldp = Password.get("Old Password: ")
-newp = get_password
-
-# We'll just replace it.  That we can bind proves that we either know
-# the old password or are an admin.
-
-replace = LDAP::Mod.new(LDAP::LDAP_MOD_REPLACE | LDAP::LDAP_MOD_BVALUES,
-                        "userPassword",
-                        [newp])
-
-conn = LDAP::SSLConn.new(ldap_server, 389, true)
-conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
-conn.bind(luser, oldp)
-conn.modify(luser, [replace])]]></programlisting>
+        <programlisting><![CDATA[import ldap # python-ldap
+import os, sys
+from getpass import getpass
+
+uri = "ldap://ldap1.example.com"
+searchbase = "ou=people,dc=example,dc=com"
+filter = "(&(objectClass=posixAccount)(uid=%s))"
+
+# get the username; if none is given, use the current user
+user = os.environ['USER']
+if len(sys.argv) > 1:
+    user = sys.argv[1]
+
+ldapobj = ldap.initialize(uri)
+ldapobj.start_tls_s() # this is pretty important
+
+# Get the users DN, and then bind as that.
+# The way to do this is first bind anonymously (if you do not allow
+# anonymous binds, there's probably some standard account you use for this.
+ldapobj.simple_bind_s()
+
+# Search for a user with the uid we gave.  We search everything under
+# the "base" we configure above (as there may be other users with the same
+# UID elsewhere in the tree; we do not want to return those.
+result = ldapobj.search_s(searchbase, ldap.SCOPE_SUBTREE, filter%user)
+
+if len(result) > 1:
+    # This is kind of suspicious; we only want one user.
+    print "I found several users that match that user id."
+    print "Talk to your sysadmin."
+    sys.exit(1)
+
+# The results are an array of (dn, attrlist) tuples.
+dn = result[0][0]
+
+# Now we get the user's old password, and bind to the server with it
+# and his DN.  If it succeeds, we have the proper credentials to
+# change his password.
+passwd = getpass("current password: ")
+try:
+    ldapobj.simple_bind_s(dn, passwd)
+except ldap.INVALID_CREDENTIALS:
+    print "Bad password."
+    sys.exit(1)
+
+# Get and confirm new password.
+npass1 = 'a'
+npass2 = 'b'
+while npass1 != npass2:
+    npass1 = getpass("new password: ")
+    npass2 = getpass("new password (again): ")
+
+# This is the key.  This uses the LDAP Password Modify Extended Operation.
+# It is important to use this when you can, although not all libraries
+# (e.g.: ruby-ldap) support it.  See rfc3062.
+ldapobj.passwd_s(dn, passwd, npass1)
+
+# And we are done.
+ldapobj.unbind()]]></programlisting>
       </example>
       <para>Although not guaranteed to be free of security holes (the
@@ -759,7 +778,6 @@
           <title>Creating a management group</title>
           <programlisting>dn: cn=homemanagement,dc=example,dc=org
-objectClass: top
 objectClass: posixGroup
 cn: homemanagement
 gidNumber: 121 # required for posixGroup

Thanks,

-- 
Tom Rhodes



More information about the freebsd-doc mailing list