/*
 * 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.felix.framework;

import java.io.File;
import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.felix.framework.ext.SecurityProvider;
import org.apache.felix.framework.security.SecurityConstants;
import org.apache.felix.framework.security.condpermadmin.ConditionalPermissionAdminImpl;
import org.apache.felix.framework.security.permissionadmin.PermissionAdminImpl;
import org.apache.felix.framework.security.util.Conditions;
import org.apache.felix.framework.security.util.LocalPermissions;
import org.apache.felix.framework.security.util.Permissions;
import org.apache.felix.framework.security.util.PropertiesCache;
import org.apache.felix.framework.util.SecureAction;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
import org.osgi.service.permissionadmin.PermissionAdmin;

/**
 * <p>
 * This Felix specific activator installs a security provider with the Felix
 * framework. The security settings can be changed via the
 * {@link PermissionAdmin} and/or the {@link ConditionalPermissionAdmin}
 * services that may be published by this class.
 * </p>
 * <p>
 * Permission informations as well as caching data will be stored in several
 * files in a directory called <tt>security</tt> obtained by a call to
 * {@link BundleContext#getDataFile(String))}.
 * </p>
 * <p>
 * The following properties are recognized:
 * <p>
 * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_PROP} - Whether or not (
 * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
 * service. The default is
 * {@link SecurityConstants#ENABLE_PERMISSIONADMIN_VALUE}.
 * </p>
 * <p>
 * {@link SecurityConstants#ENABLE_CONDPERMADMIN_PROP} - Whether or not (
 * <tt>true</tt>|<tt>false</tt>) to publish a{@link ConditionalPermissionAdmin}
 * service. The default is {@link SecurityConstants#ENABLE_CONDPERMADMIN_VALUE}.
 * </p>
 * <p>
 * {@link SecurityConstants#KEYSTORE_FILE_PROP} - The keystore URL(s) to use as
 * trusted CA stores. The urls must be separated by a guard (i.e., <tt>|</tt>).
 * The default is {@link SecurityConstants#KEYSTORE_FILE_VALUE}.
 * </p>
 * <p>
 * {@link SecurityConstants#KEYSTORE_PASS_PROP} - The keystore password(s) to
 * use for the given keystores. The passwords must be separated by a guard
 * (i.e., <tt>|</tt>).The default is
 * {@link SecurityConstants#KEYSTORE_PASS_VALUE}.
 * </p>
 * <p>
 * {@link SecurityConstants#KEYSTORE_TYPE_PROP} - The keystore type(s) to use
 * for the given keystores. The types must be separated by a guard (i.e.,
 * <tt>|</tt>).The default is {@link SecurityConstants#KEYSTORE_TYPE_VALUE}.
 * </p>
 * <p>
 * {@link SecurityConstants#CRL_FILE_PROP} - The CRL URL(s) to use for revoked
 * certificates. The urls must be separated by a guard (i.e., <tt>|</tt>). The
 * default is {@link SecurityConstants#CRL_FILE_VALUE}.
 * </p>
 * </p>
 */
/*
 * TODO: using a string for passwords is bad. We need to investigate
 * alternatives.
 * 
 * TODO: we might want to allow for the recognized properties to change without
 * a restart. This is trick because we can not publish a managed service due to
 * not being able to import as we are an extension bundle.
 */
