/*
 *
 * 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.qpid.server.security.encryption;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryPermission;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.nio.file.attribute.UserPrincipal;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.plugin.ConditionallyAvailable;
import org.apache.qpid.server.plugin.ConfigurationSecretEncrypterFactory;
import org.apache.qpid.server.plugin.PluggableService;

@PluggableService
public class AESKeyFileEncrypterFactory implements ConfigurationSecretEncrypterFactory, ConditionallyAvailable
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AESKeyFileEncrypterFactory.class);

    static final String ENCRYPTER_KEY_FILE = "encrypter.key.file";

    private static final int AES_KEY_SIZE_BITS = 256;
    private static final int AES_KEY_SIZE_BYTES = AES_KEY_SIZE_BITS / 8;
    private static final String AES_ALGORITHM = "AES";

    public static final String TYPE = "AESKeyFile";

    static final String DEFAULT_KEYS_SUBDIR_NAME = ".keys";

    private static final boolean IS_AVAILABLE;

    private static final String ILLEGAL_ARG_EXCEPTION = "Unable to determine a mechanism to protect access to the key file on this filesystem";

    static
    {
        boolean isAvailable;
        try
        {
            final int allowedKeyLength = Cipher.getMaxAllowedKeyLength(AES_ALGORITHM);
            isAvailable = allowedKeyLength >=AES_KEY_SIZE_BITS;
            if(!isAvailable)
            {
                LOGGER.warn("The {} configuration encryption encryption mechanism is not available. "
                            + "Maximum available AES key length is {} but {} is required. "
                            + "Ensure the full strength JCE policy has been installed into your JVM.", TYPE, allowedKeyLength, AES_KEY_SIZE_BITS);
            }
        }
        catch (NoSuchAlgorithmException e)
        {
            isAvailable = false;

            LOGGER.error("The " + TYPE + " configuration encryption encryption mechanism is not available. "
                        + "The " + AES_ALGORITHM + " algorithm is not available within the JVM (despite it being a requirement).");
        }

        IS_AVAILABLE = isAvailable;
    }

    @Override
    public ConfigurationSecretEncrypter createEncrypter(final ConfiguredObject<?> object)
    {
        String fileLocation;
        if(object.getContextKeys(false).contains(ENCRYPTER_KEY_FILE))
        {
            fileLocation = object.getContextValue(String.class, ENCRYPTER_KEY_FILE);
        }
        else
        {

            fileLocation = object.getContextValue(String.class, SystemConfig.QPID_WORK_DIR)
                           + File.separator + DEFAULT_KEYS_SUBDIR_NAME + File.separator
                           + object.getCategoryClass().getSimpleName() + "_"
                           + object.getName() + ".key";

            Map<String, String> context = object.getContext();
            Map<String, String> modifiedContext = new LinkedHashMap<>(context);
            modifiedContext.put(ENCRYPTER_KEY_FILE, fileLocation);

            object.setAttributes(Collections.<String, Object>singletonMap(ConfiguredObject.CONTEXT, modifiedContext));
        }
        File file = new File(fileLocation);
        if(!file.exists())
        {
            LOGGER.warn("Configuration encryption is enabled, but no configuration secret was found. A new configuration secret will be created at '{}'.", fileLocation);
            createAndPopulateKeyFile(file);
        }
        if(!file.isFile())
        {
            throw new IllegalArgumentException("File '"+fileLocation+"' is not a regular file.");
        }
        try
        {
            checkFilePermissions(fileLocation, file);
            if(Files.size(file.toPath()) != AES_KEY_SIZE_BYTES)
            {
                throw new IllegalArgumentException("Key file '" + fileLocation + "' contains an incorrect about of data");
            }

            try(FileInputStream inputStream = new FileInputStream(file))
            {
                byte[] key = new byte[AES_KEY_SIZE_BYTES];
                int pos = 0;
                int read;
                while(pos < key.length && -1 != ( read = inputStream.read(key, pos, key.length - pos)))
                {
                    pos += read;
                }
                if(pos != key.length)
                {
                    throw new IllegalConfigurationException("Key file '" + fileLocation + "' contained an incorrect about of data");
                }
                SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALGORITHM);
                return new AESKeyFileEncrypter(keySpec);
            }
        }
        catch (IOException e)
        {
            throw new IllegalConfigurationException("Unable to get file permissions: " + e.getMessage(), e);
        }
    }

    private void checkFilePermissions(String fileLocation, File file) throws IOException
    {
        if(isPosixFileSystem(file))
        {
            Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());

            if (permissions.contains(PosixFilePermission.GROUP_READ)
                    || permissions.contains(PosixFilePermission.OTHERS_READ)
                    || permissions.contains(PosixFilePermission.GROUP_WRITE)
                    || permissions.contains(PosixFilePermission.OTHERS_WRITE)) {
                throw new IllegalArgumentException("Key file '"
                        + fileLocation
                        + "' has incorrect permissions.  Only the owner "
                        + "should be able to read or write this file.");
            }
        }
        else if(isAclFileSystem(file))
        {
            AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
            ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
            ListIterator<AclEntry> iter = acls.listIterator();
            UserPrincipal owner = Files.getOwner(file.toPath());
            while(iter.hasNext())
            {
                AclEntry acl = iter.next();
                if(acl.type() == AclEntryType.ALLOW)
                {
                    Set<AclEntryPermission> originalPermissions = acl.permissions();
                    Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);


                    if (updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
                            AclEntryPermission.EXECUTE,
                            AclEntryPermission.WRITE_ACL,
                            AclEntryPermission.WRITE_DATA,
                            AclEntryPermission.WRITE_OWNER))) {
                        throw new IllegalArgumentException("Key file '"
                                + fileLocation
                                + "' has incorrect permissions.  The file should not be modifiable by any user.");
                    }
                    if (!owner.equals(acl.principal()) && updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.READ_DATA))) {
                        throw new IllegalArgumentException("Key file '"
                                + fileLocation
                                + "' has incorrect permissions.  Only the owner should be able to read from the file.");
                    }
                }
            }
        }
        else
        {
            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
        }
    }

    private boolean isPosixFileSystem(File file) throws IOException
    {
        return Files.getFileAttributeView(file.toPath(), PosixFileAttributeView.class) != null;
    }

    private boolean isAclFileSystem(File file) throws IOException
    {
        return Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class) != null;
    }


    private void createAndPopulateKeyFile(final File file)
    {
        try
        {
            createEmptyKeyFile(file);

            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
            keyGenerator.init(AES_KEY_SIZE_BITS);
            SecretKey key = keyGenerator.generateKey();
            try(FileOutputStream os = new FileOutputStream(file))
            {
                os.write(key.getEncoded());
            }

            makeKeyFileReadOnly(file);
        }
        catch (NoSuchAlgorithmException | IOException e)
        {
            throw new IllegalArgumentException("Cannot create key file: " + e.getMessage(), e);
        }

    }

    private void makeKeyFileReadOnly(File file) throws IOException
    {
        if(isPosixFileSystem(file))
        {
            Files.setPosixFilePermissions(file.toPath(), EnumSet.of(PosixFilePermission.OWNER_READ));
        }
        else if(isAclFileSystem(file))
        {
            AclFileAttributeView attributeView = Files.getFileAttributeView(file.toPath(), AclFileAttributeView.class);
            ArrayList<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
            ListIterator<AclEntry> iter = acls.listIterator();
            file.setReadOnly();
            while(iter.hasNext())
            {
                AclEntry acl = iter.next();
                Set<AclEntryPermission> originalPermissions = acl.permissions();
                Set<AclEntryPermission> updatedPermissions = EnumSet.copyOf(originalPermissions);

                if(updatedPermissions.removeAll(EnumSet.of(AclEntryPermission.APPEND_DATA,
                                                           AclEntryPermission.DELETE,
                                                           AclEntryPermission.EXECUTE,
                                                           AclEntryPermission.WRITE_ACL,
                                                           AclEntryPermission.WRITE_DATA,
                                                           AclEntryPermission.WRITE_ATTRIBUTES,
                                                           AclEntryPermission.WRITE_NAMED_ATTRS,
                                                           AclEntryPermission.WRITE_OWNER)))
                {
                    AclEntry.Builder builder = AclEntry.newBuilder(acl);
                    builder.setPermissions(updatedPermissions);
                    iter.set(builder.build());
                }
            }
            attributeView.setAcl(acls);
        }
        else
        {
            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
        }
    }

    private void createEmptyKeyFile(File file) throws IOException
    {
        final Path parentFilePath = file.getAbsoluteFile().getParentFile().toPath();

        if(isPosixFileSystem(file)) {
            Set<PosixFilePermission> ownerOnly = EnumSet.of(PosixFilePermission.OWNER_READ,
                    PosixFilePermission.OWNER_WRITE,
                    PosixFilePermission.OWNER_EXECUTE);
            Files.createDirectories(parentFilePath, PosixFilePermissions.asFileAttribute(ownerOnly));

            Files.createFile(file.toPath(), PosixFilePermissions.asFileAttribute(
                    EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)));
        }
        else if(isAclFileSystem(file))
        {
            Files.createDirectories(parentFilePath);
            final UserPrincipal owner = Files.getOwner(parentFilePath);
            AclFileAttributeView attributeView = Files.getFileAttributeView(parentFilePath, AclFileAttributeView.class);
            List<AclEntry> acls = new ArrayList<>(attributeView.getAcl());
            ListIterator<AclEntry> iter = acls.listIterator();
            boolean found = false;
            while(iter.hasNext())
            {
                AclEntry acl = iter.next();
                if(!owner.equals(acl.principal()))
                {
                    iter.remove();
                }
                else if(acl.type() == AclEntryType.ALLOW)
                {
                    found = true;
                    AclEntry.Builder builder = AclEntry.newBuilder(acl);
                    Set<AclEntryPermission> permissions = acl.permissions().isEmpty() ? new HashSet<AclEntryPermission>() : EnumSet.copyOf(acl.permissions());
                    permissions.addAll(Arrays.asList(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY));
                    builder.setPermissions(permissions);
                    iter.set(builder.build());
                }
            }
            if(!found)
            {
                AclEntry.Builder builder = AclEntry.newBuilder();
                builder.setPermissions(AclEntryPermission.ADD_FILE, AclEntryPermission.ADD_SUBDIRECTORY, AclEntryPermission.LIST_DIRECTORY);
                builder.setType(AclEntryType.ALLOW);
                builder.setPrincipal(owner);
                acls.add(builder.build());
            }
            attributeView.setAcl(acls);

            Files.createFile(file.toPath(), new FileAttribute<List<AclEntry>>()
            {
                @Override
                public String name()
                {
                    return "acl:acl";
                }

                @Override
                public List<AclEntry> value() {
                    AclEntry.Builder builder = AclEntry.newBuilder();
                    builder.setType(AclEntryType.ALLOW);
                    builder.setPermissions(EnumSet.allOf(AclEntryPermission.class));
                    builder.setPrincipal(owner);
                    return Collections.singletonList(builder.build());
                }
            });

        }
        else
        {
            throw new IllegalArgumentException(ILLEGAL_ARG_EXCEPTION);
        }
    }

    @Override
    public String getType()
    {
        return TYPE;
    }

    @Override
    public boolean isAvailable()
    {
        return IS_AVAILABLE;
    }
}
