Table of Contents Previous Next
Logo
IceSSL : 41.5 Programming with IceSSL
Copyright © 2003-2007 ZeroC, Inc.

41.5 Programming with IceSSL

The configuration properties described in Section 41.4 are flexible enough to satisfy the requirements of many applications, and IceSSL supports a public API that offers even more functionality for those applications that need it.

41.5.1 C++

This section describes the C++ API for the IceSSL plug‑in.

The Plugin Interface

Applications can interact directly with the IceSSL plug‑in using the native C++ class IceSSL::Plugin. A reference to a Plugin object must be obtained from the communicator in which the plug‑in is installed:
Ice::CommunicatorPtr communicator = // ...
Ice::PluginManagerPtr pluginMgr =
    communicator>getPluginManager();
Ice::PluginPtr plugin = pluginMgr>getPlugin("IceSSL");
IceSSL::PluginPtr sslPlugin =
    IceSSL::PluginPtr::dynamicCast(plugin);
The Plugin class supports the following methods:
namespace IceSSL
{
class Plugin : public Ice::Plugin
{
public:
    virtual void setContext(SSL_CTX*) = 0;
    virtual SSL_CTX* getContext() = 0;

    virtual void setCertificateVerifier(
        const CertificateVerifierPtr&) = 0;

    virtual void setPasswordPrompt(
        const PasswordPromptPtr&) = 0;
};
typedef IceUtil::Handle<Plugin> PluginPtr;
}
The setContext and getContext methods are rarely used in practice; see Section 41.6 for more information. The setCertificateVerifier method installs a custom certificate verifier object that the plugin invokes for each new connection. The setPasswordPrompt method provides an alternate way to supply IceSSL with passwords, as discussed in Section 41.6.

Installing a Certificate Verifier

A new connection undergoes a series of verification steps before an application is allowed to use it. The low-level SSL engine executes the validation procedures described in Section 41.2.2. Assuming the certificate chain is successfully vali­dated, IceSSL performs additional verification as directed by its configuration properties (see Section 41.4.5). Finally, if a certificate verifier is installed, IceSSL invokes it to provide the application with an opportunity to decide whether to allow the connection to proceed.
The CertificateVerifier interface has only one method:
namespace IceSSL
{
class CertificateVerifier : public IceUtil::Shared
{
public:

    virtual bool verify(const ConnectionInfo&) = 0;
};
typedef IceUtil::Handle<CertificateVerifier>
    CertificateVerifierPtr;
}
IceSSL rejects the connection if verify returns false, and allows it to proceed if the method returns true. The verify method receives a ConnectionInfo object that describes the connection’s attributes:
namespace IceSSL
{
struct ConnectionInfo
{
    std::vector<CertificatePtr> certs;
    std::string cipher;
    struct sockaddr_in localAddr;
    struct sockaddr_in remoteAddr;
    bool incoming;
    std::string adapterName;
};
}
The certs member is a vector of certificates representing the peer’s certificate chain. The vector is structured so that the first element is the peer’s certificate, followed by its signing certificates in the order they appear in the chain, with the root CA certificate as the last element. The vector is empty if the peer did not present a certificate chain.
The cipher member is a description of the ciphersuite that SSL negotiated for this connection. The local and remote address information is provided in localAddr and remoteAddr, respectively. The incoming member indi­cates whether the connection is inbound (a server connection) or outbound (a client connection). Finally, if incoming is true, the adapterName member supplies the name of the object adapter that hosts the endpoint.
The following class is a simple implementation of a certificate verifier:
class Verifier : public IceSSL::CertificateVerifier
{
public:

    bool verify(const IceSSL::ConnectionInfo& info)
    {
        if(!info.certs.empty())
        {
            string dn = info.certs[0].getIssuerDN();
            transform(dn.begin(), dn.end(), dn.begin(),
                      ::tolower);
            if(dn.find("zeroc") != string::npos)
            {
                return true;
            }
        }
        return false;
    }
}
In this example, the verifier rejects the connection unless the string zeroc is present in the issuer’s distinguished name of the peer’s certificate. In a more real­istic implementation, the application is likely to perform detailed inspection of the certificate chain.
Installing the verifier is a simple matter of calling setCertificateVeri­fier on the plugin interface:
IceSSL::PluginPtr sslPlugin = // ...
sslPlugin>setCertificateVerifier(new Verifier);
You should install the verifier before any SSL connections are established.
See Section 41.6.2 for more information on installing a certificate verifier.

Obtaining Connection Information

