Developing code using IBM Notes in Eclipse on Mac OS

I’m cleaning out my drafts folder and stumbled unto this one I never posted. The steps has changed slightly after IBM Notes 9.0.1 for Mac was released as that release works fine with the never JVM’s for the Mac. Actually there are very few steps you need to do to make the code work. To complete a standard console app that prints the username from the current session to stdout do the following:

  1. Write the code – could be something like this:
    import lotus.domino.NotesFactory;
    import lotus.domino.Session;
    import lotus.notes.NotesThread;
    
    public class Main {
       public static void main(String[] args) throws Exception {
          NotesThread.sinitThread();
          Session session = NotesFactory.createSession();
          System.out.println(session.getUserName());
          NotesThread.stermThread();
       }
    }
    
  2. Run the code as a Java Application. This will fail as the JVM cannot load the required libraries.
  3. Edit the Run Configuration (click the dropdown next to the green run button and choose “Run Configurations…”)
  4. Switch to the “Environment”-tab
  5. Add an environment variable called DYLD_LIBRARY_PATH with a value of “/Applications/IBM Notes.app/Contents/MacOS” (without the quotes)
  6. Click Apply and Run

This was done in Eclipse neon on Mac OS El Capitan (10.11) using Java 8.

IBM announce dates for bringing TLS v. 1.2 to IBM Domino

So in October of 2014 I wrote about the upcoming TLS (transport layer security) enhancements that IBM was planning to bring to IBM Domino as part of the industry wide panic about the POODLE attack which I still consider mainly theoretical. I was a bit critical towards IBM as they chose to patch their seriously lacking SSL v. 1.3 implementation and implement TLS v. 1.0 on top of IBM Domino v. 9.0.x (IBM Domino, POODLE, SHA-1 and why it’s also sad when IBM decides to update the security stack). The reason I was critical was that I thought that you either take security serious and bring the stack to the front of the line (TLS v. 1.2, v. 1.3 in draft) or get out of the game.

Since then I have been pleasantly surprised to hear about the initiatives IBM has going on. At IBM ConnectED 2015 I attended a very nice session by David Kern from IBM and Daniel Nashed (IBM Business Partner) on the TLS and security improvements planned for IBM Domino. Among others was massive cipher suite updates incl. upcoming support for Diffie-Hellman and perfect-forward-secrecy. Cool stuff! Yesterday I was very pleased to see that IBM now has announced the support for TLS v. 1.2 coming in Q1/Q2 of 2015 (the technote is a bit confusing as to when it will be out).

So all appears to be good and IBM is moving in the right direction with this. Very nice.

An important tool results from the whole POODLE/SHA-2 debacle

My stance on the POODLE / SHA-2 issues with Domino is well known and I haven’t been holding anything back. And now – after a while – IBM is starting to release the promised tools to lay the foundation for SHA-2 signature support and TLS 1.0 support on IBM Domino. As part of my IBM Support Updates today I saw and entry called “Planned SHA-2 deliveries for IBM Domino 9.x“. This is a technote outlining how IBM is bringing TLS 1.0 and SHA-2 support. This is all well and good and great that IBM starts to deliver on its promises.

But that’s not all… And by far the most interesting thing to find in that technote.

Burried within this technote is a mention of a tool called kyrtool which replaces iKeyman as the way to work with the KYR keystore file used by IBM Domino. It’s a command line tool and allows for import of standard x509 certificates generated using OpenSSL or similar and produces a KYR and a STH (stash) file as the result. There is documentation about the tool in the wikis (Generating a keyring file with a self-signed SHA-2 cert using OpenSSL and kyrtool). As an added bonus the examples with OpenSSL is done on Dave Kerns paranoia Linux box (dskern@paranoia).

The release of this tool is very good news and cannot be overstated and in my eyes far overshines the support for TLS 1.0 and SHA-2 as it allows administrators to work with the KYR files on Windows versions newer than Windows XP. It ever supports win32, win64, linux32 and linux64. How do you like them apples?

