package de.hsadmin.mods.dom; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.Query; import de.hsadmin.core.model.AbstractEntity; import de.hsadmin.core.qserv.CompoundProcessor; import de.hsadmin.core.qserv.CopyFileProcessor; import de.hsadmin.core.qserv.CreateFileProcessor; import de.hsadmin.core.qserv.EntityProcessorFactory; import de.hsadmin.core.qserv.Processor; import de.hsadmin.core.qserv.ProcessorException; import de.hsadmin.core.qserv.ShellProcessor; import de.hsadmin.core.qserv.TemplateProcessor; import de.hsadmin.core.qserv.WaitingTasksProcessor; import de.hsadmin.core.util.Config; import de.hsadmin.mods.email.EMailAddress; import de.hsadmin.mods.email.EMailAddressProcessorFactory; import de.hsadmin.mods.pac.INetAddress; import de.hsadmin.mods.pac.Pac; import de.hsadmin.mods.user.UnixUser; public class DomainProcessorFactory implements EntityProcessorFactory { private static final String[] DW_STRUCTURE = new String[] { "htdocs", "htdocs-ssl", "subs", "subs/www", "subs-ssl", "subs-ssl/www", "cgi", "fastcgi", "cgi-ssl", "fastcgi-ssl", "etc", "var" }; private static final String[] SW_STRUCTURE = new String[] { "htdocs", "htdocs-ssl", "subs", "subs/www", "subs-ssl", "subs-ssl/www", "etc", "var" }; public Processor createCreateProcessor(EntityManager em, T entity) throws ProcessorException { String hiveName = entity.getHiveName(); Domain dom = (Domain) entity; UnixUser domUser = dom.getUser(); Pac pac = domUser.getPac(); String pacName = pac.getName(); String domName = dom.getName(); Map templateVars = new HashMap(); templateVars.put("SIO", Long.toString(System.currentTimeMillis()/1000L)); templateVars.put("PAC", pacName); templateVars.put("HIVE", pac.getHiveName()); templateVars.put("DOM_HOSTNAME", domName); templateVars.put("DOM_USERNAME", domUser.getName()); templateVars.put("PAC_HOSTNAME", pacName + ".hostsharing.net"); templateVars.put("DOM_IPNUMBER", getCurrentIPAddress(pac)); templateVars.put("DOM_IPNUMBEREX", getOldIPAddress(pac)); WaitingTasksProcessor mainProcessor = new WaitingTasksProcessor(createHiveDNSSetupProcessor(domName, templateVars)); mainProcessor.appendProcessor(hiveName, createHiveEMailSetupProcessor(em, domName), "Setup EMail"); String pacInetAddr = pac.getCurINetAddr().getInetAddr(); Config config = Config.getInstance(); for (String queueName : config.getProperty("queues.dns").split(",")) { mainProcessor.appendProcessor(queueName, createDNSServerSetupProcessor(domName, pacInetAddr), queueName + ".hostsharing.net"); } for (String queueName : config.getProperty("queues.mail").split(",")) { mainProcessor.appendProcessor(queueName, createMailinSetupProcessor(em, domName, pac), queueName + ".hostsharing.net"); } templateVars = new HashMap(); templateVars.put("PAC", pacName); templateVars.put("HIVE", pac.getHiveName()); templateVars.put("DOM_HOSTNAME", domName); templateVars.put("DOM_USERNAME", domUser.getName()); templateVars.put("PAC_HOSTNAME", pacName + ".hostsharing.net"); templateVars.put("DOM_IPNUMBER", getCurrentIPAddress(pac)); templateVars.put("DOM_IPNUMBEREX", getOldIPAddress(pac)); templateVars.put("DOMAIN", domName); templateVars.put("USER_NAME", domUser.getComment()); mainProcessor.appendProcessor(hiveName, createApacheVHostSetupProcessor(em, dom, templateVars), "Setup Apache VHost"); if (dom.isPacDomain()) { mainProcessor.appendProcessor(hiveName, createMovePacDomainContent(em, dom), "Move pac domain content"); } return mainProcessor; } public Processor createUpdateProcessor(EntityManager em, T entity) throws ProcessorException { Domain dom = (Domain) entity; UnixUser domUser = dom.getUser(); Pac pac = domUser.getPac(); String pacName = pac.getName(); String domName = dom.getName(); Map templateVars = new HashMap(); templateVars.put("PAC", pacName); templateVars.put("HIVE", pac.getHiveName()); templateVars.put("DOM_HOSTNAME", domName); templateVars.put("DOM_USERNAME", domUser.getName()); templateVars.put("PAC_HOSTNAME", pacName + ".hostsharing.net"); templateVars.put("DOM_IPNUMBER", getCurrentIPAddress(pac)); templateVars.put("DOM_IPNUMBEREX", getOldIPAddress(pac)); templateVars.put("DOMAIN", domName); templateVars.put("USER_NAME", domUser.getComment()); WaitingTasksProcessor processor = new WaitingTasksProcessor(createApacheVHostSetupProcessor(em, dom, templateVars)); Config config = Config.getInstance(); for (String queueName : config.getProperty("queues.mail").split(",")) { processor.appendProcessor(queueName, createPostgreyConfiguration(em), queueName + ".hostsharing.net"); } return processor; } public Processor createDeleteProcessor(EntityManager em, T entity) throws ProcessorException { Domain dom = (Domain) entity; String domName = dom.getName(); WaitingTasksProcessor mainProcessor = new WaitingTasksProcessor( new CompoundProcessor( createHiveEMailRemoveProcessor(domName), createHiveDNSRemoveProcessor(domName) ) ); Config config = Config.getInstance(); for (String queueName : config.getProperty("queues.dns").split(",")) { mainProcessor.appendProcessor(queueName, createDNSServerRemoveProcessor(domName), queueName + ".hostsharing.net"); } for (String queueName : config.getProperty("queues.mail").split(",")) { mainProcessor.appendProcessor(queueName, createMailinDeleteProcessor(domName), queueName + ".hostsharing.net"); mainProcessor.appendProcessor(queueName, createPostgreyConfiguration(em), queueName + ".hostsharing.net"); } mainProcessor.appendProcessor(dom.getHiveName(), createApacheVHostDeleteProcessor(dom), "remove apache vhost"); return mainProcessor; } private Processor createHiveDNSSetupProcessor(String domName, Map templateVars) throws ProcessorException { String zonefileTargetPath = "/etc/bind/pri." + domName; Processor zonefileTemplateProcessor = new TemplateProcessor("/de/hsadmin/mods/dom/zonefile.jtpl", templateVars, zonefileTargetPath, false); Processor zonefileACLProcessor = new ShellProcessor("chown root:bind " + zonefileTargetPath + " && chmod 644 " + zonefileTargetPath); Processor prizonesFileProcessor = new ShellProcessor("echo 'zone \"" + domName + "\" { type master; file \"pri." + domName + "\"; };' >>/etc/bind/named.pri-zones" + " && sort /etc/bind/named.pri-zones | uniq >/etc/bind/named.pri-zones.tmp" + " && mv /etc/bind/named.pri-zones.tmp /etc/bind/named.pri-zones"); Processor dnsReloadProcessor = new ShellProcessor("invoke-rc.d bind9 reload"); Processor dnsSetupProcessor = new CompoundProcessor(zonefileTemplateProcessor, zonefileACLProcessor, prizonesFileProcessor, dnsReloadProcessor); return dnsSetupProcessor; } private ShellProcessor createHiveDNSRemoveProcessor(String domName) { return new ShellProcessor("grep -v '\"pri." + domName + "\"' /etc/bind/named.pri-zones > /etc/bind/named.pri-zones.tmp" + " && mv /etc/bind/named.pri-zones.tmp /etc/bind/named.pri-zones" + " && rm /etc/bind/pri." + domName + " && invoke-rc.d bind9 reload"); } private CompoundProcessor createHiveEMailSetupProcessor(EntityManager em, String domName) { EMailAddressProcessorFactory eMailAddressProcessorFactory = new EMailAddressProcessorFactory(); CompoundProcessor emailAdrProcessor = new CompoundProcessor(); Query query = em.createQuery( "SELECT adr FROM " + EMailAddress.class.getAnnotation(javax.persistence.Entity.class).name() + " adr " + "WHERE adr.domain.name='" + domName + "'"); List resultList = query.getResultList(); for (Object obj : resultList) { EMailAddress eMailAddress = (EMailAddress) obj; emailAdrProcessor.appendProcessor(eMailAddressProcessorFactory.createCreateProcessor(em, eMailAddress)); } return emailAdrProcessor; } private ShellProcessor createHiveEMailRemoveProcessor(String domName) { return new ShellProcessor( "postmap -d '" + domName + "' /etc/postfix-mailin/virtual && " + "for KEY in $(postmap -s /etc/postfix-mailin/virtual|grep '@" + domName + "\\s'|cut -f1); " + "do postmap -d $KEY /etc/postfix-mailin/virtual; done" ); } private Processor createDNSServerSetupProcessor(String domName, String pacInetAddr) { Processor seczonesFileProcessor; seczonesFileProcessor = new ShellProcessor("echo 'zone \"" + domName + "\" { type slave; file \"sec." + domName + "\"; masters { " + pacInetAddr + "; }; };' >>/etc/bind/named-hsh.conf" + " && sort /etc/bind/named-hsh.conf | uniq >/etc/bind/named-hsh.conf.tmp" + " && mv /etc/bind/named-hsh.conf.tmp /etc/bind/named-hsh.conf" + " && invoke-rc.d bind9 reload"); return seczonesFileProcessor; } private Processor createDNSServerRemoveProcessor(String domName) { return new ShellProcessor("grep -v '\"sec." + domName + "\"' /etc/bind/named-hsh.conf >/etc/bind/named-hsh.conf.tmp" + // TODO sed -e'/sec.abc.example.com/d' -i /etc/bind/named-hsh.conf " && mv /etc/bind/named-hsh.conf.tmp /etc/bind/named-hsh.conf" + " && rm /var/cache/bind/sec." + domName + " && invoke-rc.d bind9 reload"); } private Processor createMailinSetupProcessor(EntityManager em, String domName, Pac pac) throws ProcessorException { String inetAddr = pac.getCurINetAddr().getInetAddr(); return new CompoundProcessor( createPostgreyConfiguration(em), new ShellProcessor("postmap -r -i /etc/postfix-mailin/relaydomains", domName + " anything\n" + "." + domName + " anything\n"), new ShellProcessor("postmap -r -i /etc/postfix-mailin/transport", domName + " smtp:" + inetAddr + ":225\n" + "." + domName + " smtp:" + inetAddr + ":225\n") ); } private Processor createPostgreyConfiguration(EntityManager em) throws ProcessorException { ArrayList> domsMaps = new ArrayList>(); Query query = em.createQuery("SELECT d FROM Domains d WHERE d.domainoptions.name = :option"); query.setParameter("option", "nogreylisting"); List result = query.getResultList(); for (Object dom : result) { if (dom instanceof Domain) { HashMap hashMap = new HashMap(); hashMap.put("DOM", ((Domain) dom).getName()); domsMaps.add(hashMap); } } return new CompoundProcessor( new TemplateProcessor("/de/hsadmin/mods/dom/postgrey-whitelist-recipients.jtpl", new HashMap(), domsMaps.iterator(), "/etc/postgrey/whitelist_recipients.tmp", true), new ShellProcessor(" ( diff -q /etc/postgrey/whitelist_recipients.tmp /etc/postgrey/whitelist_recipients && rm /etc/postgrey/whitelist_recipients.tmp ) " + "|| ( mv /etc/postgrey/whitelist_recipients.tmp /etc/postgrey/whitelist_recipients && invoke-rc.d postgrey reload )") ); } private Processor createMailinDeleteProcessor(String domName) { Processor mailQueueProcessor = new ShellProcessor( "postmap -d '" + domName + "' /etc/postfix-mailin/relaydomains && " + "postmap -d '" + domName + "' /etc/postfix-mailin/transport && " + "postmap -d '." + domName + "' /etc/postfix-mailin/relaydomains && " + "postmap -d '." + domName + "' /etc/postfix-mailin/transport"); return mailQueueProcessor; } private CompoundProcessor createDomainDirectoriesProcessor(Domain dom, Map templateVars) throws ProcessorException { UnixUser domUser = dom.getUser(); String domName = dom.getName(); Pac pac = domUser.getPac(); boolean dynamicWeb = pac.isDynamicWeb() || dom.isPacDomain(); String pacName = pac.getName(); String homeDir = domUser.getHomedir(); String domsDir = homeDir + "/doms"; String userName = domUser.getName(); String domainDir = domsDir + "/" + dom.getName(); String[] subDirs = dynamicWeb ? DW_STRUCTURE : SW_STRUCTURE; String httpdRights = ""; if (pacName != userName) { httpdRights = "chgrp httpd " + homeDir + " && " + "chmod g+rx " + homeDir + " && "; } Processor mkDomainDirProzessor = new ShellProcessor( httpdRights + "chgrp httpd " + homeDir + " && " + "chmod g+rx " + homeDir + " && " + "mkdir --mode=1550 --parents " + domsDir + " && " + "chown httpd:" + pacName + " " + domsDir + " && " + "mkdir --mode=750 --parents " + domainDir + " && " + "chown " + userName + ":httpd " + domainDir ); CompoundProcessor domDirsProcessor = new CompoundProcessor(mkDomainDirProzessor); for (String subDir : subDirs) { domDirsProcessor.appendProcessor(new ShellProcessor( "mkdir --mode=755 --parents " + domainDir + "/" + subDir + " && " + "chown " + userName + ":" + pacName + " " + domainDir + "/" + subDir )); } templateVars.put("PROTOCOL", "http"); domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/htaccess.jtpl", templateVars, domainDir + "/htdocs/.htaccess", userName, pacName, "644", false) ); templateVars.put("PROTOCOL", "https"); domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/htaccess.jtpl", templateVars, domainDir + "/htdocs-ssl/.htaccess", userName, pacName, "644", false) ); domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/index.html.jtpl", templateVars, domainDir + "/subs/www/index.html", userName, pacName, "644", false) ); domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/index.html.jtpl", templateVars, domainDir + "/subs-ssl/www/index.html", userName, pacName, "644", false) ); if (dynamicWeb) { domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/test.cgi.jtpl", templateVars, domainDir + "/cgi/test.cgi", userName, pacName, "755", false) ); domDirsProcessor.appendProcessor( new CreateFileProcessor("/de/hsadmin/mods/dom/test.cgi.jtpl", templateVars, domainDir + "/cgi-ssl/test.cgi", userName, pacName, "755", false) ); domDirsProcessor.appendProcessor( new CopyFileProcessor("/usr/local/src/phpstub/phpstub", domainDir + "/fastcgi/phpstub", userName, pacName, "755") ); domDirsProcessor.appendProcessor( new CopyFileProcessor("/usr/local/src/phpstub/phpstub", domainDir + "/fastcgi-ssl/phpstub", userName, pacName, "755") ); } domDirsProcessor.appendProcessor( new ShellProcessor("ln -sf " + domainDir + " /home/doms/ && " + "chown --no-dereference " + userName + ":httpd /home/doms/" + domName + " && " + "chown " + userName + ":httpd /home/doms/" + domName + "/") ); return domDirsProcessor; } private Processor createApacheVHostSetupProcessor(EntityManager em, Domain dom, Map templateVars) throws ProcessorException { String domName = dom.getName(); int level = domName.split("\\.").length; String linkPrefix = Integer.toString(100 - level); String pac = dom.getUser().getPac().getName(); Query query = em.createQuery("SELECT d FROM Domains d WHERE d.domainoptions.name = :option AND d.name = :domname"); query.setParameter("option", "nohtdocsfallback"); query.setParameter("domname", dom.getName()); List result = query.getResultList(); List> iterateMaps = new ArrayList>(); if (!result.isEmpty()) { iterateMaps.add(new HashMap()); } Processor domSetupProcessor = new CompoundProcessor( createDomainDirectoriesProcessor(dom, templateVars), new CreateFileProcessor(selectVHostTemplate(dom), templateVars, iterateMaps.iterator(), "/etc/apache2/sites-available/" + domName + ".tmp", "root", "root", "644", true), new ShellProcessor("ls /etc/apache2/pems/" + pac + ".pem >/dev/null 2>&1 " + "&& sed -i '/SSLCertificate.*default/d' " + "/etc/apache2/sites-available/" + domName + ".tmp" + " && (ls /etc/apache2/pems/" + pac + ".chain.pem >/dev/null 2>&1 || sed -i '/SSLCertificateChain.*" + pac + "/d' " + "/etc/apache2/sites-available/" + domName + ".tmp )" + " || sed -i '/SSLCertificate.*" + pac + "/d' " + "/etc/apache2/sites-available/" + domName + ".tmp"), new ShellProcessor( " (diff -q /etc/apache2/sites-available/" + domName + ".tmp /etc/apache2/sites-available/" + domName + " && rm /etc/apache2/sites-available/" + domName + ".tmp ) " + " || (mv /etc/apache2/sites-available/" + domName + ".tmp /etc/apache2/sites-available/" + domName + " && rm -f /etc/apache2/sites-enabled/" + linkPrefix + "-" + domName + " && ln -sf /etc/apache2/sites-available/" + domName + " /etc/apache2/sites-enabled/" + linkPrefix + "-" + domName + " && invoke-rc.d apache2 reload >/dev/null 2>&1)") ); return domSetupProcessor; } private Processor createApacheVHostDeleteProcessor(Domain dom) { String domName = dom.getName(); int level = domName.split("\\.").length; String linkPrefix = Integer.toString(100 - level); Processor vhostDelProcessor = new ShellProcessor("rm /home/doms/" + domName + " && rm /etc/apache2/sites-enabled/" + linkPrefix + "-" + domName + " && rm /etc/apache2/sites-available/" + domName + " && rm -rf " + dom.getUser().getHomedir() + "/doms/" + domName + " && invoke-rc.d apache2 reload >/dev/null 2>&1"); return vhostDelProcessor; } private Processor createMovePacDomainContent(EntityManager em, Domain dom) { Pac pac = dom.getUser().getPac(); String pacDir = "/home/pacs/" + pac.getName(); String domDir = pacDir + "/doms/" + pac.getName() + ".hostsharing.net"; String[] sourceDirs = new String[] { "web", "web-ssl", "cgi", "cgi-ssl", "fastcgi", "fastcgi-ssl" } ; String[] targetDirs = new String[] { "htdocs", "htdocs-ssl", "cgi", "cgi-ssl", "fastcgi", "fastcgi-ssl" } ; CompoundProcessor processor = new CompoundProcessor( new ShellProcessor("rm -rf " + domDir + "/subs " + domDir + "/htdocs/.htaccess " + domDir + "/subs-ssl " + domDir + "/htdocs-ssl/.htaccess ")); for (int idx = 0; idx < sourceDirs.length; idx++) { processor.appendProcessor( new ShellProcessor("shopt -s dotglob && ls " + pacDir + "/" + sourceDirs[idx] + " >/dev/null 2>&1" + " && mv " + pacDir + "/" + sourceDirs[idx] + "/* " + domDir + "/" + targetDirs[idx] + "/ " + " && ( rmdir " + pacDir + "/" + sourceDirs[idx] + " || rm " + pacDir + "/" + sourceDirs[idx] + " ) " + " || echo 'directory " + pacDir + "/" + sourceDirs[idx] + " not found'")); } return processor; } private String selectVHostTemplate(Domain dom) { String domName = dom.getName(); UnixUser user = dom.getUser(); Pac pac = user.getPac(); if (domName.equals(pac.getName() + ".hostsharing.net")) { return "/de/hsadmin/mods/dom/httpd-vhost-dynamic.jtpl"; } if (pac.isDynamicWeb() || dom.isPacDomain()) { return "/de/hsadmin/mods/dom/httpd-vhost-dynamic.jtpl"; } return "/de/hsadmin/mods/dom/httpd-vhost-static.jtpl"; } private String getCurrentIPAddress(Pac pac) { return pac.getCurINetAddr().getInetAddr(); } private String getOldIPAddress(Pac pac) { INetAddress oldINetAddr = pac.getOldINetAddr(); if (oldINetAddr != null) { return oldINetAddr.getInetAddr(); } else { return getCurrentIPAddress(pac); } } }