Saturday, December 18, 2010

A new world for integration: SAML and Identity

SAML was initially a standard for cross-domain SSO. A user who is logged on to the domain *.i8c.be could transparently point his browser to a web application in another domain *.cronos.be without having to authenticate again. His identity (and other attributes) are passed on transparently, behind the scenes. Many mechanisms were defined to exchange the information contained in SAML token (signed XML structures) between an Identity Provider and a Relying Party, including SOAP very early on (the SAML SOAP Binding).

But SAML was taken further. WS-Security SAML Token Profile allows the use of SAML tokens in SOAP messages secured with WS-Security. And WS-Trust and its Secure Token Service standardized the mechanism to obtain or exchange SAML (or other) tokens.
The STS is a standard (web) service to obtain such a SAML token: 1) through standard authentication mechanisms or 2) by exchanging one token for another (SAML to SAML, non-SAML to SAML or SAML to non-SAML).

But transferring SAML tokens between domains means the exchange of information between heterogeneous organizations. The SAML standard does not define how attributes within the SAML tokens should be named nor what their content should exactly look like. Every organziation is free to specify how information is structured in a SAML token:
  • what information or attributes is contained in the SAML token: name, cost center, department, ...
  • how the atrributes should are named, e.g. LastName or lname?
  • how the information in the attributes is represented
Imagine a vendors of office materials (Staples) that wants to offer a SSO experience to the employees of its majore customers. If every customer (large enterprises themselves) use a different SAML token structure, the office material vendor will have a great time translating the information from these different SAML tokens to its own attributes. And what if information is missing in the SAML token, e.g. what is the maximum value that employee may purchase?

Another integration challenge!

Note: Microsoft prefers the use of the term claim

Authored by: Guy

Friday, December 10, 2010

Command Line JMX + SSL

The tool I use for command line JMX and which I think really works well is http://wiki.cyclopsgroup.org/jmxterm

You can download and start the single jar as shown below. In this example I'm connecting to a HornetQ instance.
[jeroen@homesrv~]# java -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://192.168.1.3:10995/jmxrmi
Welcome to JMX terminal. Type "help" for available commands.
$>
Next you can fetch a list of all the available beans (not showing all the beans):
$>beans #domain = JMImplementation: JMImplementation:type=MBeanServerDelegate #domain = com.sun.management: com.sun.management:type=HotSpotDiagnostic #domain = java.lang: java.lang:name=Code Cache,type=MemoryPool ... #domain = java.util.logging: java.util.logging:type=Logging #domain = org.hornetq: org.hornetq:address="hornetq.notifications",module=Core,name="notif.fb6d27d5-02ac-11e0-ae9b-1cc1de6fb76e",type=Queue ... org.hornetq:module=JMS,name="TEST.IN",type=Queue org.hornetq:module=JMS,type=Server
To see the available attributes and operations on a specific MBean you can use the info command:
$>info -b org.hornetq:module=JMS,name="TEST.IN",type=Queue #mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue #class name = org.hornetq.jms.management.impl.JMSQueueControlImpl # attributes %0 - Address (java.lang.String, r) %1 - ConsumerCount (int, r) %2 - DeadLetterAddress (java.lang.String, rw) %3 - DeliveringCount (int, r) %4 - ExpiryAddress (java.lang.String, rw) %5 - JNDIBindings ([Ljava.lang.String;, r) %6 - MessageCount (int, r) ... %12 - Temporary (boolean, r) # operations %0 - void addJNDI(java.lang.String jndiBinding) %1 - boolean changeMessagePriority(java.lang.String messageID,int newPriority) %2 - int changeMessagesPriority(java.lang.String filter,int newPriority) %3 - int countMessages(java.lang.String filter) ... %20 - int sendMessagesToDeadLetterAddress(java.lang.String filter) #there's no notifications
To get the actual value of an MBean attribute, use the get command
$>get -b org.hornetq:module=JMS,name="TEST.IN",type=Queue MessageCount
#mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue:
MessageCount = 0;
To invoke an operation use the run command:
$>run -b org.hornetq:module=JMS,name="TEST.IN",type=Queue resetMessageCounter
#calling operation resetMessageCounter of mbean org.hornetq:module=JMS,name="TEST.IN",type=Queue
#operation returns:
null

