Fancy Key- and Truststores in HCL Domino

Have you ever tried, to access HTTPS Resources outside with Java (in Agents or xPages) in HCL-Domino. Of course you can add your certificates to the cacerts-file within the Domino JVM. But with the next update it maybe will be gone for good, because the installer decided to replace it with his own.

But you can use some fancy Java-Tricks and create your own truststores and keystores and use them in your Java-Code.

The key Item here is the javax.net.ssl.SSLSocketFactory. Create an instace of this and pass it to your HttpsURLConnection.

First, you need am Method, which creates a javax.net.ssl.SSLSocketFactory:

/**
 * Create an Instacce of javax.net.ssl.SSLSocketFactory with a given keystore and trusstore
 * 
 * @param trustFileInputStream   a InputStream to a Java-Keystore File containing the trusted certifcates
 * @param tustPassword           the passwort for the Truststore File
 * @param keyFileInputStream     a InputStream to a Java-Keystore-File containing the client-certificate
 * @param keyPassword            the passwort for hte Keystore-File
 * 
 * @return a javax.net.ssl.SSLSocketFactory Instance configured with the provided key- and truststore.
 * 
 */
public static SSLSocketFactory getFactory(InputStream trustFileInputStream, String trustPassword, InputStream keyFileInputStream, String keyPassword)
              throws Exception {

  // the keystore holds my ClientCertificates, it is only needed if you need Client-Certificate authentication
  // I choose the PKCS12 File-Format (private key protected with a passphrase)
  KeyStore keyStore = KeyStore.getInstance("PKCS12");
  keyStore.load(keyFileInputStream, keyPassword.toCharArray());

  KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  keyManagerFactory.init(keyStore, keyPassword.toCharArray());

  KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

  // the truststore holds all the certificates you want to trust, i.e. the certifcate from the lets-encrypt-ca
  // I choose the JKS [JavaKeyStore] Format, the same formate as the famous cacerts-File
  KeyStore trustStore = KeyStore.getInstance("JKS");
  trustStore.load(trustFileInputStream, trustPassword.toCharArray());

  TrustManagerFactory trustManagerFactory = TrustManagerFactory
                  .getInstance(TrustManagerFactory.getDefaultAlgorithm());
  trustManagerFactory.init(trustStore);

  TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

  // please do not use any TLS-Version below 1.2, if possible use 1.3 :)
  SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
  sslContext.init(keyManagers, trustManagers, new SecureRandom());

  return sslContext.getSocketFactory();
}

Then some code to put the SSLSocketFactory into use. I hope you are familiar with HCL-Domino Java programming, there are some things you will need to now.

At first I get some attachments holding the files needed (ClientCertificate and TrustStore) and the passwords for them. All these things are stored in a Notes Document and are finally passed to the method from above.

Then we create an javax.net.HttpsUrlConnection and simply POST some (here not printed) content to an java.net.Url

RichTextItem rti_cert = (RichTextItem) profile_doc.getFirstItem("ClientCertificate");
EmbeddedObject eo_cert = (EmbeddedObject) rti_cert.getEmbeddedObjects().get(0);

RichTextItem rti_trust = (RichTextItem) profile_doc.getFirstItem("TrustStore");
EmbeddedObject eo_trust = (EmbeddedObject) rti_trust.getEmbeddedObjects().get(0);
               
InputStream trustfileInputStream = eo_trust.getInputStream();
InputStream keyFileInputStream = eo_cert.getInputStream();
               
String client_cert_password = profile_doc.getItemValueString("ClientCertPassword");
String truststore_password = profile_doc.getItemValueString("TrustStorePasswort");                
               
SSLSocketFactory ssl_socket_factory = SSLUtils.getFactory(trustfileInputStream,truststore_password, keyFileInputStream, client_cert_password);
       
System.out.println("Create HTTPS Connection to " + url.toString());
HttpsURLConnection conn;
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssl_socket_factory);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/soap+xml; charset=utf-8");
conn.setRequestMethod("POST");
System.out.println("Writing Content to output stream");
OutputStream os = conn.getOutputStream();
os.write(content.getBytes());
os.close();
System.out.println("Writing Content to output stream done");
               
eo_cert.recycle();
eo_cert = null;
rti_cert.recycle();
rti_cert = null;        
               
eo_trust.recycle();
eo_trust = null;
rti_trust.recycle();
rti_trust = null; 

