X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=userdir_ldap.py;h=f60b715b858476d8d5642dec55f00dd1c8d392a8;hb=8bedb26f6cfb5410fdfee34a78ff4644f6d5ced0;hp=0ea96a9571cc9ded039aab066544309236e29c30;hpb=a86d975ac15e074f142c75ba5c74596be92e740d;p=mirror%2Fuserdir-ldap.git diff --git a/userdir_ldap.py b/userdir_ldap.py index 0ea96a9..f60b715 100644 --- a/userdir_ldap.py +++ b/userdir_ldap.py @@ -1,5 +1,24 @@ +# Copyright (c) 1999-2000 Jason Gunthorpe +# Copyright (c) 2001-2003 Ryan Murray +# Copyright (c) 2004 Joey Schulze +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + # Some routines and configuration that are used by the ldap progams -import termios, TERMIOS, re, string, imp, ldap, sys, whrandom, crypt, rfc822; +import termios, re, string, imp, ldap, sys, whrandom, crypt, rfc822; +import userdir_gpg try: File = open("/etc/userdir-ldap/userdir-ldap.conf"); @@ -10,7 +29,7 @@ File.close(); # Cheap hack BaseDn = ConfModule.basedn; -BaseDn = ConfModule.basedn; +HostBaseDn = ConfModule.hostbasedn; LDAPServer = ConfModule.ldaphost; EmailAppend = ConfModule.emailappend; AdminUser = ConfModule.adminuser; @@ -22,12 +41,19 @@ PassDir = ConfModule.passdir; Ech_ErrorLog = ConfModule.ech_errorlog; Ech_MainLog = ConfModule.ech_mainlog; +# Break up the keyring list +userdir_gpg.SetKeyrings(string.split(ConfModule.keyrings,":")); + # This is a list of common last-name prefixes -LastNamesPre = {"van": None, "le": None, "de": None, "di": None}; +LastNamesPre = {"van": None, "von": None, "le": None, "de": None, "di": None}; + +# This is a list of common groups on Debian hosts +DebianGroups = {"Debian": 800, "guest": 60000} # SSH Key splitting. The result is: # (options,size,modulous,exponent,comment) SSHAuthSplit = re.compile('^(.* )?(\d+) (\d+) (\d+) ?(.+)$'); +SSH2AuthSplit = re.compile('^(.* )?ssh-(dss|rsa) ([a-zA-Z0-9=/+]+) ?(.+)$'); #'^([^\d](?:[^ "]+(?:".*")?)*)? ?(\d+) (\d+) (\d+) (.+)$'); AddressSplit = re.compile("(.*).*<([^@]*)@([^>]*)>"); @@ -65,19 +91,49 @@ def PrettyShow(DnRecord): # Function to prompt for a password def getpass(prompt = "Password: "): - import termios, TERMIOS, sys; + import termios, sys; fd = sys.stdin.fileno(); old = termios.tcgetattr(fd); new = termios.tcgetattr(fd); - new[3] = new[3] & ~TERMIOS.ECHO; # lflags + new[3] = new[3] & ~termios.ECHO; # lflags try: - termios.tcsetattr(fd, TERMIOS.TCSADRAIN, new); - passwd = raw_input(prompt); + termios.tcsetattr(fd, termios.TCSADRAIN, new); + try: + passwd = raw_input(prompt); + except KeyboardInterrupt: + termios.tcsetattr(fd, termios.TCSADRAIN, old); + print + sys.exit(0) + except EOFError: + passwd = "" finally: - termios.tcsetattr(fd, TERMIOS.TCSADRAIN, old); + termios.tcsetattr(fd, termios.TCSADRAIN, old); print; return passwd; +def passwdAccessLDAP(LDAPServer, BaseDn, AdminUser): + """ + Ask for the AdminUser's password and connect to the LDAP server. + Returns the connection handle. + """ + print "Accessing LDAP directory as '" + AdminUser + "'"; + while (1): + Password = getpass(AdminUser + "'s password: "); + + if len(Password) == 0: + sys.exit(0) + + l = ldap.open(LDAPServer); + UserDn = "uid=" + AdminUser + "," + BaseDn; + + # Connect to the ldap server + try: + l.simple_bind_s(UserDn,Password); + except ldap.INVALID_CREDENTIALS: + continue + break + return l + # Split up a name into multiple components. This tries to best guess how # to split up a name def NameSplit(Name): @@ -133,7 +189,7 @@ def GenPass(): SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/."; Rand = open("/dev/urandom"); Password = ""; - for i in range(0,10): + for i in range(0,15): Password = Password + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)]; return Password; @@ -141,10 +197,11 @@ def GenPass(): def HashPass(Password): # Hash it telling glibc to use the MD5 algorithm - if you dont have # glibc then just change Salt = "$1$" to Salt = ""; - SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/."; + SaltVals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; Salt = "$1$"; + Rand = open("/dev/urandom"); for x in range(0,10): - Salt = Salt + SaltVals[whrandom.randint(0,len(SaltVals)-1)]; + Salt = Salt + SaltVals[ord(Rand.read(1)[0]) % len(SaltVals)]; Pass = crypt.crypt(Password,Salt); if len(Pass) < 14: raise "Password Error", "MD5 password hashing failed, not changing the password!"; @@ -180,7 +237,7 @@ def FlushOutstanding(l,Outstanding,Fast=0): # Convert a lat/long attribute into Decimal degrees def DecDegree(Posn,Anon=0): - Parts = re.match('[+-]?(\d*)\\.?(\d*)?',Posn).groups(); + Parts = re.match('[-+]?(\d*)\\.?(\d*)',Posn).groups(); Val = string.atof(Posn); if (abs(Val) >= 1806060.0): @@ -208,10 +265,20 @@ def DecDegree(Posn,Anon=0): return "+" + Str; return Str; +def FormatSSH2Auth(Str): + Match = SSH2AuthSplit.match(Str); + if Match == None: + return ""; + G = Match.groups(); + + if G[0] == None: + return "ssh-%s %s..%s %s"%(G[1],G[2][:8],G[2][-8:],G[3]); + return "%s ssh-%s %s..%s %s"%(G[0],G[1],G[2][:8],G[2][-8:],G[3]); + def FormatSSHAuth(Str): Match = SSHAuthSplit.match(Str); if Match == None: - return ""; + return FormatSSH2Auth(Str); G = Match.groups(); # No options @@ -246,6 +313,10 @@ def FormatPGPKey(Str): # Take an email address and split it into 3 parts, (Name,UID,Domain) def SplitEmail(Addr): + # Is not an email address at all + if string.find(Addr,'@') == -1: + return (Addr,"",""); + Res1 = rfc822.AddrlistClass(Addr).getaddress(); if len(Res1) != 1: return ("","",Addr); @@ -285,6 +356,11 @@ def GetUID(l,Name,UnknownMap = {}): Stat = "unknown map hit for"+str(Name); return (UnknownMap[Name[2]],[Stat]); + # Then the name component (another ie there was no email address to match) + if UnknownMap.has_key(Name[0]): + Stat = "unknown map hit for"+str(Name); + return (UnknownMap[Name[0]],[Stat]); + # Search for a possible first/last name hit try: Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"(&(cn=%s)(sn=%s))"%(cn,sn),["uid"]); @@ -331,4 +407,9 @@ def GetUID(l,Name,UnknownMap = {}): return (None,None); - +def Group2GID(name): + """Returns the numerical id of a common group""" + for g in DebianGroups.keys(): + if name == g: + return DebianGroups[g] + return name