| /** |
| * 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.kerby.kerberos.kerb.admin.kadmin.local; |
| |
| import org.apache.kerby.KOptions; |
| import org.apache.kerby.kerberos.kerb.KrbException; |
| import org.apache.kerby.kerberos.kerb.identity.backend.IdentityBackend; |
| import org.apache.kerby.kerberos.kerb.keytab.Keytab; |
| import org.apache.kerby.kerberos.kerb.request.KrbIdentity; |
| import org.apache.kerby.kerberos.kerb.server.KdcConfig; |
| import org.apache.kerby.kerberos.kerb.server.KdcSetting; |
| import org.apache.kerby.kerberos.kerb.server.KdcUtil; |
| import org.apache.kerby.kerberos.kerb.server.ServerSetting; |
| import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey; |
| import org.apache.kerby.kerberos.kerb.common.EncryptionUtil; |
| import org.apache.kerby.kerberos.kerb.common.KrbUtil; |
| import org.apache.kerby.kerberos.kerb.identity.backend.BackendConfig; |
| import org.apache.kerby.kerberos.kerb.type.base.PrincipalName; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.io.File; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * The implementation of admin side admin facilities for local mode. |
| */ |
| public class LocalKadminImpl implements LocalKadmin { |
| private static final Logger LOG = LoggerFactory.getLogger(LocalKadminImpl.class); |
| |
| private final ServerSetting serverSetting; |
| private final IdentityBackend backend; |
| |
| /** |
| * Construct with prepared AdminServerConfig and BackendConfig. |
| * |
| * @param kdcConfig The kdc config |
| * @param backendConfig The backend config |
| * @throws KrbException e |
| */ |
| public LocalKadminImpl(KdcConfig kdcConfig, |
| BackendConfig backendConfig) throws KrbException { |
| this.backend = KdcUtil.getBackend(backendConfig); |
| this.serverSetting = new KdcSetting(kdcConfig, backendConfig); |
| } |
| |
| // |
| public LocalKadminImpl(ServerSetting serverSetting) throws KrbException { |
| this.backend = KdcUtil.getBackend(serverSetting.getBackendConfig()); |
| this.serverSetting = serverSetting; |
| } |
| |
| /** |
| * Construct with prepared conf dir. |
| * |
| * @param confDir The path of conf dir |
| * @throws KrbException e |
| */ |
| public LocalKadminImpl(File confDir) throws KrbException { |
| KdcConfig tmpKdcConfig = KdcUtil.getKdcConfig(confDir); |
| if (tmpKdcConfig == null) { |
| tmpKdcConfig = new KdcConfig(); |
| } |
| |
| BackendConfig tmpBackendConfig = KdcUtil.getBackendConfig(confDir); |
| if (tmpBackendConfig == null) { |
| tmpBackendConfig = new BackendConfig(); |
| } |
| |
| this.serverSetting = new KdcSetting(tmpKdcConfig, tmpBackendConfig); |
| |
| backend = KdcUtil.getBackend(tmpBackendConfig); |
| } |
| |
| /** |
| * Construct with prepared AdminServerSetting and Backend. |
| * |
| * @param kdcSetting The kdc setting |
| * @param backend The identity backend |
| */ |
| public LocalKadminImpl(KdcSetting kdcSetting, IdentityBackend backend) { |
| this.serverSetting = kdcSetting; |
| this.backend = backend; |
| } |
| |
| /** |
| * Get the tgs principal name. |
| */ |
| private String getTgsPrincipal() { |
| return KrbUtil.makeTgsPrincipal(serverSetting.getKdcRealm()).getName(); |
| } |
| |
| @Override |
| public String getKadminPrincipal() { |
| return KrbUtil.makeKadminPrincipal(serverSetting.getKdcRealm()).getName(); |
| } |
| |
| @Override |
| public void checkBuiltinPrincipals() throws KrbException { |
| String tgsPrincipal = getTgsPrincipal(); |
| String kadminPrincipal = getKadminPrincipal(); |
| if (backend.getIdentity(tgsPrincipal) == null |
| || backend.getIdentity(kadminPrincipal) == null) { |
| String errorMsg = "The built-in principals do not exist in the backend," |
| + " please run the kdcinit tool."; |
| LOG.error(errorMsg); |
| throw new KrbException(errorMsg); |
| } |
| } |
| |
| @Override |
| public void createBuiltinPrincipals() throws KrbException { |
| String tgsPrincipal = getTgsPrincipal(); |
| if (backend.getIdentity(tgsPrincipal) == null) { |
| addPrincipal(tgsPrincipal); |
| } else { |
| String errorMsg = "The tgs principal already exists in backend."; |
| LOG.error(errorMsg); |
| throw new KrbException(errorMsg); |
| } |
| |
| String kadminPrincipal = getKadminPrincipal(); |
| if (backend.getIdentity(kadminPrincipal) == null) { |
| addPrincipal(kadminPrincipal); |
| } else { |
| String errorMsg = "The kadmin principal already exists in backend."; |
| LOG.error(errorMsg); |
| throw new KrbException(errorMsg); |
| } |
| } |
| |
| @Override |
| public void deleteBuiltinPrincipals() throws KrbException { |
| deletePrincipal(getTgsPrincipal()); |
| deletePrincipal(getKadminPrincipal()); |
| } |
| |
| @Override |
| public KdcConfig getKdcConfig() { |
| return serverSetting.getKdcConfig(); |
| } |
| |
| @Override |
| public BackendConfig getBackendConfig() { |
| return serverSetting.getBackendConfig(); |
| } |
| |
| @Override |
| public IdentityBackend getIdentityBackend() { |
| return backend; |
| } |
| |
| @Override |
| public void addPrincipal(String principal) throws KrbException { |
| principal = fixPrincipal(principal); |
| addPrincipal(principal, new KOptions()); |
| } |
| |
| @Override |
| public void addPrincipal(String principal, KOptions kOptions) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| KrbIdentity identity = AdminHelper.createIdentity(principal, kOptions); |
| List<EncryptionKey> keys = EncryptionUtil.generateKeys( |
| getKdcConfig().getEncryptionTypes()); |
| identity.addKeys(keys); |
| backend.addIdentity(identity); |
| } |
| |
| @Override |
| public void addPrincipal(String principal, String password) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| addPrincipal(principal, password, new KOptions()); |
| } |
| |
| @Override |
| public void addPrincipal(String principal, String password, KOptions kOptions) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| KrbIdentity identity = AdminHelper.createIdentity(principal, kOptions); |
| List<EncryptionKey> keys = EncryptionUtil.generateKeys(principal, password, |
| getKdcConfig().getEncryptionTypes()); |
| identity.addKeys(keys); |
| backend.addIdentity(identity); |
| } |
| |
| @Override |
| public void exportKeytab(File keytabFile, String principal) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| exportKeytab(keytabFile, Collections.singletonList(principal)); |
| } |
| |
| @Override |
| public void exportKeytab(File keytabFile, List<String> principals) |
| throws KrbException { |
| //Get Identity |
| List<KrbIdentity> identities = new LinkedList<>(); |
| for (String principal : principals) { |
| KrbIdentity identity = backend.getIdentity(principal); |
| if (identity == null) { |
| throw new KrbException("Can not find the identity for principal " |
| + principal); |
| } |
| identities.add(identity); |
| } |
| |
| AdminHelper.exportKeytab(keytabFile, identities); |
| } |
| |
| @Override |
| public void exportKeytab(File keytabFile) throws KrbException { |
| Keytab keytab = AdminHelper.createOrLoadKeytab(keytabFile); |
| |
| Iterable<String> principals = backend.getIdentities(); |
| for (String principal : principals) { |
| KrbIdentity identity = backend.getIdentity(principal); |
| if (identity != null) { |
| AdminHelper.exportToKeytab(keytab, identity); |
| } |
| } |
| |
| AdminHelper.storeKeytab(keytab, keytabFile); |
| } |
| |
| @Override |
| public void removeKeytabEntriesOf(File keytabFile, String principal) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| AdminHelper.removeKeytabEntriesOf(keytabFile, principal); |
| } |
| |
| @Override |
| public void removeKeytabEntriesOf(File keytabFile, String principal, int kvno) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| AdminHelper.removeKeytabEntriesOf(keytabFile, principal, kvno); |
| } |
| |
| @Override |
| public void removeOldKeytabEntriesOf(File keytabFile, String principal) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| AdminHelper.removeOldKeytabEntriesOf(keytabFile, principal); |
| } |
| |
| @Override |
| public void deletePrincipal(String principal) throws KrbException { |
| principal = fixPrincipal(principal); |
| backend.deleteIdentity(principal); |
| } |
| |
| @Override |
| public void modifyPrincipal(String principal, KOptions kOptions) |
| throws KrbException { |
| principal = fixPrincipal(principal); |
| KrbIdentity identity = backend.getIdentity(principal); |
| if (identity == null) { |
| throw new KrbException("Principal \"" |
| + principal + "\" does not exist."); |
| } |
| AdminHelper.updateIdentity(identity, kOptions); |
| backend.updateIdentity(identity); |
| } |
| |
| @Override |
| public void renamePrincipal(String oldPrincipalName, String newPrincipalName) |
| throws KrbException { |
| oldPrincipalName = fixPrincipal(oldPrincipalName); |
| newPrincipalName = fixPrincipal(newPrincipalName); |
| KrbIdentity oldIdentity = backend.getIdentity(newPrincipalName); |
| if (oldIdentity != null) { |
| throw new KrbException("Principal \"" |
| + oldIdentity.getPrincipalName() + "\" is already exist."); |
| } |
| KrbIdentity identity = backend.getIdentity(oldPrincipalName); |
| if (identity == null) { |
| throw new KrbException("Principal \"" |
| + oldPrincipalName + "\" does not exist."); |
| } |
| backend.deleteIdentity(oldPrincipalName); |
| |
| identity.setPrincipalName(newPrincipalName); |
| identity.setPrincipal(new PrincipalName(newPrincipalName)); |
| backend.addIdentity(identity); |
| } |
| |
| @Override |
| public KrbIdentity getPrincipal(String principalName) throws KrbException { |
| KrbIdentity identity = backend.getIdentity(principalName); |
| return identity; |
| } |
| |
| @Override |
| public List<String> getPrincipals() throws KrbException { |
| Iterable<String> principalNames = backend.getIdentities(); |
| List<String> principalList = new LinkedList<>(); |
| Iterator<String> iterator = principalNames.iterator(); |
| while (iterator.hasNext()) { |
| principalList.add(iterator.next()); |
| } |
| return principalList; |
| } |
| |
| @Override |
| public List<String> getPrincipals(String globString) throws KrbException { |
| Pattern pt = AdminHelper.getPatternFromGlobPatternString(globString); |
| if (pt == null) { |
| return getPrincipals(); |
| } |
| |
| boolean containsAt = pt.pattern().indexOf('@') != -1; |
| List<String> result = new LinkedList<>(); |
| |
| List<String> principalNames = getPrincipals(); |
| for (String principal: principalNames) { |
| String toMatch = containsAt ? principal : principal.split("@")[0]; |
| Matcher m = pt.matcher(toMatch); |
| if (m.matches()) { |
| result.add(principal); |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public void changePassword(String principal, |
| String newPassword) throws KrbException { |
| principal = fixPrincipal(principal); |
| KrbIdentity identity = backend.getIdentity(principal); |
| if (identity == null) { |
| throw new KrbException("Principal " + principal |
| + " was not found. Please check the input and try again"); |
| } |
| List<EncryptionKey> keys = EncryptionUtil.generateKeys(principal, newPassword, |
| getKdcConfig().getEncryptionTypes()); |
| identity.addKeys(keys); |
| |
| backend.updateIdentity(identity); |
| } |
| |
| @Override |
| public void updateKeys(String principal) throws KrbException { |
| principal = fixPrincipal(principal); |
| KrbIdentity identity = backend.getIdentity(principal); |
| if (identity == null) { |
| throw new KrbException("Principal " + principal |
| + "was not found. Please check the input and try again"); |
| } |
| List<EncryptionKey> keys = EncryptionUtil.generateKeys( |
| getKdcConfig().getEncryptionTypes()); |
| identity.addKeys(keys); |
| backend.updateIdentity(identity); |
| } |
| |
| @Override |
| public void release() throws KrbException { |
| if (backend != null) { |
| backend.stop(); |
| } |
| } |
| |
| /** |
| * get size of principal |
| */ |
| @Override |
| public int size() throws KrbException { |
| return this.getPrincipals().size(); |
| } |
| |
| /** |
| * Fix principal name, making it complete. |
| * |
| * @param principal The principal name |
| */ |
| private String fixPrincipal(String principal) { |
| if (!principal.contains("@")) { |
| principal += "@" + serverSetting.getKdcRealm(); |
| } |
| return principal; |
| } |
| } |