Security Guide : Creating Secure CORBA Applications Using C++

Creating Secure CORBA Applications Using C++
This section describes the use of VisiSecure to make secure connections for CORBA applications using C++.
Steps to secure clients and servers
Listed below are the common steps required for developing a secure client or secure server. For CORBA users the properties are all stored in files that are located through config files. Wherever appropriate the usage models for clients and servers are separately discussed. All properties can be set in the VisiBroker Management Console by right-clicking the node of interest in the Navigation Pane and selecting “Edit Properties.”
Note
These steps are similar for both Java and C++ applications.
Step One: Providing an identity
An identity can be a username/password/realm triad, or certificates can be used. These can be collected through LoginModules or through APIs.
For more information on server-side and client-side authentication, see “Authenticating clients with usernames and passwords”.
Clients
For clients using usernames and passwords, there can be constraints about what the client knows about the server's realms. Clients may have intimate knowledge of the server's supported realms or none at all at the time of identity inquiry. Note also that clients authenticate at the server end.
Servers
For servers using username and password identities, authentication is performed locally since the realms are always known.
There can be constraints on certificate identities as well, depending on whether they are stored in a KeyStore or whether they are specified through APIs. The KeyStore in VisiSecure for C++ refers to a directory structure similar to a trustpointRepository, which contains the certificate chain.
Keeping these constraints in mind, VisiBroker supports the following usage models, any of which could be used to provide an identity to the server or client:
Username/password authentication, using JAAS
modules, for known realms
If the realm to which the client wishes to authenticate is known, the client-side JAAS configuration would take the following form:
vbroker.security.login=true
vbroker.security.login.realms=<known-realm>
Username/password authentication, using APIs
The following code sample demonstrates the use of the login APIs. This case uses a wallet. For a full description of the four login modes supported, see “VisiSecure for C++ APIs” and “Security SPI for C++”
int main(int argc, char* const* argv) {
// initialize the ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::Object_var obj = orb->resolve_initial_references("VBSecurityContext");
Context* c = dynamic_cast<Context*> (obj.in());
// Obtain a walletFactory
CORBA::Object_var o = orb->resolve_initial_references("VBWalletFactory");
vbsec::WalletFactory* wf = dynamic_cast<vbsec::WalletFactory*>(o.in());
vbsec::Wallet* wallet = wf->createIdentityWallet( <username>, <password>, <realm>);
c->login(*wallet);
}
Certificate-based authentication, using KeyStores via property settings
By setting the property vbroker.security.login.realms=Certificate#ALL, the client will be prompted for keystore location and access information. For valid values, see “Certificate mechanism”.
Certificate-based authentication, using KeyStores via APIs
You can use the same APIs discussed in ““Username/password authentication, using APIs”” to login using certificates through KeyStores. The realm name in the IdentityWallet should be CERTIFICATE#ALL. The username corresponds to an alias name in the default KeyStore that refers to a Key entry, and the password refers to the Private Key password (also the KeyStore password) corresponding to the same Key entry.
Certificate-based authentication, using APIs
If you do not want to use KeyStores directly, you can import certificates and private keys using the CertificateFactoryAPI. This class also supports the pkcs12 file format.
X509Certificate[] certChain = ...list-of-X509-certificates...
PrivateKey privKey = private-key
com.borland.security.CertificateWallet wallet =
new com.borland.security.CertificateWallet(alias,
certChain, privKey, "password".toCharArray());
The first argument in the new Certificate wallet is an alias to the entry in the KeyStore, if any. If you are not using keystores, set this argument to null.
pkcs12-based authentication, using KeyStores
You can use the same APIs discussed in “Username/password authentication, using APIs” to login using pkcs12 KeyStores. The realm name in the IdentityWallet should be CERTIFICATE#ALL, the username corresponds to an alias name in the default KeyStore that refers to a Key entry, and the password refers to the password needed to unlock the pkcs12 file. The property javax.net.ssl.KeyStore specifies the location of the pkcs12 file.
pkcs12-based authentication, using APIs
See “Certificate-based authentication, using APIs”.
Step Two: Setting properties and Quality of Protection (QoP)
There are several properties that can be used to ensure connection Quality of Protection. The VisiBroker ORB security properties for C++ can be used to fine-tune connection quality. For example, you can set the cipherList property for SSL connections to set cryptography strength.
QoP policies can be set using the ServerQoPConfig and the ClientQoPConfig APIs for servers and clients, respectively. These APIs allow you set target trust (whether or not targets must authenticate), the transport policy (whether or not to use SSL or another secure transport mechanism specified separately), and, for servers, an AccessPolicyManager that can access the RoleDB to set access policies for POA objects.
Step Three: Setting up Trust
Setting up of trust can be done through property vbroker.security.trustpointRepository=Directory:<path to directory>, where the directory contains the trusted certificates.
Other trust policies are set in the QoP configurations. See “Step Two: Setting properties and Quality of Protection (QoP)”.
Step Four: If necessary, set up identity assertion
When a client invokes a method in a mid-tier server which, in the context of this request, invokes an end-tier server, then the identity of the client is internally asserted by the mid-tier server by default. Therefore, if getCallerSubject is called on the end-tier server, it will return the Client's principal. Here the client's identity is asserted by the mid-tier server. The identity can be a username or certificate. The client's private credentials such as private keys or passwords are not propagated on assertion. This implies that such an identity cannot be authenticated at the end-tier.
If the user would like to override the default identity assertion, there are APIs available to assert a given Principal. These APIs can be called only on mid-tier servers in the context of an invocation and with special permissions.
Security configuration while setting up a server engine
In order to be able to use secure transport while defining a custom server engine, the following properties need to be set for VisiSecure for C++:
vbroker.se.<SE_NAME>.scms=<IIOP_SCM_NAME>,<SSL_SCM_NAME>
vbroker.se.<SE_NAME>.scm.<SSL_SCM_NAME>.manager.type=Socket
vbroker.se.<SE_NAME>.scm.<SSL_SCM_NAME>.listener.type=SSL
vbroker.se.<SE_NAME>.scm.<SSL_SCM_NAME>.dispatcher.type=ThreadPool
Where:
It is important to note that the 'manager.type' and the 'listener.type' must be initialized to the values indicated above whereas the 'dispatcher.type' can be any of the allowable types. The default value is ThreadPool. (For more information, see ”Managing Threads and Connections” in the VisiBroker for C++ Developer's Guide.)
Another important point to be noted here is that a valid IIOP scm (<IIOP_SCM_NAME> in this case) must be defined before the SSL scm in the SCM list of custom server engine. All the properties of the IIOP scm can be set to any of the allowable values with the following two exceptions:
vbroker.se.<SE_NAME>.scm.<IIOP_SCM_NAME>.manager.type=Socket
vbroker.se.<SE_NAME>.scm.<IIOP_SCM_NAME>.listener.type=IIOP
Examining SSL related information
VisiBroker provides APIs to inspect and set SSL-related information. The SecureContext API is used to inspect the SSL cipher suites and enable select ciphers.
Clients
To examine peer certificates, use getPeerSession() to return an SSLSession object associated with the target. You can then use standard JSSE APIs to obtain the information therein.
Servers
To examine peer certificates on the server side, you set up the SSL connection with com.borland.security.Context and use the APIs with com.borland.security.Current to examine the SSLSession object associated with the thread.
SSL example
This section demonstrates how to make a minimal SSL configuration for the client and server to communicate using SSL to enable them to perform mutual PKI authentication on the simplest, non-security aware VisiBroker example.
If you are using the same executables from basic/bank_agent to secure the non-security aware application, then no changes in the source code are required.
Using properties to install certificates, private key and trustpoints
1
2
3
prompt> Server -DORBpropStorage=cpp_server.properties -Dvbroker.orb.dynamicLibs=vbsec
4
prompt> Client -DORBpropStorage=cpp_client.properties -Dvbroker.orb.dynamicLibs=vbsec
5
Open the property files cpp_server.properties, cpp_client.properties and notice how certificates and private keys are installed using wallet property set in that file.
6
The value of vbroker.orb.dynamicLibs specifies the security library name. You can either:
Enter vbsec, as in the example above. This loads VisiSecure (on any platform) without your needing to know the full pathname, but only works if the VisiBroker lib directory is present on the shared library load path.
on win32, it is vbsec.dll,
It is recommended that you check your ${VBROKER_DIR}/lib directory if you intend to use this option.
Using initializers to install certificates, private key, trustpoints and CRL
This section is similar to the previous section, except that rather than using properties, shared libraries are used at runtime to install the certificates, keys, trustpoints and CRL. The advantage over the use of properties is that the shared library may also perform more security related initializations that are not possible to be done using properties, while at the same time, shared libraries keep the original non-secure aware application code intact. The shared libraries are transparent from the application point of view.
Build this example if you have not done so. In the previous section, we did not build, we just copied the executables. Building this example successfully, will create shared libraries: ServerInit.<ext> and ClientInit.<ext>
where <ext> depends on your platform:
for Windows, it is dll,
for Linux and Solaris, it is so,
for IBM, it is a,
for HP-UX, it is sl.
1
nmake cpp (for Windows) or
make cpp (for UNIX)
2
3
prompt> Server -DORBpropStorage=cpp_server.properties -Dvbroker.orb.dynamicLibs=ServerInit.<ext>
4
prompt> Client -DORBpropStorage=cpp_server.properties -Dvbroker.orb.dynamicLibs=ClientInit.<ext>
5
Open the shared library source code ServerInit.C and ClientInit.C to notice how certificates, keys, trustpoints and CRL are installed on the ORB. The difference between ServerInit.C and ClientInit.C is only the set of certificates, keys, trustpoints and CRL that is installed. You can swap, for instance: ServerInit for client and ClientInit for server.
6
Reading through the code, you may notice that CRL will be installed only when we provide additional -Dvbroker.app.useCRL and therefore launching the server, for example, becomes:
prompt> Server -DORBpropStorage=cpp_server.properties -Dvboker.app.useCRL=true -Dvbroker.orb.dynamicLibs=ServerInit.<ext>
Note: CRL, for this example, is prepared in such a way that when installed, the certificate that is directly issued by a trustpoint is revoked.
There is only one certificate directly issued by a trustpoint in this example. Therefore, any usage of CRL in any server or client or both will result in the SSL authentication failure and in turn, client will get NO_PERMISSION exception.
The failure can be because the client is not trusted by the server (if CRL is installed on the server) or vice versa (if the CRL is installed on the client) or both.
Using APIs with Security aware applications: SecureServer and SecureClient
This section demonstrates how the applications that are written with VisiSecure in mind take full advantage of the control and power of VisiSecure features using APIs.
1
nmake cpp (for windows) or
make cpp (for unix).
When the build succeeds, the executables SecureServer.exe on Windows and SecureClient.exe on Windows are created.
2
3
prompt> SecureServer
4
prompt> SecureClient
5
For example,
prompt> SecureClient -Dvbroker.app.useCRL=true
6
how they impose peerAuthenticationMode=require_and_trust and alwaysSecure=true through QoP
Using APIs with pkcs12Server
This section demonstrates how to use VisiSecure API for handling of a PKCS12 storage, a very widely acceptable storage format for certificates and private keys.
1
nmake c pp (for windows) or
make cpp (for unix).
When the build succeeds, the executable pkcs12Server.exe is created on Windows.
2
3
prompt> pkcs12Server frans.pfx frans
4
prompt> SecureClient
5
Launch the client using -Dvbroker.app.useCRL=true, and notice how the mutual SSL authentication fails and client gets NO_PERMISSION exception.
prompt> SecureClient -Dvbroker.app.useCRL=true
6
Read and learn from pkcs12Server.C how it installs certificates and a private key from a PKCS12 file.