Thank you IBM.

IBM Domino, POODLE, SHA-1 and why it’s also sad when IBM decides to update the security stack

Over the last few weeks the news hit about the PODDLE attack and the withdrawal of SHA-1 as an acceptable hash algorithm by Google Chrome. This is turn has prompted IBM to update the security stack in IBM Domino for all web protocols incl HTTP, LDAP and SMTP. While this is VERY good news and it will be very welcomed that we do no longer have to resort to fronting IBM Domino by IBM HTTP Server or Apache to get adequate TLS protocol support I find the whole situation a bit sad. In full disclosure I have to say that I get most of my security updates these days from the Security Now! podcast on the TWIT network and the discussion on both POODLE and the SHA-1 debacle as opened my eyes. The sad part about these updates to IBM Domino is that it has taken a theoretical attack on SSL v. 3 (POODLE) and a premature hash algorithm withdrawal by a single browser vendor (SHA-1 and Google) to have IBM update the stack. To be fair Microsoft is also removing SHA-1 support from their security stack in their OS’es but from 2017 giving customers ample time to fix it.

In other words if these attacks hadn’t come out IBM would have left IBM Domino customers with ancient protocols and keystore formats – remember it takes Windows XP to run an iKeyman old enough to edit the .key files used in Domino.

Besides being good marketing and blowing some life into the dying embers of IBM Domino it’s almost a sad move when it’s done so late. And then IBM doesn’t even take it seriously enough to go all the way. Instead they outlines their “plan to deliver SHA-2 support for Domino 9.x” and promises a fix to bring TLS 1.0 to IBM Domino. Version 1.0 – seriously?! TLS is in version 1.2 at present and the draft for v. 1.3 is out. Now I know that implementing TLS for SMTP is much different from doing so for HTTP but security cannot be done half heartedly so if you want to make it a priority do that. Do not stop short and plug a hole by not going all the way. In all honesty I would rather have IBM discontinue SSL/TLS all together on Domino than doing this. I know it’s sad but it’s how I feel about it right now.

For a very nice discussion of the PODDLE attack, and why it’s a theoretical attack, do listen to Security Now! episode 478 from 33:22 minutes in.

Fixing an IBM Connections Social Mail CPU spike problem

The other day we did a test upgrade of our internal IBM Connections 4.5 environment from CR3 to CR4 before doing the real upgrade. After the upgrade the CPU of the WebSphere Application Server node (we are in a single node architecture) would spike to a 100%. After some digging and perusing of log files we narrowed the problem down to IBM Social Mail and that component being loaded. Actually even more specifically to the Discovery Servlet which is used to discover the mail service for a particular user. The issue appeared to be a hung thread as indicated by the below stacktrace. See highlight in bold.