You can obtain information about any SSL connection using the getConnec­tionInfo function:
namespace IceSSL
{
ConnectionInfo getConnectionInfo(const Ice::ConnectionPtr&);
}
The function throws IceSSL::ConnectionInvalidException if its argument does not represent an SSL connection.
For more information on connections, see Chapter 36.

Certificates

The ConnectionInfo class contains a vector of Certificate objects representing the peer’s certificate chain. Certificate is a reference-counted convenience class that hides the complexity of the underlying OpenSSL API. Its methods are inspired by the Java class X509Certificate:
namespace IceSSL
{
class Certificate : public IceUtil::Shared
{
public:

    Certificate(X509*);

    static CertificatePtr load(const string&);
    static CertificatePtr decode(const string&);

    bool operator==(const Certificate&) const;
    bool operator!=(const Certificate&) const;

    PublicKeyPtr getPublicKey() const;

    bool verify(const PublicKeyPtr&) const;

    string encode() const;

    bool checkValidity() const;
    bool checkValidity(const IceUtil::Time&) const;

    IceUtil::Time getNotAfter() const;
    IceUtil::Time getNotBefore() const;

    string getSerialNumber() const;

    DistinguishedName getIssuerDN() const;
    vector<pair<int, string> > getIssuerAlternativeNames();

    DistinguishedName getSubjectDN() const;
    vector<pair<int, string> > getSubjectAlternativeNames();

    int getVersion() const;

    string toString() const;

    X509* getCert() const;
};
typedef IceUtil::Handle<Certificate> CertificatePtr;
}
The more commonly-used methods are described below; refer to the documenta­tion in IceSSL/Plugin.h for information on the methods that are not covered.
The static method load creates a certificate from the contents of a PEM-encoded file. If an error occurs, the function raises IceSSL::Certifica­teReadException; the reason member provides a description of the problem.
Use decode to obtain a certificate from a PEM-encoded string representing a certificate. The caller must be prepared to catch IceSSL::CertificateEn­codingException if decode fails; the reason member provides a description of the problem.
The encode method creates a PEM-encoded string that represents the certifi­cate. The return value can later be passed to decode to recreate the certificate.
The checkValidity methods determine whether the certificate is valid. The overloading with no arguments returns true if the certificate is valid at the current time; the other overloading accepts an IceUtil::Time object and returns true if the certificate is valid at the given time. See Section 31.7 for more information on IceUtil::Time.
The getNotAfter and getNotBefore methods return instances of IceUtil::Time that define the certificate’s valid period.
The methods getIssuerDN and getSubjectDN supply the distinguished names of the certificate’s issuer (i.e., the CA that signed the certificate) and subject (i.e., the person or entity to which the certificate was issued). The methods return instances of the class IceSSL::DistinguishedName, another conve­nience class that is described in the next section.
Finally, the toString method returns a human-readable string describing the certificate.

Distinguished Names

X.509 certificates use a distinguished name to identify a person or entity. The name is an ordered sequence of relative distinguished names that supply values for fields such as common name, organization, state, and country. Distinguished names are commonly displayed in stringified form according to the rules specified by RFC 2253, as shown in the following example:
C=US, ST=Florida, L=Palm Beach Gardens, O="ZeroC, Inc.",
OU=Servers, CN=Quote Server
DistinguishedName is a convenience class provided by IceSSL to simplify the tasks of parsing, formatting and comparing distinguished names.
namespace IceSSL
{
class DistinguishedName
{
public:

    DistinguishedName(const std::string&);
    DistinguishedName(
        const std::list<std::pair<std::string, std::string> >&);

    bool operator==(const DistinguishedName&) const;
    bool operator!=(const DistinguishedName&) const;
    bool operator<(const DistinguishedName&) const;

    bool match(const DistinguishedName&) const;

    operator std::string() const;
};
}
The first overloaded constructor accepts a string argument representing a distin­guished name encoded using the rules set forth in RFC 2253. The new Distin­guishedName instance preserves the order of the relative distinguished names in the string. The caller must be prepared to catch IceSSL::ParseExcep­tion if an error occurs during parsing.
The second overloaded constructor requires a list of type–value pairs repre­senting the relative distinguished names. The new DistinguishedName instance preserves the order of the relative distinguished names in the list.
The overloaded operator functions operator==, operator!=, and operator< perform an exact match of distinguished names in which the order of the relative distinguished names is important. For two distinguished names to be equal, they must have the same relative distinguished names in the same order.
The match function performs a partial comparison that does not consider the order of relative distinguished names. If N1 and N2 are instances of Distin­guishedName, N1.match(N2) returns true if all of the relative distinguished names in N2 are present in N1.
Finally, the string conversion operator encodes the distinguished name in the format described by RFC 2253.

