/*
 * 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.geode.security.generator;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.logging.log4j.Logger;

import org.apache.geode.cache.operations.OperationContext.OperationCode;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.security.AccessControl;
import org.apache.geode.security.templates.DummyAuthorization;
import org.apache.geode.security.templates.XmlAuthorization;

/**
 * Encapsulates obtaining authorized and unauthorized credentials for a given operation in a region.
 * Implementations will be for different kinds of authorization scheme and authentication scheme
 * combos.
 *
 * @since GemFire 5.5
 */
public abstract class AuthzCredentialGenerator {

  private static final Logger logger = LogService.getLogger();

  /**
   * The {@link CredentialGenerator} being used.
   */
  protected CredentialGenerator generator;

  /**
   * A set of system properties that should be added to the gemfire system properties before using
   * the authorization module.
   */
  private Properties systemProperties;

  /**
   * A factory method to create a new instance of an {@link AuthzCredentialGenerator} for the given
   * {@link ClassCode}. Caller is supposed to invoke {@link AuthzCredentialGenerator#init}
   * immediately after obtaining the instance.
   *
   * @param classCode the {@code ClassCode} of the {@code AuthzCredentialGenerator} implementation
   *
   * @return an instance of {@code AuthzCredentialGenerator} for the given class code
   */
  public static AuthzCredentialGenerator create(final ClassCode classCode) {
    switch (classCode.classType) {
      case ClassCode.ID_DUMMY:
        return new DummyAuthzCredentialGenerator();
      case ClassCode.ID_XML:
        return new XmlAuthzCredentialGenerator();
      default:
        return null;
    }
  }

  /**
   * Initialize the authorized credential generator.
   *
   * @param generator an instance of {@link CredentialGenerator} of the credential implementation
   *        for which to obtain authorized/unauthorized credentials.
   *
   * @return false when the given {@link CredentialGenerator} is incompatible with this
   *         authorization module.
   */
  public boolean init(final CredentialGenerator generator) {
    this.generator = generator;
    try {
      this.systemProperties = init();
    } catch (IllegalArgumentException ex) {
      return false;
    }
    return true;
  }

  /**
   *
   * @return A set of extra properties that should be added to Gemfire system properties when not
   *         null.
   */
  public Properties getSystemProperties() {
    return this.systemProperties;
  }

  /**
   * Get the {@link CredentialGenerator} being used by this instance.
   */
  public CredentialGenerator getCredentialGenerator() {
    return this.generator;
  }

  /**
   * Initialize the authorized credential generator.
   *
   * Required to be implemented by concrete classes that implement this abstract class.
   *
   * @return A set of extra properties that should be added to Gemfire system properties when not
   *         null.
   *
   * @throws IllegalArgumentException when the {@link CredentialGenerator} is incompatible with this
   *         authorization module.
   */
  protected abstract Properties init() throws IllegalArgumentException;

  /**
   * The {@link ClassCode} of the particular implementation.
   *
   * @return the {@code ClassCode}
   */
  public abstract ClassCode classCode();

  /**
   * The name of the {@link AccessControl} factory function that should be used as the authorization
   * module on the server side.
   *
   * @return name of the {@code AccessControl} factory function
   */
  public abstract String getAuthorizationCallback();

  /**
   * Get a set of credentials generated using the given index allowed to perform the given
   * {@link OperationCode}s for the given regions.
   *
   * @param opCodes the list of {@link OperationCode}s of the operations requiring authorization;
   *        should not be null
   * @param regionNames list of the region names requiring authorization; a value of null indicates
   *        all regions
   * @param index used to generate multiple such credentials by passing different values for this
   *
   * @return the set of credentials authorized to perform the given operation in the given regions
   */
  public Properties getAllowedCredentials(final OperationCode[] opCodes, final String[] regionNames,
      final int index) {
    int numTries = getNumPrincipalTries(opCodes, regionNames);
    if (numTries <= 0) {
      numTries = 1;
    }

    for (int tries = 0; tries < numTries; tries++) {
      final Principal principal =
          getAllowedPrincipal(opCodes, regionNames, (index + tries) % numTries);
      try {
        return this.generator.getValidCredentials(principal);
      } catch (IllegalArgumentException ex) {
      }
    }
    return null;
  }

