>From 594c4e2924069757d764a34f5cf479c8ed728357 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 15 Feb 2017 17:51:28 +0100
Subject: [PATCH] Added InfoService and LoginService.

New REST services classes have been added to PKIApplication.
The InfoService provides general information about the server
including version number and access banner. The LoginService
provides a way to notify the server that the banner has been
displayed on the client, which in that case the InfoService
will no longer return the banner again in the same session.

https://fedorahosted.org/pki/ticket/2582
---
 base/common/src/CMakeLists.txt                     |   3 +-
 base/common/src/org/dogtagpki/common/Info.java     | 138 +++++++++++++++++++++
 .../src/org/dogtagpki/common/InfoClient.java       |  48 +++++++
 .../src/org/dogtagpki/common/InfoResource.java     |  36 ++++++
 .../src/org/dogtagpki/common/LoginClient.java      |  48 +++++++
 .../src/org/dogtagpki/common/LoginResource.java    |  36 ++++++
 base/server/cms/src/CMakeLists.txt                 |   1 +
 .../com/netscape/cms/servlet/base/PKIService.java  |  22 +++-
 .../src/org/dogtagpki/server/rest/InfoService.java |  58 +++++++++
 .../org/dogtagpki/server/rest/LoginService.java    |  48 +++++++
 .../org/dogtagpki/server/rest/PKIApplication.java  |   2 +
 11 files changed, 437 insertions(+), 3 deletions(-)
 create mode 100644 base/common/src/org/dogtagpki/common/Info.java
 create mode 100644 base/common/src/org/dogtagpki/common/InfoClient.java
 create mode 100644 base/common/src/org/dogtagpki/common/InfoResource.java
 create mode 100644 base/common/src/org/dogtagpki/common/LoginClient.java
 create mode 100644 base/common/src/org/dogtagpki/common/LoginResource.java
 create mode 100644 base/server/cms/src/org/dogtagpki/server/rest/InfoService.java
 create mode 100644 base/server/cms/src/org/dogtagpki/server/rest/LoginService.java

diff --git a/base/common/src/CMakeLists.txt b/base/common/src/CMakeLists.txt
index 2c0672c..c08d1b7 100644
--- a/base/common/src/CMakeLists.txt
+++ b/base/common/src/CMakeLists.txt
@@ -101,13 +101,14 @@ javac(pki-certsrv-classes
     SOURCES
         *.java
     CLASSPATH
-        ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR}
+        ${SLF4J_API_JAR}
         ${LDAPJDK_JAR} ${SERVLET_JAR} ${VELOCITY_JAR} ${XALAN_JAR} ${XERCES_JAR}
         ${JSS_JAR} ${COMMONS_CODEC_JAR} ${COMMONS_HTTPCLIENT_JAR}
         ${APACHE_COMMONS_LANG_JAR}
         ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_JAR} ${SYMKEY_JAR}
         ${JAXRS_API_JAR} ${RESTEASY_JAXRS_JAR} ${RESTEASY_ATOM_PROVIDER_JAR} ${RESTEASY_CLIENT_JAR}
         ${HTTPCLIENT_JAR} ${HTTPCORE_JAR}
+        ${PKI_NSUTIL_JAR} ${PKI_CMSUTIL_JAR}
     OUTPUT_DIR
         ${CMAKE_CURRENT_BINARY_DIR}/classes
     DEPENDS
