HSAdmin Backend Domains, E-Mail, Datenbanken
Peter Hormanns
2019-12-02 e084e04133b773388e058edd300f0aaf9f421fe3
add autoconfig feature
2 files modified
1 files added
168 ■■■■■ changed files
hsarback/conf/WEB-INF/prod-web.xml 10 ●●●●● patch | view | raw | blame | history
hsarback/src/de/hsadmin/autoconfig/AutoconfigAutodiscoverServlet.java 156 ●●●●● patch | view | raw | blame | history
hsarback/src/de/hsadmin/pillar/JsonPillarServlet.java 2 ●●● patch | view | raw | blame | history
hsarback/conf/WEB-INF/prod-web.xml
@@ -44,6 +44,11 @@
        <servlet-class>de.hsadmin.pillar.JsonPillarServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>AutoconfigServlet</servlet-name>
        <servlet-class>de.hsadmin.autoconfig.AutoconfigAutodiscoverServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Queue Status Servlet</servlet-name>
        <url-pattern>/queueStatus</url-pattern>
@@ -54,6 +59,11 @@
        <url-pattern>/pillar</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>AutoconfigServlet</servlet-name>
        <url-pattern>/config-v1.1.xml</url-pattern>
    </servlet-mapping>
    <!--
    <servlet-mapping>
        <servlet-name>Queue PacTasks Servlet</servlet-name>
hsarback/src/de/hsadmin/autoconfig/AutoconfigAutodiscoverServlet.java
New file
@@ -0,0 +1,156 @@
package de.hsadmin.autoconfig;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.commons.httpclient.HttpStatus;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import de.hsadmin.core.model.Transaction;
import de.hsadmin.core.util.IPv6Trick;
import de.hsadmin.mods.email.EMailAddress;
import de.hsadmin.mods.pac.Pac;
import de.hsadmin.mods.user.UnixUser;
public class AutoconfigAutodiscoverServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * Thunderbird autoconfig
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        final String emailAddr = req.getParameter("emailaddress");
        if (emailAddr == null || emailAddr.length() == 0) {
            resp.sendError(HttpStatus.SC_UNAUTHORIZED);
            return;
        }
        final String[] addrParts = emailAddr.split("@");
        if (addrParts.length != 2) {
            resp.sendError(HttpStatus.SC_BAD_REQUEST);
            return;
        }
        final String localpart = addrParts[0];
        final String domain = addrParts[1];
        final Transaction transaction = new Transaction("autoconfig");
        final EntityManager em = transaction.getEntityManager();
        final Query emailQuery = em.createQuery("SELECT addr FROM EMailAddresses WHERE addr.localpart = :localpart AND addr.domain = :domain AND ( addr.subdomain IS NULL OR addr.subdomain = :subdomain)");
        emailQuery.setParameter("subdomain", "");
        emailQuery.setParameter("domain", domain);
        emailQuery.setParameter("localpart", localpart);
        final Object emailResult = emailQuery.getSingleResult();
        if (emailResult == null) {
            transaction.close();
            resp.sendError(HttpStatus.SC_BAD_REQUEST);
            return;
        }
        final EMailAddress emailAddress = (EMailAddress) emailResult;
        final Query mboxQuery = em.createQuery("SELECT mbox FROM UnixUsers WHERE mbox.name = :target");
        final String target = emailAddress.getTarget();
        if (target == null || target.length() < 5 || (target.length() > 6 && target.charAt(5) != '-')) {
            transaction.close();
            resp.sendError(HttpStatus.SC_BAD_REQUEST);
            return;
        }
        mboxQuery.setParameter("target", target);
        final Object mboxResult = mboxQuery.getSingleResult();
        if (mboxResult == null) {
            transaction.close();
            resp.sendError(HttpStatus.SC_BAD_REQUEST);
            return;
        }
        final UnixUser mbox = (UnixUser) mboxResult;
        final Pac pac = mbox.getPac();
        final String pacDomain = pac.getName() + ".hostsharing.net";
        final String userName = mbox.getName();
        try {
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            Document document = builder.newDocument();
            Element clientConfig = document.createElement("clientConfig");
            clientConfig.setAttribute("version", "1.1");
            document.appendChild(clientConfig);
            Element emailProvider = appendElementWithAttribute(document, clientConfig, "emailProvider", "id", "hostsharing.net");
            appendElementWithText(document, emailProvider, "domain", "hostsharing.net");
            Element incomingServer = appendElementWithAttribute(document, emailProvider, "incomingServer", "type", "imap");
            appendElementWithText(document, incomingServer, "hostname", pacDomain);
            appendElementWithText(document, incomingServer, "port", "993");
            appendElementWithText(document, incomingServer, "socketType", "SSL");
            appendElementWithText(document, incomingServer, "username", userName);
            appendElementWithText(document, incomingServer, "authentication", "password-cleartext");
            Element outgoingServer = appendElementWithAttribute(document, emailProvider, "outgoingServer", "type", "smtp");
            appendElementWithText(document, outgoingServer, "hostname", pacDomain);
            appendElementWithText(document, outgoingServer, "port", "465");
            appendElementWithText(document, outgoingServer, "socketType", "SSL");
            appendElementWithText(document, outgoingServer, "username", userName);
            appendElementWithText(document, outgoingServer, "authentication", "password-cleartext");
            appendElementWithText(document, outgoingServer, "addThisServer", "true");
            appendElementWithText(document, outgoingServer, "useGlobalPreferredServer", "true");
            serializeDocument(document, resp);
        } catch (DOMException e) {
            throw new ServletException(e);
        } catch (ParserConfigurationException e) {
            throw new ServletException(e);
        }
        transaction.close();
    }
    /**
     * Microsoft autodiscover
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        final String remoteAddr = req.getRemoteAddr();
        if (!IPv6Trick.isKnownRemote(remoteAddr)) {
            resp.sendError(HttpStatus.SC_UNAUTHORIZED);
            return;
        }
    }
    private Element appendElementWithAttribute(final Document document, final Element parent,
            final String childElementName, final String attributeName, final String attributeValue) {
        final Element child = document.createElement(childElementName);
        child.setAttribute(attributeName, attributeValue);
        parent.appendChild(child);
        return child;
    }
    private Element appendElementWithText(final Document document, final Element parent,
            final String childElementName, final String text) {
        final Element child = document.createElement(childElementName);
        parent.appendChild(child);
        child.appendChild(document.createTextNode(text));
        return child;
    }
    private void serializeDocument(final Document document, final HttpServletResponse resp)
            throws ServletException {
        resp.setContentType("text/xml");
        try {
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult(resp.getOutputStream()));
        } catch (TransformerException e) {
            throw new ServletException(e);
        } catch (IOException e) {
            throw new ServletException(e);
        }
    }
}
hsarback/src/de/hsadmin/pillar/JsonPillarServlet.java
@@ -137,7 +137,7 @@
        writer.println("  ]");
        writer.println("}");
        writer.close();
        em.close();
        transaction.close();
    }
    
}