diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml index 78d574b9fb6..7bc9f66c5b6 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/pom.xml @@ -94,7 +94,8 @@ io.swagger.annotations.*;resolution:=optional, org.wso2.carbon.device.mgt.core.*, org.wso2.carbon.registry.indexing.*, - javax.cache.* + javax.cache.*, + javax.naming.ldap diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java index f81539018bc..877d606af88 100755 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java @@ -61,6 +61,9 @@ import org.wso2.carbon.certificate.mgt.core.util.CommonUtil; import org.wso2.carbon.certificate.mgt.core.util.Serializer; import org.wso2.carbon.context.PrivilegedCarbonContext; +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; import javax.security.auth.x500.X500Principal; import javax.xml.bind.DatatypeConverter; import java.io.ByteArrayInputStream; @@ -112,7 +115,7 @@ public class CertificateGenerator { } } } catch (ClassNotFoundException | IOException e) { - String errorMsg = "Error while deserializing the certificate."; + String errorMsg = "Error while during deserialization of the certificate."; throw new CertificateManagementDAOException(errorMsg, e); } @@ -320,10 +323,20 @@ public class CertificateGenerator { CertificateResponse lookUpCertificate = null; KeyStoreReader keyStoreReader = new KeyStoreReader(); if (distinguishedName != null && !distinguishedName.isEmpty()) { - String[] dnSplits = distinguishedName.split("/CN="); - if (dnSplits != null) { - String commonNameExtracted = dnSplits[dnSplits.length - 1]; - lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted); + LdapName ldapName; + try { + ldapName = new LdapName(distinguishedName); + } catch (InvalidNameException e) { + throw new KeystoreException( + "Invalid name exception while trying to create a LDAP name using the distinguished name ", e); + } + for (Rdn relativeDistinuguishedNames : ldapName.getRdns()) { + if (relativeDistinuguishedNames.getType().equalsIgnoreCase("CN")) { + System.err.println("CN is: " + relativeDistinuguishedNames.getValue()); + lookUpCertificate = keyStoreReader + .getCertificateBySerial(String.valueOf(relativeDistinuguishedNames.getValue())); + break; + } } } return lookUpCertificate; @@ -409,21 +422,8 @@ public class CertificateGenerator { Date validityEndDate = commonUtil.getValidityEndDate(); X500Name certSubject = new X500Name(CertificateManagementConstants.DEFAULT_PRINCIPAL); - //X500Name certSubject = request.getSubject(); - Attribute attributes[] = request.getAttributes(); -// if (certSubject == null) { -// certSubject = new X500Name(ConfigurationUtil.DEFAULT_PRINCIPAL); -// } else { -// org.bouncycastle.asn1.x500.RDN[] rdn = certSubject.getRDNs(); -// -// if (rdn == null || rdn.length == 0) { -// certSubject = new X500Name(ConfigurationUtil.DEFAULT_PRINCIPAL); -// } -// } - - RDN[] certUniqueIdRDN; BigInteger certUniqueIdentifier; diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml index 47e777f2229..064ca592909 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/pom.xml @@ -167,21 +167,19 @@ org.wso2.tomcat tomcat-servlet-api - - org.wso2.carbon - org.wso2.carbon.logging - org.wso2.carbon org.wso2.carbon.tomcat.ext - org.wso2.carbon.identity.framework org.wso2.carbon.identity.base + + + org.opensaml + xmltooling + + org.wso2.carbon.identity.framework @@ -253,6 +251,21 @@ powermock-api-mockito test + + org.wso2.carbon.devicemgt + org.wso2.carbon.identity.jwt.client.extension + test + + + org.slf4j + slf4j-nop + test + + + org.apache.sling + org.apache.sling.testing.osgi-mock + test + diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticator.java index 1a3ac9d18d4..5a40a3a951e 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticator.java @@ -1,3 +1,22 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.authenticator; import org.apache.catalina.connector.Request; @@ -39,11 +58,8 @@ public class CertificateAuthenticator implements WebappAuthenticator { @Override public boolean canHandle(Request request) { - if (request.getHeader(CERTIFICATE_VERIFICATION_HEADER) != null || request.getHeader(MUTUAL_AUTH_HEADER) != null - || request.getHeader(PROXY_MUTUAL_AUTH_HEADER) != null) { - return true; - } - return false; + return request.getHeader(CERTIFICATE_VERIFICATION_HEADER) != null + || request.getHeader(MUTUAL_AUTH_HEADER) != null || request.getHeader(PROXY_MUTUAL_AUTH_HEADER) != null; } @Override @@ -64,8 +80,12 @@ public class CertificateAuthenticator implements WebappAuthenticator { authenticationInfo = checkCertificateResponse(certificateResponse); } else if (request.getHeader(MUTUAL_AUTH_HEADER) != null) { - X509Certificate[] clientCertificate = (X509Certificate[]) request. - getAttribute(CLIENT_CERTIFICATE_ATTRIBUTE); + Object object = request.getAttribute(CLIENT_CERTIFICATE_ATTRIBUTE); + X509Certificate[] clientCertificate = null; + if (object instanceof X509Certificate[]) { + clientCertificate = (X509Certificate[]) request. + getAttribute(CLIENT_CERTIFICATE_ATTRIBUTE); + } if (clientCertificate != null && clientCertificate[0] != null) { CertificateResponse certificateResponse = AuthenticatorFrameworkDataHolder.getInstance(). getCertificateManagementService().verifyPEMSignature(clientCertificate[0]); @@ -76,7 +96,6 @@ public class CertificateAuthenticator implements WebappAuthenticator { authenticationInfo.setMessage("No client certificate is present"); } } else if (request.getHeader(CERTIFICATE_VERIFICATION_HEADER) != null) { - String certHeader = request.getHeader(CERTIFICATE_VERIFICATION_HEADER); if (certHeader != null && AuthenticatorFrameworkDataHolder.getInstance().getCertificateManagementService(). @@ -105,7 +124,6 @@ public class CertificateAuthenticator implements WebappAuthenticator { EnrolmentInfo enrolmentInfo = tenantedDeviceWrapper.getDevice().getEnrolmentInfo(); authenticationInfo.setUsername(enrolmentInfo.getOwner()); } - authenticationInfo.setStatus(Status.CONTINUE); } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java index 99fd36d5342..87ef877351e 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/main/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticator.java @@ -86,6 +86,12 @@ public class JWTAuthenticator implements WebappAuthenticator { @Override public AuthenticationInfo authenticate(Request request, Response response) { String requestUri = request.getRequestURI(); + SignedJWT jwsObject; + String username; + String tenantDomain; + int tenantId; + String issuer; + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); if (requestUri == null || "".equals(requestUri)) { authenticationInfo.setStatus(Status.CONTINUE); @@ -94,19 +100,25 @@ public class JWTAuthenticator implements WebappAuthenticator { requestUri = ""; } StringTokenizer tokenizer = new StringTokenizer(requestUri, "/"); - String context = tokenizer.nextToken(); + String context = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; if (context == null || "".equals(context)) { authenticationInfo.setStatus(Status.CONTINUE); } try { String authorizationHeader = request.getHeader(JWT_ASSERTION_HEADER); + jwsObject = SignedJWT.parse(authorizationHeader); + username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); + tenantDomain = MultitenantUtils.getTenantDomain(username); + tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID)); + issuer = jwsObject.getJWTClaimsSet().getIssuer(); + } catch (ParseException e) { + log.error("Error occurred while parsing JWT header.", e); + authenticationInfo.setMessage("Error occurred while parsing JWT header"); + return authenticationInfo; + } + try { - SignedJWT jwsObject = SignedJWT.parse(authorizationHeader); - String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME); - String tenantDomain = MultitenantUtils.getTenantDomain(username); - int tenantId = Integer.parseInt(jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_TENANT_ID)); - String issuer = jwsObject.getJWTClaimsSet().getIssuer(); PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId); @@ -116,7 +128,7 @@ public class JWTAuthenticator implements WebappAuthenticator { loadTenantRegistry(tenantId); KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(tenantId); if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { - String alias = properties.getProperty(issuer); + String alias = properties == null ? null : properties.getProperty(issuer); if (alias != null && !alias.isEmpty()) { ServerConfiguration serverConfig = CarbonUtils.getServerConfiguration(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); @@ -124,7 +136,8 @@ public class JWTAuthenticator implements WebappAuthenticator { String trustStorePassword = serverConfig.getFirstProperty( DEFAULT_TRUST_STORE_PASSWORD); keyStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray()); - publicKey = keyStore.getCertificate(alias).getPublicKey(); + java.security.cert.Certificate certificate = keyStore.getCertificate(alias); + publicKey = certificate == null ? null : certificate.getPublicKey(); } else { authenticationInfo.setStatus(Status.FAILURE); return authenticationInfo; @@ -139,33 +152,32 @@ public class JWTAuthenticator implements WebappAuthenticator { publicKeyHolder.put(issuerAlias, publicKey); } } - //Get the filesystem keystore default primary certificate - JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey); - if (jwsObject.verify(verifier)) { + JWSVerifier verifier = null; + if (publicKey != null) { + verifier = new RSASSAVerifier((RSAPublicKey) publicKey); + } + if (verifier != null && jwsObject.verify(verifier)) { username = MultitenantUtils.getTenantAwareUsername(username); - if (tenantId == -1) { - log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " + - ": " + tenantDomain); + UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). + getTenantUserRealm(tenantId).getUserStoreManager(); + if (userStore.isExistingUser(username)) { + authenticationInfo.setTenantId(tenantId); + authenticationInfo.setUsername(username); + authenticationInfo.setTenantDomain(tenantDomain); + authenticationInfo.setStatus(Status.CONTINUE); } else { - UserStoreManager userStore = AuthenticatorFrameworkDataHolder.getInstance().getRealmService(). - getTenantUserRealm(tenantId).getUserStoreManager(); - if (userStore.isExistingUser(username)) { - authenticationInfo.setTenantId(tenantId); - authenticationInfo.setUsername(username); - authenticationInfo.setTenantDomain(tenantDomain); - authenticationInfo.setStatus(Status.CONTINUE); - } + authenticationInfo.setStatus(Status.FAILURE); } } else { authenticationInfo.setStatus(Status.FAILURE); } } catch (UserStoreException e) { log.error("Error occurred while obtaining the user.", e); - } catch (ParseException e) { - log.error("Error occurred while parsing the JWT header.", e); - } catch (Exception e) { + authenticationInfo.setStatus(Status.FAILURE); + } catch (Exception e) { log.error("Error occurred while verifying the JWT header.", e); + authenticationInfo.setStatus(Status.FAILURE); } finally { PrivilegedCarbonContext.endTenantFlow(); } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/BaseWebAppAuthenticatorFrameworkTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/BaseWebAppAuthenticatorFrameworkTest.java index d4bcaf2e200..fc437004a00 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/BaseWebAppAuthenticatorFrameworkTest.java +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/BaseWebAppAuthenticatorFrameworkTest.java @@ -21,18 +21,25 @@ package org.wso2.carbon.webapp.authenticator.framework; import org.testng.annotations.BeforeSuite; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.core.internal.CarbonCoreDataHolder; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionUtils; +import org.wso2.carbon.registry.core.config.RegistryContext; import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.internal.RegistryDataHolder; import org.wso2.carbon.registry.core.jdbc.realm.InMemoryRealmService; +import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.api.Permission; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreManager; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import org.wso2.carbon.webapp.authenticator.framework.internal.AuthenticatorFrameworkDataHolder; +import org.wso2.carbon.webapp.authenticator.framework.util.TestTenantIndexingLoader; +import org.wso2.carbon.webapp.authenticator.framework.util.TestTenantRegistryLoader; import java.io.File; +import java.io.InputStream; import java.net.URL; import static org.wso2.carbon.security.SecurityConstants.ADMIN_USER; @@ -56,6 +63,17 @@ public class BaseWebAppAuthenticatorFrameworkTest { .setTenantDomain(org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); PrivilegedCarbonContext.getThreadLocalCarbonContext() .setTenantId(org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_ID); + CarbonCoreDataHolder.getInstance().setRegistryService(getRegistryService()); + AuthenticatorFrameworkDataHolder.getInstance().setTenantRegistryLoader(new TestTenantRegistryLoader()); + AuthenticatorFrameworkDataHolder.getInstance().setTenantIndexingLoader(new TestTenantIndexingLoader()); + } + + /** + * To get the registry service. + * @return RegistryService + * @throws RegistryException Registry Exception + */ + private RegistryService getRegistryService() throws RegistryException, UserStoreException { RealmService realmService = new InMemoryRealmService(); AuthenticatorFrameworkDataHolder.getInstance().setRealmService(realmService); UserStoreManager userStoreManager = AuthenticatorFrameworkDataHolder.getInstance().getRealmService() @@ -63,5 +81,12 @@ public class BaseWebAppAuthenticatorFrameworkTest { Permission adminPermission = new Permission(PermissionUtils.ADMIN_PERMISSION_REGISTRY_PATH, CarbonConstants.UI_PERMISSION_ACTION); userStoreManager.addRole(ADMIN_ROLE + "t", new String[] { ADMIN_USER }, new Permission[] { adminPermission }); + RegistryDataHolder.getInstance().setRealmService(realmService); + DeviceManagementDataHolder.getInstance().setRealmService(realmService); + InputStream is = BaseWebAppAuthenticatorFrameworkTest.class.getClassLoader() + .getResourceAsStream("carbon-home/repository/conf/registry.xml"); + RegistryContext context = RegistryContext.getBaseInstance(is, realmService); + context.setSetup(true); + return context.getEmbeddedRegistryService(); } } diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticatorTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticatorTest.java new file mode 100644 index 00000000000..05d8bf1eb07 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/CertificateAuthenticatorTest.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.authenticator; + +import org.apache.catalina.Context; +import org.apache.catalina.connector.Request; +import org.apache.catalina.core.StandardContext; +import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.MimeHeaders; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.CMSAbsentContent; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.h2.jdbcx.JdbcDataSource; +import org.mockito.Mockito; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.certificate.mgt.core.dao.CertificateManagementDAOFactory; +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.scep.SCEPException; +import org.wso2.carbon.certificate.mgt.core.scep.SCEPManager; +import org.wso2.carbon.certificate.mgt.core.scep.SCEPManagerImpl; +import org.wso2.carbon.certificate.mgt.core.scep.TenantedDeviceWrapper; +import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService; +import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementServiceImpl; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; +import org.wso2.carbon.webapp.authenticator.framework.internal.AuthenticatorFrameworkDataHolder; +import org.wso2.carbon.webapp.authenticator.framework.util.TestCertificateGenerator; + +import javax.sql.DataSource; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URL; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * This is a test case for {@link CertificateAuthenticator}. + */ +public class CertificateAuthenticatorTest { + private CertificateAuthenticator certificateAuthenticator; + private Request certificationVerificationRequest; + private Request mutalAuthHeaderRequest; + private Request proxyMutalAuthHeaderRequest; + private Field headersField; + private static final String MUTUAL_AUTH_HEADER = "mutual-auth-header"; + private static final String PROXY_MUTUAL_AUTH_HEADER = "proxy-mutual-auth-header"; + private static final String CERTIFICATE_VERIFICATION_HEADER = "Mdm-Signature"; + private static final String CLIENT_CERTIFICATE_ATTRIBUTE = "javax.servlet.request.X509Certificate"; + private X509Certificate X509certificate; + + @BeforeClass + public void setup() throws KeystoreException, NoSuchFieldException, IllegalAccessException, SQLException, + DeviceManagementException, CertificateEncodingException, CMSException, IOException, SCEPException { + certificateAuthenticator = new CertificateAuthenticator(); + CertificateManagementService certificateManagementService = Mockito + .mock(CertificateManagementServiceImpl.class, Mockito.CALLS_REAL_METHODS); + headersField = org.apache.coyote.Request.class.getDeclaredField("headers"); + headersField.setAccessible(true); + + Field certificateManagementServiceImpl = CertificateManagementServiceImpl.class.getDeclaredField + ("certificateManagementServiceImpl"); + certificateManagementServiceImpl.setAccessible(true); + Field keyStoreReaderField = CertificateManagementServiceImpl.class.getDeclaredField("keyStoreReader"); + keyStoreReaderField.setAccessible(true); + Field certificateGeneratorField = CertificateManagementServiceImpl.class.getDeclaredField + ("certificateGenerator"); + certificateGeneratorField.setAccessible(true); + certificateManagementServiceImpl.set(null, certificateManagementService); + + // Create KeyStore Reader + Field dataSource = CertificateManagementDAOFactory.class.getDeclaredField("dataSource"); + dataSource.setAccessible(true); + dataSource.set(null, createDatabase()); + Field databaseEngine = CertificateManagementDAOFactory.class.getDeclaredField("databaseEngine"); + databaseEngine.setAccessible(true); + databaseEngine.set(null, "H2"); + KeyStoreReader keyStoreReader = new KeyStoreReader(); + keyStoreReaderField.set(null, keyStoreReader); + + CertificateGenerator certificateGenerator = new TestCertificateGenerator(); + certificateGeneratorField.set(null, certificateGenerator); + + AuthenticatorFrameworkDataHolder.getInstance(). + setCertificateManagementService(certificateManagementService); + X509certificate = certificateManagementService.generateX509Certificate(); + + proxyMutalAuthHeaderRequest = createRequest(PROXY_MUTUAL_AUTH_HEADER, String.valueOf(X509certificate)); + System.setProperty("carbon.config.dir.path", + System.getProperty("carbon.home") + File.separator + "repository" + File.separator + "conf"); + DeviceConfigurationManager.getInstance().initConfig(); + certificationVerificationRequest = createRequest(CERTIFICATE_VERIFICATION_HEADER, + createEncodedSignature(X509certificate)); + + mutalAuthHeaderRequest = createRequest(MUTUAL_AUTH_HEADER, "test"); + + SCEPManager scepManager = Mockito.mock(SCEPManagerImpl.class, Mockito.CALLS_REAL_METHODS); + TenantedDeviceWrapper tenantedDeviceWrapper = new TenantedDeviceWrapper(); + tenantedDeviceWrapper.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + tenantedDeviceWrapper.setTenantId(MultitenantConstants.SUPER_TENANT_ID); + Device device = new Device(); + device.setEnrolmentInfo(new EnrolmentInfo("admin", null, null)); + tenantedDeviceWrapper.setDevice(device); + Mockito.doReturn(tenantedDeviceWrapper).when(scepManager).getValidatedDevice(Mockito.any()); + AuthenticatorFrameworkDataHolder.getInstance().setScepManager(scepManager); + } + + @Test(description = "This test case tests the behaviour of the CertificateAuthenticator for Proxy mutal Auth " + + "Header requests") + public void testRequestsWithProxyMutalAuthHeader() + throws KeystoreException, NoSuchFieldException, IllegalAccessException { + Assert.assertTrue(certificateAuthenticator.canHandle(proxyMutalAuthHeaderRequest), "canHandle method " + + "returned false for a request with all the required header"); + AuthenticationInfo authenticationInfo = certificateAuthenticator + .authenticate(proxyMutalAuthHeaderRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertNull(authenticationInfo.getTenantDomain(), + "Authentication got succeeded without proper certificate"); + + proxyMutalAuthHeaderRequest = createRequest(PROXY_MUTUAL_AUTH_HEADER, + String.valueOf(X509certificate.getIssuerDN())); + authenticationInfo = certificateAuthenticator.authenticate(proxyMutalAuthHeaderRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertNotNull(authenticationInfo.getTenantDomain(), + "Authentication got failed for a proper certificate"); + + CertificateGenerator tempCertificateGenerator = new CertificateGenerator(); + X509Certificate certificateWithOutCN = tempCertificateGenerator.generateX509Certificate(); + proxyMutalAuthHeaderRequest = createRequest(PROXY_MUTUAL_AUTH_HEADER, + String.valueOf(certificateWithOutCN.getIssuerDN())); + authenticationInfo = certificateAuthenticator.authenticate(proxyMutalAuthHeaderRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Authentication got passed with a certificate without CN"); + + + } + + @Test(description = "This test case tests the behaviour of the CertificateAuthenticator for Certification " + + "Verification Header requests") + public void testRequestCertificateVerificationHeader() + throws CertificateEncodingException, IOException, CMSException, NoSuchFieldException, + IllegalAccessException { + Assert.assertTrue(certificateAuthenticator.canHandle(certificationVerificationRequest), + "canHandle method returned false for a request with all the required header"); + AuthenticationInfo authenticationInfo = certificateAuthenticator + .authenticate(certificationVerificationRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertNull(authenticationInfo.getTenantDomain(), "Authentication got passed without proper certificate"); + authenticationInfo = certificateAuthenticator.authenticate(certificationVerificationRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertEquals(authenticationInfo.getTenantDomain(), MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, + "Authentication failed for a valid request with " + CERTIFICATE_VERIFICATION_HEADER + " header"); + } + + @Test(description = "This test case tests the behaviour of the Certificate Authenticator for the requests with " + + "Mutal Auth Header") + public void testMutalAuthHeaderRequest() { + Assert.assertTrue(certificateAuthenticator.canHandle(mutalAuthHeaderRequest), + "canHandle method returned false for a request with all the required header"); + + AuthenticationInfo authenticationInfo = certificateAuthenticator.authenticate(mutalAuthHeaderRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertEquals(authenticationInfo.getMessage(), "No client certificate is present", + "Authentication got passed without proper certificate"); + + X509Certificate[] x509Certificates = new X509Certificate[1]; + x509Certificates[0] = X509certificate; + mutalAuthHeaderRequest.setAttribute(CLIENT_CERTIFICATE_ATTRIBUTE, x509Certificates); + authenticationInfo = certificateAuthenticator.authenticate(mutalAuthHeaderRequest, null); + Assert.assertNotNull(authenticationInfo, "Authentication Info from Certificate Authenticator is null"); + Assert.assertEquals(authenticationInfo.getTenantDomain(), MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, + "Authentication failed even with proper certificate"); + } + /** + * To create a request that can be understandable by Certificate Authenticator. + * + * @param headerName Name of the header + * @param value Value for the header + * @return Request that is created. + * @throws IllegalAccessException Illegal Access Exception. + * @throws NoSuchFieldException No Such Field Exception. + */ + private Request createRequest(String headerName, String value) throws IllegalAccessException, NoSuchFieldException { + Request request = new Request(); + Context context = new StandardContext(); + request.setContext(context); + org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request(); + MimeHeaders mimeHeaders = new MimeHeaders(); + MessageBytes bytes = mimeHeaders.addValue(headerName); + bytes.setString(value); + headersField.set(coyoteRequest, mimeHeaders); + + request.setCoyoteRequest(coyoteRequest); + return request; + } + + /** + * To create certificate management database. + * + * @return Datasource. + * @throws SQLException SQL Exception. + */ + private DataSource createDatabase() throws SQLException { + URL resourceURL = ClassLoader.getSystemResource("sql-scripts" + File.separator + "h2.sql"); + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL("jdbc:h2:mem:cert;DB_CLOSE_DELAY=-1"); + dataSource.setUser("sa"); + dataSource.setPassword("sa"); + final String LOAD_DATA_QUERY = "RUNSCRIPT FROM '" + resourceURL.getPath() + "'"; + Connection conn = null; + Statement statement = null; + try { + conn = dataSource.getConnection(); + statement = conn.createStatement(); + statement.execute(LOAD_DATA_QUERY); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException e) {} + } + if (statement != null) { + statement.close(); + } + } + return dataSource; + } + + /** + * To create a encoded signature from certificate. + * + * @param x509Certificate Certificate that need to be encoded. + * @return Encoded signature. + * @throws CertificateEncodingException Certificate Encoding Exception. + * @throws CMSException CMS Exception. + * @throws IOException IO Exception. + */ + private String createEncodedSignature(X509Certificate x509Certificate) throws CertificateEncodingException, + CMSException, IOException { + CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); + List list = new ArrayList<>(); + list.add(x509Certificate); + JcaCertStore store = new JcaCertStore(list); + generator.addCertificates(store); + AtomicReference degenerateSd = new AtomicReference<>(generator.generate(new CMSAbsentContent())); + byte[] signature = degenerateSd.get().getEncoded(); + return Base64.getEncoder().encodeToString(signature); + } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java new file mode 100644 index 00000000000..3a82156b6b8 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/authenticator/JWTAuthenticatorTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.authenticator; + +import org.apache.catalina.connector.Request; +import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.MimeHeaders; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.identity.jwt.client.extension.dto.JWTConfig; +import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException; +import org.wso2.carbon.identity.jwt.client.extension.util.JWTClientUtil; +import org.wso2.carbon.webapp.authenticator.framework.AuthenticationInfo; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * This is a test class for {@link JWTAuthenticator}. + */ +public class JWTAuthenticatorTest { + private JWTAuthenticator jwtAuthenticator; + private Field headersField; + private final String JWT_HEADER = "X-JWT-Assertion"; + private String jwtToken; + private String wrongJwtToken; + private String jwtTokenWithWrongUser; + private static final String SIGNED_JWT_AUTH_USERNAME = "http://wso2.org/claims/enduser"; + private static final String SIGNED_JWT_AUTH_TENANT_ID = "http://wso2.org/claims/enduserTenantId"; + private Properties properties; + private final String ISSUER = "wso2.org/products/iot"; + private final String ALIAS = "wso2carbon"; + + @BeforeClass + public void setup() throws NoSuchFieldException, IOException, JWTClientException { + jwtAuthenticator = new JWTAuthenticator(); + headersField = org.apache.coyote.Request.class.getDeclaredField("headers"); + headersField.setAccessible(true); + ClassLoader classLoader = getClass().getClassLoader(); + URL resourceUrl = classLoader.getResource("jwt.properties"); + File jwtPropertyFile; + JWTConfig jwtConfig = null; + if (resourceUrl != null) { + jwtPropertyFile = new File(resourceUrl.getFile()); + Properties jwtConfigProperties = new Properties(); + jwtConfigProperties.load(new FileInputStream(jwtPropertyFile)); + jwtConfig = new JWTConfig(jwtConfigProperties); + } + Map customClaims = new HashMap<>(); + customClaims.put(SIGNED_JWT_AUTH_USERNAME, "admin"); + customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, String.valueOf(MultitenantConstants.SUPER_TENANT_ID)); + jwtToken = JWTClientUtil.generateSignedJWTAssertion("admin", jwtConfig, false, customClaims); + customClaims = new HashMap<>(); + customClaims.put(SIGNED_JWT_AUTH_USERNAME, "admin"); + customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, "-1"); + wrongJwtToken = JWTClientUtil.generateSignedJWTAssertion("admin", jwtConfig, false, customClaims); + customClaims = new HashMap<>(); + customClaims.put(SIGNED_JWT_AUTH_USERNAME, "notexisting"); + customClaims.put(SIGNED_JWT_AUTH_TENANT_ID, String.valueOf(MultitenantConstants.SUPER_TENANT_ID)); + jwtTokenWithWrongUser = JWTClientUtil.generateSignedJWTAssertion("notexisting", jwtConfig, false, customClaims); + } + + @Test(description = "This method tests the get methods in the JWTAuthenticator", + dependsOnMethods = "testAuthenticate") + public void testGetMethods() { + Assert.assertEquals(jwtAuthenticator.getName(), "JWT", "GetName method returns wrong value"); + Assert.assertNotNull(jwtAuthenticator.getProperties(), "Properties are not properly added to JWT " + + "Authenticator"); + Assert.assertEquals(jwtAuthenticator.getProperties().size(), properties.size(), + "Added properties do not match with retrieved properties"); + Assert.assertNull(jwtAuthenticator.getProperty("test"), "Retrieved a propety that was never added"); + Assert.assertNotNull(jwtAuthenticator.getProperty(ISSUER), ALIAS); + } + + @Test(description = "This method tests the canHandle method under different conditions of request") + public void testHandle() throws IllegalAccessException, NoSuchFieldException { + Request request = new Request(); + org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request(); + request.setCoyoteRequest(coyoteRequest); + Assert.assertFalse(jwtAuthenticator.canHandle(request)); + MimeHeaders mimeHeaders = new MimeHeaders(); + MessageBytes bytes = mimeHeaders.addValue(JWT_HEADER); + bytes.setString("test"); + headersField.set(coyoteRequest, mimeHeaders); + request.setCoyoteRequest(coyoteRequest); + Assert.assertTrue(jwtAuthenticator.canHandle(request)); + } + + @Test(description = "This method tests authenticate method under the successful condition", dependsOnMethods = + { "testAuthenticateFailureScenarios" }) + public void testAuthenticate() throws IllegalAccessException, NoSuchFieldException { + Request request = createJWTRequest(jwtToken, "test"); + AuthenticationInfo authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo.getUsername(), "Proper authentication request is not properly " + + "authenticated by the JWTAuthenticator"); + } + + @Test(description = "This method tests the authenticate method under failure conditions") + public void testAuthenticateFailureScenarios() throws NoSuchFieldException, IllegalAccessException { + Request request = createJWTRequest("test", ""); + AuthenticationInfo authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertNull(authenticationInfo.getUsername(), "Un-authenticated request contain username"); + request = createJWTRequest(jwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertNull(authenticationInfo.getUsername(), "Un-authenticated request contain username"); + properties = new Properties(); + properties.setProperty(ISSUER, "test"); + jwtAuthenticator.setProperties(properties); + request = createJWTRequest(jwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + properties = new Properties(); + properties.setProperty(ISSUER, ALIAS); + jwtAuthenticator.setProperties(properties); + request = createJWTRequest(wrongJwtToken, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + request = createJWTRequest(jwtTokenWithWrongUser, ""); + authenticationInfo = jwtAuthenticator.authenticate(request, null); + Assert.assertNotNull(authenticationInfo, "Returned authentication info was null"); + Assert.assertEquals(authenticationInfo.getStatus(), WebappAuthenticator.Status.FAILURE, + "Un authenticated request does not contain status as failure"); + } + + + /** + * To create a JWT request with the given jwt header. + * @param jwtToken JWT token to be added to the header + * @param requestUri Request URI to be added to the request. + */ + private Request createJWTRequest(String jwtToken, String requestUri) + throws IllegalAccessException, NoSuchFieldException { + Request request = new Request(); + org.apache.coyote.Request coyoteRequest = new org.apache.coyote.Request(); + MimeHeaders mimeHeaders = new MimeHeaders(); + MessageBytes bytes = mimeHeaders.addValue(JWT_HEADER); + bytes.setString(jwtToken); + headersField.set(coyoteRequest, mimeHeaders); + Field uriMB = org.apache.coyote.Request.class.getDeclaredField("uriMB"); + uriMB.setAccessible(true); + bytes = MessageBytes.newInstance(); + bytes.setString(requestUri); + uriMB.set(coyoteRequest, bytes); + request.setCoyoteRequest(coyoteRequest); + return request; + } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java new file mode 100644 index 00000000000..a3a06039ec6 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/internal/WebappAuthenticatorFrameworkServiceComponentTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.internal; + +import org.apache.sling.testing.mock.osgi.MockOsgi; +import org.testng.annotations.Test; + +/** + * This is a test class for {@link WebappAuthenticatorFrameworkServiceComponent} + */ +public class WebappAuthenticatorFrameworkServiceComponentTest { + + @Test(description = "This method tests whether the bundle activator does not throw any exceptions, even under " + + "possible exception scenarios") + public void testActivateWithException() { + WebappAuthenticatorFrameworkServiceComponent webappAuthenticatorFrameworkServiceComponent = new + WebappAuthenticatorFrameworkServiceComponent(); + webappAuthenticatorFrameworkServiceComponent.activate(null); + } + + @Test(description = "This method tests whether bundle activation succeed with the proper confitions.") + public void testActivateWithoutExceptions() { + WebappAuthenticatorFrameworkServiceComponent webappAuthenticatorFrameworkServiceComponent = new + WebappAuthenticatorFrameworkServiceComponent(); + webappAuthenticatorFrameworkServiceComponent.activate(MockOsgi.newComponentContext()); + } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestCertificateGenerator.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestCertificateGenerator.java new file mode 100644 index 00000000000..5f8f96923df --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestCertificateGenerator.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.util; + +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.wso2.carbon.certificate.mgt.core.bean.Certificate; +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.CertificateManagementConstants; +import org.wso2.carbon.certificate.mgt.core.util.CommonUtil; +import org.wso2.carbon.context.PrivilegedCarbonContext; + +import javax.security.auth.x500.X500Principal; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * This is a mock implementation of {@link CertificateGenerator}. + */ +public class TestCertificateGenerator extends CertificateGenerator { + private int count = 0; + + public X509Certificate generateX509Certificate() throws KeystoreException { + BigInteger serialNumber = CommonUtil.generateSerialNumber(); + String defaultPrinciple = "CN=" + serialNumber + ",O=WSO2,OU=Mobile,C=LK"; + CommonUtil commonUtil = new CommonUtil(); + Date validityBeginDate = commonUtil.getValidityStartDate(); + Date validityEndDate = commonUtil.getValidityEndDate(); + Security.addProvider(new BouncyCastleProvider()); + + try { + KeyPairGenerator keyPairGenerator = KeyPairGenerator + .getInstance(CertificateManagementConstants.RSA, CertificateManagementConstants.PROVIDER); + keyPairGenerator.initialize(CertificateManagementConstants.RSA_KEY_LENGTH, new SecureRandom()); + KeyPair pair = keyPairGenerator.generateKeyPair(); + X500Principal principal = new X500Principal(defaultPrinciple); + X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder(principal, serialNumber, + validityBeginDate, validityEndDate, principal, pair.getPublic()); + ContentSigner contentSigner = new JcaContentSignerBuilder(CertificateManagementConstants.SHA256_RSA) + .setProvider(CertificateManagementConstants.PROVIDER).build(pair.getPrivate()); + X509Certificate certificate = new JcaX509CertificateConverter() + .setProvider(CertificateManagementConstants.PROVIDER) + .getCertificate(certificateBuilder.build(contentSigner)); + certificate.verify(certificate.getPublicKey()); + List 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) { + String errorMsg = "No such algorithm found when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (NoSuchProviderException e) { + String errorMsg = "No such provider found when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (OperatorCreationException e) { + String errorMsg = "Issue in operator creation when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (CertificateExpiredException e) { + String errorMsg = "Certificate expired after generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (CertificateNotYetValidException e) { + String errorMsg = "Certificate not yet valid when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (CertificateException e) { + String errorMsg = "Certificate issue occurred when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (InvalidKeyException e) { + String errorMsg = "Invalid key used when generating certificate"; + throw new KeystoreException(errorMsg, e); + } catch (SignatureException e) { + String errorMsg = "Signature related issue occurred when generating certificate"; + throw new KeystoreException(errorMsg, e); + } + } + + public String extractChallengeToken(X509Certificate certificate) { + if (count != 0) { + return "WSO2 (Challenge)"; + } else { + count++; + return null; + } + } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantIndexingLoader.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantIndexingLoader.java new file mode 100644 index 00000000000..3f8b84dacfd --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantIndexingLoader.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.util; + +import org.wso2.carbon.registry.indexing.service.TenantIndexingLoader; + +/** + * This is a mock implementation of {@link TenantIndexingLoader} + */ +public class TestTenantIndexingLoader implements TenantIndexingLoader { + @Override + public void loadTenantIndex(int i) { } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantRegistryLoader.java b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantRegistryLoader.java new file mode 100644 index 00000000000..42d6f04f76f --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/java/org/wso2/carbon/webapp/authenticator/framework/util/TestTenantRegistryLoader.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, 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.webapp.authenticator.framework.util; + +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; + +/** + * This is a mock implementation of {@link TenantRegistryLoader} for the test cases. + */ +public class TestTenantRegistryLoader implements TenantRegistryLoader { + @Override + public void loadTenantRegistry(int i) throws RegistryException { } +} diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml new file mode 100644 index 00000000000..70ff0a6f414 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -0,0 +1,96 @@ + + + + + + + + jdbc/DM_DS + + + + + 1000 + 60000 + 60000 + true + + org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.FCMBasedPushNotificationProvider + + org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt.MQTTBasedPushNotificationProvider + org.wso2.carbon.device.mgt.extensions.push.notification.provider.http.HTTPBasedPushNotificationProvider + org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp.XMPPBasedPushNotificationProvider + + + + false + + + https://localhost:9443 + admin + admin + + + org.wso2.carbon.policy.mgt + true + 60000 + 5 + 8 + 20 + + + + Simple + + + + 20 + 20 + 20 + 20 + 20 + 20 + + + + true + + + + true + 600 + + 10000 + + + false + 86400 + + + false + false + + BYOD,COPE + + diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/client-truststore.jks b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/client-truststore.jks new file mode 100644 index 00000000000..3b9fdfb9e84 Binary files /dev/null and b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/client-truststore.jks differ diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/wso2carbon.jks b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/wso2carbon.jks new file mode 100644 index 00000000000..b4b6220baec Binary files /dev/null and b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/resources/security/wso2carbon.jks differ diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/jwt.properties b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/jwt.properties new file mode 100644 index 00000000000..839769e4c37 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/jwt.properties @@ -0,0 +1,57 @@ +# +# Copyright (c) 2017, 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. +# + +#issuer of the JWT +iss=wso2.org/products/iot + +TokenEndpoint=https://${iot.gateway.host}:${iot.gateway.https.port}/token?tenantDomain=carbon.super + +#audience of JWT claim +#comma seperated values +aud=devicemgt + +#expiration time of JWT (number of minutes from the current time) +exp=1000 + +#issued at time of JWT (number of minutes from the current time) +iat=0 + +#nbf time of JWT (number of minutes from current time) +nbf=0 + +#skew between IDP and issuer(seconds) +skew=0 + +# JWT Id +#jti=token123 + +#KeyStore to cryptographic credentials +KeyStore=target/test-classes/carbon-home/repository/resources/security/wso2carbon.jks + +#Password of the KeyStore +KeyStorePassword=wso2carbon + +#Alias of the SP's private key +PrivateKeyAlias=wso2carbon + +#Private key password to retrieve the private key used to sign +#AuthnRequest and LogoutRequest messages +PrivateKeyPassword=wso2carbon + +#this will be used as the default IDP config if there isn't any config available for tenants. +default-jwt-client=false diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/sql-scripts/h2.sql b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/sql-scripts/h2.sql new file mode 100644 index 00000000000..7cf68828297 --- /dev/null +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/sql-scripts/h2.sql @@ -0,0 +1,25 @@ +-- +-- Copyright (c) 2017, 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. + +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, + USERNAME VARCHAR(500) DEFAULT NULL, + PRIMARY KEY (ID) +); diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml index d166d4b15ec..c9f3f8ad68b 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/testng.xml @@ -22,7 +22,7 @@ - + @@ -31,6 +31,9 @@ + + + diff --git a/pom.xml b/pom.xml index a4170228d22..82d0b17ca48 100644 --- a/pom.xml +++ b/pom.xml @@ -1568,6 +1568,12 @@ + + org.slf4j + slf4j-nop + test + ${slf4j.nop.version} + @@ -2005,6 +2011,7 @@ 1.0b3 1.7.0 1.4.0.wso2v1 + 1.7.25