X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=ud-mailgate;h=e6b54a9449bbc6477e2587e014e9cdd3d2ebe17e;hb=6ee830ff583d3db2afa0044a378b1737853e54b0;hp=6f9b20cfc5fb2bb7e8b1f810b0cbeda88f295653;hpb=f22595d6909859cae31bb8a33ad24b50e74cb89a;p=mirror%2Fuserdir-ldap.git diff --git a/ud-mailgate b/ud-mailgate index 6f9b20c..e6b54a9 100755 --- a/ud-mailgate +++ b/ud-mailgate @@ -11,6 +11,7 @@ import userdir_gpg, userdir_ldap, sys, traceback, time, ldap, os, commands import pwd, tempfile import subprocess import email, email.parser +import binascii from userdir_gpg import * from userdir_ldap import * @@ -38,7 +39,7 @@ SeenList = {} DNS = {} ValidHostNames = [] # will be initialized in later -SSHFingerprint = re.compile('^(\d+) ([0-9a-f\:]{47}) (.+)$') +SSHFingerprint = re.compile('^(\d+) ([0-9a-f\:]{47}|SHA256:[0-9A-Za-z/+]{43}) (.+)$') SSHRSA1Match = re.compile('^^(.* )?\d+ \d+ \d+') GenderTable = {"male": '1', @@ -321,25 +322,22 @@ def DoSSH(Str, Attrs, badkeys, uid): Subst["__USER__"] = uid Match = SSHFingerprint.match(output) + if Match is None: + return "Failed to match SSH fingerprint, has the output of ssh-keygen changed?" 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 +354,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 @@ -377,7 +372,7 @@ def DoDNS(Str,Attrs,DnRecord): cnamerecord = re.match("^[-\w]+\s+IN\s+CNAME\s+([-\w.]+\.)$",Str,re.IGNORECASE) arecord = re.match('^[-\w]+\s+IN\s+A\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$',Str,re.IGNORECASE) mxrecord = re.match("^[-\w]+\s+IN\s+MX\s+(\d{1,3})\s+([-\w.]+\.)$",Str,re.IGNORECASE) - txtrecord = re.match("^[-\w]+\s+IN\s+TXT\s+([-\d. a-z\t<>@]+)", Str, re.IGNORECASE) + txtrecord = re.match("^[-\w]+\s+IN\s+TXT\s+([-\d. a-z\t<>@:]+)", Str, re.IGNORECASE) #aaaarecord = re.match('^[-\w]+\s+IN\s+AAAA\s+((?:[0-9a-f]{1,4})(?::[0-9a-f]{1,4})*(?::(?:(?::[0-9a-f]{1,4})*|:))?)$',Str,re.IGNORECASE) aaaarecord = re.match('^[-\w]+\s+IN\s+AAAA\s+([A-F0-9:]{2,39})$',Str,re.IGNORECASE) @@ -695,6 +690,28 @@ def HandleChPass(Reply,DnRecord,Key): return Reply; +def HandleChTOTPSeed(Reply, DnRecord, Key): + # Generate a random seed + seed = binascii.hexlify(open("/dev/urandom", "r").read(32)) + msg = GPGEncrypt("Your new TOTP seed is '%s'\n" % (seed,), "0x"+Key[1],Key[4]); + + if msg is None: + raise UDFormatError, "Unable to generate the encrypted reply, gpg failed."; + + Subst = {}; + Subst["__FROM__"] = ChPassFrom + Subst["__EMAIL__"] = EmailAddress(DnRecord) + Subst["__PASSWORD__"] = msg + Subst["__ADMIN__"] = ReplyTo + Reply = Reply + TemplateSubst(Subst, open(TemplatesDir+"totp-seed-changed", "r").read()) + + l = connect_to_ldap_and_check_if_locked(DnRecord) + # Modify the password + Rec = [(ldap.MOD_REPLACE, "totpSeed", seed)] + Dn = "uid=" + GetAttr(DnRecord,"uid") + "," + BaseDn + l.modify_s(Dn,Rec) + return Reply; + def HandleChKrbPass(Reply,DnRecord,Key): # Connect to the ldap server, will throw an exception if account locked. l = connect_to_ldap_and_check_if_locked(DnRecord) @@ -822,6 +839,8 @@ try: Reply = HandleChPass(Reply,Attrs[0],pgp.key_info); elif PlainText.strip().find("Please change my Kerberos password") >= 0: Reply = HandleChKrbPass(Reply,Attrs[0],pgp.key_info); + elif PlainText.strip().find("Please change my TOTP seed") >= 0: + Reply = HandleChTOTPSeed(Reply, Attrs[0], pgp.key_info) else: raise UDFormatError,"Please send a signed message where the first line of text is the string 'Please change my Debian password' or some other string we accept here."; elif sys.argv[1] == "change":