// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed 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 adaptorlib;

import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.modules.SamlClient;

import com.sun.net.httpserver.HttpExchange;

import org.opensaml.DefaultBootstrap;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.security.SecurityHelper;
import org.opensaml.xml.security.credential.Credential;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

/**
 * A credentials gatherer that implements authentication by communicating with
 * the GSA's security manager via SAML. This class only sends the initial
 * request; the response is handled in {@link SamlAssertionConsumerHandler}.
 */
class AuthnHandler extends AbstractHandler {
  /** Manager that handles keeping track of users attempting to authenticate. */
  private final SessionManager<HttpExchange> sessionManager;
  /**
   * Http client implementation that {@code SamlClient} will use to send
   * requests directly to the GSA, for resolving SAML artifacts.
   */
  private final HttpClientInterface httpClient = new HttpClientAdapter();
  /** Credentials to use to sign messages. */
  private final Credential cred;
  private final SamlMetadata metadata;

  AuthnHandler(String fallbackHostname, Charset defaultEncoding,
               SessionManager<HttpExchange> sessionManager,
               String gsaHostname, String keyAlias, int localPort)
      throws IOException {
    super(fallbackHostname, defaultEncoding);
    this.sessionManager = sessionManager;

    cred = getCredential(keyAlias);

    try {
      DefaultBootstrap.bootstrap();
    } catch (ConfigurationException ex) {
      throw new RuntimeException(ex);
    }
    this.metadata = new SamlMetadata(fallbackHostname, localPort, gsaHostname);
  }

  @Override
  public void meteredHandle(HttpExchange ex) throws IOException {
    String requestMethod = ex.getRequestMethod();
    if (!"GET".equals(requestMethod) && !"HEAD".equals(requestMethod)) {
      cannedRespond(ex, HttpURLConnection.HTTP_BAD_METHOD, "text/plain",
          "Unsupported request method");
      return;
    }

    Session session = sessionManager.getSession(ex);
    AuthnState authnState = (AuthnState) session.getAttribute(
        AuthnState.SESSION_ATTR_NAME);
    if (authnState == null) {
      authnState = new AuthnState();
      session.setAttribute(AuthnState.SESSION_ATTR_NAME, authnState);
    }
    SamlClient client =
        new SamlClient(
            metadata.getLocalEntity(),
            metadata.getPeerEntity(),
            "GSA Adaptor",
            cred,
            httpClient);
    authnState.startAttempt(client, getRequestUri(ex));
    client.sendAuthnRequest(
        new adaptorlib.HttpExchangeOutTransportAdapter(ex, true));
  }

  /**
   * Create a {@code Credential} usable by OpenSAML by accessing the default
   * keystore. The key should have the same password as the keystore.
   */
  private static Credential getCredential(String alias) throws IOException {
    String keystoreFile = System.getProperty("javax.net.ssl.keyStore");
    if (keystoreFile == null) {
      throw new RuntimeException("You must provide a default keystore");
    }
    String keystoreType = System.getProperty("javax.net.ssl.trustStoreType",
                                             KeyStore.getDefaultType());

    PrivateKey privateKey;
    PublicKey publicKey;
    try {
      KeyStore ks = KeyStore.getInstance(keystoreType);
      InputStream ksis = new FileInputStream(keystoreFile);
      String keystorePasswordStr = System.getProperty(
          "javax.net.ssl.keyStorePassword");
      char[] keystorePassword = keystorePasswordStr == null ? null
          : keystorePasswordStr.toCharArray();
      try {
        ks.load(ksis, keystorePassword);
      } catch (NoSuchAlgorithmException ex) {
        throw new RuntimeException(ex);
      } catch (CertificateException ex) {
        throw new RuntimeException(ex);
      } finally {
        ksis.close();
      }
      Key key = null;
      try {
        key = ks.getKey(alias, keystorePassword);
      } catch (NoSuchAlgorithmException ex) {
        throw new RuntimeException(ex);
      } catch (UnrecoverableKeyException ex) {
        throw new RuntimeException(ex);
      }
      if (key == null) {
        throw new NullPointerException();
      }
      privateKey = (PrivateKey) key;
      publicKey = ks.getCertificate("adaptor").getPublicKey();
    } catch (KeyStoreException ex) {
      throw new RuntimeException(ex);
    }
    return SecurityHelper.getSimpleCredential(publicKey, privateKey);
  }
}
