--- 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:
dn: ou=people,dc=example,dc=org
-objectClass: top
objectClass: organizationalUnit
ou: people
@@ -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:
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
@@ -604,51 +600,74 @@
&prompt.root; sysctl security.bsd.see_other_uids=0.
- 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 Ruby library
- that can change LDAP passwords. It sees use both on the command
- line, and on the web.
+ 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 Python
+ library that can change LDAP passwords. It sees use both
+ on the command line, and on the web.
-
- Ruby script for changing passwords
+
+ Python script for changing passwords
-
+ 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 don't allow anon
+# 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 don't 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, he (and 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're done.
+ldapobj.unbind()]]>
Although not guaranteed to be free of security holes (the
@@ -759,7 +778,6 @@
Creating a management group
dn: cn=homemanagement,dc=example,dc=org
-objectClass: top
objectClass: posixGroup
cn: homemanagement
gidNumber: 121 # required for posixGroup