  /**
   * Get a set of credentials generated using the given index not allowed to perform the given
   * {@link OperationCode}s for the given regions. The credentials are required to be valid for
   * authentication.
   *
   * @param opCodes the {@link OperationCode}s of the operations requiring authorization failure;
   *        should not be null
   * @param regionNames list of the region names requiring authorization failure; a value of null
   *        indicates all regions
   * @param index used to generate multiple such credentials by passing different values for this
   *
   * @return the set of credentials that are not authorized to perform the given operation in the
   *         given region
   */
  public Properties getDisallowedCredentials(final OperationCode[] opCodes,
      final String[] regionNames, final int index) {
    // This may not be very correct since we use the value of
    // getNumPrincipalTries() but is used to avoid adding another method.
    // Also something like getNumDisallowedPrincipals() will be normally always
    // infinite, and the number here is just to perform some number of tries
    // before giving up.

    int numTries = getNumPrincipalTries(opCodes, regionNames);
    if (numTries <= 0) {
      numTries = 1;
    }

    for (int tries = 0; tries < numTries; tries++) {
      final Principal principal =
          getDisallowedPrincipal(opCodes, regionNames, (index + tries) % numTries);
      try {
        return this.generator.getValidCredentials(principal);
      } catch (IllegalArgumentException ex) {
      }
    }
    return null;
  }

  /**
   * Get the number of tries to be done for obtaining valid credentials for the given operations in
   * the given region. It is required that {@link #getAllowedPrincipal} method returns valid
   * principals for values of {@code index} from 0 through (n-1) where {@code n} is the value
   * returned by this method. It is recommended that the principals so returned be unique for
   * efficiency.
   *
   * This will be used by {@link #getAllowedCredentials} to step through different principals and
   * obtain a set of valid credentials.
   *
   * Required to be implemented by concrete classes that implement this abstract class.
   *
   * @param opCodes the {@link OperationCode}s of the operations requiring authorization
   * @param regionNames list of the region names requiring authorization; a value of null indicates
   *        all regions
   *
   * @return the number of principals allowed to perform the given operation in the given region
   */
  protected abstract int getNumPrincipalTries(final OperationCode[] opCodes,
      final String[] regionNames);

  /**
   * Get a {@link Principal} generated using the given index allowed to perform the given
   * {@link OperationCode}s for the given region.
   *
   * Required to be implemented by concrete classes that implement this abstract class.
   *
   * @param opCodes the {@link OperationCode}s of the operations requiring authorization
   * @param regionNames list of the region names requiring authorization; a value of null indicates
   *        all regions
   * @param index used to generate multiple such principals by passing different values for this
   *
   * @return the {@link Principal} authorized to perform the given operation in the given region
   */
  protected abstract Principal getAllowedPrincipal(final OperationCode[] opCodes,
      final String[] regionNames, final int index);

  /**
   * Get a {@link Principal} generated using the given index not allowed to perform the given
   * {@link OperationCode}s for the given region.
   *
   * Required to be implemented by concrete classes that implement this abstract class.
   *
   * @param opCodes the {@link OperationCode}s of the operations requiring authorization failure
   * @param regionNames list of the region names requiring authorization failure; a value of null
   *        indicates all regions
   * @param index used to generate multiple such principals by passing different values for this
   *
   * @return a {@link Principal} not authorized to perform the given operation in the given region
   */
  protected abstract Principal getDisallowedPrincipal(final OperationCode[] opCodes,
      final String[] regionNames, final int index);