[4/30/14 13:39:51:534 CEST] 00000040 ThreadMonitor W WSVR0605W: Thread "WebContainer : 5" (0000014b) has been
active for 770854 milliseconds and may be hung. There is/are 1 thread(s) in total in the server that may be hung.
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.getBundle(DefaultClassLoader.java:273)
at org.apache.aries.jndi.Utils.getBundleContext(Utils.java:111)
at org.apache.aries.jndi.Utils.doGetBundleContext(Utils.java:99)
at org.apache.aries.jndi.Utils.access$100(Utils.java:43)
at org.apache.aries.jndi.Utils$1.run(Utils.java:68)
at org.apache.aries.jndi.Utils$1.run(Utils.java:66)
at java.security.AccessController.doPrivileged(AccessController.java:229)
at org.apache.aries.jndi.Utils.getBundleContext(Utils.java:66)
at org.apache.aries.jndi.OSGiInitialContextFactoryBuilder.getInitialContext(OSGiInitialContextFactoryBuilder.java:44)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:232)
at javax.naming.InitialContext.initializeDefaultInitCtx(InitialContext.java:318)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:348)
at javax.naming.InitialContext.internalInit(InitialContext.java:286)
at javax.naming.InitialContext.(InitialContext.java:211)
at javax.naming.directory.InitialDirContext.(InitialDirContext.java:91)
at com.ibm.social.pim.discovery.ldap.domino.DominoLDAPConnector.connect(DominoLDAPConnector.java:68)
at com.ibm.social.pim.discovery.services.domino.LDAPPersonData.findPerson(LDAPPersonData.java:43)
at com.ibm.social.pim.discovery.services.domino.LDAPPersonData.findPerson(LDAPPersonData.java:69)
at com.ibm.social.pim.discovery.services.domino.DominoMailServiceLDAPConnector.connect(DominoMailServiceLDAPConnector.java:69)
at com.ibm.social.pim.discovery.services.domino.DominoMailServiceLDAPConnector.connect(DominoMailServiceLDAPConnector.java:61)
at com.ibm.social.pim.discovery.DiscoveryServiceManager.findUserByEmail(DiscoveryServiceManager.java:163)
at com.ibm.social.pim.discovery.servlet.DiscoveryServlet.doDiscovery(DiscoveryServlet.java:229)
at com.ibm.social.pim.discovery.servlet.DiscoveryServlet.processRequest(DiscoveryServlet.java:198)
at com.ibm.social.pim.discovery.servlet.DiscoveryServlet.doGet(DiscoveryServlet.java:139)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:575)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)

We dug around a little without success so I reached out to a friend at IBM and the answer came back. This is an issue that has been seen before and is solved by fixpack 8 of IBM WebSphere Application Server so we upgraded to 8.0.0.8 and sure enough we are back up and running. Apparently fixpack 8 is now supported and actually reading through the detailed system requirements lists that (“IBM Connections 4.5 CR4 and above recommends WAS 8.0.0.8. WAS 8.0.0.6 with required fixes is still supported (see the detailed report for CR3) .”)

Thanks to friends at IBM.

Servers upgraded to 9.0.1 and what a difference a point release makes

Yesterday night I upgraded two of our internal Domino servers to Domino 9.0.1 incl. Traveler and the new Social Edition components. The entire process for two servers took just about 15 minutes over remote desktop and VPN incl. the restart of the server which strictly speaking was superfluous.

Pretty impressive but hey it’s Domino!!

The upgrade was from Domino 9.0.0 and what a difference a point release makes. Not for the Traveler server but for the Social Edition server that runs the embedded experiences (EE’s) for us (mainly from IBM Connections). Before the upgrade we had some issues with EE’s not loading incl. timeouts when users connected from home over VPN. After the upgrade these timeouts are gone and the performance is much much better both remotely over VPN and in the office. Previously we had a noticeable delay for the remote rendering of the EE’s but now it’s just there when an email opens up.

So sweet!

So if you’re using EE’s and haven’t yet upgraded to 9.0.1 I would highly recommend you get on it.

List of OpenSocial fixes in 9.0.1?

As reported all over the Yellow-bubble we’ve now got a Domino 9.0.1 server and a Notes 9.0.1 client to install. All is good and the list of fixes reported by developerWorks is 267. The list however doesn’t mention OpenSocial at all. This is sad as this is one of the new features from 9.0 and getting an idea as to what have been fixed would have been nice (plus I know that lots have been fixed).

Hope that IBM will release more information as to what was fixed for OpenSocial.

Java in Notes/Domino Explained: On Java Security and how it relates to Notes/Domino


I get so many questions on Java security and how it all fits together that I finally decided to blog it instead of simply answering over and over again. So here goes…

