You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2013/12/12 07:44:32 UTC

git commit: updated refs/heads/4.3 to fb89a2d

Updated Branches:
  refs/heads/4.3 326a46d0a -> fb89a2d8f


CLOUDSTACK-5296: Add certificate chain support for netscaler.

adds support for trust chains in the netscaler


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/fb89a2d8
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/fb89a2d8
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/fb89a2d8

Branch: refs/heads/4.3
Commit: fb89a2d8f6c75d92ac926e9728ef9fa974ffcdd1
Parents: 326a46d
Author: Syed Ahmed <sa...@cloudops.com>
Authored: Thu Dec 12 12:11:20 2013 +0530
Committer: Murali Reddy <mu...@gmail.com>
Committed: Thu Dec 12 12:13:43 2013 +0530

----------------------------------------------------------------------
 .gitignore                                      |   2 +-
 .../com/cloud/network/lb/LoadBalancingRule.java |  15 +-
 .../com/cloud/network/dao/SslCertDaoImpl.java   |   2 +-
 .../network/resource/NetscalerResource.java     | 235 ++++++++++++++++---
 .../lb/LoadBalancingRulesManagerImpl.java       |   8 +-
 .../cloudstack/network/lb/CertServiceImpl.java  |  92 +++++---
 .../cloud/utils/security/CertificateHelper.java |  56 +++++
 7 files changed, 326 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 74739b2..2af2d17 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-G# Licensed to the Apache Software Foundation (ASF) under one
+# Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
 # regarding copyright ownership.  The ASF licenses this file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/api/src/com/cloud/network/lb/LoadBalancingRule.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/lb/LoadBalancingRule.java b/api/src/com/cloud/network/lb/LoadBalancingRule.java
