From: Peter Palfrader Date: Fri, 14 Nov 2008 19:34:55 +0000 (+0100) Subject: Change the hmac that protect sudopassword entries to also hash the purpose X-Git-Tag: userdir-ldap-0.3.46 X-Git-Url: https://git.adam-barratt.org.uk/?p=mirror%2Fuserdir-ldap.git;a=commitdiff_plain;h=0539c19e661f05d992fdeb6e05ec9dcf99bb691d Change the hmac that protect sudopassword entries to also hash the purpose ("sudo") and the owning user's uid into the mac. --- diff --git a/debian/changelog b/debian/changelog index fb006c4..fea116d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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 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 index 0000000..8e7fea8 --- /dev/null +++ b/misc/ud-update-sudopasswords @@ -0,0 +1,74 @@ +#!/usr/bin/python + +# Copyright (c) 2008 Peter Palfrader +# +# 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); + diff --git a/ud-generate b/ud-generate index 5515b98..1a3d3f6 100755 --- a/ud-generate +++ b/ud-generate @@ -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(',') diff --git a/ud-mailgate b/ud-mailgate index a8c1090..1ba2c53 100755 --- a/ud-mailgate +++ b/ud-mailgate @@ -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] diff --git a/userdir_ldap.py b/userdir_ldap.py index e6c628d..c84a655 100644 --- a/userdir_ldap.py +++ b/userdir_ldap.py @@ -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]))