$>get -b org.hornetq:module=JMS,name="TEST.IN",type=Queue MessageCount
#mbean = org.hornetq:module=JMS,name="TEST.IN",type=Queue:
MessageCount = 0;
As you can see the tool is very easy to use. BUT, since we are talking about Java Management Extensions which let you control, in this case, a HornetQ server, I think some security is in order.
The JMX agent on the JVM is by default started with TLS/SSL and username + password authentication. More information on how to set this up is on: http://download.oracle.com/javase/1.5.0/docs/guide/management/agent.html#auth. In the example above, security was switched off, which is easy to do by setting the following properties:
com.sun.management.jmxremote.authenticate=false
com.sun.management.jmxremote.ssl=false

Now to enable TLS/SSL and username + password on the JMX agent set the following properties, first 2 were set before as well:
com.sun.management.jmxremote com.sun.management.jmxremote.port=10999 com.sun.management.jmxremote.password.file=$HOME/jmxremote.password javax.net.ssl.keyStore=hornetq-srv1-keystore.jks javax.net.ssl.keyStorePassword=changeit
The jmxremote.password is following the template under java.home/jre/lib/management/jmxremote.password.template

On the client side, in this case jmxterm, you need to set the following properties:

javax.net.ssl.trustStore=jmxclient-truststore.jks
javax.net.ssl.trustStorePassword=changeit
This is all following the java specs and should work, but when we start with the following command
[jeroen@homesrv~]# java -Djavax.net.ssl.trustStore=jmxclient-truststore.jks -Djavax.net.ssl.trustStorePassword=changeit -jar jmxterm-1.0-alpha-4-uber.jar -l service:jmx:rmi:///jndi/rmi://192.168.1.3:10999/jmxrmi
The following error pops up:
constituent[0]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jmxterm.jar
constituent[1]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-beanutils.jar
constituent[2]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-cli.jar
constituent[3]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-collections.jar
constituent[4]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-lang.jar
constituent[5]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-logging.jar
constituent[6]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/commons-io.jar
constituent[7]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jcli.jar
constituent[8]: jar:file:/root/jmxterm-1.0-alpha-4-uber.jar!/WORLDS-INF/lib/jline.jar
---------------------------------------------------
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
javax.net.ssl.SSLKeyException: RSA premaster secret error
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2327)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:279)
at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
at org.cyclopsgroup.jmxterm.cc.SessionImpl.doConnect(SessionImpl.java:85)
at org.cyclopsgroup.jmxterm.cc.SessionImpl.connect(SessionImpl.java:49)
at org.cyclopsgroup.jmxterm.cc.CommandCenter.connect(CommandCenter.java:110)
at org.cyclopsgroup.jmxterm.boot.CliMain.execute(CliMain.java:139)
at org.cyclopsgroup.jmxterm.boot.CliMain.main(CliMain.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchStandard(Launcher.java:353)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:264)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.uberjar.boot.Bootstrapper.bootstrap(Bootstrapper.java:209)
at org.codehaus.classworlds.uberjar.boot.Bootstrapper.main(Bootstrapper.java:116)
Caused by: javax.net.ssl.SSLKeyException: RSA premaster secret error
at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.(RSAClientKeyExchange.java:97)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:673)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:230)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at java.io.DataOutputStream.flush(DataOutputStream.java:106)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:211)
... 25 more
Caused by: java.security.NoSuchAlgorithmException: SunTlsRsaPremasterSecret KeyGenerator not available
at javax.crypto.KeyGenerator.(DashoA13*..)
at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
at com.sun.net.ssl.internal.ssl.JsseJce.getKeyGenerator(JsseJce.java:223)
at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.(RSAClientKeyExchange.java:89)
... 37 more
It looks like the uberjar is doing something fishy with the classloaders which make that the standard sun security provider is no longer available. Bummer ...

This is the only explanation I can think of. Because when connecting with jconsole, like below, I only need to enter the username/pwd. No other issues.
[jeroen@homesrv~]# jconsole -J-Djavax.net.ssl.trustStore=jmxclient-truststore.jks -J-Djavax.net.ssl.trustStorePassword=changeit service:jmx:rmi:///jndi/rmi://192.168.1.3:10995/jmxrmi
I guess for command line jmx with SSL I'll have to look elsewhere ...
If someone has ideas please post :-)


Authored by: Jeroen

Friday, December 3, 2010

Scary: backdoor in FTP server software

While reading security.nl, I picked up the news that hackers had put a backdoor in the popular FTP server ProFTPD. A version of the software containing a backdoor was put on the distribution server by some hackers.

How often does one install software from the Internet without any verification. Yes, there are the fingerprints, but who checks them? Even more scary if you were the one installing that software on a customers's server.

And if some hacker ever finds its way into the Windows Update software distribution mechanism, the world will come to a halt (don't smile you Apple users).

Authored by: Guy