#!/usr/bin/python

#   Copyright (c) 2008 Peter Palfrader <peter@palfrader.org>
#
#   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.

# ud-ldap 0.3.46 changed the format of the sudopasswd lines so that
# the hmac also includes purpose ("sudo") and userid that owns the
# entry.  This little script updates an ldap from old to new.

from __future__ import print_function

import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, shutil, errno, tarfile, grp
from userdir_ldap import *

UUID_FORMAT = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'

# Connect to the ldap server
l = connectLDAP()
F = open(PassDir+"/pass-"+pwd.getpwuid(os.getuid())[0],"r")
Pass = F.readline().strip().split(" ")
F.close()
l.simple_bind_s("uid="+Pass[0]+","+BaseDn,Pass[1])

PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"sudoPassword=*", ["uid","sudoPassword"])
if PasswdAttrs == None:
  raise Exception("No Users")

for x in PasswdAttrs:
   if not x[1].has_key('sudoPassword'):
      continue

   uid = x[1]['uid'][0]
   Rec = []
   for entry in x[1]['sudoPassword']:
      Match = re.compile('^('+UUID_FORMAT+') (confirmed:[0-9a-f]{40}|unconfirmed) ([a-z0-9.,*]+) ([^ ]+)$').match(entry)
      if Match == None:
         continue
      uuid = Match.group(1)
      status = Match.group(2)
      hosts = Match.group(3)
      cryptedpass = Match.group(4)

      # ok old format
      oldformat = 'confirmed:'+make_hmac(':'.join(['password-is-confirmed', uuid, hosts, cryptedpass]))
      newformat = 'confirmed:'+make_passwd_hmac('password-is-confirmed', 'sudo', x[1]['uid'][0], uuid, hosts, cryptedpass)

      if status == oldformat:
         print("Updating sudo password entry for %s." % uid)
         status = newformat
      elif status == newformat:
         print("not updating sudo password entry for %s, it's already up to date." % uid)
      else:
         print("NOT Updating sudo password entry for %s, failed check." % uid)

      line = ' '.join([uuid, status, hosts, cryptedpass])
      if len(Rec) == 0:
         Rec.append((ldap.MOD_REPLACE, 'sudoPassword', line))
      else:
         Rec.append((ldap.MOD_ADD, 'sudoPassword', line))

   Dn = "uid=" + uid + "," + BaseDn
   l.modify_s(Dn,Rec)