Security was built into Java from its inception and everything in a Java Virtual Machine (JVM) runs under the control of a security manager. Now the security manager may be very lax or it may be very restrictive as the one for Java applets or Notes/Domino agents is. A security manager is installed into the JVM when it’s constructed meaning either from the command line or, in the case of Notes/Domino, when a JVM is created to run agents, XPages or the like. A security manager may decide that a certain operation (method call) is “powerful” and hence will require the code executing the operation to be allowed to do so.

The way this is done in Java is by the operation itself (the method you are calling e.g. “write file” or “do stuff with reflection”) asking the security manager whether the code calling it has a given permission that it supplies to the security manager. The security manager may either decide that it does and hence return quietly or it may decide that the calling code does not have the required permission. To signal the latter it will throw a java.security.AccessControlException which you’ve seen if you’re reading this.

So how do we grant these permissions?

In Java permissions are controlled in the java.policy file located in the file system under <notes>/jvm/lib/security or <domino>/jvm/lib/security. I will not go into detail on the syntax of this file as resources are readily available on the web but suffice to say that different locations (be those file based or network based) are granted different sets of permissions (for more info see http://docs.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html). By default jar-files in jvm/lib/ext, the XPages runtime, OSGi bundles etc. are granted all permissions possible (java.security.AllPermission) whereas other code is granted a limited set of permissions. So if you need to run code that requires a different set of permissions you edit this file and restart the server/client. Now often times simply editing this file is not an option. Either you do not control the server, you cannot edit it for all clients or your security guidelines tell you just can’t do it. In either case editing the file is seldom the entire solution. And you need to understand why. Before showing you some code let me explain the scenario I’m going to use below first.

The scenario is that Joe Notes Developer needs to use reflection (wikipedia) to change the accessibility of a method from private to public (yes it’s possible) to override the private restriction set on the generate() method of the Test class (see below). To do this he uses a method like the one below:

public void doAccessible(Object obj) throws Exception {
   Method[] methods = obj.getClass().getMethods();
   for (int i=0; i<methods.length; i++) {
      Method m = methods[i];
      m.setAccessible(true);
   }
}

The class he needs to affect is likewise simple (he needs to make the generate() method public):

private class Test {
   private String uuid = null;

   public Test() {
      this.generate();
   }

   public String getUUID() {
      return this.uuid;
   }

   private void generate() {
      this.uuid = UUID.randomUUID().toString();
   }
}

To start of Joe Notes Developer creates a Java agent in Domino Designer and sticks the below code in NotesMain of the agent:

Test t = new Test();
System.out.println(t.getUUID());
doAccessible (t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

But oh no!! Joe gets the dreaded AccessControlExeption as the code in the Java agent may not use reflection this way.

java.security.AccessControlException: Access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)
   at java.security.AccessController.checkPermission(AccessController.java:132)
   at java.lang.SecurityManager.checkPermission(SecurityManager.java:544)
   at COM.ibm.JEmpower.applet.AppletSecurity.superDotCheckPermission(AppletSecurity.java:1449)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1617)
   at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1464)
   at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:118)
   at ReflectionUtil.doAccessible(Unknown Source)
   at JavaAgent.NotesMain(Unknown Source)
   at lotus.domino.AgentBase.runNotes(Unknown Source)
   at lotus.domino.NotesThread.run(Unknown Source)