index 39c969c..36f3a44 100644
--- a/api/src/com/cloud/network/lb/LoadBalancingRule.java
+++ b/api/src/com/cloud/network/lb/LoadBalancingRule.java
@@ -439,16 +439,17 @@ public class LoadBalancingRule {
     public static class LbSslCert {
         private String cert;
         private String key;
-        private String password=null;
-        private String chain=null;
+        private String password = null;
+        private String chain = null;
+        private String fingerprint = null;
         private boolean revoked;
 
-
-        public LbSslCert(String cert, String key, String password, String chain, boolean revoked) {
+        public LbSslCert(String cert, String key, String password, String chain, String fingerprint, boolean revoked) {
             this.cert = cert;
             this.key = key;
             this.password = password;
             this.chain = chain;
+            this.fingerprint = fingerprint;
             this.revoked = revoked;
         }
 
@@ -469,7 +470,11 @@ public class LoadBalancingRule {
             return chain;
         }
 
-        public boolean isRevoked(){
+        public String getFingerprint() {
+            return fingerprint;
+        }
+
+        public boolean isRevoked() {
             return revoked;
         }
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java b/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java
index af0d970..5fd6cfb 100644
--- a/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java
+++ b/engine/schema/src/com/cloud/network/dao/SslCertDaoImpl.java
@@ -34,7 +34,7 @@ public class SslCertDaoImpl extends GenericDaoBase<SslCertVO, Long> implements S
         listByAccountId = createSearchBuilder();
         listByAccountId.and("accountId", listByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
         listByAccountId.done();
-    }
+   }
 
     @Override
     public List<SslCertVO> listByAccountId(Long accountId) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java
index e48d31d..4cd70cb 100644
--- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java
+++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java
@@ -16,6 +16,9 @@
 // under the License.
 package com.cloud.network.resource;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Formatter;
 import java.util.HashMap;
@@ -26,9 +29,14 @@ import java.util.Map;
 import javax.naming.ConfigurationException;
 
 import com.citrix.netscaler.nitro.resource.config.ssl.sslcertkey;
+import com.citrix.netscaler.nitro.resource.config.ssl.sslcertkey_sslvserver_binding;
+import com.citrix.netscaler.nitro.resource.config.ssl.sslcertlink;
 import com.citrix.netscaler.nitro.resource.config.ssl.sslvserver_sslcertkey_binding;
 import com.cloud.network.lb.LoadBalancingRule.LbSslCert;
+import com.cloud.utils.security.CertificateHelper;
 import com.cloud.utils.ssh.SshHelper;
+import com.google.common.collect.Lists;
+import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.log4j.Logger;
 
 import com.citrix.netscaler.nitro.exception.nitro_exception;
@@ -119,6 +127,7 @@ import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.exception.ExecutionException;
 import com.cloud.utils.net.NetUtils;
+import org.bouncycastle.openssl.PEMWriter;
 
 class NitroError {
     static final int NS_RESOURCE_EXISTS = 273;
@@ -664,25 +673,61 @@ public class NetscalerResource implements ServerResource {
 
                             }
 
-
-                            if(sslCert != null && lbProtocol.equals(NetUtils.SSL_PROTO)) {
-                                if ( sslCert.isRevoked() ){
+                            if (sslCert != null && lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO)) {
+                                if (sslCert.isRevoked()) {
                                     deleteCert = true;
                                 } else{
 
-                                    String certName = generateSslCertName(srcIp, srcPort);
-                                    String keyName = generateSslKeyName(srcIp, srcPort);
-                                    String certKeyName = generateSslCertKeyName(srcIp, srcPort);
+                                    // If there is a chain, that should go first to the NS
+
+                                    String previousCertKeyName = null;
+
+                                    if ( sslCert.getChain() != null ) {
+                                        List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
+                                        // go from ROOT to intermediate CAs
+                                        for ( Certificate intermediateCert : Lists.reverse(chainList)){
+
+                                            String fingerPrint=CertificateHelper.generateFingerPrint(intermediateCert);
+                                            String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);
+                                            String intermediateCertFileName = intermediateCertKeyName + ".pem";
+
+                                            if (! SSL.isSslCertKeyPresent(_netscalerService, intermediateCertKeyName)) {
+                                                byte[] certData= intermediateCert.getEncoded();
+                                                StringWriter textWriter = new StringWriter();
+                                                PEMWriter pemWriter = new PEMWriter(textWriter);
+                                                pemWriter.writeObject(intermediateCert);
+                                                pemWriter.flush();
 
-                                    if ( SSL.isSslCertKeyPresent(_netscalerService, certKeyName)){
-                                        SSL.deleteSslCertKey(_netscalerService, certKeyName);
+                                                SSL.uploadCert(_ip, _username, _password, intermediateCertFileName, textWriter.toString().getBytes());
+                                                SSL.createSslCertKey(_netscalerService, intermediateCertFileName, null, intermediateCertKeyName, null);
+                                            }
+
+                                            if ( previousCertKeyName != null && ! SSL.certLinkExists(_netscalerService, intermediateCertKeyName, previousCertKeyName)){
+                                                SSL.linkCerts(_netscalerService, intermediateCertKeyName, previousCertKeyName);
+                                            }
+
+                                            previousCertKeyName = intermediateCertKeyName;
+                                        }
                                     }
 
+                                    String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
+                                    String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
+                                    String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
 
-                                    SSL.uploadCert(_ip, _username, _password, certName, sslCert.getCert().getBytes());
-                                    SSL.uploadKey(_ip, _username, _password, keyName, sslCert.getKey().getBytes());
+                                    ByteArrayOutputStream certDataStream = new ByteArrayOutputStream( );
+                                    certDataStream.write(sslCert.getCert().getBytes());
+
+                                    if (! SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
+
+                                        SSL.uploadCert(_ip, _username, _password, certFilename, certDataStream.toByteArray());
+                                        SSL.uploadKey(_ip, _username, _password, keyFilename, sslCert.getKey().getBytes());
+                                        SSL.createSslCertKey(_netscalerService, certFilename, keyFilename, certKeyName, sslCert.getPassword());
+                                    }
+
+                                    if (previousCertKeyName != null && ! SSL.certLinkExists(_netscalerService, certKeyName, previousCertKeyName)){
+                                        SSL.linkCerts(_netscalerService, certKeyName, previousCertKeyName);
+                                    }
 
-                                    SSL.createSslCertKey(_netscalerService, certName, keyName, certKeyName, sslCert.getPassword());
                                     SSL.bindCertKeyToVserver(_netscalerService, certKeyName, nsVirtualServerName);
                                 }
 
@@ -773,18 +818,50 @@ public class NetscalerResource implements ServerResource {
                 }
                 if ( sslCert != null && deleteCert){
 
-                    String certName = generateSslCertName(srcIp, srcPort);
-                    String keyName = generateSslKeyName(srcIp, srcPort);
-                    String certKeyName = generateSslCertKeyName(srcIp, srcPort);
+                    String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
+                    String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
+                    String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
 
                     // unbind before deleting
-                    if ( nsVirtualServerExists(nsVirtualServerName) ){
+                    if (nsVirtualServerExists(nsVirtualServerName) &&
+                            SSL.isSslCertKeyPresent(_netscalerService, certKeyName) &&
+                            SSL.isBoundToVserver(_netscalerService, certKeyName, nsVirtualServerName)) {
                         SSL.unbindCertKeyFromVserver(_netscalerService, certKeyName, nsVirtualServerName);
                     }
 
-                    SSL.deleteSslCertKey(_netscalerService, certKeyName);
-                    SSL.deleteCertFile(_ip, _username, _password, certName);
-                    SSL.deleteKeyFile(_ip, _username, _password, keyName);
+                    if (SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
+
+                        SSL.deleteSslCertKey(_netscalerService, certKeyName);
+                        SSL.deleteCertFile(_ip, _username, _password, certFilename);
+                        SSL.deleteKeyFile(_ip, _username, _password, keyFilename);
+                    }
+
+
+                    /*
+                     * Check and delete intermediate certs:
+                     * we can delete an intermediate cert if no other
+                     * cert references it as the athority
+                    */
+
+                    if ( sslCert.getChain() != null ) {
+                        List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
+                        //go from intermediate CAs to ROOT
+                        for ( Certificate intermediateCert : chainList){
+
+                            String fingerPrint=CertificateHelper.generateFingerPrint(intermediateCert);
+                            String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);
+                            String intermediateCertFileName = intermediateCertKeyName + ".pem";
+
+                            if (SSL.isSslCertKeyPresent(_netscalerService, intermediateCertKeyName) &&
+                                    ! SSL.isCaforCerts(_netscalerService, intermediateCertKeyName)) {
+                                SSL.deleteSslCertKey(_netscalerService, intermediateCertKeyName);
+                                SSL.deleteCertFile(_ip, _username, _password, intermediateCertFileName);
+                            }else {
+                                break;// if this cert has another certificate as a child then stop at this point because we need the whole chain
+                            }
+
+                        }
+                    }
                 }
 
             }
@@ -1737,7 +1814,7 @@ public class NetscalerResource implements ServerResource {
             return false;
         }
 
-        private static void deleteSslCertKey(nitro_service ns, String certKeyName) throws ExecutionException {
+       private static void deleteSslCertKey(nitro_service ns, String certKeyName) throws ExecutionException {
             try {
 
                 sslcertkey certkey = new sslcertkey();
@@ -1752,21 +1829,23 @@ public class NetscalerResource implements ServerResource {
 
         }
 
-        private static void deleteCertFile(String nsIp, String username, String password, String certName) throws Exception {
-            SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + certName);
+        private static void deleteCertFile(String nsIp, String username, String password, String certFilename) throws Exception {
+            SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + certFilename);
         }
 
-        private static void deleteKeyFile(String nsIp, String username, String password, String keyName) throws Exception {
-            SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + keyName);
+        private static void deleteKeyFile(String nsIp, String username, String password, String keyFilename) throws Exception {
+            SshHelper.sshExecute(nsIp, SSH_PORT, username, null, password, "shell rm " + SSL_CERT_PATH + keyFilename);
         }
 
-        private static void createSslCertKey(nitro_service ns, String certName, String keyName, String certKeyName, String password) throws ExecutionException {
+        private static void createSslCertKey(nitro_service ns, String certFilename, String keyFilename, String certKeyName, String password) throws ExecutionException {
             s_logger.debug("Adding cert to netscaler");
             try {
                 sslcertkey certkey = new sslcertkey();
                 certkey.set_certkey(certKeyName);
-                certkey.set_cert(SSL_CERT_PATH + certName);
-                certkey.set_key(SSL_CERT_PATH + keyName);
+                certkey.set_cert(SSL_CERT_PATH + certFilename);
+
+                if ( keyFilename != null )
+                    certkey.set_key(SSL_CERT_PATH + keyFilename);
 
                 if( password != null ) {
                     certkey.set_passplain(password);
@@ -1832,19 +1911,18 @@ public class NetscalerResource implements ServerResource {
 
         }
 
-
-        private static void uploadCert(String nsIp, String user, String password, String certName, byte[] certData) throws ExecutionException {
+        private static void uploadCert(String nsIp, String user, String password, String certFilename, byte[] certData) throws ExecutionException {
             try {
-                SshHelper.scpTo(nsIp,SSH_PORT,user,null,password, SSL_CERT_PATH, certData, certName, null);
+                SshHelper.scpTo(nsIp,SSH_PORT,user,null,password, SSL_CERT_PATH, certData, certFilename, null);
             } catch (Exception e){
                 throw new ExecutionException("Failed to copy private key to device " + e.getMessage());
             }
         }
 
-        private static void uploadKey(String nsIp, String user, String password, String keyName, byte[] keyData) throws ExecutionException {
+        private static void uploadKey(String nsIp, String user, String password, String keyFilename, byte[] keyData) throws ExecutionException {
             try {
-                SshHelper.scpTo(nsIp, SSH_PORT, user, null, password, SSL_CERT_PATH, keyData, keyName, null);
-            }  catch (Exception e){
+                SshHelper.scpTo(nsIp, SSH_PORT, user, null, password, SSL_CERT_PATH, keyData, keyFilename, null);
+            } catch (Exception e) {
                 throw new ExecutionException("Failed to copy private key to device " + e.getMessage());
             }
         }
@@ -1853,7 +1931,7 @@ public class NetscalerResource implements ServerResource {
         private static void enableSslFeature(nitro_service ns) throws ExecutionException {
             try {
                 base_response result = ns.enable_features(new String[]{"SSL"});
-                if( result.errorcode != 0 )
+                if (result.errorcode != 0)
                     throw new ExecutionException("Unable to enable SSL on LB");
             } catch (nitro_exception e){
                 throw new ExecutionException("Failed to enable ssl feature on load balancer due to " + e.getMessage());
@@ -1880,7 +1958,80 @@ public class NetscalerResource implements ServerResource {
             }
         }
 
+        public static boolean certLinkExists(nitro_service ns, String userCertName, String caCertName) throws ExecutionException {
+            try {
+                // check if there is a link from userCertName to caCertName
+
+                sslcertkey userCert = sslcertkey.get(ns,userCertName);
+                String nsCaCert = userCert.get_linkcertkeyname();
 
+                if (nsCaCert != null && nsCaCert.equals(caCertName))
+                    return true;
+
+            } catch (nitro_exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
+            } catch (Exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
+            }
+            return false;
+        }
+
+        public static void linkCerts(nitro_service ns, String userCertName, String caCertName) throws ExecutionException {
+            try {
+
+                // the assumption is that that both userCertName and caCertName are present on NS
+
+                sslcertkey caCert = sslcertkey.get(ns, caCertName);
+                sslcertkey userCert = sslcertkey.get(ns, userCertName);
+
+                sslcertkey linkResource = new sslcertkey();
+
+                // link user cert to CA cert
+                linkResource.set_certkey(userCert.get_certkey());
+                linkResource.set_linkcertkeyname(caCert.get_certkey());
+                sslcertkey.link(ns, linkResource);
+
+            } catch (nitro_exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
+            } catch (Exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
+            }
+
+        }
+
+        public static boolean isCaforCerts(nitro_service ns, String caCertName) throws ExecutionException {
+            // check if this certificate  serves as a CA for other certificates
+            try {
+                sslcertlink[] childLinks = sslcertlink.get_filtered(ns,"linkcertkeyname:" + caCertName);
+                if(childLinks != null && childLinks.length > 0){
+                    return true;
+                }
+
+            } catch (nitro_exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
+            } catch (Exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
+            }
+            return false;
+
+        }
+
+        public static boolean isBoundToVserver(nitro_service ns, String certKeyName, String nsVirtualServerName) throws ExecutionException {
+            try {
+
+                sslcertkey_sslvserver_binding[] cert_vs_binding = sslcertkey_sslvserver_binding.get_filtered(ns, certKeyName, "vservername:" + nsVirtualServerName);
+                if(cert_vs_binding != null && cert_vs_binding.length > 0){
+                    return true;
+                }
+
+            } catch (nitro_exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
+            } catch (Exception e) {
+                throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
+            }
+            return false;
+
+        }
     }
 
 
@@ -3624,16 +3775,22 @@ public class NetscalerResource implements ServerResource {
         return counterName.replace(' ', '_');
     }
 
-    private String generateSslCertName(String srcIp, long srcPort) {
+    private String generateSslCertName(String fingerPrint) {
         // maximum length supported by NS is 31
-        return genObjectName("Cloud-Cert", srcIp, srcPort);
+        // the first 20 characters of the SHA-1 checksum are the unique id
+        String uniqueId = fingerPrint.replace(":","").substring(0,20);
+
+        return genObjectName("Cloud-Cert", uniqueId);
     }
 
-    private String generateSslKeyName(String srcIp, long srcPort) {
-        return genObjectName("Cloud-Key", srcIp, srcPort);
+    private String generateSslKeyName(String fingerPrint) {
+        String uniqueId = fingerPrint.replace(":","").substring(0,20);
+        return genObjectName("Cloud-Key", uniqueId);
     }
-    private String generateSslCertKeyName(String srcIp, long srcPort) {
-        return genObjectName("Cloud-CertKey", srcIp, srcPort);
+
+    private String generateSslCertKeyName(String fingerPrint){
+        String uniqueId = fingerPrint.replace(":","").substring(0,20);
+        return genObjectName("Cloud-Cert", uniqueId);
     }
 
     private String genObjectName(Object... args) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
index a1650e0..bd58e39 100755
--- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
+++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java
@@ -1121,8 +1121,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
             return null;
         }
 
-        return  new LbSslCert(certVO.getCertificate(), certVO.getKey(),
-                                    certVO.getChain(), certVO.getPassword(), lbCertMap.isRevoke());
+        return new LbSslCert(certVO.getCertificate(), certVO.getKey(), certVO.getPassword(), certVO.getChain(), certVO.getFingerPrint(), lbCertMap.isRevoke());
     }
 
     @Override
@@ -1174,11 +1173,6 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
             LoadBalancerCertMapVO certMap = new LoadBalancerCertMapVO(lbRuleId,certId,false);
             _lbCertMapDao.persist(certMap);
             applyLoadBalancerConfig(loadBalancer.getId());
-                /*s_logger.warn("Failed to apply Ssl Cert to LB " + loadBalancer.getId());
-                CloudRuntimeException ex = new CloudRuntimeException(
-                        "Failed to apply Ssl Cert to LB " + loadBalancer.getId());
-                ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId");
-                throw ex;*/
             success = true;
         } catch (ResourceUnavailableException e) {
             if (isRollBackAllowedForProvider(loadBalancer)) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java
index 74adb37..b699fc5 100644
--- a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java
+++ b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java
@@ -16,14 +16,60 @@
 // under the License.
 package org.apache.cloudstack.network.lb;
 
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.ejb.Local;
+import javax.inject.Inject;
+
 import com.cloud.event.ActionEvent;
 import com.cloud.event.EventTypes;
-import com.cloud.network.dao.*;
+import com.cloud.network.dao.LoadBalancerCertMapDao;
+import com.cloud.network.dao.LoadBalancerCertMapVO;
+import com.cloud.network.dao.LoadBalancerVO;
+import com.cloud.network.dao.SslCertDao;
+import com.cloud.network.dao.SslCertVO;
 import com.cloud.network.lb.CertService;
 import com.cloud.network.rules.LoadBalancer;
 import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.db.EntityManager;
 import com.cloud.utils.exception.CloudRuntimeException;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openssl.PEMReader;
+import org.bouncycastle.openssl.PasswordFinder;
 
 import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
 import org.apache.cloudstack.api.command.user.loadbalancer.ListSslCertsCmd;
@@ -37,30 +83,6 @@ import com.cloud.utils.db.DB;
 
 import org.apache.cloudstack.acl.SecurityChecker;
 import org.apache.cloudstack.context.CallContext;
-import org.apache.commons.io.IOUtils;
-import org.apache.log4j.Logger;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.openssl.PEMReader;
-import org.bouncycastle.openssl.PasswordFinder;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.ejb.Local;
-import javax.inject.Inject;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 
 @Local(value = {CertService.class})
 public class CertServiceImpl implements  CertService {
@@ -68,10 +90,14 @@ public class CertServiceImpl implements  CertService {
     private static final Logger s_logger = Logger.getLogger(CertServiceImpl.class);
 
     @Inject AccountManager _accountMgr;
-    @Inject AccountDao _accountDao;
-    @Inject SslCertDao _sslCertDao;
-    @Inject LoadBalancerCertMapDao _lbCertDao;
-    @Inject EntityManager _entityMgr;
+    @Inject
+    AccountDao _accountDao;
+    @Inject
+    SslCertDao _sslCertDao;
+    @Inject
+    LoadBalancerCertMapDao _lbCertDao;
+    @Inject
+    EntityManager _entityMgr;
 
 
 
@@ -92,6 +118,7 @@ public class CertServiceImpl implements  CertService {
 
             validate(cert, key, password, chain);
             s_logger.debug("Certificate Validation succeeded");
+
             String fingerPrint = generateFingerPrint(parseCertificate(cert));
 
             Long accountId = CallContext.current().getCallingAccount().getId();
@@ -365,14 +392,17 @@ public class CertServiceImpl implements  CertService {
             params = new PKIXBuilderParameters(anchors, target);
             params.setRevocationEnabled(false);
             params.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certs)));
-            CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
+            CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
             builder.build(params);
+
         } catch (InvalidAlgorithmParameterException e) {
             throw new IllegalArgumentException("Invalid certificate chain", e);
         } catch (CertPathBuilderException e) {
             throw new IllegalArgumentException("Invalid certificate chain", e);
         } catch (NoSuchAlgorithmException e) {
             throw new IllegalArgumentException("Invalid certificate chain", e);
+        } catch (NoSuchProviderException e) {
+            throw new CloudRuntimeException("No provider for certificate validation", e);
         }
 
     }
@@ -485,4 +515,4 @@ public class CertServiceImpl implements  CertService {
             return password_requested;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/fb89a2d8/utils/src/com/cloud/utils/security/CertificateHelper.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/security/CertificateHelper.java b/utils/src/com/cloud/utils/security/CertificateHelper.java
index 8344d72..e1edbbd 100644
--- a/utils/src/com/cloud/utils/security/CertificateHelper.java
+++ b/utils/src/com/cloud/utils/security/CertificateHelper.java
@@ -20,21 +20,28 @@ import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.StringReader;
 import java.security.Key;
 import java.security.KeyFactory;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
+import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
 import java.util.List;
 
+import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.commons.codec.binary.Base64;
 
 import com.cloud.utils.Ternary;
+import org.bouncycastle.openssl.PEMReader;
 
 public class CertificateHelper {
     public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException, 
@@ -105,4 +112,53 @@ public class CertificateHelper {
         PKCS8EncodedKeySpec  keysp = new PKCS8EncodedKeySpec (Base64.decodeBase64(base64EncodedKeyContent));
         return kf.generatePrivate (keysp);
     }
+
+   public static List<Certificate> parseChain(String chain) throws IOException {
+
+        List<Certificate> certs = new ArrayList<Certificate>();
+        PEMReader reader = new PEMReader(new StringReader(chain));
+
+        Certificate crt = null;
+
+        while ((crt = (Certificate)reader.readObject()) != null) {
+            if (crt instanceof X509Certificate) {
+                certs.add(crt);
+            }
+        }
+        if (certs.size() == 0)
+            throw new IllegalArgumentException("Unable to decode certificate chain");
+
+        return certs;
+    }
+
+    public static String generateFingerPrint(Certificate cert) {
+
+        final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+        StringBuilder buffer = new StringBuilder(60);
+        try {
+
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            byte[] data = md.digest(cert.getEncoded());
+
+            for (int i = 0; i < data.length; i++) {
+                if (buffer.length() > 0) {
+                    buffer.append(":");
+                }
+
+                buffer.append(HEX[(0xF0 & data[i]) >>> 4]);
+                buffer.append(HEX[0x0F & data[i]]);
+            }
+
+        } catch (CertificateEncodingException e) {
+            throw new CloudRuntimeException("Bad certificate encoding");
+        } catch (NoSuchAlgorithmException e) {
+            throw new CloudRuntimeException("Bad certificate algorithm");
+        }
+
+        return buffer.toString();
+    }
+
+
+
 }