// snf2check.cpp
//
// Copyright 2002-2004 MicroNeil Research Corporation.
//

// 20040502 _M - Completed testing. Digest checking rocks!

// 20040419 _M - Beginning modification to check an embedded digest of the entire
// rulebase file. The digest is embedded in a way that makes it backward compatible
// with all prior versions.

// This utility opens a Message Sniffer version 2 rule base file and authenticates
// the file. If the authentiaction fails then the utility returns a nonzero value.
// If the file autneticates correctly then the utility returns a zero value.
//
// This utility can be used to check that a download was performed properly so that
// corrupted rule base files won't be placed into service in a Message Sniffer engine.

#include <unistd.h>
#include <cstdio>
#include <cctype>
#include <ctime>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include "snf_engine.hpp"

using namespace std;    //introduces namespace std

const int RULEFILE_PARM = 1;        // Rule Base File Parameter.
const int AUTHENTICATION_PARM = 2;  // Parm position of authentication.
const int CORRECT_ARGS = 3;         // Correct number of command line args.


const int OK = 0;                   // OK result.
const int ERROR_CMDLINE = 65;       // Command line error result.
const int ERROR_RULE_FILE = 67;     // Rule file open error result.
const int ERROR_RULE_DATA = 68;     // Rule file authentication error result.
const int ERROR_RULE_AUTH = 73;     // Authentication failed on the rule base.
const int ERROR_BAD_MATRIX = 71;    // Something pushed us out of range.

//////////////////////////////////////////////////////////////////////////////////////////
// main()... well, that's where it all happens.

int main( int argc, char* argv[] ) {

  // Check the command line and set option flags.

  // First, are the right number of parameters present?
  // If not then remind the user of what the command line should look like.

  if(argc != CORRECT_ARGS) {

    cerr << "snf2check: Bad Command Line" << endl
         << endl
         << "use snf2check.exe rulefilepath authentication" << endl
         << endl
         << "Version 2 w/Mangler Digest Checking - build " 
         << __DATE__ << " " << __TIME__ << endl
         << endl
         << "Copyright (C) 2002-2008 MicroNeil Research Corporation"
         << endl;

    return ERROR_CMDLINE;
  }

  // Capture & rewrite path info...

  string RuleFileString(argv[RULEFILE_PARM]);         // Rule file path...
  string Authentication(argv[AUTHENTICATION_PARM]);   // Authentication...

  const int LicenseLength = 8;                        // License IDs are this long.

  string License(RuleFileString);                     // The license is in the rule file string.
  int LicensePosition = License.find_last_of("\\/");  // Find the license position.
  LicensePosition += 1;                               // Move past the stroke if present.
  string LicenseID(                                   // Extract the licenseID.
    License.substr(LicensePosition,LicenseLength));

  ///////////////////////////////////////////////////////////////////////////////////////
  // Load the RuleBase.
  ///////////////////////////////////////////////////////////////////////////////////////

  TokenMatrix RuleBase;               // Create the rule base object.

  try {
    RuleBase.Load(RuleFileString);
  }

  catch(TokenMatrix::BadAllocation) { // If we can't allocate memory report it.

    cerr << "snf2check: " << License << " ERROR_RULE_DATA!" << endl;
    return ERROR_RULE_DATA;
  }

  catch(...) { // If something else goes wrong report the following error...

    cerr << "snf2check: " << License << " ERROR_RULE_FILE!" << endl;
    return ERROR_RULE_FILE;
  }

  ///////////////////////////////////////////////////////////////////////////////////////
  // Validate the RuleBase is properly authenticated.
  ///////////////////////////////////////////////////////////////////////////////////////

                                                      // SecurityKey starts with
  string SecurityKey(LicenseID);                      // the License ID then we add
  SecurityKey += string(argv[AUTHENTICATION_PARM]);   // the authentication code.

  try {
    RuleBase.Validate(SecurityKey);
  }

  catch(...) { // If the validation fails then we produce this error...

    cerr << "snf2check: " << License << " ERROR_RULE_AUTH! " << endl;
    return ERROR_RULE_AUTH;
  }

  ///////////////////////////////////////////////////////////////////////////////////////
  // Verify the integrity of the RuleBase - this can only happen if Validated!
  ///////////////////////////////////////////////////////////////////////////////////////

  try {
    RuleBase.Verify(SecurityKey);
  }

  catch(...) { // If the verification process fails then we produce this error...
  
    cerr << "snf2check: " << License << " ERROR_BAD_MATRIX! " << endl;
    return ERROR_BAD_MATRIX;
  }

  // If we made it through all of that, then we're golden!

  return OK;
}


