
ce script permet de manipuler aisment les hash des mots de passes tels qu'ils sont dans une base LDAP Il est compatible avec lapluspart des types de scryptages de mots de passes, en tout cas, il est suffisant pour nous (on utilise du SSHA, et du crypt pour les vieux mots de passe. darcs-hash:20060427235303-4ec08-2d948c8fd2ab3c91d618ad272327ed1089bca278.gz
141 lines
4.9 KiB
Python
141 lines
4.9 KiB
Python
# -*- coding: iso8859-15 -*-
|
|
###############################################################################
|
|
# ldap_passwd.py : manipulation des mots de passes LDAP
|
|
# $Id: ldap_passwd.py,v 1.1 2006-04-27 23:53:03 chove Exp $
|
|
###############################################################################
|
|
# The authors of this code are
|
|
# Bjorn Ove Grotan <bgrotan@grotan.com>
|
|
# Etienne Chové <etienne.chove@crans.org>
|
|
#
|
|
# Copyright (C) 2005 Bjorn Ove Grotan
|
|
# Copyright (C) 2006 Etienne Chové
|
|
# All rights reserved.
|
|
#
|
|
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
###############################################################################
|
|
|
|
# For extra strength passwords, we wanted SSHA in our LDAP-environment
|
|
# as the standard python-module 'sha' does not support ssha, but this can
|
|
# easily be implemented with a few extra functions.
|
|
#
|
|
# SSHA can be described as:
|
|
# the SHA1-digest of a password with a sequence of "salt" bytes, where
|
|
# the bytes are randomly chosen - followed by the same salt bytes
|
|
# For LDAP-use, the SHA1 and SSHA-digest has to be base64-encoded.
|
|
#
|
|
# Example-LDIF:
|
|
# {SSHA}oaEG3PJ10sHxGcSxsDRRooTifL55/2NOdN3nU1VEV+NFzc9Q
|
|
#
|
|
# This package should now support passwords compatible with [1] Samba using the [2]
|
|
# smbpasswd module for [3] Python. The samba compability is added for use with Samba
|
|
# as PDC with storing user and host-information in LDAP.
|
|
#
|
|
# [1] http://www.samba.org
|
|
# [2] http://barryp.org/software/py-smbpasswd/
|
|
# [3] http://www.python.org
|
|
|
|
import string,base64
|
|
import random,sys
|
|
import exceptions
|
|
import md5,sha,crypt
|
|
|
|
try:
|
|
import smbpasswd
|
|
smb = True
|
|
except:
|
|
smb = False
|
|
|
|
def getsalt(chars=string.letters+string.digits, length=16):
|
|
''' Generate a random salt. Default length is 16 '''
|
|
salt = ''
|
|
for i in range(int(length)):
|
|
salt += random.choice(chars)
|
|
return salt
|
|
|
|
def mkpasswd(pwd, sambaver=3, algo='SSHA', salt=getsalt()):
|
|
''' Make a given password cryptated, possibly with different
|
|
crypt-algorihtms. This module was written for use with
|
|
LDAP - so default is seeded sha
|
|
'''
|
|
|
|
alg = {
|
|
'SSHA':'Seeded SHA',
|
|
'SHA':'Secure Hash Algorithm',
|
|
'MD5':'MD5',
|
|
'SMD5':'Seeded MD5',
|
|
'CRYPT':'standard unix crypt'
|
|
}
|
|
|
|
if smb:
|
|
alg['LMPassword'] = 'lan man hash'
|
|
alg['NTPassword'] = 'nt hash'
|
|
|
|
if algo not in alg.keys():
|
|
raise TypeError, 'Algorithm <%s> not supported in this version.' % algo
|
|
|
|
if algo == 'SSHA':
|
|
pwdhash = "{SSHA}" + base64.encodestring(sha.new(str(pwd) + salt).digest() + salt)
|
|
elif algo =='SHA':
|
|
pwdhash = "{SHA}" + base64.encodestring(sha.new(str(pwd)).digest())
|
|
elif algo =='MD5':
|
|
pwdhash = "{MD5}" + base64.encodestring(md5.new(str(pwd)).digest())
|
|
elif algo == 'SMD5':
|
|
pwdhash = "{SMD5}" + base64.encodestring(md5.new(str(pwd) + salt).digest() + salt)
|
|
elif algo =='CRYPT':
|
|
pwdhash = "{CRYPT}" + crypt.crypt(str(pwd),getsalt(length=2)) # crypt only uses a salt of length 2
|
|
elif algo == 'LMPassword':
|
|
if sambaver==3:
|
|
pwdhash = "{sambaLMPassword}" + smbpasswd.lmhash(pwd)
|
|
elif sambaver==2:
|
|
pwdhash = "{lmPassword}" + smbpasswd.lmhash(pwd)
|
|
elif algo == 'NTPassword':
|
|
if sambaver == 3:
|
|
pwdhash = "{sambaNTPassword}" + smbpasswd.lmhash(pwd)
|
|
elif sambaver == 2:
|
|
pwdhash = "{NTPassword}" + smbpasswd.lmhash(pwd)
|
|
return pwdhash.strip()
|
|
|
|
def checkpwd(pwd, pwdhash):
|
|
''' Check if the password matches the hash '''
|
|
|
|
alg = {
|
|
'SSHA':'Seeded SHA',
|
|
'SHA':'Secure Hash Algorithm',
|
|
'MD5':'MD5',
|
|
'SMD5':'Seeded MD5',
|
|
'CRYPT':'standard unix crypt'
|
|
}
|
|
|
|
if smb:
|
|
alg['LMPassword'] = 'lan man hash'
|
|
alg['NTPassword'] = 'nt hash'
|
|
|
|
algo = pwdhash[1:].split('}')[0]
|
|
|
|
if algo.startswith('samba'):
|
|
sambaver = 3
|
|
algo = algo[5:]
|
|
else:
|
|
sambaver = 2
|
|
|
|
if not algo in alg.keys():
|
|
raise TypeError, 'Algorithm <%s> not supported in this version.' % algo
|
|
|
|
if alg[algo].startswith('Seeded '):
|
|
salt = base64.decodestring(pwdhash.split('}')[1])[-16:]
|
|
else:
|
|
salt = None
|
|
|
|
return mkpasswd(pwd, sambaver=sambaver, algo=algo, salt=salt) == pwdhash
|