X-Git-Url: https://git.adam-barratt.org.uk/?p=mirror%2Fuserdir-ldap.git;a=blobdiff_plain;f=ud-mailgate;h=7edb3fd33b074752581d7f1b480c700babae4cb4;hp=30c9514d273550b420f97c6825f469fbb31a3279;hb=f8181b0dfa59390433a8329e61f0cfbc2f720644;hpb=4960a0dea00ac93cbcdb2fb82f850aee8d4fb4e9 diff --git a/ud-mailgate b/ud-mailgate index 30c9514..7edb3fd 100755 --- a/ud-mailgate +++ b/ud-mailgate @@ -10,6 +10,7 @@ import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, os, commands import pwd, tempfile import subprocess +import email, email.parser from userdir_gpg import * from userdir_ldap import * @@ -35,7 +36,6 @@ mailRHSBL = {} mailWhitelist = {} SeenList = {} DNS = {} -SudoPasswd = {} ValidHostNames = [] # will be initialized in later SSHFingerprint = re.compile('^(\d+) ([0-9a-f\:]{47}) (.+)$') @@ -323,10 +323,17 @@ def DoSSH(Str, Attrs, badkeys, uid): Match = SSHFingerprint.match(output) g = Match.groups() - if int(g[0]) < 1024: + if typekey == "ssh-rsa": + key_size_ok = (g[0]) >= 2048) + elif typekey == "ed25519": + key_size_ok = True + else: + key_size_ok = False + + if not key_size_ok: try: # Body - Subst["__ERROR__"] = "SSH keysize %s is below limit 1024" % (g[0]) + Subst["__ERROR__"] = "SSH key fails formal criteria. We only accept RSA keys (>= 2048 bits) or ed25519 keys." % (g[0]) ErrReply = TemplateSubst(Subst,open(TemplatesDir+"admin-info","r").read()) Child = os.popen("/usr/sbin/sendmail -t","w") @@ -338,7 +345,7 @@ def DoSSH(Str, Attrs, badkeys, uid): sys.exit(EX_TEMPFAIL) # And now break and stop processing input, which sends a reply to the user. - raise UDFormatError, "SSH keys must have at least 1024 bits, processing halted, NOTHING MODIFIED AT ALL" + raise UDFormatError, "SSH key fails formal criteria, NOTHING MODIFIED AT ALL" elif g[1] in badkeys: try: # Body @@ -356,14 +363,11 @@ def DoSSH(Str, Attrs, badkeys, uid): # And now break and stop processing input, which sends a reply to the user. raise UDFormatError, "Submitted SSH Key known to be bad and insecure, processing halted, NOTHING MODIFIED AT ALL" - if (typekey == "dss"): - return "DSA keys not accepted anymore" - global SeenKey; if SeenKey: Attrs.append((ldap.MOD_ADD,"sshRSAAuthKey",Str)); return "SSH Key added "+FormatSSHAuth(Str); - + Attrs.append((ldap.MOD_REPLACE,"sshRSAAuthKey",Str)); SeenKey = 1; return "SSH Keys replaced with "+FormatSSHAuth(Str); @@ -489,8 +493,8 @@ def DoRBL(Str,Attrs): 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) +def DoConfirmSudopassword(Str, SudoPasswd): + Match = re.compile('^confirm sudopassword ('+UUID_FORMAT+') ([a-z0-9.,*-]+) ([0-9a-f]{40})$').match(Str) if Match == None: return None @@ -498,12 +502,10 @@ def DoConfirmSudopassword(Str): 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, uid, Attrs): - global SudoPasswd +def FinishConfirmSudopassword(l, uid, Attrs, SudoPasswd): result = "\n" if len(SudoPasswd) == 0: @@ -519,7 +521,7 @@ def FinishConfirmSudopassword(l, uid, Attrs): newldap = [] for entry in inldap: - Match = re.compile('^('+UUID_FORMAT+') (confirmed:[0-9a-f]{40}|unconfirmed) ([a-z0-9.,*]+) ([^ ]+)$').match(entry) + Match = re.compile('^('+UUID_FORMAT+') (confirmed:[0-9a-f]{40}|unconfirmed) ([a-z0-9.,*-]+) ([^ ]+)$').match(entry) if Match == None: raise UDFormatError, "Could not parse existing sudopasswd entry" uuid = Match.group(1) @@ -581,6 +583,7 @@ def HandleChange(Reply,DnRecord,Key): Result = ""; Attrs = []; + SudoPasswd = {} Show = 0; CommitChanges = 1 for Line in Lines: @@ -598,7 +601,7 @@ def HandleChange(Reply,DnRecord,Key): 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) or DoConfirmSudopassword(Line) + DoDel(Line,Attrs) or DoRBL(Line,Attrs) or DoConfirmSudopassword(Line, SudoPasswd) except: Res = None; Result = Result + "==> %s: %s\n" %(sys.exc_type,sys.exc_value); @@ -614,17 +617,16 @@ def HandleChange(Reply,DnRecord,Key): # Connect to the ldap server l = connect_to_ldap_and_check_if_locked(DnRecord) - if CommitChanges == 1: # only if we are still good to go + if CommitChanges == 1 and len(SudoPasswd) > 0: # only if we are still good to go try: - Res = FinishConfirmSudopassword(l, GetAttr(DnRecord,"uid"), Attrs) + Res = FinishConfirmSudopassword(l, GetAttr(DnRecord,"uid"), Attrs, SudoPasswd) if not Res is None: Result = Result + Res + "\n"; except Error, e: CommitChanges = 0 Result = Result + "FinishConfirmSudopassword raised an error (%s) - no changes committed\n"%(e); - # Modify the record - if CommitChanges == 1: + if CommitChanges == 1 and len(Attrs) > 0: Dn = "uid=" + GetAttr(DnRecord,"uid") + "," + BaseDn; l.modify_s(Dn,Attrs); @@ -751,8 +753,8 @@ try: # Get the email ErrType = EX_PERMFAIL; ErrMsg = "Failed to understand the email or find a signature:"; - Email = mimetools.Message(sys.stdin,0); - Msg = GetClearSig(Email); + mail = email.parser.Parser().parse(sys.stdin); + Msg = GetClearSig(mail); ErrMsg = "Message is not PGP signed:" if Msg[0].find("-----BEGIN PGP SIGNED MESSAGE-----") == -1 and \ @@ -773,11 +775,8 @@ try: global PlainText; ErrMsg = "Problem stripping MIME headers from the decoded message" if Msg[1] == 1: - try: - Index = pgp.text.index("\n\n") + 2 - except ValueError: - Index = pgp.text.index("\n\r\n") + 3 - PlainText = pgp.text[Index:] + e = email.parser.Parser().parsestr(pgp.text) + PlainText = e.get_payload(decode=True) else: PlainText = pgp.text @@ -800,22 +799,13 @@ try: # Check the signature against the replay cache RC = ReplayCache(ReplayCacheFile); - RC.Clean(); - ErrMsg = "The replay cache rejected your message. Check your clock!"; - Rply = RC.Check(pgp.sig_info); - if Rply != None: - RC.close() - raise UDNotAllowedError, Rply; - RC.Add(pgp.sig_info); - RC.close() + RC.process(pgp.sig_info) # Determine the sender address ErrMsg = "A problem occured while trying to formulate the reply"; - Sender = Email.getheader("Reply-To"); - if Sender == None: - Sender = Email.getheader("From"); - if Sender == None: - raise UDFormatError, "Unable to determine the sender's address"; + Sender = mail['Reply-To'] + if not Sender: Sender = mail['From'] + if not Sender: raise UDFormatError, "Unable to determine the sender's address"; # Formulate a reply Date = time.strftime("%a, %d %b %Y %H:%M:%S +0000",time.gmtime(time.time()));