  /**
   * Enumeration for various {@link AuthzCredentialGenerator} implementations.
   *
   * <p>
   * The following schemes are supported as of now:
   * <ul>
   * <li>{@code DummyAuthorization} with {@code DummyAuthenticator}</li>
   * <li>{@code XMLAuthorization} with {@code DummyAuthenticator}</li>
   * <li>{@code XMLAuthorization} with {@code LDAPAuthenticator}</li>
   * <li>{@code XMLAuthorization} with {@code PKCSAuthenticator}</li>
   * <li>{@code XMLAuthorization} when using SSL sockets</li>
   * </ul>
   *
   * <p>
   * To add a new authorization scheme the following needs to be done:
   * <ul>
   * <li>Add implementation for {@link AccessControl}.</li>
   * <li>Choose the authentication schemes that it shall work with from
   * {@link CredentialGenerator.ClassCode}</li>
   * <li>Add a new enumeration value for the scheme in this class. Notice the size of {@code VALUES}
   * array and increase that if it is getting overflowed. Note the methods and fields for existing
   * schemes and add for the new one in a similar manner.</li>
   * <li>Add an implementation for {@link AuthzCredentialGenerator}. Note the
   * {@link AuthzCredentialGenerator#init} method where different authentication schemes can be
   * passed and initialize differently for the authentication schemes that shall be handled.</li>
   * <li>Modify the {@link AuthzCredentialGenerator#create} method to add creation of an instance of
   * the new implementation for the {@code ClassCode} enumeration value.</li>
   * </ul>
   *
   * <p>
   * All dunit tests will automagically start testing the new implementation after this.
   *
   * @since GemFire 5.5
   */
  public static class ClassCode {

    private static byte nextOrdinal = 0;

    private static final byte ID_DUMMY = 1;
    private static final byte ID_XML = 2;

    private static final ClassCode[] VALUES = new ClassCode[10];
    private static final Map CODE_NAME_MAP = new HashMap();

    public static final ClassCode DUMMY =
        new ClassCode(DummyAuthorization.class.getName() + ".create", ID_DUMMY);
    public static final ClassCode XML =
        new ClassCode(XmlAuthorization.class.getName() + ".create", ID_XML);

    /** The name of this class. */
    private final String name;

    /** byte used as ordinal to represent this class */
    private final byte ordinal;

    /**
     * One of the following: ID_DUMMY, ID_LDAP, ID_PKI
     */
    private final byte classType;

    /** Creates a new instance of class code. */
    private ClassCode(final String name, final byte classType) {
      this.name = name;
      this.classType = classType;
      this.ordinal = nextOrdinal++;
      VALUES[this.ordinal] = this;
      CODE_NAME_MAP.put(name, this);
    }

    public boolean isDummy() {
      return this.classType == ID_DUMMY;
    }

    public boolean isXml() {
      return this.classType == ID_XML;
    }

    /**
     * Returns the {@code ClassCode} represented by specified ordinal.
     */
    public static ClassCode fromOrdinal(final byte ordinal) {
      return VALUES[ordinal];
    }

    /**
     * Returns the {@code ClassCode} represented by specified string.
     */
    public static ClassCode parse(final String operationName) {
      return (ClassCode) CODE_NAME_MAP.get(operationName);
    }

    /**
     * Returns all the possible values.
     */
    public static List getAll() {
      final List codes = new ArrayList();
      for (Iterator iter = CODE_NAME_MAP.values().iterator(); iter.hasNext();) {
        codes.add(iter.next());
      }
      return codes;
    }

    /**
     * Returns the ordinal for this class code.
     *
     * @return the ordinal of this class code.
     */
    public byte toOrdinal() {
      return this.ordinal;
    }

    /**
     * Returns a string representation for this class code.
     *
     * @return the name of this class code.
     */
    @Override
    public String toString() {
      return this.name;
    }

    /**
     * Indicates whether other object is same as this one.
     *
     * @return true if other object is same as this one.
     */
    @Override
    public boolean equals(final Object obj) {
      if (obj == this) {
        return true;
      }
      if (!(obj instanceof ClassCode)) {
        return false;
      }
      final ClassCode other = (ClassCode) obj;
      return other.ordinal == this.ordinal;
    }

    /**
     * Indicates whether other {@code ClassCode} is same as this one.
     *
     * @return true if other {@code ClassCode} is same as this one.
     */
    public boolean equals(final ClassCode opCode) {
      return opCode != null && opCode.ordinal == this.ordinal;
    }

    /**
     * Returns a hash code value for this {@code ClassCode} which is the same as its ordinal.
     *
     * @return the ordinal of this {@code ClassCode}.
     */
    @Override
    public int hashCode() {
      return this.ordinal;
    }
  }
}
