diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5331727af90..131ba030632 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ tomcat-jakarta-version = "10.1.18" apache-version = "4.1.5" apache5-version = "5.3" -apacheds-version = "2.0.0-M24" +apacheds-version = "2.0.0.AM27" okhttp-version = "4.12.0" okio-version = "3.7.0" diff --git a/ktor-server/ktor-server-plugins/ktor-server-auth-ldap/jvm/test/io/ktor/tests/auth/ldap/LdapAuthTest.kt b/ktor-server/ktor-server-plugins/ktor-server-auth-ldap/jvm/test/io/ktor/tests/auth/ldap/LdapAuthTest.kt deleted file mode 100644 index ddfe1b9346f..00000000000 --- a/ktor-server/ktor-server-plugins/ktor-server-auth-ldap/jvm/test/io/ktor/tests/auth/ldap/LdapAuthTest.kt +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. - */ - -package io.ktor.tests.auth.ldap - -import io.ktor.http.* -import io.ktor.http.auth.* -import io.ktor.server.application.* -import io.ktor.server.auth.* -import io.ktor.server.auth.ldap.* -import io.ktor.server.response.* -import io.ktor.server.routing.* -import io.ktor.server.testing.* -import org.apache.directory.api.ldap.util.* -import org.apache.directory.server.annotations.* -import org.apache.directory.server.core.integ.* -import org.apache.directory.server.core.integ.IntegrationUtils.* -import org.apache.directory.server.ldap.* -import org.junit.runner.* -import java.net.* -import java.util.* -import javax.naming.directory.* -import javax.naming.ldap.* -import kotlin.test.* - -@Suppress("DEPRECATION") -@RunWith(FrameworkRunner::class) -@CreateLdapServer(transports = arrayOf(CreateTransport(protocol = "LDAP"))) -@Ignore("LdapAuthTest is ignored because it is very slow. Run it explicitly when you need.") -class LdapAuthTest { - @BeforeTest - fun setUp() { - // notice: it is just a test: never keep user password but message digest or hash with salt - apply( - ldapServer.directoryService, - getUserAddLdif("uid=user-test,ou=users,ou=system", "test".toByteArray(), "Test user", "test") - ) - } - - @Test - fun testLoginToServer() { - withTestApplication { - application.install(Authentication) { - basic { - realm = "realm" - validate { credential -> - ldapAuthenticate(credential, "ldap://$localhost:${ldapServer.port}", "uid=%s,ou=system") - } - } - } - - application.routing { - authenticate { - get("/") { - call.respondText(call.authentication.principal()?.name ?: "null") - } - } - } - - handleRequest(HttpMethod.Get, "/").let { result -> - result.response.headers[HttpHeaders.WWWAuthenticate].let { - assertNotNull(it, "No auth challenge sent") - val challenge = parseAuthorizationHeader(it) - assertNotNull(challenge, "Challenge has incorrect format") - assertEquals("Basic", challenge.authScheme) - assertTrue(challenge is HttpAuthHeader.Parameterized, "It should be parameterized challenge") - assertEquals("realm", challenge.parameter("realm")) - assertEquals("UTF-8", challenge.parameter("charset")) - } - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("admin:secret".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.OK, result.response.status()) - assertEquals("admin", result.response.content) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("admin:bad-pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - assertNull(result.response.content) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("bad-user:bad-pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - assertNull(result.response.content) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString(" \",; \u0419:pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - assertNull(result.response.content) - } - } - } - - @Test - fun testCustomLogin() { - withTestApplication { - application.install(Authentication) { - val ldapUrl = "ldap://$localhost:${ldapServer.port}" - val configure: (MutableMap) -> Unit = { env -> - env.put("java.naming.security.principal", "uid=admin,ou=system") - env.put("java.naming.security.credentials", "secret") - env.put("java.naming.security.authentication", "simple") - } - - basic { - validate { credential -> - ldapAuthenticate(credential, ldapUrl, configure) { - val users = (lookup("ou=system") as LdapContext).lookup("ou=users") as LdapContext - val controls = SearchControls().apply { - searchScope = SearchControls.ONELEVEL_SCOPE - returningAttributes = arrayOf("+", "*") - } - - users.search("", "(uid=user-test)", controls).asSequence().firstOrNull { - val ldapPassword = (it.attributes.get("userPassword")?.get() as ByteArray?) - ?.toString(Charsets.ISO_8859_1) - ldapPassword == credential.password - }?.let { UserIdPrincipal(credential.name) } - } - } - } - } - - application.routing { - authenticate { - get("/") { - call.respondText(call.authentication.principal()?.name ?: "null") - } - } - } - - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("user-test:test".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.OK, result.response.status()) - assertEquals("user-test", result.response.content) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("user-test:bad-pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString("bad-user:bad-pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - } - handleRequest(HttpMethod.Get, "/") { - addHeader( - HttpHeaders.Authorization, - "Basic " + Base64.getEncoder().encodeToString(" \",; \u0419:pass".toByteArray()) - ) - }.let { result -> - assertEquals(HttpStatusCode.Unauthorized, result.response.status()) - assertNull(result.response.content) - } - } - } - - @Test - fun testEnsureUser() { - val env = Hashtable() - env.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory") - env.put("java.naming.provider.url", "ldap://$localhost:${ldapServer.port}") - env.put("java.naming.security.principal", "uid=admin,ou=system") - env.put("java.naming.security.credentials", "secret") - env.put("java.naming.security.authentication", "simple") - - val ctx = ( - InitialLdapContext( - env, - JndiUtils.toJndiControls(ldapServer.directoryService.ldapCodecService) - ).lookup("ou=system") as LdapContext - ).lookup("ou=users") as LdapContext - - val controls = SearchControls() - controls.searchScope = SearchControls.ONELEVEL_SCOPE - controls.returningAttributes = arrayOf("+", "*") - val res = ctx.search("", "(ObjectClass=*)", controls).toList() - - assertEquals(listOf("user-test"), res.map { it.attributes.get("uid").get().toString() }) - } - - private val localhost: String - get() = - try { - InetAddress.getLocalHost().hostAddress - } catch (any: Throwable) { - "127.0.0.1" - } - - companion object { - @JvmStatic - lateinit var ldapServer: LdapServer - } -}