From e3f53172bf7198ffc15d853a9cfef02200f32c88 Mon Sep 17 00:00:00 2001 From: Ade Lee Date: Thu, 20 Dec 2012 17:38:13 -0500 Subject: Resolved Trac Ticket 367 - pkidestroy does not remove connector * Added RESTful servlet to add/remove a KRA connector from the CA. * Modified ACL to allow KRA subsystem user to remove connector. * Modified connector code to allow the connector to be replaced without a server restart. * Added functionality to pki CLI to add/remove connector * Added code to pkidestroy to remove the connector (using both pki CLI and sslget) When the issues with pki connection are resolved, we will use that method instead. * Modified sslget to accept HTTP return codes != 200. In this case, we were returning 204 - which is perfectly legitimate. --- base/ca/shared/conf/acl.ldif | 2 +- base/ca/shared/webapps/ca/WEB-INF/auth.properties | 1 + .../ca/CertificateAuthorityApplication.java | 4 + .../com/netscape/certsrv/connector/IConnector.java | 5 + .../com/netscape/certsrv/connector/IResender.java | 3 + .../certsrv/system/KRAConnectorClient.java | 54 +++++ .../netscape/certsrv/system/KRAConnectorInfo.java | 184 +++++++++++++++++ .../certsrv/system/KRAConnectorResource.java | 55 +++++ .../cms/servlet/admin/KRAConnectorProcessor.java | 223 +++++++++++++++++++++ .../cms/servlet/admin/KRAConnectorService.java | 61 ++++++ .../cms/servlet/csadmin/UpdateConnector.java | 89 ++++---- .../netscape/cmscore/connector/HttpConnector.java | 11 +- .../netscape/cmscore/connector/LocalConnector.java | 3 + .../com/netscape/cmscore/connector/Resender.java | 68 ++++--- base/deploy/src/scriptlets/initialization.py | 4 + base/deploy/src/scriptlets/pkihelper.py | 178 ++++++++++++++-- base/deploy/src/scriptlets/pkimessages.py | 6 + .../src/com/netscape/cmstools/cli/MainCLI.java | 2 + .../cmstools/system/KRAConnectorAddCLI.java | 77 +++++++ .../netscape/cmstools/system/KRAConnectorCLI.java | 92 +++++++++ .../cmstools/system/KRAConnectorRemoveCLI.java | 52 +++++ base/native-tools/src/sslget/sslget.c | 6 +- 22 files changed, 1071 insertions(+), 109 deletions(-) create mode 100644 base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java create mode 100644 base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java create mode 100644 base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java create mode 100644 base/common/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java create mode 100644 base/common/src/com/netscape/cms/servlet/admin/KRAConnectorService.java create mode 100644 base/java-tools/src/com/netscape/cmstools/system/KRAConnectorAddCLI.java create mode 100644 base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java create mode 100644 base/java-tools/src/com/netscape/cmstools/system/KRAConnectorRemoveCLI.java diff --git a/base/ca/shared/conf/acl.ldif b/base/ca/shared/conf/acl.ldif index c7d71f9e6..732179216 100644 --- a/base/ca/shared/conf/acl.ldif +++ b/base/ca/shared/conf/acl.ldif @@ -47,7 +47,7 @@ resourceACLS: certServer.ca.connector:submit:allow (submit) group="Trusted Manag resourceACLS: certServer.ca.clone:submit:allow (submit) group="Certificate Manager Agents":Certificate Manager Agents are allowed to submit request to the master CA resourceACLS: certServer.ca.systemstatus:read:allow (read) group="Certificate Manager Agents":Certificate Manager agents may view statistics resourceACLS: certServer.ca.group:read,modify:allow (modify,read) group="Administrators":Only administrators are allowed to read and modify users and groups -resourceACLS: certServer.ca.connectorInfo:read,modify:allow (modify,read) group="Enterprise KRA Administrators":Only Enterprise Administrators are allowed to update the connector information +resourceACLS: certServer.ca.connectorInfo:read,modify:allow (read) group="Enterprise KRA Administrators";allow (modify) group="Enterprise KRA Administrators" || group="Subsystem Group":Only Enterprise Administrators and Subsystem Group are allowed to update the connector information resourceACLS: certServer.ca.registerUser:read,modify:allow (modify,read) group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise RA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TKS Administrators" || group="Enterprise TPS Administrators":Only Enterprise Administrators are allowed to register a new agent resourceACLS: certServer.clone.configuration:read,modify:allow (modify,read) group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise RA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TKS Administrators":Only Enterprise Administrators are allowed to clone the configuration. resourceACLS: certServer.admin.ocsp:read,modify:allow (modify,read) group="Enterprise OCSP Administrators":Only Enterprise Administrators are allowed to read or update the OCSP configuration. diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/auth.properties index 08f5bea50..b73b9ac10 100644 --- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties +++ b/base/ca/shared/webapps/ca/WEB-INF/auth.properties @@ -8,6 +8,7 @@ account.login = certServer.ca.account,login account.logout = certServer.ca.account,logout admin.users = certServer.ca.users,execute admin.groups = certServer.ca.groups,execute +admin.kraconnector = certServer.ca.connectorInfo,modify agent.certrequests = certServer.ca.certrequests,execute agent.certs = certServer.ca.certs,execute securityDomain.installToken = certServer.securitydomain.domainxml,read diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java index bc6dd71a6..14b44e5d7 100644 --- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java +++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java @@ -13,6 +13,7 @@ import com.netscape.certsrv.base.PKIException; import com.netscape.cms.servlet.account.AccountService; import com.netscape.cms.servlet.admin.GroupMemberService; import com.netscape.cms.servlet.admin.GroupService; +import com.netscape.cms.servlet.admin.KRAConnectorService; import com.netscape.cms.servlet.admin.SystemCertService; import com.netscape.cms.servlet.admin.UserCertService; import com.netscape.cms.servlet.admin.UserService; @@ -50,6 +51,9 @@ public class CertificateAuthorityApplication extends Application { // system certs classes.add(SystemCertService.class); + // kra connector + classes.add(KRAConnectorService.class); + // security domain IConfigStore cs = CMS.getConfigStore(); diff --git a/base/common/src/com/netscape/certsrv/connector/IConnector.java b/base/common/src/com/netscape/certsrv/connector/IConnector.java index 61001be5b..02e7231ab 100644 --- a/base/common/src/com/netscape/certsrv/connector/IConnector.java +++ b/base/common/src/com/netscape/certsrv/connector/IConnector.java @@ -58,4 +58,9 @@ public interface IConnector { * Starts this connector. */ public void start(); + + /** + * Stop the connector. + */ + public void stop(); } diff --git a/base/common/src/com/netscape/certsrv/connector/IResender.java b/base/common/src/com/netscape/certsrv/connector/IResender.java index b1cd6149e..0b643c272 100644 --- a/base/common/src/com/netscape/certsrv/connector/IResender.java +++ b/base/common/src/com/netscape/certsrv/connector/IResender.java @@ -36,4 +36,7 @@ public interface IResender extends Runnable { */ public void addRequest(IRequest r); + public void start(final String name); + + public void stop(); } diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java new file mode 100644 index 000000000..f7b2c7246 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorClient.java @@ -0,0 +1,54 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.certsrv.system; +import java.net.URISyntaxException; + +import com.netscape.certsrv.client.ClientConfig; +import com.netscape.certsrv.client.PKIClient; +import com.netscape.certsrv.client.PKIConnection; + +/** + * @author Ade Lee + */ +public class KRAConnectorClient extends PKIClient { + public KRAConnectorResource kraConnectorClient; + + public KRAConnectorClient(PKIConnection connection) throws URISyntaxException { + super(connection); + init(); + } + + public KRAConnectorClient(ClientConfig config) throws URISyntaxException { + super(config); + init(); + } + + public void init() throws URISyntaxException { + kraConnectorClient = createProxy(KRAConnectorResource.class); + } + + public void addConnector(KRAConnectorInfo info) { + kraConnectorClient.addConnector(info); + } + + public void removeConnector(String host, String port) { + kraConnectorClient.removeConnector(host, port); + } + +} diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java new file mode 100644 index 000000000..a8caca601 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorInfo.java @@ -0,0 +1,184 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.certsrv.system; + +import java.io.ByteArrayOutputStream; + +import javax.ws.rs.core.MultivaluedMap; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author Ade Lee + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class KRAConnectorInfo { + private static final String HOST = "host"; + private static final String PORT = "port"; + private static final String TRANSPORT_CERT= "transportCert"; + private static final String URI = "uri"; + private static final String TIMEOUT = "timeout"; + private static final String LOCAL = "local"; + private static final String ENABLE = "enable"; + + @XmlElement + String host; + + @XmlElement + String port; + + @XmlElement + String transportCert; + + @XmlElement + String uri; + + @XmlElement + String timeout; + + @XmlElement + String local; + + @XmlElement + String enable; + + public KRAConnectorInfo() { + // needed for jaxb + } + + public KRAConnectorInfo(MultivaluedMap form) { + host = form.getFirst(HOST); + port = form.getFirst(PORT); + transportCert = form.getFirst(TRANSPORT_CERT); + uri = form.getFirst(URI); + timeout = form.getFirst(TIMEOUT); + local = form.getFirst(LOCAL); + enable = form.getFirst(ENABLE); + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getTransportCert() { + return transportCert; + } + + public void setTransportCert(String transportCert) { + this.transportCert = transportCert; + } + + public String getUri() { + return uri; + } + + public void setUri(String uri) { + this.uri = uri; + } + + public String getTimeout() { + return timeout; + } + + public void setTimeout(String timeout) { + this.timeout = timeout; + } + + public String getLocal() { + return local; + } + + public void setLocal(String local) { + this.local = local; + } + + public String getEnable() { + return enable; + } + + public void setEnable(String enable) { + this.enable = enable; + } + + public String toString() { + try { + JAXBContext context = JAXBContext.newInstance(KRAConnectorInfo.class); + Marshaller marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + marshaller.marshal(this, stream); + return stream.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void main(String args[]) throws Exception { + KRAConnectorInfo info = new KRAConnectorInfo(); + info.setEnable("true"); + info.setHost("host1.example.com"); + info.setLocal("false"); + info.setPort("8443"); + info.setTimeout("30"); + info.setUri(""); + info.setTransportCert( + "MIIDnDCCAoSgAwIBAgIBDzANBgkqhkiG9w0BAQsFADBGMSMwIQYDVQQKExpyZWRo" + + "YXQuY29tIFNlY3VyaXR5IERvbWFpbjEfMB0GA1UEAxMWQ0EgU2lnbmluZyBDZXJ0" + + "aWZpY2F0ZTAeFw0xMzAxMDkyMTE5MDBaFw0xNDEyMzAyMTE5MDBaMEkxIzAhBgNV" + + "BAoTGnJlZGhhdC5jb20gU2VjdXJpdHkgRG9tYWluMSIwIAYDVQQDExlEUk0gVHJh" + + "bnNwb3J0IENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC" + + "AQEAqayxDggWH9Cld0O/j+HDfv7cLQexYiaDq/sEcFPYkREGisaxZggiovqLfMkz" + + "rSjutVtHuIEb3pU9frHYUjskbzdMbeU3nqDnA/ZPUw+YJe/6l19AbieADVB/L+6p" + + "TkNMwS/xsQIRnalYW9R4rebw3WiwQFxVHIorGL9qxUS5d12uguJokH/CbIML9Pek" + + "NgAZRGx87J4UkqTe5FImuEX8EwVWoW8Huc8QDthk1w5osz3jOTefwrJBEiI54d9F" + + "hl4O8ckXfecCAPYfn0Mi54I1VAbSRZEiq6GJ/xrN1IwLkaG7EmXtLU2IkaMz62MJ" + + "UmgBrlrtRj1eyAXLGwS4Fh4NVwIDAQABo4GRMIGOMB8GA1UdIwQYMBaAFMjscbmB" + + "k0Gz2wVxGWkn9bjSA88wMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcwAYYqaHR0" + + "cDovL2FsZWUtd29ya3BjLnJlZGhhdC5jb206ODI4MC9jYS9vY3NwMA4GA1UdDwEB" + + "/wQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEA" + + "gCCPZ5+pkxZDgKJpisJ8/5TfKtN/q5pO8CNKIM9Cz78ucGEaR2lzJVH5EOdO2ZM6" + + "y+5AhK2hcKifNI3DPAfYdYsSVBR6Mrij4/aAMZlqtKjlNs/LJ2TdKGRxxYsEAQL+" + + "OToCfXijDh0kzQ9oSII+9fBCWljkq/K89bSGcwR/y1v+ll+z9Wci+QAFKUzmqZyL" + + "eEbOOmYhgvVSnYV1XdB6lbWQOOdpytvECl1UaQUSsDfJkk8mH1Fkl0dnrChh7mXM" + + "2ZBYwBsI2DhAyWBKQgQfgxQwxmobbg6BVnn9/CW7gJ0Gwb+VJEvRtaBOnjliP74/" + + "Jb+fenCZE47zRNCDubBe+Q=="); + + System.out.println(info); + } +} + diff --git a/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java b/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java new file mode 100644 index 000000000..01f159e96 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/KRAConnectorResource.java @@ -0,0 +1,55 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.certsrv.system; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + +import com.netscape.certsrv.acls.ACLMapping; + +/** + * @author Ade Lee + */ +@Path("admin/kraconnector") +@ACLMapping("admin.kraconnector") +public interface KRAConnectorResource { + + @POST + @Path("add") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void addConnector(KRAConnectorInfo info); + + @POST + @Path("add") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) + public void addConnector(MultivaluedMap form); + + @POST + @Path("remove") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) + public void removeConnector(@FormParam("host") String host, @FormParam("port") String port); + +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java b/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java new file mode 100644 index 000000000..0ac54b20f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorProcessor.java @@ -0,0 +1,223 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.admin; + +import java.util.ArrayList; +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.BadRequestException; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.PKIException; +import com.netscape.certsrv.ca.ICAService; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.connector.IConnector; +import com.netscape.certsrv.system.KRAConnectorInfo; +import com.netscape.cms.servlet.processors.Processor; + +/** + * @author Ade Lee + */ +public class KRAConnectorProcessor extends Processor { + private boolean connectorExists = false; + + // Connector constants + public final static String PREFIX = "ca.connector.KRA"; + + public KRAConnectorProcessor(Locale locale) throws EPropertyNotFound, EBaseException { + super("kraconnector", locale); + ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); + ICAService caService = (ICAService)ca.getCAService(); + connectorExists = (caService.getKRAConnector() != null)? true:false; + } + + public void removeConnector(String newHost, String newPort) throws EPropertyNotFound, EBaseException { + if (! connectorExists) { + CMS.debug("removeConnector: no KRA connector exists, returning success"); + return; + } + + if ((newHost == null) || (newPort == null)) { + CMS.debug("removeConnector: malformed request. newHost or newPort is null"); + throw new BadRequestException("Bad Request: KRA Host or Port not defined"); + } + IConfigStore cs = CMS.getConfigStore(); + String host = cs.getString(PREFIX + ".host"); + String port = cs.getString(PREFIX + ".port"); + + if ((host == null) || (port == null)) { + CMS.debug("removeConnector: bad connector configuration - host or port are null"); + throw new PKIException("Bad Connector configuration on this CA"); + } + + String hostport = newHost + ":" + newPort; + if ((host.equals(newHost)) && port.equals(newPort)) { + CMS.debug("removeConnector: Removing " + PREFIX + " substore"); + cs.removeSubStore(PREFIX); + cs.commit(true); + deleteConnector(); + } else if (host.indexOf(' ') != -1) { // host is a list + String[] hostList = host.trim().split(" "); + ArrayList finalList = new ArrayList(); + for (String h : hostList) { + if (! h.equals(hostport)) { + finalList.add(h); + } + } + if (finalList.size() == hostList.length) { + CMS.debug("removeConnector: no connector for " + hostport + " exists. Returning success"); + return; + } + + CMS.debug("removeConnector: Removing " + hostport + " from " + PREFIX); + + if (finalList.size() == 0) { + CMS.debug("removeConnector: Removing " + PREFIX + " substore"); + cs.removeSubStore(PREFIX); + cs.commit(true); + deleteConnector(); + } else if (finalList.size() == 1) { + cs.putString(PREFIX + ".host", finalList.get(0).split(":")[0]); + cs.putString(PREFIX + ".port", finalList.get(0).split(":")[1]); + cs.commit(true); + replaceConnector(); + } else { + String finalString = ""; + for (String h : finalList) + finalString += h + " "; + cs.putString(PREFIX + ".host", finalString.trim()); + cs.commit(true); + replaceConnector(); + } + } else { + CMS.debug("removeConnector: no connector for " + hostport + " exists. Returning success"); + } + } + + public void stopConnector() { + ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); + ICAService caService = (ICAService)ca.getCAService(); + IConnector kraConnector = caService.getKRAConnector(); + if (kraConnector != null) { + kraConnector.stop(); + } + } + + public void startConnector() { + ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); + ICAService caService = (ICAService)ca.getCAService(); + IConnector kraConnector = caService.getKRAConnector(); + if (kraConnector != null) { + kraConnector.start(); + } + } + + public void replaceConnector() throws EBaseException { + // stop the old connector + stopConnector(); + + ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); + ICAService caService = (ICAService)ca.getCAService(); + IConfigStore cs = CMS.getConfigStore(); + + IConnector kraConnector = caService.getConnector(cs.getSubStore(PREFIX)); + caService.setKRAConnector(kraConnector); + + startConnector(); + } + + public void deleteConnector() { + stopConnector(); + + ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); + ICAService caService = (ICAService)ca.getCAService(); + caService.setKRAConnector(null); + } + + public void addConnector(KRAConnectorInfo info) throws EPropertyNotFound, EBaseException { + IConfigStore cs = CMS.getConfigStore(); + String newHost = info.getHost(); + String newPort = info.getPort(); + String newTransportCert = info.getTransportCert(); + + if ((newHost == null) || (newPort == null) || (newTransportCert == null)) { + CMS.debug("addConnector: malformed request. newHost, newPort or transport cert is null"); + throw new BadRequestException("Bad Request: KRA host, port or transport cert not defined"); + } + + if (connectorExists) { + String host = cs.getString(PREFIX + ".host"); + String port = cs.getString(PREFIX + ".port"); + + if ((!host.equals(newHost)) || (!port.equals(newPort))) { //existing connector is not the same + + // check transport cert + String transportCert = cs.getString(PREFIX + ".transportCert"); + if (!transportCert.equals(newTransportCert)) { + CMS.debug("addConnector: Connector is already defined"); + throw new BadRequestException("KRA connector has already been defined for this CA"); + } + + String hostport = newHost + ":" + newPort; + if (host.indexOf(' ') != -1) { // host is a list + String[] hostList = host.trim().split(" "); + for (String h : hostList) { + if (h.equals(hostport)) { + CMS.debug("addConnector: connector for " + hostport + + " is already present. Returning success"); + return; + } + } + + CMS.debug("addConnector: adding " + hostport + " to KRA connector host list"); + cs.putString(PREFIX + ".host", host + " " + hostport); + cs.commit(true); + replaceConnector(); + return; + } else { // host is not a list, turn it into one + CMS.debug("addConnector: adding " + hostport + " to KRA connector"); + cs.putString(PREFIX + ".host", host + ":" + port + " " + hostport); + cs.commit(true); + replaceConnector(); + return; + } + } + } + + // connector does not exist, or existing connector is the same host/port and we are replacing it + cs.putString(PREFIX + ".host", info.getHost()); + cs.putString(PREFIX + ".port", info.getPort()); + cs.putString(PREFIX + ".enable", info.getEnable() != null ? info.getEnable() : "true"); + cs.putString(PREFIX + ".local", info.getLocal() != null ? info.getLocal(): "false"); + cs.putString(PREFIX + ".timeout", info.getTimeout() != null ? info.getTimeout() : "30"); + cs.putString(PREFIX + ".uri", info.getUri() != null ? info.getUri() : "/kra/agent/kra/connector"); + cs.putString(PREFIX + ".transportCert", info.getTransportCert()); + + String nickname = cs.getString("ca.subsystem.nickname", ""); + String tokenname = cs.getString("ca.subsystem.tokenname", ""); + if (!tokenname.equals("Internal Key Storage Token")) + nickname = tokenname + ":" + nickname; + cs.putString(PREFIX + ".nickName", nickname); + cs.commit(true); + + replaceConnector(); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorService.java b/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorService.java new file mode 100644 index 000000000..b1d0b07c2 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/KRAConnectorService.java @@ -0,0 +1,61 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.admin; + +import javax.ws.rs.core.MultivaluedMap; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.PKIException; +import com.netscape.certsrv.system.KRAConnectorInfo; +import com.netscape.certsrv.system.KRAConnectorResource; +import com.netscape.cms.servlet.base.PKIService; + +/** + * @author Ade Lee + */ +public class KRAConnectorService extends PKIService implements KRAConnectorResource { + + @Override + public void addConnector(KRAConnectorInfo info) { + try { + KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale()); + processor.addConnector(info); + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException(e.getMessage()); + } + } + + @Override + public void removeConnector(String host, String port) { + try { + KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale()); + processor.removeConnector(host, port); + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException(e.getMessage()); + } + } + + @Override + public void addConnector(MultivaluedMap form) { + KRAConnectorInfo info = new KRAConnectorInfo(form); + addConnector(info); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java index b62e184b7..efc0d5d34 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java @@ -18,7 +18,6 @@ package com.netscape.cms.servlet.csadmin; import java.io.IOException; -import java.util.Enumeration; import java.util.Locale; import javax.servlet.ServletConfig; @@ -26,6 +25,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.jboss.resteasy.spi.BadRequestException; import org.w3c.dom.Node; import com.netscape.certsrv.apps.CMS; @@ -33,11 +33,10 @@ import com.netscape.certsrv.authentication.IAuthToken; import com.netscape.certsrv.authorization.AuthzToken; import com.netscape.certsrv.authorization.EAuthzAccessDenied; import com.netscape.certsrv.base.EBaseException; -import com.netscape.certsrv.base.IConfigStore; -import com.netscape.certsrv.ca.ICAService; -import com.netscape.certsrv.ca.ICertificateAuthority; -import com.netscape.certsrv.connector.IConnector; +import com.netscape.certsrv.base.PKIException; import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.system.KRAConnectorInfo; +import com.netscape.cms.servlet.admin.KRAConnectorProcessor; import com.netscape.cms.servlet.base.CMSServlet; import com.netscape.cms.servlet.base.UserInfo; import com.netscape.cms.servlet.common.CMSRequest; @@ -46,9 +45,6 @@ import com.netscape.cmsutil.xml.XMLObject; public class UpdateConnector extends CMSServlet { - /** - * - */ private static final long serialVersionUID = 972871860008509849L; private final static String SUCCESS = "0"; private final static String FAILED = "1"; @@ -69,6 +65,18 @@ public class UpdateConnector extends CMSServlet { CMS.debug("UpdateConnector: done initializing..."); } + public KRAConnectorInfo createConnectorInfo(HttpServletRequest httpReq) { + KRAConnectorInfo info = new KRAConnectorInfo(); + info.setHost(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".host")); + info.setPort(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".port")); + info.setTimeout(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".timeout")); + info.setTransportCert(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".transportCert")); + info.setUri(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".uri")); + info.setLocal(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".local")); + info.setEnable(httpReq.getParameter(KRAConnectorProcessor.PREFIX + ".enable")); + return info; + } + /** * Process the HTTP request. */ @@ -122,47 +130,24 @@ public class UpdateConnector extends CMSServlet { return; } - // check if connector exists - ICertificateAuthority ca = (ICertificateAuthority)CMS.getSubsystem("ca"); - ICAService caService = (ICAService)ca.getCAService(); - boolean connectorExists = (caService.getKRAConnector() != null)? true:false; - if (connectorExists) { - CMS.debug("UpdateConnector: KRA connector already exists"); - } else { - IConfigStore cs = CMS.getConfigStore(); - - @SuppressWarnings("unchecked") - Enumeration list = httpReq.getParameterNames(); - while (list.hasMoreElements()) { - String name = list.nextElement(); - String val = httpReq.getParameter(name); - if (name != null && name.startsWith("ca.connector")) { - CMS.debug("Adding connector update name=" + name + " val=" + val); - cs.putString(name, val); - } else { - CMS.debug("Skipping connector update name=" + name + " val=" + val); - } - } - - try { - String nickname = cs.getString("ca.subsystem.nickname", ""); - String tokenname = cs.getString("ca.subsystem.tokenname", ""); - if (!tokenname.equals("Internal Key Storage Token")) - nickname = tokenname + ":" + nickname; - cs.putString("ca.connector.KRA.nickName", nickname); - cs.commit(false); - } catch (Exception e) { - } + String op = httpReq.getParameter("op"); + if (op == null) { + op="add"; + } - // start the connector - try { - IConnector kraConnector = caService.getConnector( - cs.getSubStore("ca.connector.KRA")); - caService.setKRAConnector(kraConnector); - kraConnector.start(); - } catch (Exception e) { - CMS.debug("Failed to start connector " + e); + String status = SUCCESS; + String error = ""; + KRAConnectorProcessor processor = new KRAConnectorProcessor(getLocale(httpReq)); + KRAConnectorInfo info = createConnectorInfo(httpReq); + try { + if (op.equals("add")) { + processor.addConnector(info); + } else { + processor.removeConnector(info.getHost(), info.getPort()); } + } catch (BadRequestException | PKIException e) { + status = FAILED; + error = e.getMessage(); } // send success status back to the requestor @@ -170,13 +155,13 @@ public class UpdateConnector extends CMSServlet { CMS.debug("UpdateConnector: Sending response"); XMLObject xmlObj = new XMLObject(); Node root = xmlObj.createRoot("XMLResponse"); - - if (connectorExists) { - xmlObj.addItemToContainer(root, "Status", FAILED); - xmlObj.addItemToContainer(root, "Error", "DRM connector already exists."); - } else { + if (status.equals(SUCCESS)) { xmlObj.addItemToContainer(root, "Status", SUCCESS); + } else { + xmlObj.addItemToContainer(root, "Status", FAILED); + xmlObj.addItemToContainer(root, "Error", error); } + byte[] cb = xmlObj.toByteArray(); outputResult(httpResp, "application/xml", cb); diff --git a/base/common/src/com/netscape/cmscore/connector/HttpConnector.java b/base/common/src/com/netscape/cmscore/connector/HttpConnector.java index f947164d9..33b0d62b7 100644 --- a/base/common/src/com/netscape/cmscore/connector/HttpConnector.java +++ b/base/common/src/com/netscape/cmscore/connector/HttpConnector.java @@ -43,7 +43,6 @@ public class HttpConnector implements IConnector { // XXX todo make this a pool. // XXX use CMMF in the future. protected IHttpConnection mConn = null; - private Thread mResendThread = null; private IResender mResender = null; @SuppressWarnings("unused") private int mTimeout; @@ -73,7 +72,6 @@ public class HttpConnector implements IConnector { // mConn = CMS.getHttpConnection(dest, mFactory); // this will start resending past requests in parallel. mResender = CMS.getResender(mSource, nickName, dest, resendInterval); - mResendThread = new Thread(mResender, "HttpConnector"); } // Inserted by beomsuk @@ -98,7 +96,6 @@ public class HttpConnector implements IConnector { // this will start resending past requests in parallel. mResender = CMS.getResender(mSource, nickName, dest, resendInterval); - mResendThread = new Thread(mResender, "HttpConnector"); } // Insert end @@ -202,7 +199,13 @@ public class HttpConnector implements IConnector { } public void start() { - mResendThread.start(); + CMS.debug("Starting HttpConnector resender thread"); + mResender.start("HttpConnector"); + } + + public void stop() { + CMS.debug("Stopping HttpConnector resender thread"); + mResender.stop(); } } diff --git a/base/common/src/com/netscape/cmscore/connector/LocalConnector.java b/base/common/src/com/netscape/cmscore/connector/LocalConnector.java index c4eb78625..ba2db83a1 100644 --- a/base/common/src/com/netscape/cmscore/connector/LocalConnector.java +++ b/base/common/src/com/netscape/cmscore/connector/LocalConnector.java @@ -204,6 +204,9 @@ public class LocalConnector implements IConnector { public void start() { } + public void stop() { + } + protected void transferRequest(IRequest src, IRequest dest) { RequestTransfer.transfer(src, dest); } diff --git a/base/common/src/com/netscape/cmscore/connector/Resender.java b/base/common/src/com/netscape/cmscore/connector/Resender.java index e1b19749a..a949b993e 100644 --- a/base/common/src/com/netscape/cmscore/connector/Resender.java +++ b/base/common/src/com/netscape/cmscore/connector/Resender.java @@ -20,6 +20,10 @@ package com.netscape.cmscore.connector; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authority.IAuthority; @@ -40,14 +44,12 @@ import com.netscape.cmsutil.http.JssSSLSocketFactory; * Default interval is 5 minutes. */ public class Resender implements IResender { - public static final int SECOND = 1000; //milliseconds - public static final int MINUTE = 60 * SECOND; - public static final int HOUR = 60 * MINUTE; - public static final int DAY = 24 * HOUR; + public static final int MINUTE = 60; protected IAuthority mAuthority = null; IRequestQueue mQueue = null; protected IRemoteAuthority mDest = null; + ScheduledExecutorService executorService; /* Vector of Request Id *Strings* */ protected Vector mRequestIds = new Vector(); @@ -55,6 +57,7 @@ public class Resender implements IResender { protected HttpConnection mConn = null; protected String mNickName = null; + protected boolean connected = false; // default interval. // XXX todo add another interval for requests unsent because server @@ -66,9 +69,6 @@ public class Resender implements IResender { mQueue = mAuthority.getRequestQueue(); mDest = dest; mNickName = nickName; - - //mConn = new HttpConnection(dest, - // new JssSSLSocketFactory(nickName)); } public Resender( @@ -77,11 +77,9 @@ public class Resender implements IResender { mAuthority = authority; mQueue = mAuthority.getRequestQueue(); mDest = dest; + mNickName = nickName; if (interval > 0) - mInterval = interval * SECOND; // interval specified in seconds. - - //mConn = new HttpConnection(dest, - // new JssSSLSocketFactory(nickName)); + mInterval = interval; // interval specified in seconds. } // must be done after a subsystem 'start' so queue is initialized. @@ -93,9 +91,7 @@ public class Resender implements IResender { while (list != null && list.hasMoreElements()) { RequestId rid = list.nextRequestId(); - - CMS.debug( - "added request Id " + rid + " in init to resend queue."); + CMS.debug("added request Id " + rid + " in init to resend queue."); // note these are added as strings mRequestIds.addElement(rid.toString()); } @@ -106,26 +102,38 @@ public class Resender implements IResender { // note the request ids are added as strings. mRequestIds.addElement(r.getRequestId().toString()); } - CMS.debug( - "added " + r.getRequestId() + " to resend queue"); + CMS.debug("added " + r.getRequestId() + " to resend queue"); } - public void run() { - - CMS.debug("Resender: In resender Thread run:"); - mConn = new HttpConnection(mDest, - new JssSSLSocketFactory(mNickName)); - initRequests(); + public void start(final String name) { + CMS.debug("Starting resender thread with interval " + mInterval); - do { - resend(); - try { - Thread.sleep(mInterval); - } catch (InterruptedException e) { - mAuthority.log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_CONNECTOR_RESENDER_INTERRUPTED")); - continue; + // schedule task to run immediately and repeat after specified interval + executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + public Thread newThread(Runnable r) { + return new Thread(r, name); } - } while (true); + }); + executorService.scheduleWithFixedDelay(this, 0, mInterval, TimeUnit.SECONDS); + + } + + public void run() { + if (! CMS.isInRunningState()) + return; + + if (! connected) { + CMS.debug("Connecting ..."); + mConn = new HttpConnection(mDest, new JssSSLSocketFactory(mNickName)); + initRequests(); + connected = true; + } + resend(); + } + + public void stop() { + // shutdown executorService without interrupting running task + if (executorService != null) executorService.shutdown(); } private void resend() { diff --git a/base/deploy/src/scriptlets/initialization.py b/base/deploy/src/scriptlets/initialization.py index 034179ef1..102fd4245 100644 --- a/base/deploy/src/scriptlets/initialization.py +++ b/base/deploy/src/scriptlets/initialization.py @@ -104,6 +104,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): util.identity.set_gid(master['pki_group']) # get ports to remove selinux context util.configuration_file.populate_non_default_ports() + + # remove kra connector from CA if this is a KRA + util.kra_connector.deregister() + # de-register instance from its Security Domain # # NOTE: Since the security domain of an instance must be up diff --git a/base/deploy/src/scriptlets/pkihelper.py b/base/deploy/src/scriptlets/pkihelper.py index 48c5f84f0..c58fcf0e8 100644 --- a/base/deploy/src/scriptlets/pkihelper.py +++ b/base/deploy/src/scriptlets/pkihelper.py @@ -1983,6 +1983,28 @@ class password: sys.exit(1) return + def get_password(self, path, token_name, critical_failure=True): + if os.path.exists(path) and os.path.isfile(path) and\ + os.access(path, os.R_OK): + tokens = PKIConfigParser.read_simple_configuration_file(path) + hardware_token = "hardware-" + token_name + if tokens.has_key(hardware_token): + token_name = hardware_token + token_pwd = tokens[hardware_token] + elif tokens.has_key(token_name): + token_pwd = tokens[token_name] + + if token_pwd is None or token_pwd == '': + # TODO prompt for this password + config.pki_log.error(log.PKIHELPER_PASSWORD_NOT_FOUND_1, + token_name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + return token_pwd + # PKI Deployment NSS 'certutil' Class class certutil: @@ -2260,6 +2282,136 @@ class certutil: sys.exit(1) return +# KRA Connector Class +class kra_connector: + def deregister(self, critical_failure=False): + try: + # this is applicable to KRAs only + if master['pki_subsystem_type'] != "kra": + return + + config.pki_log.info( + log.PKIHELPER_KRACONNECTOR_UPDATE_CONTACT, + extra=config.PKI_INDENTATION_LEVEL_2) + + cs_cfg = PKIConfigParser.read_simple_configuration_file( + master['pki_target_cs_cfg']) + krahost = cs_cfg.get('service.machineName') + kraport = cs_cfg.get('pkicreate.secure_port') + cahost = cs_cfg.get('cloning.ca.hostname') + caport = cs_cfg.get('cloning.ca.httpsport') + if cahost is None or\ + caport is None: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CA_HOST_PORT, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + # retrieve subsystem nickname + subsystemnick = cs_cfg.get('kra.cert.subsystem.nickname') + if subsystemnick is None: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + # retrieve name of token based upon type (hardware/software) + if ':' in subsystemnick: + token_name = subsystemnick.split(':')[0] + else: + token_name = "internal" + + token_pwd = password.get_password( + master['pki_shared_password_conf'], + token_name, + critical_failure) + + if token_pwd is None or token_pwd == '': + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_TOKEN_PASSWD_1, + token_name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + self.execute_using_sslget(caport, cahost, subsystemnick, + token_pwd, krahost, kraport) + + except subprocess.CalledProcessError as exc: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2, + str(krahost), + str(kraport), + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + return + + def execute_using_pki(self, caport, cahost, subsystemnick, + token_pwd, krahost, kraport, critical_failure=False): + command = "/bin/pki -p '{}' -h '{}' -n '{}' -P https -d '{}' -w '{}' "\ + "kraconnector-del {} {}".format( + caport, cahost, subsystemnick, + master['pki_database_path'], + token_pwd, krahost, kraport) + + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) + + error = re.findall("ClientResponseFailure:(.*?)", output) + if error: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2, + str(krahost), + str(kraport), + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, output, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + + def execute_using_sslget(self, caport, cahost, subsystemnick, + token_pwd, krahost, kraport): + urlheader = "https://{}:{}".format(cahost, caport) + updateURL = "/ca/rest/admin/kraconnector/remove" + + params = "host=" + str(krahost) +\ + "&port=" + str(kraport) + + command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\ + "-v -r '{}' {}:{} 2>&1".format( + subsystemnick, token_pwd, + master['pki_database_path'], + params, updateURL, + cahost, caport) + + # update KRA connector + # Execute this "sslget" command + # Note that sslget will return non-zero value for HTTP code != 200 + # and this will raise an exception + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) # PKI Deployment Security Domain Class class security_domain: @@ -2337,33 +2489,16 @@ class security_domain: urladminheader = "https://{}:{}".format(sechost, secadminport) updateURL = "/ca/agent/ca/updateDomainXML" - # process this PKI subsystem instance's 'password.conf' - # - # REMINDER: NEVER log this 'sensitive' information! - # - if os.path.exists(master['pki_shared_password_conf']) and\ - os.path.isfile(master['pki_shared_password_conf']) and\ - os.access(master['pki_shared_password_conf'], os.R_OK): - tokens = PKIConfigParser.read_simple_configuration_file( - master['pki_shared_password_conf']) - hardware_token = "hardware-" + token_name - if tokens.has_key(hardware_token): - token_name = hardware_token - token_pwd = tokens[hardware_token] - elif tokens.has_key(token_name): - token_pwd = tokens[token_name] - + token_pwd = password.get_password( + master['pki_shared_password_conf'], + token_name, + critical_failure) if token_pwd is None or token_pwd == '': - # 'pkiremove' prompts with - # "What is the password for this token?" config.pki_log.warning( log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2, typeval, secname, extra=config.PKI_INDENTATION_LEVEL_2) - config.pki_log.error(log.PKIHELPER_PASSWORD_NOT_FOUND_1, - token_name, - extra=config.PKI_INDENTATION_LEVEL_2) if critical_failure == True: sys.exit(-1) else: @@ -2608,5 +2743,6 @@ war = war() password = password() certutil = certutil() security_domain = security_domain() +kra_connector = kra_connector() systemd = systemd() jython = jython() diff --git a/base/deploy/src/scriptlets/pkimessages.py b/base/deploy/src/scriptlets/pkimessages.py index ade19422e..3a6bec1e3 100644 --- a/base/deploy/src/scriptlets/pkimessages.py +++ b/base/deploy/src/scriptlets/pkimessages.py @@ -194,6 +194,10 @@ PKIHELPER_IS_A_DIRECTORY_1 = "'%s' is a directory" PKIHELPER_IS_A_FILE_1 = "'%s' is a file" PKIHELPER_IS_A_SYMLINK_1 = "'%s' is a symlink" PKIHELPER_JAR_XF_C_2 = "jar -xf %s -C %s" +PKIHELPER_KRACONNECTOR_UPDATE_CONTACT =\ + "contacting the CA to update the KRA connector" +PKIHELPER_KRACONNECTOR_UPDATE_FAILURE = "Failed to update KRA connector on CA" +PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2 = "Failed to update KRA connector for %s:%s" PKIHELPER_LINK_S_2 = "ln -s %s %s" PKIHELPER_MKDIR_1 = "mkdir -p %s" PKIHELPER_MODIFY_DIR_1 = "modifying '%s'" @@ -259,12 +263,14 @@ PKIHELPER_TOMCAT_INSTANCES_2 = "PKI Tomcat registry '%s' contains '%d' "\ "Tomcat PKI instances" PKIHELPER_TOUCH_1 = "touch %s" PKIHELPER_UID_2 = "UID of '%s' is %s" +PKIHELPER_UNDEFINED_CA_HOST_PORT = "CA Host or Port is undefined" PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 =\ "Either a value for '%s' MUST be defined in '%s', or "\ "the randomly generated client pin MUST be used" PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 =\ "A value for '%s' MUST be defined in '%s'" PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME = "subsystem nickname not defined" +PKIHELPER_UNDEFINED_TOKEN_PASSWD_1 = "Password for token '%s' not defined" PKIHELPER_USER_1 = "retrieving UID for '%s' . . ." PKIHELPER_USER_ADD_2 = "adding UID '%s' for user '%s' . . ." PKIHELPER_USER_ADD_DEFAULT_2 = "adding default UID '%s' for user '%s' . . ." diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java index 2e661fcc6..191a6326d 100644 --- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java @@ -36,6 +36,7 @@ import com.netscape.certsrv.client.PKIConnection; import com.netscape.cmstools.cert.CertCLI; import com.netscape.cmstools.group.GroupCLI; import com.netscape.cmstools.key.KeyCLI; +import com.netscape.cmstools.system.KRAConnectorCLI; import com.netscape.cmstools.system.SecurityDomainCLI; import com.netscape.cmstools.user.UserCLI; @@ -55,6 +56,7 @@ public class MainCLI extends CLI { addModule(new CertCLI(this)); addModule(new GroupCLI(this)); addModule(new KeyCLI(this)); + addModule(new KRAConnectorCLI(this)); addModule(new SecurityDomainCLI(this)); addModule(new UserCLI(this)); } diff --git a/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorAddCLI.java b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorAddCLI.java new file mode 100644 index 000000000..cc163341b --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorAddCLI.java @@ -0,0 +1,77 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools.system; + +import java.io.FileInputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.ParseException; + +import com.netscape.certsrv.system.KRAConnectorInfo; +import com.netscape.cmstools.cli.CLI; +import com.netscape.cmstools.cli.MainCLI; + +/** + * @author Ade Lee + */ +public class KRAConnectorAddCLI extends CLI { + public KRAConnectorCLI parent; + + public KRAConnectorAddCLI(KRAConnectorCLI parent) { + super("add", "Add KRA Connector"); + this.parent = parent; + } + + public void printHelp() { + formatter.printHelp(parent.name + "-" + name + " ", options); + } + + public void execute(String[] args) throws Exception { + + CommandLine cmd = null; + + try { + cmd = parser.parse(options, args); + } catch (ParseException e) { + System.err.println("Error: " + e.getMessage()); + printHelp(); + System.exit(-1); + } + + String[] cLineArgs = cmd.getArgs(); + + if (cLineArgs.length < 1) { + System.err.println("Error: No file name specified."); + printHelp(); + System.exit(-1); + } + + FileInputStream fis = new FileInputStream(cLineArgs[0].trim()); + + JAXBContext context = JAXBContext.newInstance(KRAConnectorInfo.class); + Unmarshaller unmarshaller = context.createUnmarshaller(); + KRAConnectorInfo info = (KRAConnectorInfo) unmarshaller.unmarshal(fis); + + parent.client.addConnector(info); + + MainCLI.printMessage("Added KRA Connector"); + } +} diff --git a/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java new file mode 100644 index 000000000..d59d7445a --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorCLI.java @@ -0,0 +1,92 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools.system; + +import java.util.Arrays; + +import org.apache.commons.lang.StringUtils; + +import com.netscape.certsrv.system.KRAConnectorClient; +import com.netscape.cmstools.cli.CLI; +import com.netscape.cmstools.cli.MainCLI; + +/** + * @author Ade Lee + */ +public class KRAConnectorCLI extends CLI { + + public MainCLI parent; + public KRAConnectorClient client; + + public KRAConnectorCLI(MainCLI parent) { + super("kraconnector", "KRA Connector management commands"); + this.parent = parent; + addModule(new KRAConnectorAddCLI(this)); + addModule(new KRAConnectorRemoveCLI(this)); + } + + public void printHelp() { + + System.out.println("Commands:"); + + int leftPadding = 1; + int rightPadding = 25; + + for (CLI module : modules.values()) { + String label = name+"-"+module.getName(); + + int padding = rightPadding - leftPadding - label.length(); + if (padding < 1) padding = 1; + + System.out.print(StringUtils.repeat(" ", leftPadding)); + System.out.print(label); + System.out.print(StringUtils.repeat(" ", padding)); + System.out.println(module.getDescription()); + } + } + + public void execute(String[] args) throws Exception { + + client = new KRAConnectorClient(parent.connection); + + if (args.length == 0) { + printHelp(); + System.exit(1); + } + + String command = args[0]; + String[] commandArgs = Arrays.copyOfRange(args, 1, args.length); + + if (command == null) { + printHelp(); + System.exit(1); + } + + CLI module = getModule(command); + if (module != null) { + module.execute(commandArgs); + + } else { + System.err.println("Error: Invalid command \""+command+"\""); + printHelp(); + System.exit(1); + } + } + + +} diff --git a/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorRemoveCLI.java new file mode 100644 index 000000000..d69e08ed4 --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/KRAConnectorRemoveCLI.java @@ -0,0 +1,52 @@ +// --- 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) 2013 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmstools.system; + +import com.netscape.cmstools.cli.CLI; +import com.netscape.cmstools.cli.MainCLI; + +/** + * @author Ade Lee + */ +public class KRAConnectorRemoveCLI extends CLI { + public KRAConnectorCLI parent; + + public KRAConnectorRemoveCLI(KRAConnectorCLI parent) { + super("del", "Remove KRA connector from CA"); + this.parent = parent; + } + + public void printHelp() { + formatter.printHelp(parent.name + "-" + name + " ", options); + } + + public void execute(String[] args) throws Exception { + + if (args.length != 2) { + printHelp(); + System.exit(1); + } + + String kraHost = args[0]; + String kraPort = args[1]; + + parent.client.removeConnector(kraHost, kraPort); + + MainCLI.printMessage("Removed KRA connector \""+kraHost + ":" + kraPort +"\""); + } +} diff --git a/base/native-tools/src/sslget/sslget.c b/base/native-tools/src/sslget/sslget.c index 7288a1c58..a7c6a3f09 100644 --- a/base/native-tools/src/sslget/sslget.c +++ b/base/native-tools/src/sslget/sslget.c @@ -426,7 +426,11 @@ do_io( PRFileDesc *ssl_sock, int connection) buf2 = 0; } - if ( ! PL_strnstr(buf,"200",13)) { + char *status_string = PL_strndup(buf+9, 3); + int status = atoi(status_string); + PL_strfree(status_string); + + if (status >= 300) { PR_Free(buf); buf = 0; exit(3); -- cgit