Date: Mon, 9 Nov 2009 19:39:52 -0500 From: Tom Rhodes <trhodes@FreeBSD.org> To: Toby Burress <kurin@delete.org> Cc: freebsd-doc@FreeBSD.org Subject: Re: ldap-auth article patch Message-ID: <20091109193952.1b8f790e.trhodes@FreeBSD.org> In-Reply-To: <20091109184326.GG67127@lithium.delete.org> References: <20091109184326.GG67127@lithium.delete.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 9 Nov 2009 13:43:26 -0500 Toby Burress <kurin@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20091109193952.1b8f790e.trhodes>