41.5.2 Java

This section describes the Java API for the IceSSL plug‑in.

The Plugin Interface

Applications can interact directly with the IceSSL plug‑in using the native Java interface IceSSL.Plugin. A reference to a Plugin object must be obtained from the communicator in which the plug‑in is installed:
Ice.Communicator comm = // ...
Ice.PluginManager pluginMgr = comm.getPluginManager();
Ice.Plugin plugin = pluginMgr.getPlugin("IceSSL");
IceSSL.Plugin sslPlugin = (IceSSL.Plugin)plugin;
The Plugin interface supports the following methods:
package IceSSL;

public interface Plugin extends Ice.Plugin
{
    void setContext(javax.net.ssl.SSLContext context);
    javax.net.ssl.SSLContext getContext();

    void setCertificateVerifier(CertificateVerifier verifier);
}
The setContext and getContext methods are rarely used in practice; see Section 41.6 for more information. The setCertificateVerifier method installs a custom certificate verifier object that the plugin invokes for each new connection.

Installing a Certificate Verifier

A new connection undergoes a series of verification steps before an application is allowed to use it. The low-level SSL engine executes the validation procedures described in Section 41.2.2. Assuming the certificate chain is successfully vali­dated, IceSSL performs additional verification as directed by its configuration properties (see Section 41.4.5). Finally, if a certificate verifier is installed, IceSSL invokes it to provide the application with an opportunity to decide whether to allow the connection to proceed.
The CertificateVerifier interface has only one method:
package IceSSL;

public interface CertificateVerifier
{
    boolean verify(ConnectionInfo info);
}
IceSSL rejects the connection if verify returns false, and allows it to proceed if the method returns true. The verify method receives a ConnectionInfo object that describes the connection’s attributes:
package IceSSL;

public class ConnectionInfo
{
    public java.security.cert.Certificate[] certs;
    public String cipher;
    public java.net.InetSocketAddress localAddr;
    public java.net.InetSocketAddress remoteAddr;
    boolean incoming;
    String adapterName;
}
The certs member is an array of certificates representing the peer’s certificate chain. The array is structured so that the first element is the peer’s certificate, followed by its signing certificates in the order they appear in the chain, with the root CA certificate as the last element. This member is null if the peer did not present a certificate chain.
The cipher member is a description of the ciphersuite that SSL negotiated for this connection. The local and remote address information is provided in localAddr and remoteAddr, respectively. The incoming member indi­cates whether the connection is inbound (a server connection) or outbound (a client connection). Finally, if incoming is true, the adapterName member supplies the name of the object adapter that hosts the endpoint.
The following class is a simple implementation of a certificate verifier:
import java.security.cert.X509Certificate;
import javax.security.auth.x500.X500Principal;

class Verifier implements IceSSL.CertificateVerifier
{
    public boolean
    verify(IceSSL.ConnectionInfo info)
    {
        if(info.certs != null)
        {
            X509Certificate cert = (X509Certificate)info.certs[0];
            X500Principal p = cert.getIssuerX500Principal();
            if(p.getName().toLowerCase().indexOf("zeroc") != 1)
            {
                return true;
            }
        }
        return false;
    }
}
In this example, the verifier rejects the connection unless the string zeroc is present in the issuer’s distinguished name of the peer’s certificate. In a more real­istic implementation, the application is likely to perform detailed inspection of the certificate chain.
Installing the verifier is a simple matter of calling setCertificateVeri­fier on the plugin interface:
IceSSL.Plugin sslPlugin = // ...
sslPlugin.setCertificateVerifier(new Verifier());
You should install the verifier before any SSL connections are established.
See Section 41.6.2 for more information on installing a certificate verifier.

Obtaining Connection Information

You can obtain information about any SSL connection using the getConnec­tionInfo function:
package IceSSL;

public final class Util
{
    public static ConnectionInfo
    getConnectionInfo(Ice.Connection connection);

    // ...
}
The function throws IceSSL.ConnectionInvalidException if its argu­ment does not represent an SSL connection.
For more information on connections, see Chapter 36.

Converting Certificates

Java does not provide a simple way to create a certificate object from a PEM-encoded string, therefore IceSSL offers the following convenience method:
package IceSSL;

public final class Util
{
    // ...

    public static java.security.cert.X509Certificate
    createCertificate(String certPEM)
        throws java.security.cert.CertificateException;
}
Given a string in the PEM format, createCertificate returns the equivalent X509Certificate object.

41.5.3 C#

This section describes the C# API for the IceSSL plug‑in.

The Plugin Interface

