########################################################################
# web2ldap
# (c) by Michael Stroeder <michael@stroeder.com>
# Distributed under GNU Public License (GPL)
# web-based LDAP Client, see http://www.web2ldap.de for details
########################################################################

import sys,string,charset,web2ldapcnf,w2lcnf, cgiforms,ldap,w2lcore, w2lgui

# Try to determine the avaiable hash types
available_hashtypes = [('','None')]

# Alphabet for encrypted passwords (see module crypt)
crypt_alphabet = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
crypt_alphabet_len = len(crypt_alphabet)

# Check if all required modules are in place to
# determine the available encryption methods
try:
  import random
  import base64
  import crypt
  available_hashtypes.append(('crypt','Crypt'))
  import md5
  available_hashtypes.append(('md5','MD5'))
  available_hashtypes.append(('smd5','salted MD5'))
  import sha
  available_hashtypes.append(('sha','SHA-1'))
  available_hashtypes.append(('ssha','salted SHA-1'))
except ImportError:
  pass


########################################################################
# Change userpassword
########################################################################

def w2l_Passwd(outf,command,form,ls):


  if not ls.who:
    ls.who = ls.dn

  if ls.dn and \
     ('passwd_newpasswd' in form.inputkeys):

    try:
      ls.l.bind_s(ls.who.encode('utf-8'),ls.cred.encode('utf-8'),ldap.AUTH_SIMPLE)
    except ldap.INVALID_CREDENTIALS:
      raise w2lcore.ErrorExitClass(ls,'Wrong password for binding as <strong>%s</strong> to %s.' % (w2lcore.utf2display(form.accept_charset,ls.who),ls.host))
    except ldap.INAPPROPRIATE_AUTH:
      raise w2lcore.ErrorExitClass(ls,'Wrong password for binding as <strong>%s</strong> to %s.' % (w2lcore.utf2display(form.accept_charset,ls.who),ls.host))

    if len(form.field['passwd_newpasswd'][0].content)!=2:
      raise w2lcore.ErrorExitClass(ls,'Repeat password!')

    if form.field['passwd_newpasswd'][0].content[0]!=form.field['passwd_newpasswd'][0].content[1]:
      raise w2lcore.ErrorExitClass(ls,'New passwords do not match!')

    if not form.field['passwd_newpasswd'][0].content[0]:
      raise w2lcore.ErrorExitClass(ls,'Empty passwords not allowed!')

    passwdinput = form.field['passwd_newpasswd'][0].content[0]

    if 'passwd_hash' in form.inputkeys:
      passwd_hash = string.lower(form.field['passwd_hash'][0].content)
      if passwd_hash in ['crypt','smd5','ssha']:
        crypt_salt = ''
        for i in range(2):
  	  crypt_salt = crypt_salt+crypt_alphabet[random.randint(0,crypt_alphabet_len-1)]
      else:
	crypt_salt = ''
      if passwd_hash=='crypt':
	new_passwd = '{crypt}%s' % crypt.crypt(form.field['passwd_newpasswd'][0].content[0],crypt_salt)
      elif passwd_hash in ['md5','smd5']:
	new_passwd = string.strip('{%s}%s' % (passwd_hash,base64.encodestring(md5.new(passwdinput+crypt_salt).digest()+crypt_salt)))
      elif passwd_hash in ['sha','ssha']:
	new_passwd = string.strip('{%s}%s' % (passwd_hash,base64.encodestring(sha.new(passwdinput+crypt_salt).digest()+crypt_salt)))
      else:
	new_passwd = passwdinput
    else:
      raise w2lcore.ErrorExitClass(ls,'Password encryption method required!')

    modlist = [(ldap.MOD_REPLACE,'userPassword',new_passwd.encode('utf-8'))]

    # Passwort aendern
    ls.l.modify_s(ls.dn.encode('utf-8'),modlist)

    w2lgui.PrintHeader(outf,'Set password',form.accept_charset)
    if ls.dn==ls.who:
      w2lgui.CommandTable(outf,[
	w2lgui.CommandButton(
	  form,'login','Login as',
	  ls.who,None,
	  ls.host,
	  extrastr='<input type=hidden name="login_binddn" value="%s">' % (w2lcore.utf2display(form.accept_charset,ls.who)))
      ],div_id='ContextMenuDiv',table_id='ContextMenuTable')
      outf.write('<div id=messagediv>\n<p>Password changed of entry %s. A new login is required!</p>\n</div>' % (w2lgui.DisplayDN(form.accept_charset,ls.dn)))
    else:
      w2lgui.MainMenuTable(outf,form,ls)
      outf.write('<div id=messagediv>\n<p>Set password of entry %s.</p>\n</div>' % (w2lgui.DisplayDN(form.accept_charset,ls.dn)))
    w2lgui.PrintFooter(outf)

  else:

    
    config_hashtypes = map(string.lower,w2lcnf.GetParam(ls,'passwd_hashtypes',[]))
    if config_hashtypes:
      # The set of hash types are restricted by local configuration
      default_hashtypes = []
      for hash_type in available_hashtypes:
	if hash_type[0] in config_hashtypes:
          default_hashtypes.append(hash_type)
      form.field['passwd_hash'][0].options = default_hashtypes

    # Leeres Passworteingabeformular ausgeben
    w2lgui.PrintHeader(outf,'Change password',form.accept_charset)
    w2lgui.MainMenuTable(outf,form,ls)
    outf.write("""<div id=InputDiv>
<h1>Change password</h1>
<form
  action="%s/passwd"
  method="%s"
  enctype="application/x-www-form-urlencoded"
  accept-charset="%s"
>
  <input type=hidden name="host"       value="%s">
  <input type=hidden name="who"     value="%s">
  <table summary="Password input form">
  <tr>
    <td>Change password for</td>
    <td><INPUT type="hidden" name="dn" value="%s">%s on %s</td>
  </tr>
  <tr>
    <td>Password for <strong>%s</strong></td>
    <td><input type="password" name="cred" maxlength="30" size="15" value=""></td>
  </tr>
  <tr>
    <td>New password</td>
    <td><input type="password" name="passwd_newpasswd" maxlength="30" size="30" value=""></td>
  </tr>
  <tr>
    <td>repeat new password</td>
    <td><input type="password" name="passwd_newpasswd" maxlength="30" size="30" value=""></td>
  </tr>
  <tr>
    <td>Password encryption method</td>
    <td>%s</td>
  </tr>
</table>
<input type="submit" value="Change Password">
<input type="reset" value="Reset">
</form>
</div>
""" % (
    form.script_name,
    web2ldapcnf.script_method,
    form.accept_charset,
    ls.host.encode('ascii'),
    w2lcore.utf2display(form.accept_charset,ls.who),
    w2lcore.utf2display(form.accept_charset,ls.dn),
    w2lgui.DisplayDN(form.accept_charset,ls.dn),
    ls.host.encode('ascii'),
    w2lcore.utf2display(form.accept_charset,ls.who),
    form.field['passwd_hash'][0].inputfield()
  )
)

    w2lgui.PrintFooter(outf)


