X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=ud-mailgate;h=c54aee5c1649aac2b4c70304359152fdc8565f81;hb=b22af6dffb85542441935a2c117105b38f0b53b5;hp=30c9514d273550b420f97c6825f469fbb31a3279;hpb=4960a0dea00ac93cbcdb2fb82f850aee8d4fb4e9;p=mirror%2Fuserdir-ldap.git diff --git a/ud-mailgate b/ud-mailgate index 30c9514..c54aee5 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}) (.+)$') @@ -322,24 +322,19 @@ def DoSSH(Str, Attrs, badkeys, uid): Match = SSHFingerprint.match(output) g = Match.groups() + key_size = g[0] + fingerprint = g[1] - if int(g[0]) < 1024: - try: - # Body - Subst["__ERROR__"] = "SSH keysize %s is below limit 1024" % (g[0]) - ErrReply = TemplateSubst(Subst,open(TemplatesDir+"admin-info","r").read()) - - Child = os.popen("/usr/sbin/sendmail -t","w") - Child.write(ErrReplyHead) - Child.write(ErrReply) - if Child.close() != None: - raise UDExecuteError, "Sendmail gave a non-zero return code" - except: - sys.exit(EX_TEMPFAIL) + if typekey == "rsa": + key_size_ok = (int(key_size) >= 2048) + elif typekey == "ed25519": + key_size_ok = True + else: + key_size_ok = False - # 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" - elif g[1] in badkeys: + if not key_size_ok: + return "SSH key fails formal criteria, not added. We only accept RSA keys (>= 2048 bits) or ed25519 keys." + elif fingerprint in badkeys: try: # Body Subst["__ERROR__"] = "SSH key with fingerprint %s known as bad key" % (g[1]) @@ -356,17 +351,14 @@ 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); - + return "SSH Key added: %s %s [%s]"%(key_size, fingerprint, FormatSSHAuth(Str)) + Attrs.append((ldap.MOD_REPLACE,"sshRSAAuthKey",Str)); SeenKey = 1; - return "SSH Keys replaced with "+FormatSSHAuth(Str); + return "SSH Keys replaced with: %s %s [%s]"%(key_size, fingerprint, FormatSSHAuth(Str)) # Handle changing a dns entry # host IN A 12.12.12.12 @@ -489,8 +481,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 +490,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 +509,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 +571,7 @@ def HandleChange(Reply,DnRecord,Key): Result = ""; Attrs = []; + SudoPasswd = {} Show = 0; CommitChanges = 1 for Line in Lines: @@ -598,7 +589,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 +605,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 +741,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 +763,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 +787,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()));