diff options
20 files changed, 1298 insertions, 2 deletions
diff --git a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java index 23021a573..4fdf594d1 100644 --- a/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java +++ b/base/common/src/com/netscape/certsrv/system/ConfigurationRequest.java @@ -84,6 +84,8 @@ public class ConfigurationRequest { private static final String KRA_URI = "kraUri"; private static final String ENABLE_SERVER_SIDE_KEYGEN = "enableServerSideKeygen"; + // TKS/TPS shared secret parameters + private static final String IMPORT_SHARED_SECRET = "importSharedSecret"; //defaults public static final String TOKEN_DEFAULT = "Internal Key Storage Token"; @@ -243,6 +245,9 @@ public class ConfigurationRequest { @XmlElement(defaultValue="false") protected String enableServerSideKeyGen; + @XmlElement(defaultValue="false") + protected String importSharedSecret; + public ConfigurationRequest() { // required for JAXB } @@ -298,6 +303,7 @@ public class ConfigurationRequest { tksUri = form.getFirst(TKS_URI); kraUri = form.getFirst(KRA_URI); enableServerSideKeyGen = form.getFirst(ENABLE_SERVER_SIDE_KEYGEN); + importSharedSecret = form.getFirst(IMPORT_SHARED_SECRET); } public String getSubsystemName() { @@ -878,6 +884,14 @@ public class ConfigurationRequest { this.enableServerSideKeyGen = enableServerSideKeyGen; } + public String getImportSharedSecret() { + return importSharedSecret; + } + + public void setImportSharedSecret(String importSharedSecret) { + this.importSharedSecret = importSharedSecret; + } + @Override public String toString() { return "ConfigurationRequest [pin=XXXX" + @@ -930,6 +944,7 @@ public class ConfigurationRequest { ", kraUri=" + kraUri + ", tksUri=" + tksUri + ", enableServerSideKeyGen=" + enableServerSideKeyGen + + ", importSharedSecret=" + importSharedSecret + "]"; } } diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java new file mode 100644 index 000000000..09ba9db45 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorClient.java @@ -0,0 +1,66 @@ +package com.netscape.certsrv.system; + +import java.net.URISyntaxException; + +import com.netscape.certsrv.client.Client; +import com.netscape.certsrv.client.PKIClient; +import com.netscape.certsrv.key.KeyData; + +public class TPSConnectorClient extends Client { + + private TPSConnectorResource tpsConnectorClient; + + public TPSConnectorClient(PKIClient client) throws URISyntaxException { + this(client, client.getSubsystem()); + } + + public TPSConnectorClient(PKIClient client, String subsystem) throws URISyntaxException { + super(client, subsystem, "tpsconnector"); + init(); + } + + public void init() throws URISyntaxException { + tpsConnectorClient = createProxy(TPSConnectorResource.class); + } + + public TPSConnectorCollection listConnectors() { + return tpsConnectorClient.listConnectors(); + } + + public TPSConnectorData getConnector(String id) { + return tpsConnectorClient.getConnector(id); + } + + public TPSConnectorData getConnector(String host, String port) { + return tpsConnectorClient.getConnector(host, port); + } + + public TPSConnectorData createConnector(String tpsHost, String tpsPort) { + return tpsConnectorClient.createConnector(tpsHost, tpsPort); + } + + public void deleteConnector(String id) { + tpsConnectorClient.deleteConnector(id); + } + + public KeyData createSharedSecret(String id) { + return tpsConnectorClient.createSharedSecret(id); + } + + public KeyData replaceSharedSecret(String id) { + return tpsConnectorClient.replaceSharedSecret(id); + }; + + public void deleteSharedSecret(String id) { + tpsConnectorClient.deleteSharedSecret(id); + } + + public KeyData getSharedSecret(String id) { + return tpsConnectorClient.getSharedSecret(id); + } + + public void deleteConnector(String host, String port) { + tpsConnectorClient.deleteConnector(host, port); + } + +} diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorCollection.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorCollection.java new file mode 100644 index 000000000..106a681bf --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorCollection.java @@ -0,0 +1,17 @@ +package com.netscape.certsrv.system; + +import java.util.Collection; + +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; + +import com.netscape.certsrv.base.DataCollection; + +@XmlRootElement(name="TPSConnectors") +public class TPSConnectorCollection extends DataCollection<TPSConnectorData> { + + @XmlElementRef + public Collection<TPSConnectorData> getEntries() { + return super.getEntries(); + } +} diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorData.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorData.java new file mode 100644 index 000000000..d5e1480eb --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorData.java @@ -0,0 +1,153 @@ +package com.netscape.certsrv.system; + +import java.io.StringReader; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.jboss.resteasy.plugins.providers.atom.Link; + +@XmlRootElement(name="TPSSystemClient") +public class TPSConnectorData { + + public static Marshaller marshaller; + public static Unmarshaller unmarshaller; + + static { + try { + marshaller = JAXBContext.newInstance(TPSConnectorData.class).createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + unmarshaller = JAXBContext.newInstance(TPSConnectorData.class).createUnmarshaller(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + String id; + String host; + String port; + String userID; + String nickname; + + Link link; + + @XmlAttribute(name="id") + public String getID() { + return id; + } + + public void setID(String id) { + this.id = id; + } + + @XmlAttribute(name="Host") + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + @XmlAttribute(name="Port") + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + @XmlElement(name="UserID") + public String getUserID() { + return userID; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + @XmlAttribute(name="Nickname") + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public Link getLink() { + return link; + } + + public void setLink(Link link) { + this.link = link; + } + + public static TPSConnectorData valueOf(String string) throws Exception { + try { + return (TPSConnectorData)unmarshaller.unmarshal(new StringReader(string)); + } catch (Exception e) { + return null; + } + } + + @Override + public String toString() { + return "TPSSystemClientData [id=" + id + ", host=" + host + ", port=" + port + + ", userID=" + userID + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((host == null) ? 0 : host.hashCode()); + result = prime * result + ((port == null) ? 0 : port.hashCode()); + result = prime * result + ((userID == null) ? 0 : userID.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TPSConnectorData other = (TPSConnectorData) obj; + if (host == null) { + if (other.host != null) + return false; + } else if (!host.equals(other.host)) + return false; + if (port == null) { + if (other.port != null) + return false; + } else if (!port.equals(other.port)) + return false; + if (userID == null) { + if (other.userID != null) + return false; + } else if (!userID.equals(other.userID)) + return false; + return true; + } + + public static void main(String args[]) throws Exception { + TPSConnectorData before = new TPSConnectorData(); + before.setID("tps0"); + before.setUserID("user1"); + + String string = before.toString(); + System.out.println(string); + + TPSConnectorData after = TPSConnectorData.valueOf(string); + System.out.println(before.equals(after)); + } +} diff --git a/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java b/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java new file mode 100644 index 000000000..8a76ee696 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/system/TPSConnectorResource.java @@ -0,0 +1,91 @@ +// --- 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.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import com.netscape.certsrv.acls.ACLMapping; +import com.netscape.certsrv.authentication.AuthMethodMapping; +import com.netscape.certsrv.key.KeyData; + +/** + * @author Ade Lee + */ +@Path("/admin/tps-connectors") +@AuthMethodMapping("admin") +public interface TPSConnectorResource { + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public TPSConnectorCollection listConnectors(); + + @GET + @Path("{id}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public TPSConnectorData getConnector(@PathParam("id") String id); + + @GET + @Path("search") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public TPSConnectorData getConnector(@QueryParam("host") String host, + @QueryParam("port") String port); + + @POST + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public TPSConnectorData createConnector(@QueryParam("host") String host, + @QueryParam("port") String port); + + @DELETE + @Path("{id}") + public void deleteConnector(@PathParam("id") String id); + + @POST + @Path("{id}/shared-secret") + @ACLMapping("admin.sharedsecret") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyData createSharedSecret(@PathParam("id") String id); + + @PUT + @Path("{id}/shared-secret") + @ACLMapping("admin.sharedsecret") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyData replaceSharedSecret(@PathParam("id") String id); + + @DELETE + @Path("{id}/shared-secret") + @ACLMapping("admin.sharedsecret") + public void deleteSharedSecret(@PathParam("id") String id); + + @DELETE + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public void deleteConnector(@QueryParam("host") String host, + @QueryParam("port") String port); + + @GET + @Path("{id}/shared-secret") + @ACLMapping("admin.sharedsecret") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyData getSharedSecret(@PathParam("id") String id); +} diff --git a/base/common/src/com/netscape/certsrv/tks/TKSClient.java b/base/common/src/com/netscape/certsrv/tks/TKSClient.java index baecf8ddb..a13089f86 100644 --- a/base/common/src/com/netscape/certsrv/tks/TKSClient.java +++ b/base/common/src/com/netscape/certsrv/tks/TKSClient.java @@ -22,6 +22,7 @@ import java.net.URISyntaxException; import com.netscape.certsrv.client.PKIClient; import com.netscape.certsrv.client.SubsystemClient; import com.netscape.certsrv.group.GroupClient; +import com.netscape.certsrv.system.TPSConnectorClient; import com.netscape.certsrv.user.UserClient; public class TKSClient extends SubsystemClient { @@ -34,5 +35,6 @@ public class TKSClient extends SubsystemClient { public void init() throws URISyntaxException { addClient(new GroupClient(client, name)); addClient(new UserClient(client, name)); + addClient(new TPSConnectorClient(client, name)); } } diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java index 78d14b3f5..1e6ee25a3 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java @@ -147,11 +147,14 @@ import com.netscape.certsrv.client.PKIClient; import com.netscape.certsrv.client.PKIConnection; import com.netscape.certsrv.dbs.IDBSubsystem; import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.key.KeyData; import com.netscape.certsrv.ldap.ILdapConnFactory; import com.netscape.certsrv.ocsp.IDefStore; import com.netscape.certsrv.ocsp.IOCSPAuthority; import com.netscape.certsrv.system.InstallToken; import com.netscape.certsrv.system.SecurityDomainClient; +import com.netscape.certsrv.system.TPSConnectorClient; +import com.netscape.certsrv.system.TPSConnectorData; import com.netscape.certsrv.usrgrp.EUsrGrpException; import com.netscape.certsrv.usrgrp.IGroup; import com.netscape.certsrv.usrgrp.IUGSubsystem; @@ -3568,6 +3571,63 @@ public class ConfigurationUtils { return null; } + public static void getSharedSecret(String tksHost, int tksPort, boolean importKey) throws EPropertyNotFound, + EBaseException, URISyntaxException { + IConfigStore cs = CMS.getConfigStore(); + String host = cs.getString("service.machineName"); + String port = cs.getString("service.securePort"); + String dbDir = cs.getString("instanceRoot") + "/alias"; + String dbNick = cs.getString("tps.cert.subsystem.nickname"); + + String passwordFile = cs.getString("passwordFile"); + IConfigStore psStore = CMS.createFileConfigStore(passwordFile); + String dbPass = psStore.getString("internal"); + + ClientConfig config = new ClientConfig(); + config.setServerURI("https://" + tksHost + ":" + tksPort + "/tks"); + config.setCertDatabase(dbDir); + config.setCertNickname(dbNick); + config.setCertPassword(dbPass); + + PKIClient client = new PKIClient(config); + PKIConnection connection = client.getConnection(); + + // Ignore the "UNTRUSTED_ISSUER" and "CA_CERT_INVALID" validity status + // during PKI instance creation since we are using an untrusted temporary CA cert. + connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER); + connection.addIgnoredCertStatus(SSLCertificateApprovalCallback.ValidityStatus.CA_CERT_INVALID); + + AccountClient accountClient = new AccountClient(client); + TPSConnectorClient tpsConnectorClient = new TPSConnectorClient(client); + + accountClient.login(); + TPSConnectorData data = tpsConnectorClient.getConnector(host, port); + KeyData keyData = null; + if (data == null) { + data = tpsConnectorClient.createConnector(host, port); + keyData = tpsConnectorClient.createSharedSecret(data.getID()); + } else { + String connId = data.getID(); + keyData = tpsConnectorClient.getSharedSecret(connId); + if (keyData != null) { + keyData = tpsConnectorClient.replaceSharedSecret(connId); + } else { + keyData = tpsConnectorClient.createSharedSecret(connId); + } + } + accountClient.logout(); + + if (importKey) { + // TODO - we need code here to import the key into the tps certdb + // this is not needed if we are using a shared database with + // the tks. + } + + // store the new nick in CS.cfg + String nick = "TPS-" + host + "-" + port + " sharedSecret"; + cs.putString("conn.tks1.tksSharedSymKeyName", nick); + cs.commit(false); + } public static void importCACertToOCSP() throws IOException, EBaseException, CertificateEncodingException { IConfigStore config = CMS.getConfigStore(); @@ -3729,7 +3789,7 @@ public class ConfigurationUtils { CMS.debug("registerUser: status=" + status); if (status.equals(SUCCESS)) { - CMS.debug("registerUser: Successfully added user " + uid + " to " + targetURI + + CMS.debug("registerUser: Successfully added user " + uid + " to " + targetURI + " using " + targetURL); } else if (status.equals(AUTH_FAILURE)) { throw new EAuthException(AUTH_FAILURE); diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java b/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java index 1884ca3d2..fbadc80d3 100644 --- a/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java @@ -504,6 +504,13 @@ public class SystemConfigService extends PKIService implements SystemConfigResou String transportCert = ConfigurationUtils.getTransportCert(secdomainURI, kraURI); ConfigurationUtils.exportTransportCert(secdomainURI, tksURI, transportCert); } + + // generate shared secret from the tks + ConfigurationUtils.getSharedSecret( + tksURI.getHost(), + tksURI.getPort(), + Boolean.getBoolean(data.getImportSharedSecret())); + } catch (URISyntaxException e) { throw new BadRequestException("Invalid URI for CA, TKS or KRA"); } catch (Exception e) { @@ -1146,6 +1153,12 @@ public class SystemConfigService extends PKIService implements SystemConfigResou } // TODO check connection with authdb + + if (data.getImportSharedSecret().equalsIgnoreCase("true")) { + data.setImportSharedSecret("true"); + } else { + data.setImportSharedSecret("false"); + } } } } diff --git a/base/common/src/com/netscape/cms/servlet/tks/TPSConnectorService.java b/base/common/src/com/netscape/cms/servlet/tks/TPSConnectorService.java new file mode 100644 index 000000000..97478d699 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/tks/TPSConnectorService.java @@ -0,0 +1,376 @@ +package com.netscape.cms.servlet.tks; + +import java.io.IOException; +import java.net.URI; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.lang.StringUtils; +import org.jboss.resteasy.plugins.providers.atom.Link; +import org.mozilla.jss.CryptoManager.NotInitializedException; +import org.mozilla.jss.crypto.InvalidKeyFormatException; +import org.mozilla.jss.crypto.TokenException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.BadRequestException; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.PKIException; +import com.netscape.certsrv.base.UnauthorizedException; +import com.netscape.certsrv.key.KeyData; +import com.netscape.certsrv.system.TPSConnectorCollection; +import com.netscape.certsrv.system.TPSConnectorData; +import com.netscape.certsrv.system.TPSConnectorResource; +import com.netscape.certsrv.tps.cert.TPSCertResource; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cmscore.realm.PKIPrincipal; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.util.Utils; + +public class TPSConnectorService implements TPSConnectorResource { + + IConfigStore cs = CMS.getConfigStore(); + + @Context + private UriInfo uriInfo; + + @Context + private HttpServletRequest servletRequest; + + public IUGSubsystem userGroupManager = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + @Override + public TPSConnectorCollection listConnectors() { + try { + String tpsList = cs.getString("tps.list", ""); + if (tpsList.isEmpty()) { + return null; + } + + TPSConnectorCollection ret = new TPSConnectorCollection(); + for (String tpsID : tpsList.split(",")) { + ret.addEntry(createTPSSystemClientData(tpsID)); + } + return ret; + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException("Unable to get TPS connection data" + e); + } + } + + private TPSConnectorData createTPSSystemClientData(String tpsID) throws EBaseException { + TPSConnectorData data = new TPSConnectorData(); + data.setID(tpsID); + data.setHost(cs.getString("tps." + tpsID + ".host", "")); + data.setPort(cs.getString("tps." + tpsID + ".port", "")); + data.setUserID(cs.getString("tps." + tpsID + ".userid", "")); + data.setNickname(cs.getString("tps." + tpsID + ".nickname", "")); + URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class).path("{id}").build(tpsID); + data.setLink(new Link("self", uri)); + return data; + } + + @Override + public TPSConnectorData getConnector(String id) { + try { + String tpsList = cs.getString("tps.list", ""); + if (tpsList.isEmpty()) { + return null; + } + + for (String tpsID : tpsList.split(",")) { + if (tpsID.equals(id)) + return createTPSSystemClientData(tpsID); + } + return null; + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException("Unable to get TPS connection data" + e); + } + } + + @Override + public TPSConnectorData getConnector(String host, String port) { + try { + String tpsList = cs.getString("tps.list", ""); + if (tpsList.isEmpty()) { + return null; + } + + for (String tpsID : tpsList.split(",")) { + TPSConnectorData data = createTPSSystemClientData(tpsID); + if (data.getHost().equals(host) && data.getPort().equals(port)) + return data; + } + return null; + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException("Unable to get TPS connection data" + e); + } + } + + @Override + public TPSConnectorData createConnector(String tpsHost, String tpsPort) { + TPSConnectorData newData = new TPSConnectorData(); + newData.setHost(tpsHost); + newData.setPort(tpsPort); + newData.setUserID("TPS-" + tpsHost + "-" + tpsPort); + try { + int index = 0; + boolean indexFound = false; + String tpsList = cs.getString("tps.list", ""); + if (!tpsList.isEmpty()) { + List<String> sorted = new ArrayList<String>(Arrays.asList(tpsList.split(","))); + Collections.sort(sorted); + for (String tpsID : sorted) { + TPSConnectorData data = createTPSSystemClientData(tpsID); + if (data.equals(newData)) { + throw new BadRequestException("TPS connection already exists at " + data.getLink()); + } + if (!indexFound && tpsID.equals(index)) { + index++; + } else { + indexFound = true; + } + } + } + String newID = Integer.toString(index); + newData.setID(newID); + URI uri = uriInfo.getBaseUriBuilder().path(TPSCertResource.class).path("{id}").build(newID); + newData.setLink(new Link("self", uri)); + saveClientData(newData); + + cs.putString("tps.list", tpsList.isEmpty() ? Integer.toString(index) : + tpsList + "," + index); + cs.commit(false); + + return newData; + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException("Unable to create new TPS connection data" + e); + } + } + + private void saveClientData(TPSConnectorData newData) throws EBaseException { + String id = newData.getID(); + if ((id == null) || (id.isEmpty())) { + CMS.debug("saveClientData: Attempt to save tps connection with null or empty id"); + return; + // throw exception here? + } + String prefix = "tps." + id + "."; + + if (newData.getHost() != null) + cs.putString(prefix + "host", newData.getHost()); + if (newData.getPort() != null) + cs.putString(prefix + "port", newData.getPort()); + if (newData.getUserID() != null) + cs.putString(prefix + "userid", newData.getUserID()); + if (newData.getNickname() != null) + cs.putString(prefix + "nickname", newData.getNickname()); + + cs.commit(false); + } + + @Override + public void deleteConnector(String id) { + try { + if ((id == null) || id.isEmpty()) + throw new BadRequestException("Attempt to delete TPS connection with null or empty id"); + + if (getConnector(id) == null) { + return; + // return 404 here? + } + + deleteSharedSecret(id); + + String prefix = "tps." + id; + cs.removeSubStore(prefix); + + String tpsList = cs.getString("tps.list", ""); + if (tpsList.isEmpty()) { + return; + } + + List<String> newList = new ArrayList<String>(); + for (String tpsID : tpsList.split(",")) { + if (!tpsID.equals(id)) { + newList.add(tpsID); + } + } + cs.putString("tps.list", StringUtils.join(newList, ",")); + cs.commit(false); + } catch (EBaseException e) { + e.printStackTrace(); + throw new PKIException("Failed to delete TPS connection" + e); + } + } + + @Override + public KeyData createSharedSecret(String id) { + try { + if (getConnector(id) == null) { + throw new BadRequestException("TPS Connection does not exist"); + } + + // get and validate user + String userid = validateUser(id); + + // get user cert + IUser user = userGroupManager.getUser(userid); + X509Certificate[] certs = user.getX509Certificates(); + + String nickname = userid + " sharedSecret"; + if (CryptoUtil.sharedSecretExists(nickname)) { + throw new BadRequestException("Shared secret already exists"); + } + + CryptoUtil.createSharedSecret(nickname); + + cs.putString("tps." + id + ".nickname", nickname); + cs.commit(false); + + byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); + KeyData keyData = new KeyData(); + keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); + return keyData; + + } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException + | InvalidAlgorithmParameterException | EBaseException + | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) { + e.printStackTrace(); + CMS.debug("Error in generating and exporting shared secret: " + e); + throw new PKIException("Error in generating and exporting shared secret: " + e); + } + } + + private String validateUser(String id) throws EBaseException { + String userid = cs.getString("tps." + id + ".userid", ""); + if (userid.isEmpty()) { + throw new PKIException("Bad TPS connection configuration: userid not defined"); + } + + PKIPrincipal principal = (PKIPrincipal) servletRequest.getUserPrincipal(); + if (principal == null) { + throw new UnauthorizedException("User credentials not provided"); + } + + String uid = principal.getName(); + if (!uid.equals(userid)) { + throw new UnauthorizedException("TPS Connection belongs to another user"); + } + return userid; + } + + @Override + public KeyData replaceSharedSecret(String id) { + try { + if (getConnector(id) == null) { + throw new BadRequestException("TPS Connection does not exist"); + } + + // get and validate user + String userid = validateUser(id); + + // get user cert + IUser user = userGroupManager.getUser(userid); + X509Certificate[] certs = user.getX509Certificates(); + + String nickname = userid + " sharedSecret"; + if (!CryptoUtil.sharedSecretExists(nickname)) { + throw new BadRequestException("Cannot replace. Shared secret does not exist"); + } + + CryptoUtil.deleteSharedSecret(nickname); + CryptoUtil.createSharedSecret(nickname); + byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); + KeyData keyData = new KeyData(); + keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); + return keyData; + } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException + | InvalidAlgorithmParameterException | EBaseException + | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) { + e.printStackTrace(); + CMS.debug("Error in replacing shared secret: " + e); + throw new PKIException("Error in replacing shared secret: " + e); + } + } + + @Override + public void deleteSharedSecret(String id) { + try { + if (getConnector(id) == null) { + return; + } + + // get and validate user + String userid = validateUser(id); + + String nickname = userid + " sharedSecret"; + if (!CryptoUtil.sharedSecretExists(nickname)) { + return; + } + CryptoUtil.deleteSharedSecret(nickname); + + cs.putString("tps." + id + ".nickname", ""); + cs.commit(false); + } catch (InvalidKeyException | IllegalStateException | EBaseException + | NotInitializedException | TokenException e) { + e.printStackTrace(); + CMS.debug("Error in deleting shared secret: " + e); + throw new PKIException("Error in deleting shared secret: " + e); + } + } + + @Override + public KeyData getSharedSecret(String id) { + try { + if (getConnector(id) == null) { + throw new BadRequestException("TPS Connection does not exist"); + } + + // get and validate user + String userid = validateUser(id); + + // get user cert + IUser user = userGroupManager.getUser(userid); + X509Certificate[] certs = user.getX509Certificates(); + + String nickname = userid + " sharedSecret"; + if (!CryptoUtil.sharedSecretExists(nickname)) { + return null; + } + byte[] wrappedKey = CryptoUtil.exportSharedSecret(nickname, certs[0]); + KeyData keyData = new KeyData(); + keyData.setWrappedPrivateData(Utils.base64encode(wrappedKey)); + return keyData; + } catch (InvalidKeyException | IllegalStateException | NoSuchAlgorithmException + | InvalidAlgorithmParameterException | EBaseException + | NotInitializedException | TokenException | IOException | InvalidKeyFormatException e) { + e.printStackTrace(); + CMS.debug("Error in obtaining shared secret: " + e); + throw new PKIException("Error in obtaining shared secret: " + e); + } + } + + @Override + public void deleteConnector(String host, String port) { + TPSConnectorData data = getConnector(host, port); + if (data == null) { + return; + } + deleteConnector(data.getID()); + } +} diff --git a/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java index df7050189..b8c90ed47 100644 --- a/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java +++ b/base/java-tools/src/com/netscape/cmstools/cli/TKSCLI.java @@ -21,6 +21,7 @@ package com.netscape.cmstools.cli; import com.netscape.certsrv.client.Client; import com.netscape.certsrv.tks.TKSClient; import com.netscape.cmstools.group.GroupCLI; +import com.netscape.cmstools.system.TPSConnectorCLI; import com.netscape.cmstools.user.UserCLI; /** @@ -34,6 +35,7 @@ public class TKSCLI extends SubsystemCLI { super("tks", "TKS management commands", parent); addModule(new GroupCLI(this)); + addModule(new TPSConnectorCLI(this)); addModule(new UserCLI(this)); } diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorAddCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorAddCLI.java new file mode 100644 index 000000000..c9e1df985 --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorAddCLI.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 TPSConnectorAddCLI extends CLI { + public TPSConnectorCLI tpsConnectorCLI; + + public TPSConnectorAddCLI(TPSConnectorCLI tpsConnectorCLI) { + super("add", "Add TPS Connector to TKS", tpsConnectorCLI); + this.tpsConnectorCLI = tpsConnectorCLI; + } + + public void printHelp() { + formatter.printHelp(getFullName() + " <TPS Host> <TPS Port>", options); + } + + public void execute(String[] args) throws Exception { + if (args.length != 2) { + printHelp(); + System.exit(1); + } + + String tpsHost = args[0]; + String tpsPort = args[1]; + + tpsConnectorCLI.tpsConnectorClient.createConnector(tpsHost, tpsPort); + + MainCLI.printMessage("Added TPS connector \""+tpsHost + ":" + tpsPort +"\""); + } + +} diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorCLI.java new file mode 100644 index 000000000..7a87c3428 --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorCLI.java @@ -0,0 +1,94 @@ +// --- 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.jboss.resteasy.plugins.providers.atom.Link; + +import com.netscape.certsrv.system.TPSConnectorClient; +import com.netscape.certsrv.system.TPSConnectorData; +import com.netscape.cmstools.cli.CLI; + +/** + * @author Ade Lee + */ +public class TPSConnectorCLI extends CLI { + + public TPSConnectorClient tpsConnectorClient; + + public TPSConnectorCLI(CLI parent) { + super("tpsconnector", "TPS Connector management commands", parent); + + addModule(new TPSConnectorAddCLI(this)); + addModule(new TPSConnectorFindCLI(this)); + addModule(new TPSConnectorRemoveCLI(this)); + } + + public String getFullName() { + return parent.getFullName() + "-" + name; + } + + public void execute(String[] args) throws Exception { + + client = parent.getClient(); + tpsConnectorClient = (TPSConnectorClient)parent.getClient("tpsconnector"); + + if (tpsConnectorClient == null) { + // if parent doesn't have user client then create a new one + tpsConnectorClient = new TPSConnectorClient(client); + } + + 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); + } + } + + public static void printConnectorInfo(TPSConnectorData data) { + System.out.println(" Connector ID: " + data.getID()); + if (data.getHost() != null) System.out.println(" Host: " + data.getHost()); + if (data.getPort() != null) System.out.println(" Port: " + data.getPort()); + if (data.getUserID() != null) System.out.println(" User ID: " + data.getUserID()); + if (data.getNickname() != null) System.out.println(" Nickname: " + data.getNickname()); + + Link link = data.getLink(); + if (verbose && link != null) { + System.out.println(" Link: " + link.getHref()); + } + } + +} diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java new file mode 100644 index 000000000..0a42b7d3f --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorFindCLI.java @@ -0,0 +1,88 @@ +// --- 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.Collection; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; + +import com.netscape.certsrv.system.TPSConnectorCollection; +import com.netscape.certsrv.system.TPSConnectorData; +import com.netscape.cmstools.cli.CLI; + +/** + * @author Ade Lee + */ +public class TPSConnectorFindCLI extends CLI { + public TPSConnectorCLI tpsConnectorCLI; + + public TPSConnectorFindCLI(TPSConnectorCLI tpsConnectorCLI) { + super("find", "Find TPS connector details on TKS", tpsConnectorCLI); + this.tpsConnectorCLI = tpsConnectorCLI; + } + + public void printHelp() { + formatter.printHelp(getFullName() + " [OPTIONS...]", options); + } + + public void execute(String[] args) throws Exception { + Option option = new Option(null, "host", true, "TPS host"); + option.setArgName("host"); + options.addOption(option); + + option = new Option(null, "port", true, "TPS port"); + option.setArgName("port"); + options.addOption(option); + + CommandLine cmd = null; + + try { + cmd = parser.parse(options, args); + + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + printHelp(); + System.exit(1); + } + + String tpsHost = cmd.getOptionValue("host"); + String tpsPort = cmd.getOptionValue("port"); + + if (tpsHost != null) { + if (tpsPort == null) tpsPort = "443"; + TPSConnectorData data = tpsConnectorCLI.tpsConnectorClient.getConnector( + tpsHost, tpsPort); + TPSConnectorCLI.printConnectorInfo(data); + } else { + TPSConnectorCollection result = tpsConnectorCLI.tpsConnectorClient.listConnectors(); + Collection<TPSConnectorData> conns = result.getEntries(); + + boolean first = true; + for (TPSConnectorData data: conns) { + if (first) { + first = false; + } else { + System.out.println(); + } + + TPSConnectorCLI.printConnectorInfo(data); + } + } + } +} diff --git a/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorRemoveCLI.java new file mode 100644 index 000000000..f721fe28f --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/system/TPSConnectorRemoveCLI.java @@ -0,0 +1,53 @@ +// --- 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 TPSConnectorRemoveCLI extends CLI { + public TPSConnectorCLI tpsConnectorCLI; + + public TPSConnectorRemoveCLI(TPSConnectorCLI tpsConnectorCLI) { + super("del", "Remove TPS connector from TKS", tpsConnectorCLI); + this.tpsConnectorCLI = tpsConnectorCLI; + } + + public void printHelp() { + formatter.printHelp(getFullName() + " <TPS Host> <TPS Port>", options); + } + + public void execute(String[] args) throws Exception { + + if (args.length != 2) { + printHelp(); + System.exit(1); + } + + String tpsHost = args[0]; + String tpsPort = args[1]; + + tpsConnectorCLI.tpsConnectorClient.deleteConnector(tpsHost, tpsPort); + + MainCLI.printMessage("Removed TPS connector \""+tpsHost + ":" + tpsPort +"\""); + } + +} diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index d8ca7fe1f..88f9f780c 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -551,6 +551,7 @@ pki_ca_uri=https://%(pki_hostname)s:%(pki_https_port)s pki_kra_uri=https://%(pki_hostname)s:%(pki_https_port)s pki_tks_uri=https://%(pki_hostname)s:%(pki_https_port)s pki_enable_server_side_keygen=False +pki_import_shared_secret=False # Paths # These are used in the processing of pkispawn and are not supposed diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py index 9257cbfb8..ce800471b 100644 --- a/base/server/python/pki/server/deployment/pkihelper.py +++ b/base/server/python/pki/server/deployment/pkihelper.py @@ -2721,6 +2721,129 @@ class KRAConnector: # and this will raise an exception subprocess.check_output(command,stderr=subprocess.STDOUT) +class TPSConnector: + """PKI Deployment TPS Connector Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.password = deployer.password + + def deregister(self, critical_failure=False): + try: + # this is applicable to TPSs only + if self.master_dict['pki_subsystem_type'] != "tps": + return + + config.pki_log.info( + log.PKIHELPER_TPSCONNECTOR_UPDATE_CONTACT, + extra=config.PKI_INDENTATION_LEVEL_2) + + cs_cfg = PKIConfigParser.read_simple_configuration_file( + self.master_dict['pki_target_cs_cfg']) + tpshost = cs_cfg.get('service.machineName') + tpsport = cs_cfg.get('pkicreate.secure_port') + tkshostport = cs_cfg.get('conn.tks1.hostport') + if tkshostport is None: + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_TKS_HOST_PORT, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKIHELPER_UNDEFINED_TKS_HOST_PORT) + else: + return + + #retrieve tks host and port + if ':' in tkshostport: + tkshost = tkshostport.split(':')[0] + tksport = tkshostport.split(':')[1] + else: + tkshost = tkshostport + tksport = '443' + + # retrieve subsystem nickname + subsystemnick = cs_cfg.get('tps.cert.subsystem.nickname') + if subsystemnick is None: + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_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: + raise Exception(log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME) + 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 = self.password.get_password( + self.master_dict['pki_shared_password_conf'], + token_name, + critical_failure) + + if token_pwd is None or token_pwd == '': + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_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: + raise Exception(log.PKIHELPER_UNDEFINED_TOKEN_PASSWD_1 % token_name) + else: + return + + self.execute_using_pki(tkshost, tksport, subsystemnick, + token_pwd, tpshost, tpsport) + + except subprocess.CalledProcessError as exc: + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE_2, + str(tkshost), + str(tksport), + 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: + raise + return + + def execute_using_pki(self, tkshost, tksport, subsystemnick, + token_pwd, tpshost, tpsport, critical_failure=False): + command = ["/bin/pki", + "-p", str(tksport), + "-h", tkshost, + "-n", subsystemnick, + "-P", "https", + "-d", self.master_dict['pki_database_path'], + "-c", token_pwd, + "-t", "tks", + "tks-tpsconnector-del", tpshost, str(tpsport)] + + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=False) + + error = re.findall("ClientResponseFailure:(.*?)", output) + if error: + config.pki_log.warning( + log.PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE_2, + str(tpshost), + str(tpsport), + 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: + raise Exception(log.PKI_SUBPROCESS_ERROR_1 % output) + class SecurityDomain: """PKI Deployment Security Domain Class""" @@ -3498,6 +3621,7 @@ class ConfigClient: data.authdbPort = self.master_dict['pki_authdb_port'] data.authdbBaseDN = self.master_dict['pki_authdb_basedn'] data.authdbSecureConn = self.master_dict['pki_authdb_secure_conn'] + data.importSharedSecret = self.master_dict['pki_import_shared_secret'] def create_system_cert(self, tag): cert = pki.system.SystemCertData() @@ -3549,6 +3673,7 @@ class PKIDeployer: self.kra_connector = KRAConnector(self) self.security_domain = SecurityDomain(self) self.systemd = Systemd(self) + self.tps_connector = TPSConnector(self) self.config_client = ConfigClient(self) diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py index a3be42e97..339ee149e 100644 --- a/base/server/python/pki/server/deployment/pkimessages.py +++ b/base/server/python/pki/server/deployment/pkimessages.py @@ -272,6 +272,10 @@ PKIHELPER_TOMCAT_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ PKIHELPER_TOMCAT_INSTANCES_2 = "PKI Tomcat registry '%s' contains '%d' "\ "Tomcat PKI instances" PKIHELPER_TOUCH_1 = "touch %s" +PKIHELPER_TPSCONNECTOR_UPDATE_CONTACT = \ + "contacting the TKS to update the TPS connector" +PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE = "Failed to update TPS connector on TKS" +PKIHELPER_TPSCONNECTOR_UPDATE_FAILURE_2 = "Failed to update TPS connector for %s:%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 = \ @@ -280,6 +284,7 @@ PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 = \ 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_TKS_HOST_PORT = "TKS Host or Port is undefined" 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' . . ." diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py index 54349fc01..ecfb4d195 100644 --- a/base/server/python/pki/server/deployment/scriptlets/initialization.py +++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py @@ -99,6 +99,9 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): # remove kra connector from CA if this is a KRA deployer.kra_connector.deregister() + # remove tps connector from TKS if this is a TPS + deployer.tps_connector.deregister() + # de-register instance from its Security Domain # # NOTE: Since the security domain of an instance must be up diff --git a/base/tks/src/com/netscape/tks/TKSApplication.java b/base/tks/src/com/netscape/tks/TKSApplication.java index b2d43ae87..1ec0576e4 100644 --- a/base/tks/src/com/netscape/tks/TKSApplication.java +++ b/base/tks/src/com/netscape/tks/TKSApplication.java @@ -16,6 +16,7 @@ import com.netscape.cms.servlet.admin.UserCertService; import com.netscape.cms.servlet.admin.UserMembershipService; import com.netscape.cms.servlet.admin.UserService; import com.netscape.cms.servlet.csadmin.SystemConfigService; +import com.netscape.cms.servlet.tks.TPSConnectorService; public class TKSApplication extends Application { @@ -40,6 +41,9 @@ public class TKSApplication extends Application { // system certs classes.add(SystemCertService.class); + // tps connections and shared secrets + classes.add(TPSConnectorService.class); + // exception mapper classes.add(PKIException.Mapper.class); diff --git a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java index 5957f046d..c8941777d 100644 --- a/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java +++ b/base/util/src/com/netscape/cmsutil/crypto/CryptoUtil.java @@ -42,6 +42,8 @@ import java.util.HashMap; import java.util.StringTokenizer; import java.util.Vector; +import javax.crypto.SecretKey; + import netscape.security.pkcs.PKCS10; import netscape.security.pkcs.PKCS7; import netscape.security.util.BigInt; @@ -68,6 +70,7 @@ import netscape.security.x509.X509Key; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.CryptoManager.NotInitializedException; import org.mozilla.jss.NoSuchTokenException; +import org.mozilla.jss.SecretDecoderRing.KeyManager; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; @@ -95,12 +98,14 @@ import org.mozilla.jss.crypto.NoSuchItemOnTokenException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkcs11.PK11ECPublicKey; +import org.mozilla.jss.pkcs11.PK11PubKey; import org.mozilla.jss.pkcs12.PasswordConverter; import org.mozilla.jss.pkcs7.EncryptedContentInfo; import org.mozilla.jss.pkix.crmf.CertReqMsg; @@ -1639,6 +1644,78 @@ public class CryptoUtil { return encoded; } + public static boolean sharedSecretExists(String nickname) throws NotInitializedException, TokenException { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyManager km = new KeyManager(token); + return km.uniqueNamedKeyExists(nickname); + } + + public static void createSharedSecret(String nickname) throws NotInitializedException, TokenException { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyManager km = new KeyManager(token); + km.generateUniqueNamedKey(nickname); + } + + public static void deleteSharedSecret(String nickname) throws NotInitializedException, TokenException, + InvalidKeyException { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyManager km = new KeyManager(token); + km.deleteUniqueNamedKey(nickname); + } + + public static byte[] exportSharedSecret(String nickname, java.security.cert.X509Certificate wrappingCert) + throws NotInitializedException, TokenException, IOException, NoSuchAlgorithmException, InvalidKeyException, + InvalidAlgorithmParameterException, InvalidKeyFormatException { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyManager km = new KeyManager(token); + if (!km.uniqueNamedKeyExists(nickname)) { + throw new IOException("Shared secret " + nickname + " does not exist"); + } + SecretKey skey = km.lookupUniqueNamedKey(EncryptionAlgorithm.DES3_ECB, nickname); + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); + PublicKey pub = wrappingCert.getPublicKey(); + PK11PubKey pubK = PK11PubKey.fromSPKI(pub.getEncoded()); + keyWrap.initWrap(pubK, null); + byte[] wrappedKey = keyWrap.wrap(((SecretKeyFacade) skey).key); + return wrappedKey; + } + + /* + public static void importSharedSecret(KeyData data) throws EBaseException, NotInitializedException, TokenException, + NoSuchAlgorithmException, ObjectNotFoundException, InvalidKeyException, InvalidAlgorithmParameterException, + IOException { + byte[] wrappedKey = Utils.base64decode(data.getWrappedPrivateData()); + + IConfigStore cs = CMS.getConfigStore(); + String subsystemNick = cs.getString("tps.cert.subsystem.nickname"); + String keyNick = cs.getString("conn.tks1.tksSharedSymKeyName", "sharedSecret"); + + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyManager km = new KeyManager(token); + + if (km.uniqueNamedKeyExists(keyNick)) { + throw new IOException("Shared secret " + keyNick + " already exists"); + } + + KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); + X509Certificate cert = cm.findCertByNickname(subsystemNick); + PrivateKey subsystemPrivateKey = cm.findPrivKeyByCert(cert); + keyWrap.initUnwrap(subsystemPrivateKey, null); + + @SuppressWarnings("unused") + SymmetricKey unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.DES, + SymmetricKey.Usage.DECRYPT, 0); + + // TODO - I have a key - now what to do with it? + // need to somehow import/label the symkey + }*/ + public static String[] getECcurves() { return ecCurves; } @@ -1667,7 +1744,6 @@ public class CryptoUtil { } } - // START ENABLE_ECC // This following can be removed when JSS with ECC capability // is integrated. |