Nothing is holding Joe back though so he puts the reflection code into a ReflectionUtil class which he puts in a jar-file in jvm/lib/ext as he has heard that this location allows for this kind of funky stuff. Using the ReflectionUtil instead of a class method from his agent is like this:

ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessible(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

Arrrghhhh no!! He still gets an AccessControlException. But how can this be?? He did put the code in the special jvm/lib/ext folder which is granted AllPermissions. Hmmm…

The reason is that security in Java is layered and it’s the layer or “context” in Java parlance initiating the call that decides which permissions are assigned. This is why simply making a call from a Java agent in Notes/Domino to a Java library in jvm/lib/ext that need permissions other than the default set doesn’t just work. It doesn’t work because it’s the context of the Java agent which is in effect. So wouldn’t it be great if you could change the context? Well you can… 🙂 This is done using the java.security.AccessController class (docs).
The AccessController class is a nifty little thing. It works by you supplying an instance of the java.security.PrivilegedAction interface which is an interface with a single method called run. Inside the run-method you put the code requiring special permissions. Below is an example of using the AccessController class:

AccessController.doPrivileged(new PrivilegedExceptionAction() {
   public Object run() throws Exception {
      ReflectionUtil l = new ReflectionUtil();
      Test t = new Test();
      l.doAccessible(t);
      System.out.println("Completed...");
      return null;
   }
});

But wouldn’t you know it – this also fails! Of course the reason is quite obvious – I think – we cnanot just have developers go ahead elevating their persmissions themselves. As Paul Mooney would say – developers mus be controlled and kept down. It needs to be the privileged code meaning the code in jvm/lib/etc that needs to elevate the permissions. To do this we move the AccessController call info the ReflectionUtil in a special “doAccessiblePrivileged” method as this code can then decide to elevate permissions as it runs from a location with a higher security context. The code in the agent is therefor now like this (change in bold):

ReflectionUtil l = new ReflectionUtil();
Test t = new Test();
System.out.println(t.getUUID());
l.doAccessiblePrivileged(t);
t.generate();
System.out.println(t.getUUID());
System.out.println("Completed...");

And the code in ReflectionUtil looks like this:

public void doAccessiblePrivileged(final Object obj) throws Exception {
   AccessController.doPrivileged(new PrivilegedExceptionAction() {
      @Override
      public Object run() throws Exception {
         ReflectionUtil.this.doAccessible(obj);
         return null;
      }
   });
}

Now the code runs just fine as Joe is using code that knows that it might need to elevate the permissions so it provides a call doing just that (doAccessiblePrivileged).

Of course this can make it very difficult to just use a standard library from the web in Notes as it may not provide a way to elevate the permissions as no one ever saw that as a use case. In this case a wrapper API that elevates the permissions in jvm/lib/ext may be necessary to make it work.

Hope this explains it… 🙂

The example code is available for download including the required jar-file to put in jvm/lib/ext.

Calendar integration example using OnTime Group Calendar API

The Problem

A Danish insurance company was running a CRM system to control and maintain customer relationship information and plan meetings for its insurance agents. Because the CRM system wasn’t integrated with their IBM Domino infrastructure running their mail and calendar the insurance agents in effect had two calendars – one in IBM Notes holding their company appointments and one in a CRM system holding their external customer meetings. This meant that the insurance agents effective stopped using their calendars or maintained a third, non-company, calendar) as there were no single place to see all appointments. Besides this the organization as a whole was unable to plan internal meetings with the insurance agents as their calendars didn’t reflect their actual whereabouts.

The Solution

To remedy this they decided to use the OnTime Group Calendar API to integrate the two systems using web services using an intermediate Enterprise Service Bus (ESB). The OnTime Group Calendar API web services are hosted directly on IBM Domino and performs extremely well. After implementing the solution the insurance agents only need to maintain their calendar in Notes as it will reflect their true calendar showing both internal, external and personal appointments and meetings.

The solution provides a true two-way synchronization so any appointment planned from their CRM system shows up in the calendar in Notes. If the user reschedule the appointment the corresponding appointment in CRM is automatically updated and if the appointment is deleted the appointment get cancelled in the CRM system as well as a follow-up activity being created to make sure a new meeting is planned. The personal calendar in Notes is also updated once a meeting is marked completed in the CRM system to allow for automated expense reporting based on the personal calendars in Notes. As an added benefit of the using the OnTime Group Calendar API all insurance agents are now able to use their Notes client, their iNotes webmail or their mobile device to do their job resulting in true mobility and added flexibility.

Below is an architectural drawing showing how it all integrates using Domino as a central application server.


(click image for a larger version)