Applications can interact directly with the IceSSL plug‑in using the native C# interface IceSSL.Plugin. A reference to a Plugin object must be obtained from the communicator in which the plug‑in is installed:
Ice.Communicator comm = // ...
Ice.PluginManager pluginMgr = comm.getPluginManager();
Ice.Plugin plugin = pluginMgr.getPlugin("IceSSL");
IceSSL.Plugin sslPlugin = (IceSSL.Plugin)plugin;
The Plugin interface supports the following methods:
namespace IceSSL
{
    using System.Security.Cryptography.X509Certificates;

    abstract public class Plugin : Ice.LocalObjectImpl, Ice.Plugin
    {
        abstract public void
        setCertificates(X509Certificate2Collection certs);

        abstract public void
        setCertificateVerifier(CertificateVerifier verifier);
    }
}
The setCertificates method is rarely used in practice; see Section 41.6 for more information. The setCertificateVerifier method installs a custom certificate verifier object that the plugin invokes for each new connection.

Installing a Certificate Verifier

A new connection undergoes a series of verification steps before an application is allowed to use it. The low-level SSL engine executes the validation procedures described in Section 41.2.2. Assuming the certificate chain is successfully vali­dated, IceSSL performs additional verification as directed by its configuration properties (see Section 41.4.5). Finally, if a certificate verifier is installed, IceSSL invokes it to provide the application with an opportunity to decide whether to allow the connection to proceed.
The CertificateVerifier interface has only one method:
namespace IceSSL
{
    public interface CertificateVerifier
    {
        bool verify(ConnectionInfo info);
    }
}
IceSSL rejects the connection if verify returns false, and allows it to proceed if the method returns true. The verify method receives a ConnectionInfo object that describes the connection’s attributes:
namespace IceSSL
{
    using System.Security.Cryptography.X509Certificates;

    public sealed class ConnectionInfo
    {
        public X509Certificate2[] certs;
        public string cipher;
        public System.Net.IPEndPoint localAddr;
        public System.Net.IPEndPoint remoteAddr;
        public bool incoming;
        public string adapterName;
    }
}
The certs member is an array of certificates representing the peer’s certificate chain. The array is structured so that the first element is the peer’s certificate, followed by its signing certificates in the order they appear in the chain, with the root CA certificate as the last element. This member is null if the peer did not present a certificate chain.
The cipher member is a description of the ciphersuite that SSL negotiated for this connection. The local and remote address information is provided in localAddr and remoteAddr, respectively. The incoming member indi­cates whether the connection is inbound (a server connection) or outbound (a client connection). Finally, if incoming is true, the adapterName member supplies the name of the object adapter that hosts the endpoint.
The following class is a simple implementation of a certificate verifier:
using System.Security.Cryptography.X509Certificates;

class Verifier : IceSSL.CertificateVerifier
{
    public boolean
    verify(IceSSL.ConnectionInfo info)
    {
        if(info.certs != null)
        {
            X500DistinguishedName dn = info.certs[0].IssuerName;
            if(dn.Name.ToLower().Contains("zeroc"))
            {
                return true;
            }
        }
        return false;
    }
}
In this example, the verifier rejects the connection unless the string zeroc is present in the issuer’s distinguished name of the peer’s certificate. In a more real­istic implementation, the application is likely to perform detailed inspection of the certificate chain.
Installing the verifier is a simple matter of calling setCertificateVeri­fier on the plugin interface:
IceSSL.Plugin sslPlugin = // ...
sslPlugin.setCertificateVerifier(new Verifier());
You should install the verifier before any SSL connections are established.
See Section 41.6.2 for more information on installing a certificate verifier.

Obtaining Connection Information

You can obtain information about any SSL connection using the getConnec­tionInfo function:
namespace IceSSL
{
    public sealed class Util
    {
        // ...

        public static ConnectionInfo
        getConnectionInfo(Ice.Connection connection);
    }
}
The function throws IceSSL.ConnectionInvalidException if its argu­ment does not represent an SSL connection.
For more information on connections, see Chapter 36.

Converting Certificates

IceSSL offers the following convenience method to create a certificate object from a PEM-encoded string:
namespace IceSSL
{
    using System.Security.Cryptography.X509Certificates;

    public sealed class Util
    {
        // ...

        public static X509Certificate2
        createCertificate(string certPEM);
    }
}
Given a string in the PEM format, createCertificate returns the equivalent X509Certificate2 object.

41.5.4 Visual Basic

This section describes the Visual Basic API for the IceSSL plug‑in.

The Plugin Interface

