Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * 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.apache.directory.server.kerberos.kdc; import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; import java.util.Collections; import javax.security.auth.Subject; import javax.security.auth.kerberos.KerberosTicket; import org.apache.directory.api.util.FileUtils; import org.apache.commons.lang.SystemUtils; import org.apache.directory.api.ldap.model.entry.DefaultEntry; import org.apache.directory.api.ldap.model.entry.DefaultModification; import org.apache.directory.api.ldap.model.entry.Entry; import org.apache.directory.api.ldap.model.entry.Modification; import org.apache.directory.api.ldap.model.entry.ModificationOperation; import org.apache.directory.api.ldap.model.exception.LdapException; import org.apache.directory.api.util.Strings; import org.apache.directory.server.core.api.LdapCoreSessionConnection; import org.apache.directory.server.core.integ.AbstractLdapTestUnit; import org.apache.directory.server.protocol.shared.transport.TcpTransport; import org.apache.directory.server.protocol.shared.transport.Transport; import org.apache.directory.shared.kerberos.codec.types.EncryptionType; import org.apache.directory.shared.kerberos.crypto.checksum.ChecksumType; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; /** * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class AbstractKerberosITest extends AbstractLdapTestUnit { public static final String USERS_DN = "ou=users,dc=example,dc=com"; public static final String REALM = "EXAMPLE.COM"; public static final String USER_UID = "hnelson"; public static final String USER_PASSWORD = "secret"; public static final String LDAP_SERVICE_NAME = "ldap"; public static final String HOSTNAME = KerberosTestUtils.getHostName(); @Rule public TemporaryFolder folder = new TemporaryFolder(); protected LdapCoreSessionConnection conn; @Before public void setUp() throws Exception { conn = new LdapCoreSessionConnection(service); enableKerberosSchema(); } @After public void tearDown() throws Exception { conn.close(); } class ObtainTicketParameters { Class<? extends Transport> transport; EncryptionType encryptionType; ChecksumType checksumType; Integer oldUdpPrefLimit; Integer oldCksumtypeDefault; public ObtainTicketParameters(Class<? extends Transport> transport, EncryptionType encryptionType, ChecksumType checksumType) { this.transport = transport; this.encryptionType = encryptionType; this.checksumType = checksumType; } } /** * Obtains a TGT and service tickets for the user. * Also makes some assertions on the received tickets. * * @param encryptionType the encryption type to use * @throws Exception */ protected void testObtainTickets(ObtainTicketParameters parameters) throws Exception { setupEnv(parameters); Subject subject = new Subject(); KerberosTestUtils.obtainTGT(subject, USER_UID, USER_PASSWORD); assertEquals(1, subject.getPrivateCredentials().size()); assertEquals(0, subject.getPublicCredentials().size()); KerberosTestUtils.obtainServiceTickets(subject, USER_UID, LDAP_SERVICE_NAME, HOSTNAME); assertEquals(2, subject.getPrivateCredentials().size()); assertEquals(0, subject.getPublicCredentials().size()); for (KerberosTicket kt : subject.getPrivateCredentials(KerberosTicket.class)) { // System.out.println( kt.getClient() ); // System.out.println( kt.getServer() ); // System.out.println( kt.getSessionKeyType() ); assertEquals(parameters.encryptionType.getValue(), kt.getSessionKeyType()); } } private void enableKerberosSchema() throws LdapException { Modification mod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "m-disabled", "FALSE"); conn.modify("cn=Krb5kdc,ou=schema", mod); } protected void setupEnv(ObtainTicketParameters parameters) throws Exception { // create krb5.conf with proper encryption type String krb5confPath = createKrb5Conf(parameters.checksumType, parameters.encryptionType, parameters.transport == TcpTransport.class); System.setProperty("java.security.krb5.conf", krb5confPath); // change encryption type in KDC kdcServer.getConfig().setEncryptionTypes(Collections.singleton(parameters.encryptionType)); // create principals createPrincipal("uid=" + USER_UID, "Last", "First Last", USER_UID, USER_PASSWORD, USER_UID + "@" + REALM); createPrincipal("uid=krbtgt", "KDC Service", "KDC Service", "krbtgt", "secret", "krbtgt/" + REALM + "@" + REALM); String servicePrincipal = LDAP_SERVICE_NAME + "/" + HOSTNAME + "@" + REALM; createPrincipal("uid=ldap", "Service", "LDAP Service", "ldap", "randall", servicePrincipal); } /** * Creates the krb5.conf file for the test. * * It looks similar to this: * * <pre> * [libdefaults] * default_realm = EXAMPLE.COM * default_tkt_enctypes = aes256-cts-hmac-sha1-96 * default_tgs_enctypes = aes256-cts-hmac-sha1-96 * permitted_enctypes = aes256-cts-hmac-sha1-96 * * [realms] * EXAMPLE.COM = { * kdc = localhost:6088 * } * * [domain_realm] * .example.com = EXAMPLE.COM * example.com = EXAMPLE.COM * </pre> * * @param encryptionType * @param checksumType * @return the path to the krb5.conf file * @throws IOException */ private String createKrb5Conf(ChecksumType checksumType, EncryptionType encryptionType, boolean isTcp) throws IOException { File file = folder.newFile("krb5.conf"); String data = ""; data += "[libdefaults]" + SystemUtils.LINE_SEPARATOR; data += "default_realm = " + REALM + SystemUtils.LINE_SEPARATOR; data += "default_tkt_enctypes = " + encryptionType.getName() + SystemUtils.LINE_SEPARATOR; data += "default_tgs_enctypes = " + encryptionType.getName() + SystemUtils.LINE_SEPARATOR; data += "permitted_enctypes = " + encryptionType.getName() + SystemUtils.LINE_SEPARATOR; // data += "default_checksum = " + checksumType.getName() + SystemUtils.LINE_SEPARATOR; // data += "ap_req_checksum_type = " + checksumType.getName() + SystemUtils.LINE_SEPARATOR; data += "default-checksum_type = " + checksumType.getName() + SystemUtils.LINE_SEPARATOR; if (isTcp) { data += "udp_preference_limit = 1" + SystemUtils.LINE_SEPARATOR; } data += "[realms]" + SystemUtils.LINE_SEPARATOR; data += REALM + " = {" + SystemUtils.LINE_SEPARATOR; data += "kdc = " + HOSTNAME + ":" + kdcServer.getTransports()[0].getPort() + SystemUtils.LINE_SEPARATOR; data += "}" + SystemUtils.LINE_SEPARATOR; data += "[domain_realm]" + SystemUtils.LINE_SEPARATOR; data += "." + Strings.toLowerCaseAscii(REALM) + " = " + REALM + SystemUtils.LINE_SEPARATOR; data += Strings.toLowerCaseAscii(REALM) + " = " + REALM + SystemUtils.LINE_SEPARATOR; FileUtils.writeStringToFile(file, data); return file.getAbsolutePath(); } private void createPrincipal(String rdn, String sn, String cn, String uid, String userPassword, String principalName) throws LdapException { Entry entry = new DefaultEntry(); entry.setDn(rdn + "," + USERS_DN); entry.add("objectClass", "top", "person", "inetOrgPerson", "krb5principal", "krb5kdcentry"); entry.add("cn", cn); entry.add("sn", sn); entry.add("uid", uid); entry.add("userPassword", userPassword); entry.add("krb5PrincipalName", principalName); entry.add("krb5KeyVersionNumber", "0"); conn.add(entry); } }