# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, sha;
+import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, sha
from userdir_ldap import *;
global Allowed;
# Generate the email forwarding list
def GenForward(l,File):
F = None;
- Fdb = None;
try:
OldMask = os.umask(0022);
F = open(File + ".tmp","w",0644);
# Oops, something unspeakable happened.
except:
- Die(File,F,Fdb);
+ Die(File,F,None);
raise;
- Done(File,F,Fdb);
+ Done(File,F,None);
def GenAllForward(l,File):
Fdb = None;
# Generate the anon XEarth marker file
def GenMarkers(l,File):
F = None;
- Fdb = None;
try:
F = open(File + ".tmp","w");
- Fdb = None;
# Fetch all the users
global PasswdAttrs;
# Oops, something unspeakable happened.
except:
- Die(File,F,Fdb);
+ Die(File,F,None);
raise;
- Done(File,F,Fdb);
+ Done(File,F,None);
# Generate the debian-private subscription list
def GenPrivate(l,File):
F = None;
- Fdb = None;
try:
F = open(File + ".tmp","w");
- Fdb = None;
# Fetch all the users
global PasswdAttrs;
# Oops, something unspeakable happened.
except:
- Die(File,F,Fdb);
+ Die(File,F,None);
+ raise;
+ Done(File,F,None);
+
+# Generate the list of local addresses that refuse all mail
+def GenMailDisable(l,File):
+ F = None;
+ try:
+ F = open(File + ".tmp","w");
+
+ # Fetch all the users
+ global PasswdAttrs;
+ if PasswdAttrs == None:
+ raise "No Users";
+
+ for x in PasswdAttrs:
+ Reason = None
+
+ # If the account is locked, disable incoming mail
+ if (string.find(GetAttr(x,"userPassword"),"*LK*") != -1) or \
+ x[1].has_key("keyFingerPrint") == 0:
+ Reason = "user account locked"
+ else:
+ if x[1].has_key("mailDisableMessage"):
+ Reason = GetAttr(x,"mailDisableMessage")
+ else:
+ continue
+
+ # Must be in the Debian group (yuk, hard coded for now)
+ if GetAttr(x,"gidNumber") != "800":
+ continue;
+
+ try:
+ Line = "%s: %s"%(GetAttr(x,"uid"),Reason);
+ Line = Sanitize(Line) + "\n";
+ F.write(Line);
+ except:
+ pass;
+
+ # Oops, something unspeakable happened.
+ except:
+ Die(File,F,None);
+ raise;
+ Done(File,F,None);
+
+# Generate a list of uids that should have boolean affects applied
+def GenMailBool(l,File,Key):
+ F = None;
+ try:
+ F = open(File + ".tmp","w");
+
+ # Fetch all the users
+ global PasswdAttrs;
+ if PasswdAttrs == None:
+ raise "No Users";
+
+ for x in PasswdAttrs:
+ Reason = None
+
+ if x[1].has_key(Key) == 0:
+ continue
+
+ # Must be in the Debian group (yuk, hard coded for now)
+ if GetAttr(x,"gidNumber") != "800":
+ continue
+
+ if GetAttr(x,Key) != "TRUE":
+ continue
+
+ try:
+ Line = "%s"%(GetAttr(x,"uid"));
+ Line = Sanitize(Line) + "\n";
+ F.write(Line);
+ except:
+ pass;
+
+ # Oops, something unspeakable happened.
+ except:
+ Die(File,F,None);
raise;
- Done(File,F,Fdb);
+ Done(File,F,None);
+
+# Generate a list of hosts for RBL or whitelist purposes.
+def GenMailList(l,File,Key):
+ F = None;
+ try:
+ F = open(File + ".tmp","w");
+
+ # Fetch all the users
+ global PasswdAttrs;
+ if PasswdAttrs == None:
+ raise "No Users";
+
+ for x in PasswdAttrs:
+ Reason = None
+
+ if x[1].has_key(Key) == 0:
+ continue
+
+ # Must be in the Debian group (yuk, hard coded for now)
+ if GetAttr(x,"gidNumber") != "800":
+ continue
+
+ try:
+ found = 0
+ Line = None
+ for z in x[1][Key]:
+ if Key == "mailWhitelist":
+ if re.match('^[-\w.]+(/[\d]+)?$',z) == None:
+ continue
+ else:
+ if re.match('^[-\w.]+$',z) == None:
+ continue
+ if found == 0:
+ found = 1
+ Line = GetAttr(x,"uid")
+ Line += ": " + z
+
+ if Line != None:
+ Line = Sanitize(Line) + "\n";
+ F.write(Line);
+ except:
+ pass;
+
+ # Oops, something unspeakable happened.
+ except:
+ Die(File,F,None);
+ raise;
+ Done(File,F,None);
# Generate the DNS Zone file
def GenDNS(l,File,HomePrefix):
"shadowMin","shadowMax","shadowWarning","shadowinactive",
"shadowexpire","emailForward","latitude","longitude",\
"allowedHost","sshRSAAuthKey","dnsZoneEntry","cn","sn",\
- "keyFingerPrint","privateSub"]);
+ "keyFingerPrint","privateSub","mailDisableMessage",\
+ "mailGreylisting","mailCallout","mailRBL","mailRHSBL",\
+ "mailWhitelist"]);
# Fetch all the hosts
HostAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"sshRSAHostKey=*",\
["hostname","sshRSAHostKey"]);
GenPrivate(l,GlobalDir+"debian-private");
GenSSHKnown(l,GlobalDir+"ssh_known_hosts");
GenHosts(l,GlobalDir+"debianhosts");
+GenMailDisable(l,GlobalDir+"mail-disable");
+GenMailBool(l,GlobalDir+"mail-greylist","mailGreylisting");
+GenMailBool(l,GlobalDir+"mail-callout","mailCallout");
+GenMailList(l,GlobalDir+"mail-rbl","mailRBL");
+GenMailList(l,GlobalDir+"mail-rhsbl","mailRHSBL");
+GenMailList(l,GlobalDir+"mail-whitelist","mailWhitelist");
# Compatibility.
GenForward(l,GlobalDir+"forward-alias");
DoLink(GlobalDir,OutDir,"ssh-rsa-shadow");
DoLink(GlobalDir,OutDir,"markers");
DoLink(GlobalDir,OutDir,"mail-forward.cdb");
- DoLink(GlobalDir,OutDir,"ssh_known_hosts");
DoLink(GlobalDir,OutDir,"debianhosts");
+ DoLink(GlobalDir,OutDir,"ssh_known_hosts");
+ DoLink(GlobalDir,OutDir,"mail-disable");
+ DoLink(GlobalDir,OutDir,"mail-greylist");
+ DoLink(GlobalDir,OutDir,"mail-callout");
+ DoLink(GlobalDir,OutDir,"mail-rbl");
+ DoLink(GlobalDir,OutDir,"mail-rhsbl");
+ DoLink(GlobalDir,OutDir,"mail-whitelist");
# Compatibility.
DoLink(GlobalDir,OutDir,"forward-alias");
"icqUin": ["ICQ UIN",14],
"jabberJID": ["Jabber ID",15],
"privateSub": ["Debian-Private",16],
+ "gender": ["Gender",17],
+ "birthDate": ["Date of Birth",18],
+ "mailDisableMessage": ["Mail Disabled",19],
+ "mailGreylisting": ["Mail Greylisting",20],
+ "mailCallout": ["Mail Callouts",21],
+ "mailRBL": ["Mail RBLs",22],
+ "mailRHSBL": ["Mail RHSBLs",23],
+ "mailWhitelist": ["Mail Whitelist",24],
"comment": ["Comment",116],
"userPassword": ["Crypted Password",117],
"dnsZoneEntry": ["d.net Entry",118]};
"supplementaryGid": ["Groups the user is in"],
"allowedHost": ["Grant access to certain hosts"],
"privateSub": ["Debian-Private mailing list subscription"],
+ "gender": ["ISO5218 Gender code (1=male,2=female,9=unspecified)"],
+ "birthDate": ["Date of Birth (YYYYMMDD)"],
+ "mailDisableMessage": ["Error message to return via SMTP"],
+ "mailGreylisting": ["SMTP Greylisting (TRUE/FALSE)"],
+ "mailCallout": ["SMTP Callouts (TRUE/FALSE)"],
+ "mailRBL": ["SMTP time RBL lists"],
+ "mailRHSBL": ["SMTP time RHSBL lists"],
+ "mailWhitelist": ["SMTP time whitelist from other checks"],
"member": ["LDAP Group Member for slapd ACLs"],
"latitude": ["XEarth latitude in ISO 6709 format - see /usr/share/zoneinfo/zone.tab or etak.com"],
"longitude": ["XEarth latitude in ISO 6709 format - see /usr/share/zoneinfo/zone.tab or etak.com"],
# Change a single attribute
def ChangeAttr(Attrs,Attr):
if (Attr == "supplementaryGid" or Attr == "allowedHost" or \
- Attr == "member" or Attr == "dnsZoneEntry"):
+ Attr == "member" or Attr == "dnsZoneEntry" or Attr == "mailWhitelist" or \
+ Attr == "mailRBL" or Attr == "mailRHSBL"):
return MultiChangeAttr(Attrs,Attr);
print "Old value: '%s'" % (GetAttr(Attrs,Attr,""));
Error = 'Message Error';
SeenKey = 0;
SeenDNS = 0;
+mailRBL = {}
+mailRHSBL = {}
+mailWhitelist = {}
+SeenList = {}
DNS = {}
ArbChanges = {"c": "..",
"postalCode": ".*",
"loginShell": ".*",
"emailForward": "^([^<>@]+@.+)?$",
+ "jabberJID": "^([^<>@]+@.+)?$",
"ircNick": ".*",
"icqUin": "^[0-9]*$",
"onVacation": ".*",
- "labeledURI": ".*"};
+ "labeledURI": ".*",
+ "mailDisableMessage": ".*",
+ "mailGreylisting": "^(TRUE|FALSE)$",
+ "mailCallout": "^(TRUE|FALSE)$",
+};
DelItems = {"c": None,
"l": None,
"latitude": None,
"longitude": None,
"icqUin": None,
+ "jabberJID": None,
+ "jpegPhoto": None,
"dnsZoneEntry": None,
"sshRSAAuthKey": None,
- "sshDSAAuthKey": None};
+ "sshDSAAuthKey": None,
+ "birthDate" : None,
+ "mailGreylisting": None,
+ "mailCallout": None,
+ "mailRBL": None,
+ "mailRHSBL": None,
+ "mailWhitelist": None,
+ "mailDisableMessage": None,
+ };
# Decode a GPS location from some common forms
def LocDecode(Str,Dir):
SeenDNS = 1;
return "DNS Entry replaced with "+Str;
+# Handle an RBL list (mailRBL, mailRHSBL, mailWhitelist)
+def DoRBL(Str,Attrs):
+ Match = re.compile('^mail(rbl|rhsbl|whitelist) ([\w.]+)$').match(string.lower(Str))
+ if Match == None:
+ return None
+
+ if Match.group(1) == "rbl":
+ Key = "mailRBL"
+ if Match.group(1) == "rhsbl":
+ Key = "mailRHSBL"
+ if Match.group(1) == "whitelist":
+ Key = "mailWhitelist"
+ Host = Match.group(2)
+
+ global SeenList
+ if SeenList.has_key(Key):
+ Attrs.append((ldap.MOD_ADD,Key,Host))
+ return "%s added %s" % (Key,Host)
+
+ Attrs.append((ldap.MOD_REPLACE,Key,Host))
+ SeenList[Key] = 1;
+ return "%s replaced with %s" % (Key,Host)
+
# Handle an [almost] arbitary change
def HandleChange(Reply,DnRecord,Key):
global PlainText;
else:
Res = DoPosition(Line,Attrs) or DoDNS(Line,Attrs,DnRecord) or \
DoArbChange(Line,Attrs) or DoSSH(Line,Attrs) or \
- DoDel(Line,Attrs);
+ DoDel(Line,Attrs) or DoRBL(Line,Attrs);
except:
Res = None;
Result = Result + "==> %s: %s\n" %(sys.exc_type,sys.exc_value);