I hope this post has some information for you to use.

Münchausen Zahlen

Dieses Posting ist furchtbar inspiriert durch einen Eintrag von diesem Blog: https://zach.se/munchausen-numbers-and-how-to-find-them/

Wer mehr zu den Münchhausen-Zahlen wissen will, findet es genauer hier beschrieben: https://de.wikipedia.org/wiki/M%C3%BCnchhausen-Zahl

Kurz gesagt: 3^3 + 4^4 + 3^3 + 5^5 = 3435

In F# schreibt man das so, Zweck der Übung ist ja, das ich mich gerade ein wenig in F# reinschnuppere:

let specialpown (i:int64) =
    match i with
    | 0L -> 0L
    | _ -> pown i (int i)
    
let digits (number:int64) = 
    (string) number |> Seq.map(fun i -> ( (int64) ((int i) % 48) ) )

let isMunchhausen number =
    digits number |> Seq.map (fun i -> specialpown i) |> Seq.sum = number 

digits 1234L |> Seq.toList
isMunchhausen 3435L

seq { 1L..500000000L } |> Seq.filter isMunchhausen |> Seq.toList

F# interactive zeigt dann folgendes in der Konsole:

val specialpown : i:int64 -> int64
val digits : number:int64 -> seq<int64>
val isMunchhausen : number:int64 -> bool
val it : int64 list = [1L; 3435L; 438579088L]

Ja, und die einzigen (bisher) bekannten Münchhausenzahlen sind diese 3:

  • 1
  • 3.435
  • 438.579.088

 

Send a „Cancel current Operation“ to IBM Notes with Powershell

On new Notebooks or Tablets, one key is missing:

– the pause-key

To cancel the current Operation within Notes, you can send a key-combination to the Notes-Process.

I realized this with the following Powershell-Script:

add-type -AssemblyName microsoft.VisualBasic
add-type -AssemblyName System.Windows.Forms

$id = (Get-Process "notes2").Id
[Microsoft.VisualBasic.Interaction]::AppActivate($id)
[System.Windows.Forms.SendKeys]::SendWait(“{BREAK}”)

Exporting Java-keystore certificates into a Textfile (.pem)

Sometimes products get simply better, so does Tomcat. Beginning with Version 7 it is possible to specify the certificates for the listener in Apache httpd (OpenSSL-Style). For me, this is much easier to understand and easier to configure.

To export all your trusted CA’s to a textfile in .pem format, you can use the much loved/hated java keytool:

The keytool lives in %JAVA_HOME%/bin/ and has to be called with this parameters:

  • -list (lists all certificates in the store)
  • -rfc (lists the certificates in rfc style
  • -keystore (path to the java-keystore you want to export
  • -storepass (password to the java-keystore you want to export

This parameterset gives you an nice formatted text-output of your certificates.

The final step is, to forward the text-output into a file, and voila – finished you have a file, which you can use in your Tomcat-Connector for the parameter „SSLCACertificateFile“.

& 'C:\Program Files\Java\jdk1.8.0_60\bin\keytool.exe' -list -rfc -keystore C:\certs\cacerts -storepass changeit > all-cas.pem

Using NotesUI* Classes in C# with COM

The NotesUI* Classes are not accesible in Visual Studio via the References-Dialog. Also in the DesignerHelp it is said, that you can not use the UI-Classes.

 

But there is a very simple Solution in C# by using the dynamic – Keyword and the .NET System.Activator Class.

 

The following Code-Sample connects to an running Notes Client and performs some actions:

class Program
    {
        static void Main(string[] args)
        {
            dynamic session = Activator.CreateInstance(Type.GetTypeFromProgID("Notes.NotesSession"));
            dynamic uiws = Activator.CreateInstance(Type.GetTypeFromProgID("Notes.NotesUIWorkspace"));
            dynamic uidb = uiws.CurrentDatabase;
            dynamic dbDir = session.GetDbDirectory("NTSDEV2008");

            Console.WriteLine("Benutzer : {0}", session.UserName);
            Console.WriteLine("Datenbank: {0}", uidb.Database.FilePath);



            uiws.OpenDatabase("NTSDEV2008", "names.nsf");

            uiws.URLOpen("https://www.google.at");
                       
            


            Console.ReadKey(); 
        }
     }

 

I found no current usecase for this at the moment, but good to know that this is possible …