diff --git a/base/common/src/org/dogtagpki/common/Info.java b/base/common/src/org/dogtagpki/common/Info.java
new file mode 100644
index 0000000..0a216f4
--- /dev/null
+++ b/base/common/src/org/dogtagpki/common/Info.java
@@ -0,0 +1,138 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.common;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netscape.certsrv.base.ResourceMessage;
+
+/**
+ * @author Endi S. Dewata
+ */
+@XmlRootElement(name="Info")
+public class Info extends ResourceMessage {
+
+    private static Logger logger = LoggerFactory.getLogger(Info.class);
+
+    public static Marshaller marshaller;
+    public static Unmarshaller unmarshaller;
+
+    static {
+        try {
+            marshaller = JAXBContext.newInstance(Info.class).createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+            unmarshaller = JAXBContext.newInstance(Info.class).createUnmarshaller();
+        } catch (Exception e) {
+            logger.error(e.getMessage(), e);
+        }
+    }
+
+    String version;
+    String banner;
+
+    @XmlElement(name="Version")
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    @XmlElement(name="Banner")
+    public String getBanner() {
+        return banner;
+    }
+
+    public void setBanner(String banner) {
+        this.banner = banner;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((banner == null) ? 0 : banner.hashCode());
+        result = prime * result + ((version == null) ? 0 : version.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (!super.equals(obj))
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Info other = (Info) obj;
+        if (banner == null) {
+            if (other.banner != null)
+                return false;
+        } else if (!banner.equals(other.banner))
+            return false;
+        if (version == null) {
+            if (other.version != null)
+                return false;
+        } else if (!version.equals(other.version))
+            return false;
+        return true;
+    }
+
+    public String toString() {
+        try {
+            StringWriter sw = new StringWriter();
+            marshaller.marshal(this, sw);
+            return sw.toString();
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static Info valueOf(String string) throws Exception {
+        return (Info)unmarshaller.unmarshal(new StringReader(string));
+    }
+
+    public static void main(String args[]) throws Exception {
+
+        Info before = new Info();
+        before.setVersion("10.4.0");
+        before.setBanner(
+                "WARNING!\n" +
+                "Access to this service is restricted to those individuals with " +
+                "specific permissions.");
+
+        String string = before.toString();
+        System.out.println(string);
+
+        Info after = Info.valueOf(string);
+        System.out.println(before.equals(after));
+    }
+}
diff --git a/base/common/src/org/dogtagpki/common/InfoClient.java b/base/common/src/org/dogtagpki/common/InfoClient.java
new file mode 100644
index 0000000..9feddb7
--- /dev/null
+++ b/base/common/src/org/dogtagpki/common/InfoClient.java
@@ -0,0 +1,48 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2017 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.common;
+
+import java.net.URISyntaxException;
+
+import javax.ws.rs.core.Response;
+
+import com.netscape.certsrv.client.Client;
+import com.netscape.certsrv.client.PKIClient;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class InfoClient extends Client {
+
+    public InfoResource resource;
+
+    public InfoClient(PKIClient client) throws URISyntaxException {
+        super(client, "pki", "info");
+        init();
+    }
+
+    public void init() throws URISyntaxException {
+        resource = createProxy(InfoResource.class);
+    }
+
+    public Info getInfo() throws Exception {
+        Response response = resource.getInfo();
+        return client.getEntity(response, Info.class);
+    }
+}
diff --git a/base/common/src/org/dogtagpki/common/InfoResource.java b/base/common/src/org/dogtagpki/common/InfoResource.java
new file mode 100644
index 0000000..2861a6a
--- /dev/null
+++ b/base/common/src/org/dogtagpki/common/InfoResource.java
@@ -0,0 +1,36 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.common;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.ClientResponseType;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Path("info")
+public interface InfoResource {
+
+    @GET
+    @ClientResponseType(entityType=Info.class)
+    public Response getInfo() throws Exception;
+}
diff --git a/base/common/src/org/dogtagpki/common/LoginClient.java b/base/common/src/org/dogtagpki/common/LoginClient.java
new file mode 100644
index 0000000..575915e
--- /dev/null
+++ b/base/common/src/org/dogtagpki/common/LoginClient.java
@@ -0,0 +1,48 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2017 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.common;
+
+import java.net.URISyntaxException;
+
+import javax.ws.rs.core.Response;
+
+import com.netscape.certsrv.client.Client;
+import com.netscape.certsrv.client.PKIClient;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class LoginClient extends Client {
+
+    public LoginResource resource;
+
+    public LoginClient(PKIClient client) throws URISyntaxException {
+        super(client, "pki", "login");
+        init();
+    }
+
+    public void init() throws URISyntaxException {
+        resource = createProxy(LoginResource.class);
+    }
+
+    public void login() throws Exception {
+        Response response = resource.login();
+        client.getEntity(response, Void.class);
+    }
+}
diff --git a/base/common/src/org/dogtagpki/common/LoginResource.java b/base/common/src/org/dogtagpki/common/LoginResource.java
new file mode 100644
index 0000000..57936eb
--- /dev/null
+++ b/base/common/src/org/dogtagpki/common/LoginResource.java
@@ -0,0 +1,36 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.common;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.ClientResponseType;
+
+/**
+ * @author Endi S. Dewata
+ */
+@Path("login")
+public interface LoginResource {
+
+    @POST
+    @ClientResponseType(entityType=Void.class)
+    public Response login() throws Exception;
+}
diff --git a/base/server/cms/src/CMakeLists.txt b/base/server/cms/src/CMakeLists.txt
index 7c56595..2ca0285 100644
--- a/base/server/cms/src/CMakeLists.txt
+++ b/base/server/cms/src/CMakeLists.txt
@@ -101,6 +101,7 @@ javac(pki-cms-classes
     SOURCES
         *.java
     CLASSPATH
+        ${SLF4J_API_JAR}
         ${COMMONS_CODEC_JAR} ${COMMONS_IO_JAR} ${COMMONS_LANG_JAR} ${COMMONS_HTTPCLIENT_JAR}
         ${HTTPCLIENT_JAR} ${HTTPCORE_JAR}
         ${XALAN_JAR} ${XERCES_JAR}
diff --git a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
index 3ed4b91..8dfbef1 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
@@ -17,8 +17,12 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.cms.servlet.base;
 
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -78,8 +82,22 @@ public class PKIService {
     @Context
     protected ServletContext servletContext;
 
-    public String getInstanceDir() {
-        return System.getProperty("catalina.base");
+    public static Path bannerFile = Paths.get(getInstanceDir(), "conf", "banner.txt");
+
+    public static String getInstanceDir() {
+        return System.getProperty("catalina.base");  // provided by Tomcat
+    }
+
+    public static String getVersion() {
+        return System.getenv("PKI_VERSION");  // defined in tomcat.conf
+    }
+
+    public static boolean isBannerEnabled() {
+        return Files.exists(bannerFile);
+    }
+
+    public static String getBanner() throws IOException {
+        return new String(Files.readAllBytes(bannerFile));
     }
 
     public static MediaType resolveFormat(MediaType format) {
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java b/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java
new file mode 100644
index 0000000..13581dd
--- /dev/null
+++ b/base/server/cms/src/org/dogtagpki/server/rest/InfoService.java
@@ -0,0 +1,58 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.rest;
+
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.Response;
+
+import org.dogtagpki.common.Info;
+import org.dogtagpki.common.InfoResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class InfoService extends PKIService implements InfoResource {
+
+    private static Logger logger = LoggerFactory.getLogger(InfoService.class);
+
+    @Override
+    public Response getInfo() throws Exception {
+
+        HttpSession session = servletRequest.getSession();
+        logger.debug("InfoService.getInfo(): session: " + session.getId());
+
+        Info info = new Info();
+        info.setVersion(getVersion());
+
+        boolean bannerDisplayed = session.getAttribute("bannerDisplayed") != null;
+        boolean bannerEnabled = isBannerEnabled();
+
+        // if banner not yet displayed in this session and it's enabled, return banner
+        if (!bannerDisplayed && bannerEnabled) {
+            String banner = getBanner();
+            info.setBanner(banner);
+        }
+
+        return createOKResponse(info);
+    }
+}
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/LoginService.java b/base/server/cms/src/org/dogtagpki/server/rest/LoginService.java
new file mode 100644
index 0000000..40f8913
--- /dev/null
+++ b/base/server/cms/src/org/dogtagpki/server/rest/LoginService.java
@@ -0,0 +1,48 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2017 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.rest;
+
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.Response;
+
+import org.dogtagpki.common.LoginResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class LoginService extends PKIService implements LoginResource {
+
+    private static Logger logger = LoggerFactory.getLogger(LoginService.class);
+
+    @Override
+    public Response login() throws Exception {
+
+        HttpSession session = servletRequest.getSession();
+        logger.debug("LoginService.login(): session: " + session.getId());
+
+        // mark banner displayed in this session
+        session.setAttribute("bannerDisplayed", "true");
+
+        return createNoContentResponse();
+    }
+}
diff --git a/base/server/cms/src/org/dogtagpki/server/rest/PKIApplication.java b/base/server/cms/src/org/dogtagpki/server/rest/PKIApplication.java
index d6ac793..9f31cae 100644
--- a/base/server/cms/src/org/dogtagpki/server/rest/PKIApplication.java
+++ b/base/server/cms/src/org/dogtagpki/server/rest/PKIApplication.java
@@ -31,6 +31,8 @@ public class PKIApplication extends Application {
     public PKIApplication() {
 
         // services
+        classes.add(InfoService.class);
+        classes.add(LoginService.class);
 
         // exception mappers
         classes.add(PKIExceptionMapper.class);
-- 
2.9.3

