/*
 * 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.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;

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.security.verifier.BundleDNParser;
import org.apache.felix.framework.util.SecureAction;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
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
{
    private SecurityProviderImpl m_provider = null;
    private PropertiesCache m_dnsCache = null;
    private PropertiesCache m_localCache = null;
    private LocalPermissions m_localPermissions = null;

    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");
            }
            File localCache = 
                context.getDataFile("security" + File.separator + "local.txt");
            if ((localCache == null) || (!localCache.isFile() && !localCache.createNewFile()))
            {
                throw new IOException("Can't create cache file");
            }
            
            m_localCache = new PropertiesCache(localCache, tmp, action);
            m_localPermissions  = new LocalPermissions(permissions, m_localCache);
            
            cpai =
                new ConditionalPermissionAdminImpl(permissions, new Conditions(
                    action), m_localPermissions,
                    new PropertiesCache(cpaCache, tmp, action));
        }

        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);

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

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

            m_provider =
                new SecurityProviderImpl(crlList, typeList, passwdList,
                    storeList, pai, cpai, action);

            File cache =
                context.getDataFile("security" + File.separator + "dns.txt");
            if ((cache == null) || (!cache.isFile() && !cache.createNewFile()))
            {
                throw new IOException("Can't create cache file");
            }
            m_dnsCache = new PropertiesCache(cache, tmp, action);

            Map store = m_dnsCache.read(String[].class);

            if (store != null)
            {
                BundleDNParser parser = m_provider.getParser();

                for (Iterator iter = store.entrySet().iterator(); iter
                    .hasNext();)
                {
                    Entry entry = (Entry) iter.next();
                    String[] value = (String[]) entry.getValue();
                    if ("none".equals(value[0]))
                    {
                        parser.put((String) entry.getKey(), null);
                    }
                    else if ("invalid".equals(value[0]))
                    {
                        parser.put((String) entry.getKey(), new String[0]);
                    }
                    else
                    {
                        parser.put((String) entry.getKey(), value);
                    }
                }
            }
            ((Felix) context.getBundle(0)).setSecurityProvider(m_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
    {
        if (m_provider != null)
        {
            m_dnsCache.write(write(m_provider.getParser().getCache(), context));
        }
        if (m_localPermissions != null)
        {
           m_localCache.write(write(m_localPermissions.getStore(), context));
        }
        m_provider = null;
        m_dnsCache = null;
        m_localPermissions = null;
    }

    private Map write(Map cache, BundleContext context)
    {
        // Filter the cached dn chains and only store the latest for each 
        // bundle. This is ok because the framework will prune old revisions
        // after a restart. The format is <id>-<timestamp>
        Map store = new HashMap();
        Map index = new HashMap();
        for (Iterator iter = cache.entrySet().iterator(); iter.hasNext();)
        {
            Entry entry = (Entry) iter.next();
            
            String key = (String) entry.getKey();
            String id = key.substring(0, key.indexOf("-"));
            String time = key.substring(key.indexOf("-") + 1);
            Bundle bundle = context.getBundle(Long.parseLong(id));
            long timeLong = Long.parseLong(time);
            if ((bundle == null) || 
                ((FelixBundle) bundle).getInfo().getLastModified() > timeLong)
            {
                continue;
            }
            String last = (String) index.get(id);

            if ((last == null)
                || (Long.parseLong(last) < timeLong))
            {
                index.put(id, time);
                Object[] dns = (Object[]) entry.getValue();
                store.remove(id + "-" + last);
                if ((dns != null) && (dns.length > 0))
                {
                    store.put(key, dns);
                }
                else
                {
                    store.put(key, (dns == null) ? new String[] {"none"} : new String[] {"invalid"});
                }
            }
        }
        return store;
    }

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

        return ((result != null) && (result.trim().length() > 0)) ? result
            : defaultValue;
    }
}