Applications can interact directly with the IceSSL plug‑in using the native Visual Basic interface IceSSL.Plugin. A reference to a Plugin object must be obtained from the communicator in which the plug‑in is installed:
Dim comm As Ice.Communicator = // ...
Dim pluginMgr As Ice.PluginManager = comm.getPluginManager()
Dim plugin As Ice.Plugin = pluginMgr.getPlugin("IceSSL")
Dim sslPlugin As IceSSL.Plugin = (IceSSL.Plugin)plugin
The Plugin interface supports the following methods:
Namespace IceSSL

Imports System.Security.Cryptography.X509Certificates

Public Interface Plugin Inherits Ice.Plugin

        Public MustOverride Sub
        setCertificates(ByVal certs As X509Certificate2Collection)

        Public MustOverride Sub
        setCertificateVerifier(
            ByVal verifier As CertificateVerifier)

End Class

End Namespace
The setCertificates method is rarely used in practice; see Section 41.6 for more information. The setCertificateVerifier method installs a custom certificate verifier object that the plugin invokes for each new connection.

Installing a Certificate Verifier

A new connection undergoes a series of verification steps before an application is allowed to use it. The low-level SSL engine executes the validation procedures required by the protocol specification, which includes checking the validity of the peer’s certificate chain. If this step completes successfully, IceSSL performs addi­tional verification as directed by its configuration properties (see Section 41.4.5). Finally, if a certificate verifier is installed, IceSSL invokes it to provide the appli­cation with an opportunity to decide whether to allow the connection to proceed.
The CertificateVerifier interface has only one method:
Namespace IceSSL

Public Interface CertificateVerifier

    Function verify(ByVal info As ConnectionInfo) As Boolean

End Interface

End Namespace
IceSSL rejects the connection if verify returns False, and allows it to proceed if the method returns True. The verify method receives a ConnectionInfo object that describes the connection’s attributes:
Namespace IceSSL

Imports System.Security.Cryptography.X509Certificates

Public NotInheritable Class ConnectionInfo
    Public certs As X509Certificate2()
    Public cipher As String
    Public localAddr As System.Net.IPEndPoint
    Public remoteAddr As System.Net.IPEndPoint
    Public incoming As Boolean
    Public adapterName As String
End Class

End Namespace
The certs member is an array of certificates representing the peer’s certificate chain. This member is Nothing if the peer did not present a certificate chain, otherwise the first element of the array is the peer’s certificate.
The cipher member is a description of the ciphersuite that SSL negotiated for this connection. The local and remote address information is provided in localAddr and remoteAddr, respectively. The incoming member indi­cates whether the connection is inbound (a server connection) or outbound (a client connection). Finally, if incoming is True, the adapterName member supplies the name of the object adapter that received the connection.
The following class is a simple implementation of a certificate verifier:
Imports System.Security.Cryptography.X509Certificates

Class Verifier Implements IceSSL.CertificateVerifier

    Public Function
    verify(ByVal info As IceSSL.ConnectionInfo) As Boolean
        Implements IceSSL.CertificateVerifier.verify

        If info.certs <> Nothing
            Dim dn As X500DistinguishedName =
                info.certs(0).IssuerName
            If dn.Name.ToLower().Contains("zeroc"))
                Return True
            End If
        End If
        Return False

    End Function

End Class
In this example, the verifier rejects the connection unless the string zeroc is present in the issuer’s distinguished name of the peer’s certificate. In a more real­istic implementation, the application is likely to perform detailed inspection of the certificate chain.
Installing the verifier is a simple matter of calling setCertificateVeri­fier on the plugin interface:
Dim sslPlugin As IceSSL.Plugin = // ...
sslPlugin.setCertificateVerifier(New Verifier())
You should install the verifier before any SSL connections are established.
See Section 41.6.2 for more information on installing a certificate verifier.

Obtaining Connection Information

You can obtain information about any SSL connection using the getConnec­tionInfo function:
Namespace IceSSL

Public NotInheritable Class Util

    Public Shared Function
    getConnectionInfo(connection As Ice.Connection)
        As ConnectionInfo

End Class

End Namespace
The function throws IceSSL.ConnectionInvalidException if its argu­ment does not represent an SSL connection.
For more information on connections, see Chapter 36.

 Converting Certificates

IceSSL offers the following convenience method to create a certificate object from a PEM-encoded string:
Namespace IceSSL

Imports System.Security.Cryptography.X509Certificates

Public NotInheritable Class Util

    Public Shared Function
    createCertificate(certPEM As String)
        As X509Certificate2

End Class

End Namespace
Given a string in the PEM format, createCertificate returns the equivalent X509Certificate2 object.
Table of Contents Previous Next
Logo