[Da-tools-commits] ./debian/userdir-ldap r443: ud-mailgate: Implement confirmation of sudoPassword field
Peter Palfrader
peter at palfrader.org
Sat Sep 13 16:33:19 UTC 2008
------------------------------------------------------------
revno: 443
committer: Peter Palfrader <peter at palfrader.org>
branch nick: userdir-ldap
timestamp: Sat 2008-09-13 18:33:19 +0200
message:
ud-mailgate: Implement confirmation of sudoPassword field
modified:
debian/changelog
ud-mailgate
-------------- next part --------------
=== modified file 'debian/changelog'
--- a/debian/changelog 2008-09-13 14:35:17 +0000
+++ b/debian/changelog 2008-09-13 16:33:19 +0000
@@ -2,8 +2,14 @@
* ud-mailgate: Do not commit any changes if one of the requests is invalid
or could not be parsed or caused an error or anything.
+ * Add sudoPassword to schema, and the slapd.conf/ACL snippet
+ A sudoPassword entry in LDAP has the form of
+ "<uuid> (confirmed|unconfirmed) <hostlist> <cryptedpassword>"
+ * ud-mailgate: Implement confirmation of sudoPassword field:
+ A confirmationation is of the form
+ "confirm sudopassword <uuid> <hostlist> <hmac_sha1("<uuid>:<hosts>:<cryptedpass>")>"
- -- Peter Palfrader <weasel at debian.org> Sat, 13 Sep 2008 16:29:37 +0200
+ -- Peter Palfrader <weasel at debian.org> Sat, 13 Sep 2008 18:27:47 +0200
userdir-ldap (0.3.36) unstable; urgency=low
=== modified file 'ud-mailgate'
--- a/ud-mailgate 2008-09-13 14:35:17 +0000
+++ b/ud-mailgate 2008-09-13 16:33:19 +0000
@@ -7,6 +7,7 @@
import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, os, commands
import pwd, tempfile
+import hmac, haslib
from userdir_gpg import *
from userdir_ldap import *
@@ -18,6 +19,8 @@
ReplayCacheFile = ConfModule.replaycachefile;
SSHFingerprintFile = ConfModule.fingerprintfile
+UUID_FORMAT = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
+
EX_TEMPFAIL = 75;
EX_PERMFAIL = 65; # EX_DATAERR
Error = 'Message Error';
@@ -28,6 +31,7 @@
mailWhitelist = {}
SeenList = {}
DNS = {}
+SudoPasswd = {}
SSHFingerprint = re.compile('^(\d+) ([0-9a-f\:]{47}) (.+)$')
SSHRSA1Match = re.compile('^^(.* )?\d+ \d+ \d+')
@@ -89,6 +93,15 @@
"VoIP": None,
};
+def make_hmac(str):
+ F = open(PassDir+"/key-hmac","r");
+ key = F.readline()
+ F.close();
+
+ return hmac.new(key, str, hashlib.sha1).hexdigest
+
+
+
# Decode a GPS location from some common forms
def LocDecode(Str,Dir):
# Check for Decimal degrees, DGM, or DGMS
@@ -446,6 +459,69 @@
SeenList[Key] = 1;
return "%s replaced with %s" % (Key,Host)
+# Handle a ConfirmSudoPassword request
+def DoConfirmSudopassword(Str):
+ Match = re.compile('^confirm sudopassword ('+UUID_FORMAT+') ([a-z0-9,*]+) ([0-9a-f]{40})$').match(Str.lower())
+ if Match == None:
+ return None
+
+ uuid = Match.group(1)
+ hosts = Match.group(2)
+ hmac = Match.group(3)
+
+ global SudoPasswd
+ SudoPasswd[uuid] = (hosts, hmac)
+ return "got confirm for sudo password %s on host(s) %s, auth code %s" % (uuid,hosts, hmac)
+
+def FinishConfirmSudopassword(l, dn, Attrs):
+ global SudoPasswd
+ result = "\n"
+
+ res = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"uid="+uid, ['sudoPassword']);
+ if len(res) != 1:
+ raise Error, "Not exactly one hit when searching for user"
+ Attrs = res[0][1]
+ if Attrs.has_key('sudoPassword'):
+ inldap = Attrs['sudoPassword']
+ else:
+ inldap = []
+
+ first_entry = 0
+ for entry in inldap:
+ Match = re.compile('^('+UUID_FORMAT+') (confirmed|unconfirmed) ([a-z0-9,*]+) ([^ ]+)$'),match(entry.lower())
+ if Match == None:
+ raise Error, "Could not parse existing sudopasswd entry"
+ uuid = Match.group(1)
+ status = Match.group(2)
+ hosts = Match.group(3)
+ cryptedpass = Match.group(4)
+
+ if SudoPasswd.has_key(uuid):
+ confirmedHosts = SudoPasswd[uuid][0]
+ confirmedHmac = SudoPasswd[uuid][1]
+ if status == "confirmed":
+ result = result + "Entry %s for sudo password on hosts %s already confirmed.\n"%(uuid, hosts)
+ elif confirmedHosts != hosts:
+ result = result + "Entry %s hostlist mismatch (%s vs. %s).\n"%(uuid, hosts, confirmedHosts)
+ elif make_hmac(':'.join([uuid, hosts, cryptedpass])) == confirmedHmac:
+ result = result + "Entry %s for sudo password on hosts %s now confirmed.\n"%(uuid, hosts)
+ status = 'confirmed'
+ else:
+ result = result + "Entry %s for sudo password on hosts %s HMAC verify failed.\n"%(uuid, hosts)
+ del SudoPasswd[uuid]
+
+ newentry = " ".join([uuid, status, hosts, cryptedpass])
+ if first_entry:
+ Attrs.append((ldap.MOD_ADD,"sudoPassword",newentry))
+ else:
+ Attrs.append((ldap.MOD_REPLACE,"sudoPassword",newentry))
+ first_entry = 1
+
+ for entry in SudoPasswd:
+ result = result + "Entry %s that you confirm is not listed in ldap."%(entry)
+
+ return result
+
# Handle an [almost] arbitary change
def HandleChange(Reply,DnRecord,Key):
global PlainText;
@@ -470,11 +546,11 @@
badkeys = LoadBadSSH()
Res = DoPosition(Line,Attrs) or DoDNS(Line,Attrs,DnRecord) or \
DoArbChange(Line,Attrs) or DoSSH(Line,Attrs,badkeys,GetAttr(DnRecord,"uid")) or \
- DoDel(Line,Attrs) or DoRBL(Line,Attrs)
+ DoDel(Line,Attrs) or DoRBL(Line,Attrs) or DoConfirmSudopassword(Line)
except:
Res = None;
Result = Result + "==> %s: %s\n" %(sys.exc_type,sys.exc_value);
-
+
# Fail, if someone tries to send someone elses signed email to the
# daemon then we want to abort ASAP.
if Res == None:
@@ -489,12 +565,18 @@
AccessPass = F.readline().strip().split(" ")
F.close();
- # Modify the record
l.simple_bind_s("uid="+AccessPass[0]+","+BaseDn,AccessPass[1]);
oldAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"uid="+GetAttr(DnRecord,"uid"));
if ((GetAttr(oldAttrs[0],"userPassword").find("*LK*") != -1)
or GetAttr(oldAttrs[0],"userPassword").startswith("!")):
raise Error, "This account is locked";
+ try:
+ Res = FinishConfirmSudopassword(l, GetAttr(DnRecord,"uid"), Attrs)
+ Result = Result + Res + "\n";
+ except:
+ CommitChanges = 0
+ Result = Result + "ConfirmSudopassword raised an error - no changes committed\n";
+ # Modify the record
Dn = "uid=" + GetAttr(DnRecord,"uid") + "," + BaseDn;
if CommitChanges == 1:
l.modify_s(Dn,Attrs);
More information about the Da-tools-commits
mailing list