/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013, Regents of the University of California
 *                     Yingdi Yu
 *
 * BSD license, See the LICENSE file for more information
 *
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 */

#include "validator-invitation.h"
#include "invitation.h"

#include "logging.h"

using namespace std;
using namespace ndn;

INIT_LOGGER("ValidatorInvitation");

namespace chronos{

const shared_ptr<CertificateCache> ValidatorInvitation::DefaultCertificateCache = shared_ptr<CertificateCache>();

ValidatorInvitation::ValidatorInvitation()
  : Validator()
  , m_invitationReplyRule("^([^<CHRONOCHAT-INVITATION>]*)<CHRONOCHAT-INVITATION>", 
                          "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$", 
                          "==", "\\1", "\\1\\2", true)
  , m_invitationInterestRule("^[^<CHRONOCHAT-INVITATION>]*<CHRONOCHAT-INVITATION><>{6}$")
  , m_innerKeyRegex("^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT><>$", "\\1\\2")
{
}

void
ValidatorInvitation::checkPolicy (const Data& data, 
                                  int stepCount, 
                                  const OnDataValidated& onValidated, 
                                  const OnDataValidationFailed& onValidationFailed,
                                  vector<shared_ptr<ValidationRequest> >& nextSteps)
{
  try
    {
      SignatureSha256WithRsa sig(data.getSignature());    
      const Name & keyLocatorName = sig.getKeyLocator().getName();
      
      if(!m_invitationReplyRule.satisfy(data.getName(), keyLocatorName))
        return onValidationFailed(data.shared_from_this(),
                                  "Does not comply with the invitation rule: "
                                  + data.getName().toUri() + " signed by: "
                                  + keyLocatorName.toUri());

      Data innerData;
      innerData.wireDecode(data.getContent().blockFromValue());
      
      return internalCheck(data.wireEncode().wire(), 
                           data.wireEncode().size(),
                           sig,
                           innerData,
                           bind(onValidated, data.shared_from_this()), 
                           bind(onValidationFailed, data.shared_from_this(), _1));
    }
   catch(SignatureSha256WithRsa::Error &e)
     {
       return onValidationFailed(data.shared_from_this(), 
                                 "Not SignatureSha256WithRsa signature: " + data.getName().toUri());
     }
}

void
ValidatorInvitation::checkPolicy (const Interest& interest, 
                                  int stepCount, 
                                  const OnInterestValidated& onValidated, 
                                  const OnInterestValidationFailed& onValidationFailed,
                                  vector<shared_ptr<ValidationRequest> >& nextSteps)
{
  try
    {
      Name interestName  = interest.getName();
      
      if(!m_invitationInterestRule.match(interestName))
        return onValidationFailed(interest.shared_from_this(), 
                                  "Invalid interest name: " +  interest.getName().toUri());

      Name signedName = interestName.getPrefix(-1);
      Buffer signedBlob = Buffer(signedName.wireEncode().value(), signedName.wireEncode().value_size());

      Block signatureBlock = interestName.get(Invitation::SIGNATURE).blockFromValue();
      Block signatureInfo = interestName.get(Invitation::KEY_LOCATOR).blockFromValue();
      Signature signature(signatureInfo, signatureBlock);
      SignatureSha256WithRsa sig(signature);

      Data innerData;
      innerData.wireDecode(interestName.get(Invitation::INVITER_CERT).blockFromValue());

      return internalCheck(signedBlob.buf(), 
                           signedBlob.size(),
                           sig,
                           innerData,
                           bind(onValidated, interest.shared_from_this()), 
                           bind(onValidationFailed, interest.shared_from_this(), _1));
    }
  catch(SignatureSha256WithRsa::Error& e)
    {
      return onValidationFailed(interest.shared_from_this(), 
                                "Not SignatureSha256WithRsa signature: " + interest.getName().toUri());
    }
}

void
ValidatorInvitation::internalCheck(const uint8_t* buf, size_t size,
                                   const SignatureSha256WithRsa& sig,
                                   const Data& innerData,
                                   const OnValidated& onValidated, 
                                   const OnValidationFailed& onValidationFailed)
{
  try
    {
      const Name & keyLocatorName = sig.getKeyLocator().getName();
      Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
      
      if(m_trustAnchors.find(signingKeyName) == m_trustAnchors.end())
        return onValidationFailed("Cannot reach any trust anchor");

      if(!Validator::verifySignature(buf, size, sig, m_trustAnchors[signingKeyName]))
        return onValidationFailed("Cannot verify interest signature");

      if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
        return onValidationFailed("Cannot verify interest signature");

      if(!m_innerKeyRegex.match(innerData.getName())
          || m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))
         return onValidationFailed("Inner certificate does not comply with the rule");

      return onValidated();
    }
  catch(KeyLocator::Error& e)
    {
      return onValidationFailed("Key Locator is not a name");
    }
}


}//chronos
