adding mutual SLL authentication and certificate management DAOs

revert-70aa11f8
inosh-perera 9 years ago
parent 3726a57d96
commit ef117ffa74

@ -69,8 +69,10 @@
org.bouncycastle.operator,
org.bouncycastle.operator.jcajce,
org.bouncycastle.pkcs,
org.bouncycastle.openssl,
org.bouncycastle.util,
org.jscep.message,
org.wso2.carbon.context,
org.jscep.transaction,
org.w3c.dom,
org.xml.sax,

@ -0,0 +1,60 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.certificate.mgt.core.bean;
import java.security.cert.X509Certificate;
public class Certificate {
String serial;
X509Certificate certificate;
int tenantId;
String tenantDomain;
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
public X509Certificate getCertificate() {
return certificate;
}
public void setCertificate(X509Certificate certificate) {
this.certificate = certificate;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
}

@ -18,7 +18,11 @@
package org.wso2.carbon.certificate.mgt.core.dao;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.io.ByteArrayInputStream;
import java.util.List;
/**
* This class represents the key operations associated with persisting certificate related
@ -30,21 +34,34 @@ public interface CertificateDAO {
* This can be used to store a certificate in the database, where it will be stored against the serial number
* of the certificate.
*
* @param byteArrayInputStream Holds the certificate.
* @param serialNumber Serial number of the certificate.
* @param certificate Holds the certificate and relevant details.
* @throws CertificateManagementDAOException
*/
void addCertificate(ByteArrayInputStream byteArrayInputStream, String serialNumber
) throws CertificateManagementDAOException;
void addCertificate(List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificate)
throws CertificateManagementDAOException;
/**
* Usage is to obtain a certificate stored in the database by providing the serial number.
* Usage is to obtain a certificate stored in the database by providing the common name.
*
* @param serialNumber Serial number of the certificate.
* @return representation of the certificate.
* @throws CertificateManagementDAOException
*/
byte[] retrieveCertificate(String serialNumber
org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse retrieveCertificate(String serialNumber
) throws CertificateManagementDAOException;
/**
* Get all the certificates in a paginated manner.
* @param request Request mentioning pagination details such as length and stating index.
* @return Pagination result with data and the count of results.
* @throws CertificateManagementDAOException
*/
PaginationResult getAllCertificates(PaginationRequest request) throws CertificateManagementDAOException;
/**
* Delete a certificate identified by a serial number()
* @param serialNumber serial number
* @return whether the certificate was removed or not.
*/
boolean removeCertificate(String serialNumber) throws CertificateManagementDAOException;
}

@ -18,58 +18,172 @@
package org.wso2.carbon.certificate.mgt.core.dao.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.bean.Certificate;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateDAO;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOFactory;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOUtil;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator;
import org.wso2.carbon.certificate.mgt.core.util.CertificateManagerUtil;
import org.wso2.carbon.certificate.mgt.core.util.Serializer;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOUtil;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class GenericCertificateDAOImpl implements CertificateDAO {
private static final Log log = LogFactory.getLog(GenericCertificateDAOImpl.class);
@Override
public void addCertificate(ByteArrayInputStream byteArrayInputStream, String serialNumber)
public void addCertificate(List<Certificate> certificates)
throws CertificateManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
try {
conn = this.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_DEVICE_CERTIFICATE (SERIAL_NUMBER, CERTIFICATE) VALUES (?,?)");
stmt = conn.prepareStatement(
"INSERT INTO DM_DEVICE_CERTIFICATE (SERIAL_NUMBER, CERTIFICATE, TENANT_ID) VALUES (?,?,?)");
for (Certificate certificate : certificates) {
String serialNumber = certificate.getSerial();
if (serialNumber == null || serialNumber.isEmpty()) {
serialNumber = String.valueOf(certificate.getCertificate().getSerialNumber());
}
byte[] bytes = Serializer.serialize(certificate.getCertificate());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
stmt.setString(1, serialNumber);
stmt.setObject(2, byteArrayInputStream);
stmt.execute();
} catch (SQLException e) {
throw new CertificateManagementDAOException("Error occurred while saving certificate with serial " +
serialNumber, e);
stmt.setInt(3, certificate.getTenantId());
stmt.addBatch();
}
stmt.executeBatch();
} catch (SQLException | IOException e) {
throw new CertificateManagementDAOException("Error occurred while saving certificates. "
, e);
} finally {
CertificateManagementDAOUtil.cleanupResources(stmt, null);
}
}
@Override
public byte[] retrieveCertificate(String serialNumber)
public CertificateResponse retrieveCertificate(String serialNumber)
throws CertificateManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
byte[] binaryStream = null;
CertificateResponse certificateResponse = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
conn = this.getConnection();
String query = "SELECT CERTIFICATE FROM DM_DEVICE_CERTIFICATE WHERE SERIAL_NUMBER = ?";
String query =
"SELECT CERTIFICATE, SERIAL_NUMBER, TENANT_ID FROM DM_DEVICE_CERTIFICATE WHERE SERIAL_NUMBER = ?" +
" AND TENANT_ID = ? ";
stmt = conn.prepareStatement(query);
stmt.setString(1, serialNumber);
stmt.setInt(2, tenantId);
resultSet = stmt.executeQuery();
while (resultSet.next()) {
certificateResponse = new CertificateResponse();
byte [] certificateBytes = resultSet.getBytes("CERTIFICATE");
certificateResponse.setCertificate(certificateBytes);
certificateResponse.setSerialNumber(resultSet.getString("SERIAL_NUMBER"));
certificateResponse.setTenantId(resultSet.getInt("TENANT_ID"));
CertificateGenerator.extractCertificateDetails(certificateBytes, certificateResponse);
break;
}
} catch (SQLException e) {
String errorMsg =
"Unable to get the read the certificate with serial" + serialNumber;
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOUtil.cleanupResources(stmt, resultSet);
}
return certificateResponse;
}
@Override
public PaginationResult getAllCertificates(PaginationRequest request) throws CertificateManagementDAOException {
PreparedStatement stmt = null;
ResultSet resultSet = null;
CertificateResponse certificateResponse;
List<CertificateResponse> certificates = new ArrayList<>();
PaginationResult paginationResult;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
Connection conn = this.getConnection();
String sql = "SELECT CERTIFICATE, SERIAL_NUMBER, TENANT_ID FROM DM_DEVICE_CERTIFICATE WHERE TENANT_ID = ? " +
"ORDER BY ID DESC LIMIT ?,?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, tenantId);
stmt.setInt(2, request.getStartIndex());
stmt.setInt(3, request.getRowCount());
resultSet = stmt.executeQuery();
int resultCount = 0;
while (resultSet.next()) {
binaryStream = resultSet.getBytes("CERTIFICATE");
certificateResponse = new CertificateResponse();
byte [] certificateBytes = resultSet.getBytes("CERTIFICATE");
certificateResponse.setSerialNumber(resultSet.getString("SERIAL_NUMBER"));
certificateResponse.setTenantId(resultSet.getInt("TENANT_ID"));
CertificateGenerator.extractCertificateDetails(certificateBytes, certificateResponse);
certificates.add(certificateResponse);
resultCount++;
}
paginationResult = new PaginationResult();
paginationResult.setData(certificates);
paginationResult.setRecordsTotal(resultCount);
} catch (SQLException e) {
String errorMsg = "SQL error occurred while retrieving the certificates.";
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, resultSet);
}
return paginationResult;
}
@Override
public boolean removeCertificate(String serialNumber) throws CertificateManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
conn = this.getConnection();
String query =
"DELETE FROM DM_DEVICE_CERTIFICATE WHERE SERIAL_NUMBER = ?" +
" AND TENANT_ID = ? ";
stmt = conn.prepareStatement(query);
stmt.setString(1, serialNumber);
stmt.setInt(2, tenantId);
if(stmt.executeUpdate() > 0) {
return true;
}
return false;
} catch (SQLException e) {
throw new CertificateManagementDAOException(
"Unable to get the read the certificate with serial" + serialNumber, e);
String errorMsg =
"Unable to get the read the certificate with serial" + serialNumber;
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOUtil.cleanupResources(stmt, resultSet);
}
return binaryStream;
}
private Connection getConnection() throws SQLException {

@ -0,0 +1,115 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.certificate.mgt.core.dto;
import java.math.BigInteger;
public class CertificateResponse {
byte[] certificate;
String serialNumber;
int tenantId;
String commonName;
long notAfter;
long notBefore;
BigInteger certificateserial;
String issuer;
String subject;
int certificateVersion;
public long getNotAfter() {
return notAfter;
}
public void setNotAfter(long notAfter) {
this.notAfter = notAfter;
}
public long getNotBefore() {
return notBefore;
}
public void setNotBefore(long notBefore) {
this.notBefore = notBefore;
}
public BigInteger getCertificateserial() {
return certificateserial;
}
public void setCertificateserial(BigInteger certificateserial) {
this.certificateserial = certificateserial;
}
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public int getCertificateVersion() {
return certificateVersion;
}
public void setCertificateVersion(int certificateVersion) {
this.certificateVersion = certificateVersion;
}
public String getCommonName() {
return commonName;
}
public void setCommonName(String commonName) {
this.commonName = commonName;
}
public byte[] getCertificate() {
return certificate;
}
public void setCertificate(byte[] certificate) {
this.certificate = certificate;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public int getTenantId() {
return tenantId;
}
public void setTenantId(int tenantId) {
this.tenantId = tenantId;
}
}

@ -39,6 +39,7 @@ import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
@ -52,16 +53,19 @@ import org.wso2.carbon.certificate.mgt.core.dao.CertificateDAO;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOFactory;
import org.wso2.carbon.certificate.mgt.core.dto.CAStatus;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.util.CommonUtil;
import org.wso2.carbon.certificate.mgt.core.util.ConfigurationUtil;
import org.wso2.carbon.certificate.mgt.core.util.Serializer;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
import javax.security.auth.x500.X500Principal;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
@ -154,7 +158,13 @@ public class CertificateGenerator {
certificate.verify(certificate.getPublicKey());
saveCertInKeyStore(certificate);
List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificates = new ArrayList<>();
org.wso2.carbon.certificate.mgt.core.bean.Certificate certificateToStore =
new org.wso2.carbon.certificate.mgt.core.bean.Certificate();
certificateToStore.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
certificateToStore.setCertificate(certificate);
certificates.add(certificateToStore);
saveCertInKeyStore(certificates);
return certificate;
} catch (NoSuchAlgorithmException e) {
@ -269,6 +279,57 @@ public class CertificateGenerator {
return (certificate != null);
}
public CertificateResponse verifyPEMSignature(X509Certificate requestCertificate) throws KeystoreException {
KeyStoreReader keyStoreReader = new KeyStoreReader();
CertificateResponse lookUpCertificate;
String commonNameExtracted = getCommonName(requestCertificate);
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted);
return lookUpCertificate;
}
public static String getCommonName(X509Certificate requestCertificate) {
String distinguishedName = requestCertificate.getSubjectDN().getName();
if(distinguishedName != null && !distinguishedName.isEmpty()) {
String[] dnSplits = distinguishedName.split(",");
for (String dnSplit : dnSplits) {
if (dnSplit.contains("CN=")) {
String[] cnSplits = dnSplit.split("=");
if (cnSplits[1] != null) {
return cnSplits[1];
}
}
}
}
return null;
}
public X509Certificate pemToX509Certificate(String pem)
throws KeystoreException {
InputStream inputStream = null;
X509Certificate x509Certificate = null;
try {
inputStream = new ByteArrayInputStream(Base64.decodeBase64(pem.getBytes()));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
x509Certificate = (X509Certificate) cf.generateCertificate(inputStream);
} catch (CertificateException e) {
String errorMsg = "Certificate issue occurred when generating converting PEM to x509Certificate";
log.error(errorMsg, e);
throw new KeystoreException(errorMsg, e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
log.error("Error closing Certificate input stream", e);
}
}
return x509Certificate;
}
public X509Certificate extractCertificateFromSignature(String headerSignature) throws KeystoreException {
if (headerSignature == null || headerSignature.isEmpty()) {
@ -364,8 +425,13 @@ public class CertificateGenerator {
issuedCert = new JcaX509CertificateConverter().setProvider(
ConfigurationUtil.PROVIDER).getCertificate(
certificateBuilder.build(sigGen));
saveCertInKeyStore(issuedCert);
org.wso2.carbon.certificate.mgt.core.bean.Certificate certificate =
new org.wso2.carbon.certificate.mgt.core.bean.Certificate();
List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificates = new ArrayList<>();
certificate.setTenantId(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
certificate.setCertificate(issuedCert);
certificates.add(certificate);
saveCertInKeyStore(certificates);
} catch (CertIOException e) {
String errorMsg = "Certificate Input output issue occurred when generating generateCertificateFromCSR";
log.error(errorMsg, e);
@ -522,7 +588,7 @@ public class CertificateGenerator {
}
}
private void saveCertInKeyStore(X509Certificate certificate)
public void saveCertInKeyStore(List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificate)
throws KeystoreException {
if (certificate == null) {
@ -530,18 +596,10 @@ public class CertificateGenerator {
}
try {
String serialNumber = certificate.getSerialNumber().toString();
byte[] bytes = Serializer.serialize(certificate);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
CertificateDAO certificateDAO = CertificateManagementDAOFactory.getCertificateDAO();
CertificateManagementDAOFactory.beginTransaction();
certificateDAO.addCertificate(byteArrayInputStream, serialNumber);
certificateDAO.addCertificate(certificate);
CertificateManagementDAOFactory.commitTransaction();
} catch (IOException e) {
String errorMsg = "IOException occurred when saving the generated certificate";
log.error(errorMsg, e);
CertificateManagementDAOFactory.rollbackTransaction();
throw new KeystoreException(errorMsg, e);
} catch (CertificateManagementDAOException e) {
String errorMsg = "Error occurred when saving the generated certificate";
log.error(errorMsg, e);
@ -557,6 +615,8 @@ public class CertificateGenerator {
}
}
public String extractChallengeToken(X509Certificate certificate) {
byte[] challengePassword = certificate.getExtensionValue(
@ -617,4 +677,28 @@ public class CertificateGenerator {
certCA.getIssuerX500Principal().getName());
return signedCertificate;
}
public static void extractCertificateDetails(byte[] certificateBytes, CertificateResponse certificateResponse)
throws CertificateManagementDAOException {
try {
if (certificateBytes != null) {
java.security.cert.Certificate x509Certificate =
(java.security.cert.Certificate) Serializer.deserialize(certificateBytes);
if (x509Certificate instanceof X509Certificate) {
X509Certificate certificate = (X509Certificate) x509Certificate;
certificateResponse.setNotAfter(certificate.getNotAfter().getTime());
certificateResponse.setNotBefore(certificate.getNotBefore().getTime());
certificateResponse.setCertificateserial(certificate.getSerialNumber());
certificateResponse.setIssuer(certificate.getIssuerDN().getName());
certificateResponse.setSubject(certificate.getSubjectDN().getName());
certificateResponse.setCertificateVersion(certificate.getVersion());
}
}
} catch (ClassNotFoundException | IOException e) {
String errorMsg = "Error while deserializing the certificate.";
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
}
}
}

@ -21,6 +21,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOFactory;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.util.ConfigurationUtil;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.util.Serializer;
@ -30,13 +31,10 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.sql.SQLException;
public class KeyStoreReader {
@ -213,8 +211,11 @@ public class KeyStoreReader {
Certificate raCertificate = null;
try {
CertificateManagementDAOFactory.openConnection();
byte[] certificateBytes = CertificateManagementDAOFactory.getCertificateDAO().retrieveCertificate(alias);
raCertificate = (Certificate) Serializer.deserialize(certificateBytes);
CertificateResponse certificateResponse = CertificateManagementDAOFactory.getCertificateDAO().
retrieveCertificate(alias);
if(certificateResponse != null) {
raCertificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate());
}
} catch (CertificateManagementDAOException e) {
String errorMsg = "Error when retrieving certificate the the database for the alias " + alias;
log.error(errorMsg, e);
@ -261,4 +262,39 @@ public class KeyStoreReader {
return raPrivateKey;
}
public CertificateResponse getCertificateBySerial(String serialNumber) throws KeystoreException {
CertificateResponse certificateResponse = null;
try {
CertificateManagementDAOFactory.openConnection();
certificateResponse = CertificateManagementDAOFactory.getCertificateDAO().
retrieveCertificate(serialNumber);
if(certificateResponse != null && certificateResponse.getCertificate() != null) {
Certificate certificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate());
if (certificate instanceof X509Certificate) {
X509Certificate x509cert = (X509Certificate) certificate;
String commonName = CertificateGenerator.getCommonName(x509cert);
certificateResponse.setCommonName(commonName);
}
}
} catch (CertificateManagementDAOException e) {
String errorMsg = "Error when retrieving certificate from the the database for the serial number: " +
serialNumber;
log.error(errorMsg, e);
throw new KeystoreException(errorMsg, e);
} catch (SQLException e) {
String errorMsg = "Error when making a connection to the database.";
log.error(errorMsg, e);
throw new KeystoreException(errorMsg, e);
} catch (ClassNotFoundException | IOException e) {
String errorMsg = "Error when deserializing saved certificate.";
log.error(errorMsg, e);
throw new KeystoreException(errorMsg, e);
} finally {
CertificateManagementDAOFactory.closeConnection();
}
return certificateResponse;
}
}

@ -18,8 +18,12 @@
package org.wso2.carbon.certificate.mgt.core.service;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import java.io.InputStream;
import java.security.PrivateKey;
@ -50,9 +54,24 @@ public interface CertificateManagementService {
boolean verifySignature(String headerSignature) throws KeystoreException;
public CertificateResponse verifyPEMSignature(X509Certificate requestCertificate) throws KeystoreException;
public X509Certificate extractCertificateFromSignature(String headerSignature) throws KeystoreException;
String extractChallengeToken(X509Certificate certificate);
X509Certificate getSignedCertificateFromCSR(String binarySecurityToken) throws KeystoreException;
public CertificateResponse getCertificateBySerial(String serial) throws KeystoreException;
public void saveCertificate(List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificate)
throws KeystoreException;
public X509Certificate pemToX509Certificate(String pem) throws KeystoreException;
public CertificateResponse retrieveCertificate(String serialNumber) throws CertificateManagementDAOException;
public PaginationResult getAllCertificates(PaginationRequest request) throws CertificateManagementDAOException;
boolean removeCertificate(String serialNumber) throws CertificateManagementDAOException;
}

@ -20,16 +20,24 @@ package org.wso2.carbon.certificate.mgt.core.service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateDAO;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOException;
import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOFactory;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.dto.SCEPResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator;
import org.wso2.carbon.certificate.mgt.core.impl.KeyStoreReader;
import org.wso2.carbon.certificate.mgt.core.util.ConfigurationUtil;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOFactory;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.sql.SQLException;
import java.util.List;
public class CertificateManagementServiceImpl implements CertificateManagementService {
@ -94,6 +102,10 @@ public class CertificateManagementServiceImpl implements CertificateManagementSe
return certificateGenerator.verifySignature(headerSignature);
}
public CertificateResponse verifyPEMSignature(X509Certificate requestCertificate) throws KeystoreException {
return certificateGenerator.verifyPEMSignature(requestCertificate);
}
public X509Certificate extractCertificateFromSignature(String headerSignature) throws KeystoreException {
return certificateGenerator.extractCertificateFromSignature(headerSignature);
}
@ -106,4 +118,63 @@ public class CertificateManagementServiceImpl implements CertificateManagementSe
return certificateGenerator.getSignedCertificateFromCSR(binarySecurityToken);
}
public CertificateResponse getCertificateBySerial(String serial) throws KeystoreException {
return keyStoreReader.getCertificateBySerial(serial);
}
public void saveCertificate(List<org.wso2.carbon.certificate.mgt.core.bean.Certificate> certificate)
throws KeystoreException {
certificateGenerator.saveCertInKeyStore(certificate);
}
public X509Certificate pemToX509Certificate(String pem) throws KeystoreException {
return certificateGenerator.pemToX509Certificate(pem);
}
public CertificateResponse retrieveCertificate(String serialNumber)
throws CertificateManagementDAOException {
CertificateDAO certificateDAO;
try {
CertificateManagementDAOFactory.openConnection();
certificateDAO = CertificateManagementDAOFactory.getCertificateDAO();
return certificateDAO.retrieveCertificate(serialNumber);
} catch (SQLException e) {
String errorMsg = "Error when opening connection";
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOFactory.closeConnection();
}
}
public PaginationResult getAllCertificates(PaginationRequest request)
throws CertificateManagementDAOException {
try {
CertificateManagementDAOFactory.openConnection();
CertificateDAO certificateDAO = CertificateManagementDAOFactory.getCertificateDAO();
return certificateDAO.getAllCertificates(request);
} catch (SQLException e) {
String errorMsg = "Error when opening connection";
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOFactory.closeConnection();
}
}
@Override
public boolean removeCertificate(String serialNumber) throws CertificateManagementDAOException {
try {
CertificateManagementDAOFactory.openConnection();
CertificateDAO certificateDAO = CertificateManagementDAOFactory.getCertificateDAO();
return certificateDAO.removeCertificate(serialNumber);
} catch (SQLException e) {
String errorMsg = "Error when opening connection";
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOFactory.closeConnection();
}
}
}

@ -0,0 +1,15 @@
package org.wso2.carbon.certificate.mgt.core.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.exception.CertificateManagementException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
public class TenantUtil {
private static final Log log = LogFactory.getLog(TenantUtil.class);
public static int getTenanntId(String tenantDomain) throws CertificateManagementException {
return PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
}
}

@ -95,8 +95,7 @@
javax.xml,
org.apache.axis2.transport.http,
org.wso2.carbon.apimgt.impl,
org.wso2.carbon.certificate.mgt.core.service,
org.wso2.carbon.certificate.mgt.core.exception,
org.wso2.carbon.certificate.mgt.core.*,
org.wso2.carbon.device.mgt.core.permission.mgt,
org.wso2.carbon.device.mgt.common,
org.wso2.carbon.device.mgt.common.permission.mgt,

@ -21,9 +21,12 @@ package org.wso2.carbon.webapp.authenticator.framework.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException;
@ -47,4 +50,28 @@ public class Utils {
}
return tenantId;
}
public static String getTenantDomain(int tenantId) throws AuthenticationException {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RealmService realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
if (realmService == null) {
String msg = "RealmService is not initialized";
log.error(msg);
throw new AuthenticationException(msg);
}
return realmService.getTenantManager().getDomain(tenantId);
} catch (UserStoreException e) {
String msg = "User store not initialized";
log.error(msg);
throw new AuthenticationException(msg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -4,6 +4,7 @@ import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.dto.CertificateResponse;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementConstants;
@ -11,8 +12,10 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.core.scep.SCEPException;
import org.wso2.carbon.device.mgt.core.scep.SCEPManager;
import org.wso2.carbon.device.mgt.core.scep.TenantedDeviceWrapper;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationException;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticatorFrameworkDataHolder;
import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo;
import org.wso2.carbon.webapp.authenticator.framework.Utils.Utils;
import java.security.cert.X509Certificate;
import java.util.Properties;
@ -24,7 +27,9 @@ public class CertificateAuthenticator implements WebappAuthenticator {
private static final Log log = LogFactory.getLog(CertificateAuthenticator.class);
private static final String CERTIFICATE_AUTHENTICATOR = "CertificateAuth";
private static final String MUTUAL_AUTH_HEADER = "mutual-auth-header";
private static final String CERTIFICATE_VERIFICATION_HEADER = "certificate-verification-header";
private static final String CLIENT_CERTIFICATE_ATTRIBUTE = "javax.servlet.request.X509Certificate";
@Override
public void init() {
@ -33,10 +38,9 @@ public class CertificateAuthenticator implements WebappAuthenticator {
@Override
public boolean canHandle(Request request) {
String certVerificationHeader = request.getContext().findParameter(CERTIFICATE_VERIFICATION_HEADER);
if (certVerificationHeader != null && !certVerificationHeader.isEmpty()) {
String certHeader = request.getHeader(certVerificationHeader);
return certHeader != null;
if (request.getHeader(CERTIFICATE_VERIFICATION_HEADER) != null || request.getHeader(MUTUAL_AUTH_HEADER) !=
null) {
return true;
}
return false;
}
@ -52,7 +56,38 @@ public class CertificateAuthenticator implements WebappAuthenticator {
String certVerificationHeader = request.getContext().findParameter(CERTIFICATE_VERIFICATION_HEADER);
try {
if (certVerificationHeader != null && !certVerificationHeader.isEmpty()) {
if (request.getHeader(MUTUAL_AUTH_HEADER) != null) {
X509Certificate[] clientCertificate = (X509Certificate[]) request.
getAttribute(CLIENT_CERTIFICATE_ATTRIBUTE);
if (clientCertificate[0] != null) {
CertificateResponse certificateResponse = AuthenticatorFrameworkDataHolder.getInstance().
getCertificateManagementService().verifyPEMSignature(clientCertificate[0]);
if (certificateResponse == null) {
authenticationInfo.setStatus(Status.FAILURE);
authenticationInfo.setMessage("Certificate sent doesn't match any certificate in the store." +
" Unauthorized access attempt.");
} else if (certificateResponse.getCommonName() != null && !certificateResponse.getCommonName().
isEmpty()) {
authenticationInfo.setTenantId(certificateResponse.getTenantId());
authenticationInfo.setStatus(Status.CONTINUE);
authenticationInfo.setUsername(certificateResponse.getCommonName());
try {
authenticationInfo.setTenantDomain(Utils.
getTenantDomain(
certificateResponse.getTenantId()));
} catch (AuthenticationException e) {
authenticationInfo.setStatus(Status.FAILURE);
authenticationInfo.setMessage("Could not identify tenant domain.");
}
} else {
authenticationInfo.setStatus(Status.FAILURE);
authenticationInfo.setMessage("A matching certificate is found, " +
"but the serial number is missing in the database.");
}
}
} else if (request.getHeader(CERTIFICATE_VERIFICATION_HEADER) != null) {
String certHeader = request.getHeader(certVerificationHeader);
if (certHeader != null &&
@ -76,7 +111,7 @@ public class CertificateAuthenticator implements WebappAuthenticator {
authenticationInfo.setTenantDomain(tenantedDeviceWrapper.getTenantDomain());
authenticationInfo.setTenantId(tenantedDeviceWrapper.getTenantId());
if(tenantedDeviceWrapper.getDevice() != null &&
if (tenantedDeviceWrapper.getDevice() != null &&
tenantedDeviceWrapper.getDevice().getEnrolmentInfo() != null) {
EnrolmentInfo enrolmentInfo = tenantedDeviceWrapper.getDevice().getEnrolmentInfo();

@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
ID INTEGER auto_increment NOT NULL,
SERIAL_NUMBER VARCHAR(500) DEFAULT NULL,
CERTIFICATE BLOB DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (ID)
);

Loading…
Cancel
Save