/* * RoleInfo.java * * Created on Apr 13, 2010, 10:32:10 AM * * Description: Provides a role information container for persisting in the Chord distributed hash table. * * Copyright (C) Apr 13, 2010, Stephen L. Reed. * * 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; either * version 3 of the License, or (at your option) any later version. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.texai.ahcsSupport; import java.io.IOException; import java.io.Serializable; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.SignatureException; import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.util.UUID; import net.jcip.annotations.Immutable; import org.openrdf.model.URI; import org.texai.kb.util.UUIDUtils; import org.texai.util.TexaiException; import org.texai.x509.SerializableObjectSigner; import org.texai.x509.X509Utils; /** Provides a role information container for persisting in the Chord distributed hash table. * * @author reed */ @Immutable public class RoleInfo implements Serializable { /** the serial version universal identifier */ private static final long serialVersionUID = 1L; /** the role id, which is the key to retrieving this RoleInfo from the Chord distributed hash table */ private final URI roleId; /** the role's local area network ID, used to determine whether the internal or external host address should be used to access it */ private final UUID localAreaNetworkID; /** the host address as presented to the Internet, e.g. texai.dyndns.org */ private final String externalHostName; /** the TCP port as presented to the Internet */ private final int externalPort; /** the host address as presented to the LAN, e.g. turing */ private final String internalHostName; /** the TCP port as presented to the LAN */ private final int internalPort; /** the role's X.509 certificate path */ private final CertPath certPath; /** the signature bytes of this RoleInfo by the role's X.509 certificate */ private byte[] signatureBytes; /** Constructs a new RoleInfo instance. * @param roleId the role id, which is the key to retrieving this RoleInfo from the Chord distributed hash table * @param certPath the role's X.509 certificate path * @param privateKey the role's private key * @param localAreaNetworkID the role's local area network ID * @param externalHostName the external host name * @param externalPort the external port * @param internalHostName the internal host name * @param internalPort the internal port */ public RoleInfo( final URI roleId, final CertPath certPath, final PrivateKey privateKey, final UUID localAreaNetworkID, final String externalHostName, final int externalPort, final String internalHostName, final int internalPort) { //Preconditions assert roleId != null : "roleId must not be null"; assert certPath != null : "certPath must not be null"; assert !certPath.getCertificates().isEmpty() : "certPath must not be empty"; assert X509Utils.getUUID((X509Certificate) certPath.getCertificates().get(0)).equals(UUIDUtils.uriToUUID(roleId)) : "roleId must equal certificate UID, roleId: " + roleId + " as UUID: " + UUIDUtils.uriToUUID(roleId) + "\ncertificate UID: " + X509Utils.getUUID((X509Certificate) certPath.getCertificates().get(0)) + "\nX.509 certificate:\n" + certPath.getCertificates().get(0); assert privateKey != null : "privateKey must not be null"; assert localAreaNetworkID != null : "localAreaNetworkID must not be null"; assert externalHostName != null : "externalHostName must not be null"; assert !externalHostName.isEmpty() : "externalHostName must not be empty"; assert externalPort > 0 : "externalPort must be positive"; assert internalHostName != null : "internalHostName must not be null"; assert !internalHostName.isEmpty() : "internalHostName must not be empty"; assert internalPort > 0 : "internalPort must be positive"; this.roleId = roleId; this.certPath = certPath; this.localAreaNetworkID = localAreaNetworkID; this.externalHostName = externalHostName; this.externalPort = externalPort; this.internalHostName = internalHostName; this.internalPort = internalPort; try { signatureBytes = SerializableObjectSigner.sign(this, privateKey); } catch (NoSuchAlgorithmException | InvalidKeyException | IOException | SignatureException ex) { throw new TexaiException(ex); } } /** Gets the role id, which is the key to retrieving this RoleInfo from the Chord distributed hash table. * * @return the role id */ public URI getRoleId() { return roleId; } /** Gets the role's X.509 certificate path. * * @return the role's X.509 certificate path */ public CertPath getCertPath() { return certPath; } /** Gets the role's X.509 certificate. * * @return the role's X.509 certificate */ public X509Certificate getRoleX509Certificate() { return (X509Certificate) certPath.getCertificates().get(0); } /** Gets the signature bytes of this RoleInfo by the role's X.509 certificate. * * @return the signature bytes */ public byte[] getSignatureBytes() { return signatureBytes; } /** Returns whether the contained signature verifies this RoleInfo, throwing an exception if not OK. * * @return whether the given signature verifies the given file */ public boolean verify() { //Preconditions assert signatureBytes.length > 0 : "signatureBytes must not be empty"; final byte[] savedSignatureBytes = signatureBytes; signatureBytes = null; final boolean result; try { result = SerializableObjectSigner.verify( this, (X509Certificate) certPath.getCertificates().get(0), savedSignatureBytes); } catch (NoSuchAlgorithmException | InvalidKeyException | IOException | SignatureException ex) { throw new TexaiException(ex); } signatureBytes = savedSignatureBytes; return result; } /** Returns whether some other object equals this one. * * @param obj the other object * @return whether the other object equals this one */ @Override public boolean equals(final Object obj) { if (obj instanceof RoleInfo) { final RoleInfo that = (RoleInfo) obj; if (this.roleId.equals(that.roleId)) { assert this.certPath.equals(that.certPath); return true; } else { return false; } } else { return false; } } /** Returns a hash code for this object. * * @return a hash code for this object */ @Override public int hashCode() { return roleId.hashCode(); } /** Returns a string representation of this object. * * @return a string representation of this object */ @Override public String toString() { final StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("[RoleInfo "); stringBuilder.append(roleId); stringBuilder.append(", lan: "); stringBuilder.append(localAreaNetworkID); stringBuilder.append(", external host address: "); stringBuilder.append(externalHostName); stringBuilder.append(":"); stringBuilder.append(externalPort); stringBuilder.append(", internal host address: "); stringBuilder.append(internalHostName); stringBuilder.append(":"); stringBuilder.append(internalPort); stringBuilder.append(']'); return stringBuilder.toString(); } /** Gets the host address as presented to the Internet, e.g. texai.dyndns.org. * * @return the host address as presented to the Internet */ public String getExternalHostName() { return externalHostName; } /** Gets the TCP port as presented to the Internet. * * @return the TCP port as presented to the Internet */ public int getExternalPort() { return externalPort; } /** Gets the host address as presented to the LAN, e.g. turing. * * @return the host address as presented to the LAN */ public String getInternalHostName() { return internalHostName; } /** Gets the TCP port as presented to the LAN. * * @return the TCP port as presented to the LAN */ public int getInternalPort() { return internalPort; } /** Gets the role's local area network ID, used to determine whether the internal or external host address should be used to access it. * * @return the role's local area network ID */ public UUID getLocalAreaNetworkID() { return localAreaNetworkID; } }