This page describes the C++ API for the IceSSL plug-in.
On this page:
The IceSSL C++ plug-in has several implementations listed in the table below. Its API consists of implementation-independent classes directly in the IceSSL
namespace plus implementation-dependent classes in nested namespaces such as IceSSL::OpenSSL.
Underlying SSL/TLS Implementation | IceSSL Plug-in Class | IceSSL Certificate Class | Platform Availability |
---|---|---|---|
OpenSSL |
|
| Linux (default), Windows |
SecureTransport | IceSSL::Plugin |
| macOS (default) |
SChannel |
|
| Windows (default) |
UWP | IceSSL::Plugin |
| UWP (default) |
Each platform has a default implementation, indicated with (default) in the table above. Static functions on the IceSSL::Certificate
class are supplied by the default platform-dependent implementation.
Applications can interact directly with the IceSSL plug-in using the C++ class IceSSL::Plugin
. You can retrieve this Plugin
object as shown below:
|
The Plugin
class provides the following functions:
|
The setCertificateVerifier
function installs a custom certificate verifier object that the plug-in invokes for each new connection. The setPasswordPrompt
function provides an alternate way to supply IceSSL with passwords. We discuss certificate verifiers below and revisit the other functions in our discussion of advanced IceSSL programming.
The load
function creates a Certificate
object from a file in PEM encoded format. Likewise, the decode
function creates a certificate from a string in the PEM encoding format. The most-derived type of the certificate object depends on the plug-in implementation you're using:
Plug-in | Certificate |
---|---|
OpenSSL | IceSSL::OpenSSL::Certificate |
SChannel | IceSSL::SChannel::Certificiate |
SecureTransport | IceSSL::SecureTransport::Certificate |
UWP | IceSSL::UWP::Certificate |
|
You can obtain information about any SSL connection using the getInfo
operation on a Connection
object. IceSSL defines the following type in Slice:
// from Ice/Connection.ice module Ice { local class ConnectionInfo { ConnectionInfo underlying; bool incoming; string adapterName; string connectionId; } } // from IceSSL/ConnectionInfo.ice module IceSSL { local class ConnectionInfo extends Ice::ConnectionInfo { string cipher; ["cpp:type:std::vector<CertificatePtr>", "java:type:java.security.cert.Certificate[]", "cs:type:System.Security.Cryptography.X509Certificates.X509Certificate2[]"] Ice::StringSeq certs; bool verified; } } |
The certs
member contains the peer's certificate chain as a sequence of IceSSL::CertificatePtr
objects. The cpp:type
metadata changes the default mapping of the certs
member to that native type. The cipher
member is a description of the ciphersuite that SSL negotiated for this connection. The verified
member indicates whether IceSSL was able to successfully verify the peer's certificate.
The inherited underlying
data member contains the connection information of the underlying transport (if SSL is based on TCP, this member will contain an instance of Ice::TCPEndpointInfo
which you can use to retrieve the remote and local addresses). The incoming
member indicates whether the connection is inbound (a server connection) or outbound (a client connection). The connectionId
data member matches the connection identifier set on the proxy. Finally, if incoming
is true, the adapterName
member supplies the name of the object adapter that hosts the endpoint.
A new connection undergoes a series of verification steps before an application is allowed to use it. The low-level SSL engine executes certificate validation procedures and, assuming the certificate chain is successfully validated, IceSSL performs additional verification as directed by its configuration properties. If a certificate verifier is installed, IceSSL invokes it to provide the application with an opportunity to decide whether to accept or reject the connection. The value of the IceSSL.VerifyPeer
property also plays an important role here. We've summarized the process in the following flow chart:
|
You should install the verifier before any SSL connections are established.
You can also install a certificate verifier using a custom plug-in to avoid making changes to the code of an existing application.
The Ice run time calls the certificate verifier during the connection-establishment process, therefore delays in the certificate verifier implementation have a direct impact on the performance of the application. Do not make remote invocations from your implementation of the certificate verifier. |
The IceSSL::ConnectionInfo
class contains a vector of IceSSL::Certificate
objects representing the peer's certificate chain. IceSSL::Certificate
is a reference-counted convenience class that hides the complexity of the platform's native SSL API inspired by the Java class X509Certificate
. The IceSSL::Certificate
class defines the common API for all IceSSL implementations, and APIs that use platform-dependent types are provided by extensions of this class. When a common method is not supported by a SSL implementation it raises Ice::FeatureNotSupportedException
.
|
The more commonly-used functions are described below; refer to the documentation in IceSSL/Plugin.h
for information on the functions that are not covered.
The static function load
creates a certificate from the contents of a certificate file PEM-encoded. If an error occurs, the function raises IceSSL::CertificateReadException
; the reason member provides a description of the problem.
The UWP implementation of load uses GetFileFromApplicationUriAsync and the file path must use an appropriate URI format. |
Use decode
to obtain a certificate from a PEM-encoded string representing a certificate. The caller must be prepared to catch IceSSL::CertificateEncodingException
if decode
fails; the reason member provides a description of the problem.
Both load
and decode
return a certificate using the default IceSSL::Certificate
implementation:
IceSSL::SChannel::Certificate
on WindowsIceSSL::SecureTransport::Certificate
on macOSIceSSL::UWP::Certificate
for UWPIceSSL::OpenSSL::Certificate
for OpenSSLAll of these classes derive from IceSSL::Certificate
to provide platform-dependent methods.
The encode
function creates a PEM-encoded string that represents the certificate. The return value can later be passed to decode
to recreate the certificate.
The checkValidity
functions 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 a system_clock::time_point
with the C++11 mapping (IceUtil::Time
with the C++98 mapping) and returns true if the certificate is valid at the given time.
The getNotAfter
and getNotBefore
functions return the times that define the certificate's valid period, as a system_clock::time_point
with the C++11 mapping and as a IceUtil::Time
with the C++98 mapping.
The functions 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 functions return instances of the class IceSSL::DistinguishedName
, another convenience class that is described below.
The getX509Extensions
and getX509Extension
functions can be used to retrieve a list of the X509 extensions included in the certificate or a specific X509 extension by providing its OID
, respectively. These methods are only supported by the OpenSSL and SChannel implementations. We discuss extensions further below.
The getAuthorityKeyIdentifier
and getSubjectKeyIdentifier
functions return the authority key identifier and subject key identifier respectively as a sequence of bytes. These methods are not supported with UWP or with SecureTransport on iOS.
Finally, the toString
function returns a human-readable string describing the certificate.
It is possible to interact with the SSL implementation's native certificates. Tthese APIs are platform-dependent and are defined in extensions of the IceSSL::Certificate
class. Refer to the header file for each implementation to get more details. The following table summarizes the header files specific to each implementation:
SSL Implementation | Header File |
---|---|
OpenSSL | IceSSL/OpenSSL.h |
SecureTransport | IceSSL/SecureTransport.h |
SChannel | IceSSL/SChannel.h |
UWP | IceSSL/UWP.h |
Usually you don't need to include these header files in your application; you'll just include IceSSL/IceSSL.h
which includes the appropriate header files for your platform's default implementation. If you are using the OpenSSL implementation on Windows and need to access OpenSSL-specific APIs, you must include IceSSL/OpenSSL.h
.
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: explicit DistinguishedName(const std::string&); explicit DistinguishedName(const std::list<std::pair<std::string, std::string>>&); bool match(const DistinguishedName&) const; bool match(const std::string&) const; operator std::string() const; friend bool operator==(const DistinguishedName&, const DistinguishedName&); friend bool operator<(const DistinguishedName&, const DistinguishedName&); }; inline bool operator!=(const DistinguishedName&, const DistinguishedName&) { ... } // etc., provides all comparison operators. } |
The first overloaded constructor accepts a string argument representing a distinguished name encoded using the rules set forth in RFC 2253. The new DistinguishedName
instance preserves the order of the relative distinguished names in the string. The caller must be prepared to catch IceSSL::ParseException
if an error occurs during parsing.
The second overloaded constructor requires a list of type-value pairs representing the relative distinguished names. The new DistinguishedName
instance preserves the order of the relative distinguished names in the list.
The match
functions perform a partial comparison that does not consider the order of relative distinguished names. Given two instances N1 and N2 of DistinguishedName
, 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.
The comparison operators 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 Certificate
class provides the methods getX509Extensions
and getX509Extension
for obtaining information about its X509 extensions.
These methods are only supported when using the OpenSSL or Schannel implementations. |
The methods return instances of IceSSL::X509Extension
:
|
An OID is represented as a string. For example, the OID for the subject alternative name extension is "
2.5.29.17"
. The data associated with the extension is provided as a vector of bytes.
The following code demonstrates how to retrieve an extension:
|