Change the hmac that protect sudopassword entries to also hash the purpose userdir-ldap-0.3.46
authorPeter Palfrader <peter@palfrader.org>
Fri, 14 Nov 2008 19:34:55 +0000 (20:34 +0100)
committerPeter Palfrader <peter@palfrader.org>
Fri, 14 Nov 2008 19:34:55 +0000 (20:34 +0100)
("sudo") and the owning user's uid into the mac.

debian/changelog
misc/ud-update-sudopasswords [new file with mode: 0755]
ud-generate
ud-mailgate
userdir_ldap.py

index fb006c4..fea116d 100644 (file)
@@ -1,3 +1,11 @@
+userdir-ldap (0.3.46) unstable; urgency=low
+
+  * Change the hmac that protect sudopassword entries to also
+    hash the purpose ("sudo") and the owning user's uid into
+    the mac.
+
+ -- Peter Palfrader <weasel@debian.org>  Fri, 14 Nov 2008 20:27:38 +0100
+
 userdir-ldap (0.3.45) unstable; urgency=low
 
   * ud-generate: Declare [UNTRSUTED] flag as obsolete.
diff --git a/misc/ud-update-sudopasswords b/misc/ud-update-sudopasswords
new file mode 100755 (executable)
index 0000000..8e7fea8
--- /dev/null
@@ -0,0 +1,74 @@
+#!/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.
+
+import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, sha, 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 "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);
+
index 5515b98..1a3d3f6 100755 (executable)
@@ -230,7 +230,7 @@ def GenShadowSudo(l,File, untrusted):
             hosts = Match.group(3)
             cryptedpass = Match.group(4)
 
-            if status != 'confirmed:'+make_sudopasswd_hmac('password-is-confirmed', uuid, hosts, cryptedpass):
+            if status != 'confirmed:'+make_passwd_hmac('password-is-confirmed', 'sudo', x[1]['uid'][0], uuid, hosts, cryptedpass):
                continue
             for_all = hosts == "*"
             for_this_host = CurrentHost in hosts.split(',')
index a8c1090..1ba2c53 100755 (executable)
@@ -490,15 +490,15 @@ def FinishConfirmSudopassword(l, uid, Attrs):
          confirmedHosts = SudoPasswd[uuid][0]
          confirmedHmac = SudoPasswd[uuid][1]
          if status.startswith('confirmed:'):
-            if status == 'confirmed:'+make_sudopasswd_hmac('password-is-confirmed', uuid, hosts, cryptedpass):
+            if status == 'confirmed:'+make_passwd_hmac('password-is-confirmed', 'sudo', uid, ,uuid, hosts, cryptedpass):
                result = result + "Entry %s for sudo password on hosts %s already confirmed.\n"%(uuid, hosts)
             else:
                result = result + "Entry %s for sudo password on hosts %s is listed as confirmed, but HMAC does not verify.\n"%(uuid, hosts)
          elif confirmedHosts != hosts:
             result = result + "Entry %s hostlist mismatch (%s vs. %s).\n"%(uuid, hosts, confirmedHosts)
-         elif make_sudopasswd_hmac('confirm-new-password', uuid, hosts, cryptedpass) == confirmedHmac:
+         elif make_passwd_hmac('confirm-new-password', 'sudo', uid, uuid, hosts, cryptedpass) == confirmedHmac:
             result = result + "Entry %s for sudo password on hosts %s now confirmed.\n"%(uuid, hosts)
-            status = 'confirmed:'+make_sudopasswd_hmac('password-is-confirmed', uuid, hosts, cryptedpass)
+            status = 'confirmed:'+make_passwd_hmac('password-is-confirmed', 'sudo', uid, uuid, hosts, cryptedpass)
          else:
             result = result + "Entry %s for sudo password on hosts %s HMAC verify failed.\n"%(uuid, hosts)
          del SudoPasswd[uuid]
index e6c628d..c84a655 100644 (file)
@@ -459,5 +459,5 @@ def make_hmac(str):
    File.close();
    return hmac.new(HmacKey, str, sha1_module).hexdigest()
 
-def make_sudopasswd_hmac(purpose, uuid, hosts, cryptedpass):
-   return make_hmac(':'.join([purpose, uuid, hosts, cryptedpass]))
+def make_passwd_hmac(status, purpose, uid, uuid, hosts, cryptedpass):
+   return make_hmac(':'.join([status, purpose, uid, uuid, hosts, cryptedpass]))