--- 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