public final class SecurityActivator implements BundleActivator
{
    public synchronized void start(BundleContext context) throws Exception
    {
        PermissionAdminImpl pai = null;

        SecureAction action = new SecureAction();

        Permissions permissions = new Permissions(context, action);

        File tmp = context.getDataFile("security" + File.separator + "tmp");
        if ((tmp == null) || (!tmp.isDirectory() && !tmp.mkdirs()))
        {
            throw new IOException("Can't create tmp dir.");
        }
        // TODO: log something if we can not clean-up the tmp dir
        File[] old = tmp.listFiles();
        if (old != null)
        {
            for (int i = 0; i < old.length; i++)
            {
                old[i].delete();
            }
        }

        if ("TRUE".equalsIgnoreCase(getProperty(context,
            SecurityConstants.ENABLE_PERMISSIONADMIN_PROP,
            SecurityConstants.ENABLE_PERMISSIONADMIN_VALUE)))
        {
            File cache = context.getDataFile("security" + File.separator
                + "pa.txt");
            if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
            {
                throw new IOException("Can't create cache file");
            }
            pai = new PermissionAdminImpl(permissions, new PropertiesCache(
                cache, tmp, action));
        }

        ConditionalPermissionAdminImpl cpai = null;

        if ("TRUE".equalsIgnoreCase(getProperty(context,
            SecurityConstants.ENABLE_CONDPERMADMIN_PROP,
            SecurityConstants.ENABLE_CONDPERMADMIN_VALUE)))
        {
            File cpaCache = context.getDataFile("security" + File.separator
                + "cpa.txt");
            if ((cpaCache == null)
                || (!cpaCache.isFile() && !cpaCache.createNewFile()))
            {
                throw new IOException("Can't create cache file");
            }

            LocalPermissions localPermissions = new LocalPermissions(
                permissions);

            cpai = new ConditionalPermissionAdminImpl(permissions,
                new Conditions(action), localPermissions, new PropertiesCache(
                    cpaCache, tmp, action), pai);
        }

        if ((pai != null) || (cpai != null))
        {
            String crlList = getProperty(context,
                SecurityConstants.CRL_FILE_PROP,
                SecurityConstants.CRL_FILE_VALUE);
            String storeList = getProperty(context,
                SecurityConstants.KEYSTORE_FILE_PROP,
                SecurityConstants.KEYSTORE_FILE_VALUE);
            String passwdList = getProperty(context,
                SecurityConstants.KEYSTORE_PASS_PROP,
                SecurityConstants.KEYSTORE_PASS_VALUE);
            String typeList = getProperty(context,
                SecurityConstants.KEYSTORE_TYPE_PROP,
                SecurityConstants.KEYSTORE_TYPE_VALUE);
            String osgi_keystores = getProperty(context,
                Constants.FRAMEWORK_TRUST_REPOSITORIES, null);
            if (osgi_keystores != null)
            {
                StringTokenizer tok = new StringTokenizer(osgi_keystores,
                    File.pathSeparator);

                if (storeList.length() == 0)
                {
                    storeList += "file:" + tok.nextToken();
                    passwdList += " ";
                    typeList += "JKS";
                }
                while (tok.hasMoreTokens())
                {
                    storeList += "|file:" + tok.nextToken();
                    passwdList += "| ";
                    typeList += "|JKS";
                }
            }

            StringTokenizer storeTok = new StringTokenizer(storeList, "|");
            StringTokenizer passwdTok = new StringTokenizer(passwdList, "|");
            StringTokenizer typeTok = new StringTokenizer(typeList, "|");

            if ((storeTok.countTokens() != typeTok.countTokens())
                || (passwdTok.countTokens() != storeTok.countTokens()))
            {
                throw new BundleException(
                    "Each CACerts keystore must have one type and one passwd entry and vice versa.");
            }

            SecurityProvider provider = new SecurityProviderImpl(crlList,
                typeList, passwdList, storeList, pai, cpai, action, ((Felix) context.getBundle(0)).getLogger());

            ((Felix) context.getBundle(0)).setSecurityProvider(provider);
        }

        if (pai != null)
        {
            context.registerService(PermissionAdmin.class.getName(), pai, null);
        }

        if (cpai != null)
        {
            context.registerService(ConditionalPermissionAdmin.class.getName(),
                cpai, null);
        }
    }

    public synchronized void stop(BundleContext context) throws Exception
    {
        ((Felix) context.getBundle(0)).setSecurityProvider(null);
    }

    private String getProperty(BundleContext context, String key,
        String defaultValue)
    {
        String result = context.getProperty(key);

        return (result != null) ? result : defaultValue;
    }
}
