#if !defined(__alffx509_h) // Sentry, use file only if it's not already included.
#define __alffx509_h
/*  Project Biblio-Tec

	 SUBSYSTEM:    TECSecurity.dll Library
	 FILE:         alffx509.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:
	 Source file for definition of
         ALFFCertificateExpiredException,
         ALFFCertificateNotYetValidException,
         ALFFCertificateEncodingException,
         ALFFX509Oid,
         ALFFX509Name,
         ALFFX509Names,
         ALFFX509AuthorityInfo,
         ALFFX509AlternativeNames,
         ALFFX509UserNotice,
         ALFFX509PolicyQualifier,
         ALFFX509CertificatePolicy,
         ALFFX509CertificatePolicies,
         ALFFX509NameEntry,
         ALFFX509NameEntries,
         ALFFX509DistPointName,
         ALFFX509CRLDistPoint,
         ALFFX509CRLDistPoints,
         ALFFX509PKeyUsagePeriod,
         ALFFX509AuthKeyId,
         ALFFX509SubjectKeyId,
         ALFFX509BasicConstraints,
         ALFFX509NetscapeCertType,
         ALFFX509NetscapeOther,
         ALFFX509Extension,
         ALFFX509Extensions,
         ALFFX509Algorithm,
         ALFFX509PublicKey,
         ALFFX509KeyUsage,
         ALFFX509ExtKeyUsage,
         ALFFX509Certificate  and
         ALFFX509Certificates

	 (Classes for accessing all attributes and extensions of an X509 Certificate)
    Uses OpenSSL (SSL API) (www.openssl.org).

    COPYRIGHT:    © 2003,2005
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Biblio-Tec license (BiblTec.txt)
*/

//General Settings for TEC Libraries
#include "teclibs.h"

// ALFFLib classes
#include "alffutil.h"
#include "alffobj.h"
#include "alffexpt.h"

// ALFFSSLib classes
#include "alffx509object.h"
#include "alffusesecurity.h"
#include "alffsslcomm.h"

// OpenSSL includes
#include <openssl/x509.h>
#include <openssl/x509v3.h>

#define HEXLINELENGTH 18

#ifdef X509_CERT_DIR
#undef X509_CERT_DIR
#endif
#define X509_CERT_DIR "security/trustedCAs"

class _TECSECCLASS
ALFFCertificateExpiredException: ALFFException
{
 public:
  ALFFCertificateExpiredException();
  ~ALFFCertificateExpiredException();
};

class _TECSECCLASS
ALFFCertificateNotYetValidException: ALFFException
{
 public:
  ALFFCertificateNotYetValidException();
  ~ALFFCertificateNotYetValidException();
};

class _TECSECCLASS
ALFFCertificateEncodingException: ALFFException
{
 public:
  ALFFCertificateEncodingException();
  ~ALFFCertificateEncodingException();
};


class ALFFX509Certificate;
class ALFFX509Extension;


/* OpenSSL  *NID* */
class _TECSECCLASS ALFFX509Oid  : public ALFFX509Object
{
  public:

   enum X509OID
    {
      OID_None                         = -1,
      // X509 V3 Extensions  //OBJ_id_ce (2.5.29)
      OID_subject_key_id					=NID_subject_key_identifier,    //OBJ_id_ce,14L
		OID_key_usage 		  					=NID_key_usage,                 //OBJ_id_ce,15L
		OID_priv_key_usage_per				=NID_private_key_usage_period,  //OBJ_id_ce,16L
      OID_subject_alt_name					=NID_subject_alt_name,          //OBJ_id_ce,17L
      OID_issuer_alt_name					=NID_issuer_alt_name,           //OBJ_id_ce,18L
      OID_basic_constraints				=NID_basic_constraints,         //OBJ_id_ce,19L
      OID_crl_number							=NID_crl_number,                //OBJ_id_ce,20L
      OID_crl_reason							=NID_crl_reason,                //OBJ_id_ce,21L
      OID_invalidity_date					=NID_invalidity_date,           //OBJ_id_ce,24L
      OID_delta_crl							=NID_delta_crl,                 //OBJ_id_ce,27L
//      OID_name_constraints,            =NID_undef,                 //????OBJ_id_ce,30L
      OID_crl_dist_points					=NID_crl_distribution_points,   //OBJ_id_ce,31L
      OID_certificate_policies			=NID_certificate_policies,      //OBJ_id_ce,32L
      OID_authority_key_id					=NID_authority_key_identifier,  //OBJ_id_ce,35L
      OID_policy_constraints           =NID_policy_constraints,        //OBJ_id_ce,36L
      OID_extended_key_usage				=NID_ext_key_usage,             //OBJ_id_ce,37L

      /* X509 V3 Private Extensions */
      /* Authority information access */
      OID_info_access						=NID_info_access,					  //OBJ_id_pe,1L

      /* Netscape Extensions */
      OID_netscape_cert_type				=NID_netscape_cert_type,        //OBJ_netscape_cert_extension,1L
      OID_netscape_base_url				=NID_netscape_base_url,         //OBJ_netscape_cert_extension,2L
      OID_netscape_revocation_url		=NID_netscape_revocation_url,   //OBJ_netscape_cert_extension,3L
      OID_netscape_ca_revocation_url	=NID_netscape_ca_revocation_url,//OBJ_netscape_cert_extension,4L
      OID_netscape_renewal_url			=NID_netscape_renewal_url,      //OBJ_netscape_cert_extension,7L
      OID_netscape_ca_policy_url			=NID_netscape_ca_policy_url,    //OBJ_netscape_cert_extension,8L
      OID_netscape_ssl_server_name		=NID_netscape_ssl_server_name,  //OBJ_netscape_cert_extension,12L
      OID_netscape_comment					=NID_netscape_comment,          //OBJ_netscape_cert_extension,13L

      /* Extended Key Usages */
      OID_server_auth						=NID_server_auth,
      OID_client_auth						=NID_client_auth,
      OID_code_sign							=NID_code_sign,
      OID_email_protect						=NID_email_protect,
      OID_time_stamp							=NID_time_stamp,
      OID_OCSP_sign							=NID_OCSP_sign,

      /*  Certificate Signature and Hash code Algorithms  */
      OID_sha1                         =NID_sha1,
      OID_sha1WithRSAEncryption        =NID_sha1WithRSAEncryption,
      OID_md5									=NID_md5,
      OID_md5WithRSAEncryption         =NID_md5WithRSAEncryption,

      /* RFC822 Mail Box Names  */
      OID_rfc822Mailbox                =NID_rfc822Mailbox,

      /* DNS Domain Name */
      OID_dNSDomain							=NID_dNSDomain,

      /* Directory Name */
      OID_Directory							=NID_Directory,
    };

    ALFFX509Oid();  // Default Constructor
 	 ALFFX509Oid(X509OID oidNum);
    ALFFX509Oid(ASN1_OBJECT * oidObject);
 	 ~ALFFX509Oid();
    char far* GetClassName() {return "ALFFX509Oid";}

    bool IsPresent()  { return present; }

    bool     SetOid(ALFFX509Oid* x509Oid);
    bool     SetOid(X509OID oidNum);
    bool     SetDottedId(string dotId);
    string   getLongName();
    string   getShortName();
    string   getDottedId();
    X509OID  getId();
    int      getResId();

  protected:
    string longName;
    string shortName;
    string dottedId;
    bool   present;
    X509OID oid;
};

/*  -------------------------------------------------------- *
 *  typedef struct asn1_type_st
 *  	{
 *  	int type;
 *  	union	{
 *  		char *ptr;
 *  		ASN1_BOOLEAN		boolean;
 *  		ASN1_STRING *		asn1_string;
 *  		ASN1_OBJECT *		object;
 *  		ASN1_INTEGER *		integer;
 *  		ASN1_ENUMERATED *	enumerated;
 *  		ASN1_BIT_STRING *	bit_string;
 *  		ASN1_OCTET_STRING *	octet_string;
 *  		ASN1_PRINTABLESTRING *	printablestring;
 *  		ASN1_T61STRING *	t61string;
 *  		ASN1_IA5STRING *	ia5string;
 *  		ASN1_GENERALSTRING *	generalstring;
 *  		ASN1_BMPSTRING *	bmpstring;
 *  		ASN1_UNIVERSALSTRING *	universalstring;
 *  		ASN1_UTCTIME *		utctime;
 *  		ASN1_GENERALIZEDTIME *	generalizedtime;
 *  		ASN1_VISIBLESTRING *	visiblestring;
 *  		ASN1_UTF8STRING *	utf8string;
 *  		// set and sequence are left complete and still
 *  		// * contain the set or sequence bytes
 *  		ASN1_STRING *		set;
 *  		ASN1_STRING *		sequence;
 *  		} value;
 *  	} ASN1_TYPE;
 *  -------------------------------------------------------- *
 *  typedef struct asn1_object_st
 *  	{
 *  	const char *sn,*ln;
 *  	int nid;
 *  	int length;
 *  	unsigned char *data;
 *  	int flags;	// Should we free this one *
 *  	} ASN1_OBJECT;
 *
 *  -------------------------------------------------------- *
 *  typedef struct asn1_string_st
 *  	{
 *  	int length;
 *  	int type;
 *  	unsigned char *data;
 *  	 * The value of the following field depends on the type being
 *  	 * held.  It is mostly being used for BIT_STRING so if the
 *  	 * input data has a non-zero 'unused bits' value, it will be
 *  	 * handled correctly
 *  	long flags;
 *  	} ASN1_STRING;
 *
 *  -------------------------------------------------------- *
 *  typedef struct asn1_object_st
 *  	{
 *  	const char *sn,*ln;
 *  	int nid;
 *  	int length;
 *  	unsigned char *data;
 *  	int flags;	// Should we free this one
 *  	} ASN1_OBJECT;
 *
 *  -------------------------------------------------------- *
 *  typedef struct otherName_st {
 *  ASN1_OBJECT *type_id;
 *  ASN1_TYPE *value;
 *  } OTHERNAME;
 *
 *  -------------------------------------------------------- *
 *  typedef struct X509_name_entry_st
 *  	{
 *  	ASN1_OBJECT *object;
 *  	ASN1_STRING *value;
 *  	int set;
 *  	int size; 	// temp variable
 *  	} X509_NAME_ENTRY;
 *
 *  -------------------------------------------------------- *
 *  struct X509_name_st
 *  	{
 *  	STACK_OF(X509_NAME_ENTRY) *entries;
 *  	int modified;	// true if 'bytes' needs to be built
 *  #ifndef OPENSSL_NO_BUFFER
 *  	BUF_MEM *bytes;
 *  #else
 *  	char *bytes;
 *  #endif
 *  	unsigned long hash; // Keep the hash around for lookups
 *  	} // X509_NAME ;
 *
 *  -------------------------------------------------------- *
 *  typedef struct EDIPartyName_st {
 *  	ASN1_STRING *nameAssigner;
 *  	ASN1_STRING *partyName;
 *  } EDIPARTYNAME;
 *
 *  -------------------------------------------------------- *
 *      typedef struct GENERAL_NAME_st {
 *  		#define GEN_OTHERNAME	0
 *  		#define GEN_EMAIL	1
 *  		#define GEN_DNS		2
 *  		#define GEN_X400	3
 *  		#define GEN_DIRNAME	4
 *  		#define GEN_EDIPARTY	5
 *  		#define GEN_URI		6
 *  		#define GEN_IPADD	7
 *  		#define GEN_RID		8
 *
 *        /// Openssl Types ///
 *        #define ASN1_IA5STRING		ASN1_STRING
 *        #define ASN1_OCTET_STRING	ASN1_STRING
 *
 *  		int type;
 *  		union {
 *  			char *ptr;
 *  			OTHERNAME *otherName;    // otherName
 *  			ASN1_IA5STRING *rfc822Name;
 *  			ASN1_IA5STRING *dNSName;
 *  			ASN1_TYPE *x400Address;
 *  			X509_NAME *directoryName;
 *  			EDIPARTYNAME *ediPartyName;
 *  			ASN1_IA5STRING *uniformResourceIdentifier;
 *  			ASN1_OCTET_STRING *iPAddress;
 *  			ASN1_OBJECT *registeredID;
 *
 *  			// Old names
 *  			ASN1_OCTET_STRING *ip; //* iPAddress
 *  			X509_NAME *dirn;		  //* dirn
 *  			ASN1_IA5STRING *ia5;   //* rfc822Name, dNSName,
 *                                     uniformResourceIdentifier
 *  			ASN1_OBJECT *rid;      //* registeredID
 *  			ASN1_TYPE *other;      //* x400Address
 *  			} d;
 *  	} GENERAL_NAME;
 *  -------------------------------------------------------- *
*/
class _TECSECCLASS ALFFX509Name : public ALFFX509Object   //GENERAL_NAME
{
  public:
    ALFFX509Name(GENERAL_NAME* gName);
    ~ALFFX509Name();
    char far* GetClassName() {return "ALFFX509Name";}

    enum   ALFFX509NameType{
           ALFFX509_OTHERNAME = GEN_OTHERNAME,
           ALFFX509_EMAIL     = GEN_EMAIL,
           ALFFX509_DNS       = GEN_DNS,
           ALFFX509_X400      = GEN_X400,
           ALFFX509_DIRNAME   = GEN_DIRNAME,
           ALFFX509_EDIPARTY  = GEN_EDIPARTY,
           ALFFX509_URI       = GEN_URI,
           ALFFX509_IPADD     = GEN_IPADD,
           ALFFX509_RID       = GEN_RID };

    ALFFX509Oid* getOID() {return oid; }
    int 	  getType();
    int    getTypeResource();
    const char* 	getValue();
    const char*  getValueNoId();
    string getValueEntries(char* separator);

  protected:
    ALFFX509Oid*   oid;
    int    nameType;
    int    nameTypeResource;
    char*  nameValue;
    string nameValueNoId;
};

/*
	typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
*/
class _TECSECCLASS ALFFX509Names : public ALFFX509Object //GENERAL_NAMES
 {
   public:
 	 ALFFX509Names(GENERAL_NAMES* gNames);
 	 ~ALFFX509Names();
    char far* GetClassName() {return "ALFFX509Names";}

    ALFFX509Name* getName(int index);
    int           getCount() {return nameCount;}
    bool          IsPresent();

   protected:
    GENERAL_NAMES* generalNames;
    ALFFX509Name*  x509Name;
    int nameCount;
    bool present;
 };

/*
 *  typedef struct ACCESS_DESCRIPTION_st {
 *			ASN1_OBJECT *method;
 *			GENERAL_NAME *location;
 * 	} ACCESS_DESCRIPTION;
 *
 *  typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
 */
class  _TECSECCLASS ALFFX509AuthorityInfo : public ALFFX509Object  //AUTHORITY_INFO_ACCESS
{
  public:

  	ALFFX509AuthorityInfo(AUTHORITY_INFO_ACCESS* infoAccess, bool crit);
  	~ALFFX509AuthorityInfo();
   char far* GetClassName() {return "ALFFX509AuthorityInfo";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   int            getInfoCount() {return infoCount;}
   ALFFX509Name*  getLocation(int index);
   ALFFX509Oid*   getMethod(int index);

  protected:
   AUTHORITY_INFO_ACCESS* authInfoAccess;
   int            infoCount;
   ALFFX509Name*  infoLocation;
   ALFFX509Oid*   infoMethod;

   /* Extension info */
   ALFFX509Oid*   oid;
   bool           present;
   bool           critical;
};

/*
 * Subject Alternative Name  or
 * Issuer  Alternative Name Extensions
 * (RFC 2459 - 4.2.1.7  Subject Alternative Name
 *           - 4.2.1.8  Issuer Alternative Names)
 *
 *	typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
 */
class _TECSECCLASS ALFFX509AlternativeNames : public ALFFX509Object
{
  public:
  	ALFFX509AlternativeNames(GENERAL_NAMES* gNames, ALFFX509Oid::X509OID nameOid, bool crit);
  	~ALFFX509AlternativeNames();
   char far* GetClassName() {return "ALFFX509AlternativeNames";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   int            getCount() {return altNameCount;}
   ALFFX509Name*  getAltName(int index);

  protected:
   GENERAL_NAMES* generalNames;
   ALFFX509Name*  x509Name;
   int 				altNameCount;

   /* Extension info */
   ALFFX509Oid*   oid;
   bool           present;
   bool           critical;
};

/*
 *	typedef struct NOTICEREF_st {
 *			ASN1_STRING *organization;
 *			STACK_OF(ASN1_INTEGER) *noticenos;
 *		} NOTICEREF;
 *
 *	typedef struct USERNOTICE_st {
 *			NOTICEREF *noticeref;
 *			ASN1_STRING *exptext;
 *		} USERNOTICE;
 */
class  _TECSECCLASS ALFFX509UserNotice : public ALFFX509Object  //USERNOTICE
{
  public:
#define NOTICEREFMAXNUM    32
  	ALFFX509UserNotice(USERNOTICE* userNot);
  	~ALFFX509UserNotice();
   char far* GetClassName() {return "ALFFX509UserNotice";}

   bool                      HasNoticeRef();
   bool                      HasExpText();
   string                    getNoticeRefOrg();
   int                       getNoticeRefNumCount();
   long                      getNoticeRefNum(int index);
   string                    getExpText();

  protected:
    USERNOTICE*   userNotice;
    string  noticeRefOrg;
    int     noticeRefNumCount;
    long*   noticeRefNum;
    string  expText;
    bool    hasNoticeRef;
    bool    hasExpText;
};

/*
 *  -- policyQualifierIds for Internet policy qualifiers
 *
 *    id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
 *    id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
 *    id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
 *
 *    PolicyQualifierId ::=
 *         OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
 *
 *    Qualifier ::= CHOICE {
 *         cPSuri           CPSuri,
 *         userNotice       UserNotice }
 *
 *    CPSuri ::= IA5String
 *
 *    UserNotice ::= SEQUENCE {
 *         noticeRef        NoticeReference OPTIONAL,
 *         explicitText     DisplayText OPTIONAL}
 *-------------------------------------------------------------*
 * X509 Structure (OpenSSL):
 *
 *	typedef struct POLICYQUALINFO_st {
 *		ASN1_OBJECT *pqualid;
 *		union {
 *				 ASN1_IA5STRING *cpsuri;
 *				 USERNOTICE *usernotice;
 *				 ASN1_TYPE *other;
 *				} d;
 *	} POLICYQUALINFO;
 *
*/
class _TECSECCLASS ALFFX509PolicyQualifier : public ALFFX509Object  //POLICYQUALINFO
{
  public:

  	ALFFX509PolicyQualifier(POLICYQUALINFO* qualInfo);
  	~ALFFX509PolicyQualifier();
   char far* GetClassName() {return "ALFFX509PolicyQualifier";}

   bool IsPresent()  { return present; }

   bool                      IsCPSUri();
   bool                      IsUserNotice();
   bool                      IsOther();
   string                    getCPSUri();
   ALFFX509UserNotice*       getUserNotice();
   string                    getOther();

   /* OID Informations */
   ALFFX509Oid*              getQualifierOID();

  protected:
   bool                      present;
   bool                      isCPSUri;
   bool                      isUserNotice;
   bool                      isOther;
   ALFFX509UserNotice*       userNotice;
   string                    cpsURI;
   string                    otherText;
   // OID
   ALFFX509Oid* qualifierOid;

};

/*
 *	typedef struct POLICYINFO_st {
 *		ASN1_OBJECT *policyid;
 *		STACK_OF(POLICYQUALINFO) *qualifiers;
 *	} POLICYINFO;
 */
class _TECSECCLASS ALFFX509CertificatePolicy : public ALFFX509Object  //POLICYINFO
{
  public:
  	ALFFX509CertificatePolicy(POLICYINFO* polInfo);
  	~ALFFX509CertificatePolicy();
   char far* GetClassName() {return "ALFFX509CertificatePolicy";}

  	ALFFX509PolicyQualifier*  getQualifier(int index);
   long                      getQualifiersCount();
  	bool                      IsQualifiersPresent();
   /* OID Informations */
   ALFFX509Oid*              getPolicyOID();

  protected:
    POLICYINFO*               policyInfo;
    long                      qualifiersCount;
  	 ALFFX509PolicyQualifier*  x509PolicyQualifier;
    bool                      present;
    // OID
    ALFFX509Oid*              policyOid;
};

/*
 * typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
 */
class _TECSECCLASS ALFFX509CertificatePolicies: public ALFFX509Object //CERTIFICATEPOLICIES
 {
   public:
 	 ALFFX509CertificatePolicies(CERTIFICATEPOLICIES* cPolicies, bool crit);
 	 ~ALFFX509CertificatePolicies();
    char far* GetClassName() {return "ALFFX509CertificatePolicies";}

    bool IsCritical() { return critical; }
    bool IsPresent()  { return present; }
    ALFFX509Oid* getOID() {return oid; }

    ALFFX509CertificatePolicy* getPolicyInfo(int index);
    int  getCount();

   protected:
    CERTIFICATEPOLICIES* certificatePolicies;
    ALFFX509CertificatePolicy*  x509CertPolicy;
    int policyInfoCount;
    bool critical;
    bool present;

   // OID
   ALFFX509Oid* oid;
 };

/*
	typedef struct X509_name_entry_st
	{
		ASN1_OBJECT *object;
		ASN1_STRING *value;
		int set;
		int size; 	// temp variable
	} X509_NAME_ENTRY;
*/
class _TECSECCLASS ALFFX509NameEntry : public ALFFX509Object  //X509_NAME_ENTRY
{
  public:
  ALFFX509NameEntry(X509_NAME_ENTRY* nEntry);
  ~ALFFX509NameEntry();
  char far* GetClassName() {return "ALFFX509NameEntry";}

  char* 	getEntryShortName();
  char* 	getEntryLongName();
  unsigned char* 	getEntryValue();
  int    getSet();
  int    getSize();

  protected:
    char*  entryShortName;
    char*  entryLongName;
    unsigned char*  entryValue;
    int    entrySet;
    int    entrySize;
};

/*
	DECLARE_STACK_OF(X509_NAME_ENTRY)
	DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
*/
class _TECSECCLASS ALFFX509NameEntries : public ALFFX509Object //STACK_OF(X509_NAME_ENTRY)
{
   public:
 	 ALFFX509NameEntries(STACK_OF(X509_NAME_ENTRY)* nEntries);
 	 ~ALFFX509NameEntries();
    char far* GetClassName() {return "ALFFX509NameEntries";}

    bool IsPresent()  { return present; }

    ALFFX509NameEntry* getX509NameEntry(int index);
    int  getCount() { return nameEntriesCount; }

   protected:
    STACK_OF(X509_NAME_ENTRY)* nameEntries;
    ALFFX509NameEntry*  x509NameEntry;
    int nameEntriesCount;
    bool present;
};

/*
	typedef struct DIST_POINT_NAME_st {
		int type;
		union {
			GENERAL_NAMES *fullname;
			STACK_OF(X509_NAME_ENTRY) *relativename;
		} name;
	} DIST_POINT_NAME;
*/
class _TECSECCLASS ALFFX509DistPointName : public ALFFX509Object  //DIST_POINT_NAME
{
  public:
  		ALFFX509DistPointName(DIST_POINT_NAME* distPointName);
  		~ALFFX509DistPointName();
      char far* GetClassName() {return "ALFFX509DistPointName";}

      ALFFX509Names*       getFullName();
      ALFFX509NameEntries* getRelativeName();

  protected:
      ALFFX509Names*       fullName;
      ALFFX509NameEntries* relativeName;
};

/*
	typedef struct DIST_POINT_st {
		DIST_POINT_NAME	*distpoint;
		ASN1_BIT_STRING *reasons;
		GENERAL_NAMES *CRLissuer;
	} DIST_POINT;
*/
class _TECSECCLASS ALFFX509CRLDistPoint : public ALFFX509Object  //DIST_POINT
{
  public:
  	ALFFX509CRLDistPoint(DIST_POINT* distPoint);
  	~ALFFX509CRLDistPoint();
   char far* GetClassName() {return "ALFFX509DistPoint";}

  	enum DistReason {
        KeyCompromise,
        CACompromise,
        AffiliationChanged,
        Superseded,
        CessationOfOperation,
        CertificateHold,
        PrivilegeWithdrawn,
        AACompromise };

  	ALFFX509DistPointName*  getName();
  	bool                    IsReasonPresent();
  	bool                    IsDistReason(DistReason reason);
  	ALFFX509Names*          getIssuer();

  protected:
    ALFFX509DistPointName*  distPointName;
    bool                    isReasonPresent;
    /*---------------- REASONS ----------------------------*/
    /*  ReasonFlags ::= BIT STRING {
        unused                  (0),
        keyCompromise           (1),
        cACompromise            (2),
        affiliationChanged      (3),
        superseded              (4),
        cessationOfOperation    (5),
        certificateHold         (6),
        privilegeWithdrawn      (7),
        aACompromise            (8) } */
    bool                   keyCompromise;          // (1),
    bool                   cACompromise;           // (2),
    bool                   affiliationChanged;     // (3),
    bool                   superseded;             // (4),
    bool                   cessationOfOperation;   // (5),
    bool                   certificateHold;        // (6),
    bool                   privilegeWithdrawn;     // (7),
    bool                   aACompromise ;          // (8)
    /*-----------------------------------------------------*/
    ALFFX509Names*          crlIssuer;
};


/*
 *	typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
 */
class _TECSECCLASS ALFFX509CRLDistPoints : public ALFFX509Object //CRL_DIST_POINTS
 {
   public:
 	 ALFFX509CRLDistPoints(CRL_DIST_POINTS* gDistPoints, bool crit);
 	 ~ALFFX509CRLDistPoints();
    char far* GetClassName() {return "ALFFX509DistPoints";}

	 bool IsCritical() { return critical; }
    bool IsPresent()  { return present; }
    ALFFX509Oid* getOID() {return oid; }

    ALFFX509CRLDistPoint* getDistPoint(int index);
    int  getCount() { return distPointsCount; }

   protected:
    CRL_DIST_POINTS*       crlDistPoints;
    ALFFX509CRLDistPoint*  x509DistPoint;
    int distPointsCount;
    bool critical;
    bool present;
   // OID
   ALFFX509Oid* oid;

 };

/*
 *  typedef struct PKEY_USAGE_PERIOD_st {
 *		ASN1_GENERALIZEDTIME *notBefore;
 *		ASN1_GENERALIZEDTIME *notAfter;
 *	 } PKEY_USAGE_PERIOD;
 *
 */
class _TECSECCLASS ALFFX509PKeyUsagePeriod : public ALFFX509Object //PKEY_USAGE_PERIOD
{
 public:
	ALFFX509PKeyUsagePeriod(PKEY_USAGE_PERIOD* pKeyPeriod, bool crit);
	~ALFFX509PKeyUsagePeriod();
   char far* GetClassName() {return "ALFFX509PKeyUsagePeriod";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   ALFFDate*      getNotBefore();
   ALFFDate*      getNotAfter();

 protected:
   PKEY_USAGE_PERIOD*  pKUPeriod;
   ALFFDate*      pDate;
   bool critical;

   // OID
   ALFFX509Oid* oid;

   // Object presence
   bool present;
};

/*
	typedef struct AUTHORITY_KEYID_st {
		ASN1_OCTET_STRING *keyid;
		GENERAL_NAMES *issuer;
		ASN1_INTEGER *serial;
	} AUTHORITY_KEYID;
*/
class  _TECSECCLASS ALFFX509AuthKeyId : public ALFFX509Object  //AUTHORITY_KEYID
{
 public:
	ALFFX509AuthKeyId(AUTHORITY_KEYID* pAkid, bool crit);
   ALFFX509AuthKeyId(unsigned char* keyId, int keyLen);
	~ALFFX509AuthKeyId();
   char far* GetClassName() {return "ALFFX509AuthKeyId";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   unsigned char* getKeyId();
   long           getKeyIdLength();
   ALFFX509Names* getIssuer();
   long  			getSerialNumber();

 protected:
   unsigned char* akidData;
   long akidLength;
   long serialNumber;
   ALFFX509Names* issuerName;
   bool critical;

   // OID
   ALFFX509Oid* oid;

   // Object presence
   bool present;
};

/*
	 *	typedef struct asn1_string_st
	 *	  {
	 *		int length;
	 *		int type;
	 *		unsigned char *data;
	 *		* The value of the following field depends on the type being
	 *		* held.  It is mostly being used for BIT_STRING so if the
	 *		* input data has a non-zero 'unused bits' value, it will be
	 *		* handled correctly
	 *		long flags;
	 *	  } ASN1_STRING;
*/
class _TECSECCLASS ALFFX509SubjectKeyId : public ALFFX509Object //ASN1_STRING
{
 public:
	ALFFX509SubjectKeyId(ASN1_STRING* bSubj, bool crit);
   ALFFX509SubjectKeyId(unsigned char* keyId, int keyLen);
	~ALFFX509SubjectKeyId();
   char far* GetClassName() {return "ALFFX509SubjectKeyId";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   unsigned char* getKeyId();
   long           getKeyIdLength();

 protected:
   unsigned char* skidData;
   long skidLength;
   bool critical;

   // OID
   ALFFX509Oid* oid;

   // Object presence
   bool present;
};

/*
	typedef struct BASIC_CONSTRAINTS_st {
		int ca;
		ASN1_INTEGER *pathlen;
	} BASIC_CONSTRAINTS;
*/
class _TECSECCLASS ALFFX509BasicConstraints : public ALFFX509Object  //BASIC_CONSTRAINTS
{
 public:

	ALFFX509BasicConstraints(BASIC_CONSTRAINTS* bCons, bool crit);
	~ALFFX509BasicConstraints();
   char far* GetClassName() {return "ALFFX509BasicConstraints";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   bool IsCertificateAuthority();
   bool IsPathLenPresent();
   long getPathLenConstraint();

 protected:
   ALFFX509Oid* oid;
   bool present;
   bool critical;

   bool isCA;
   long pathLen;
};

/**
 * Defines for class ALFFX509NetscapeCertType:
 *         Specific Netscape Certificate Type Extension Handling
 */
class _TECSECCLASS ALFFX509NetscapeCertType : public ALFFX509Object  //ASN1_BIT_STRING
{
 public:
	/* Constructor */
	ALFFX509NetscapeCertType(ASN1_BIT_STRING* certType, bool crit);
	~ALFFX509NetscapeCertType();
   char far* GetClassName() {return "ALFFX509NetscapeCertType";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }
   
   bool 			 IsSSLClient() {return sslClient; }
   bool			 IsSSLServer() {return sslServer; }
   bool			 IsSMime() {return sMime; }
   bool         IsObjectSigning() {return objectSigning; }
   bool			 IsSSLCA() {return sslCA; }
   bool			 IsSMimeCA() {return sMimeCA; }
   bool			 IsObjectSigningCA() {return objectSigningCA; }

 protected:
   ALFFX509Oid*    oid;
   bool            critical;
   bool            present;

   /* Certificate Type */
   bool 			sslClient;
   bool			sslServer;
   bool			sMime;
   bool        objectSigning;
   bool			sslCA;
   bool			sMimeCA;
   bool			objectSigningCA;
};

/**
 * Defines for class ALFFX509NetscapeOther:
 *     Other Netscape Extensions Handling  (ASN1_IA5STRING)
 */
class  _TECSECCLASS ALFFX509NetscapeOther : public ALFFX509Object  //ASN1_IA5STRING
{
 public:
	/* Constructor */
	ALFFX509NetscapeOther(ASN1_IA5STRING* otherExt, ALFFX509Oid::X509OID oidExt, bool crit);
	~ALFFX509NetscapeOther();
   char far* GetClassName() {return "ALFFX509NetscapeOther";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   char*  getValue();
   int    getLength();

 protected:
   ALFFX509Oid*    oid;
   bool            critical;
   bool            present;

   /* Extension Info */
   int         otherLength;
   char*       otherValue;
};

/**
 * Defines for class ALFFX509Extension: Specific Extension Handling
 *
 *		typedef struct X509_extension_st
 *			{
 *			 ASN1_OBJECT *object;
 *			 ASN1_BOOLEAN critical;
 *			 ASN1_OCTET_STRING *value;
 *			} X509_EXTENSION;
 *
 */
class _TECSECCLASS ALFFX509Extension : public ALFFX509Object //X509_EXTENSION
{
 public:
	/**
	 * Constructor for X.509 Extensions.
	 */
	ALFFX509Extension(X509_EXTENSION* ext);
   //, ALFFX509Oid::X509OID oidExt = ALFFX509Oid::OID_None);
	~ALFFX509Extension();
   char far* GetClassName() {return "ALFFX509Extension";}

   bool IsCritical() { return critical; }
   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }
   unsigned char*  getData() {return data;}
   long            getDataLength() {return dataLen;}

 protected:
	bool            present;
   bool            critical;
   long            dataLen;
   unsigned char*  data;
   ALFFX509Oid*    oid;
};

/**
 * Defines for class ALFFX509Extensions: Extensions Handling
 */
#define EXTBUFFSIZE  1024
class _TECSECCLASS ALFFX509Extensions : public ALFFX509Object
{
 public:
	/**
	 * Constructor for X.509 Extensions.
	 */
	ALFFX509Extensions(STACK_OF(X509_EXTENSION)* extensions);
	~ALFFX509Extensions();
   char far* GetClassName() {return "ALFFX509Extensions";}

   /* Get Certificate Extensions Info */
   int getNumExtensions();

   /* Returns an extension itself and its length (int)          */
   /* ------->>>> "ext" MUST be deleted by caller  <<<--------- */
   int getExtension(ALFFX509Oid::X509OID oid, ALFFX509Extension** ext);

   /* Return a pointer to an specific X509 Extension Structure */
   void* getExtension(ALFFX509Oid::X509OID oid);

   /* Return a pointer to an specific X509 Extension Structure */
   ALFFX509Extension* getExtension(int extPos);

   /* Verify if there is an extension in this certificate */
   bool  IsExtensionPresent(ALFFX509Oid::X509OID oid);
   bool  IsExtensionPresent(int resId);

   /*
    *  get Resource Id of extension that is located at "extPos"
    *    ------- may be IDS_CERTUNKNOWEXTENSION --------
    */
   int   getExtensionResId(int extPos);

   /* get Extension OID in dotted format */
   string getExtensionDottedOid(int extPos);

   /* get Extension OID in ALFFX509Oid::X509OID format */
   ALFFX509Oid* getExtensionOid(int extPos);

 protected:
   STACK_OF(X509_EXTENSION)* baseExtensions;
   int   extCount;
   ALFFX509Extension* certExtension;
   ALFFX509Oid*       extensionOid;
};


/**
 * Defines for class ALFFX509Algorithm: Public Key  Algorithm Handling
 *
 *
 *		struct X509_algor_st
 *		 {
 *			ASN1_OBJECT *algorithm;
 *			ASN1_TYPE *parameter;
 *		 } // X509_ALGOR ;
 */
class  _TECSECCLASS ALFFX509Algorithm : public ALFFX509Object  //X509_ALGOR
{
#define ALGORITHMDATALEN 1024
 public:
	ALFFX509Algorithm(X509_ALGOR* pPubKey);
	~ALFFX509Algorithm();
   char far* GetClassName() {return "ALFFX509Algorithm";}

   bool IsPresent()  { return present; }
   ALFFX509Oid* getOID() {return oid; }

   int            getParameterType();
   unsigned char* getParameterValue();

 protected:

   ALFFX509Oid*   oid;
   X509_ALGOR*    pubKeyAlgorithm;
   unsigned char* parameterData;

   // Object presence
   bool present;
};

/**
 * Defines for class ALFFX509PublicKey: Public Key  Handling
 *
 *		typedef struct X509_pubkey_st
 *		{
 *		    X509_ALGOR *algor;
 *		    ASN1_BIT_STRING *public_key;
 *		    EVP_PKEY *pkey;
 *		} X509_PUBKEY;
 *   Copy of EVP_PKEY defines on evp.h file
 *   #define EVP_PK_RSA	0x0001
 *   #define EVP_PK_DSA	0x0002
 *   #define EVP_PK_DH	0x0004
 *   #define EVP_PKT_SIGN	0x0010
 *   #define EVP_PKT_ENC	0x0020
 *   #define EVP_PKT_EXCH	0x0040
 *   #define EVP_PKS_RSA	0x0100
 *   #define EVP_PKS_DSA	0x0200
 *   #define EVP_PKT_EXP	0x1000 //* <= 512 bit key
 *
 *   #define EVP_PKEY_NONE	NID_undef
 *   #define EVP_PKEY_RSA		NID_rsaEncryption
 *   #define EVP_PKEY_RSA2	NID_rsa
 *   #define EVP_PKEY_DSA		NID_dsa
 *   #define EVP_PKEY_DSA1	NID_dsa_2
 *   #define EVP_PKEY_DSA2	NID_dsaWithSHA
 *   #define EVP_PKEY_DSA3	NID_dsaWithSHA1
 *   #define EVP_PKEY_DSA4	NID_dsaWithSHA1_2
 *   #define EVP_PKEY_DH		NID_dhKeyAgreement
 *
 *   #ifdef	__cplusplus
 *   extern "C" {
 *   #endif
 *
 *   /* Type needs to be a bit field
 *    * Sub-type needs to be for variations on the method, as in, can it do
 *    * arbitrary encryption....
 *   		struct evp_pkey_st
 *   		{
 *   		int type;
 *   		int save_type;
 *   		int references;
 *   		union	{
 *   			char *ptr;
 *   		#ifndef OPENSSL_NO_RSA
 *   			struct rsa_st *rsa;	//* RSA
 *   		#endif
 *   		#ifndef OPENSSL_NO_DSA
 *   			struct dsa_st *dsa;	//* DSA
 *   		#endif
 *   		#ifndef OPENSSL_NO_DH
 *   			struct dh_st *dh;	//* DH
 *   		#endif
 *   				} pkey;
 *   		int save_parameters;
 *   		STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ]
 *   		} //* EVP_PKEY ;
 *
 */
class _TECSECCLASS ALFFX509PublicKey : public ALFFX509Object  //X509_PUBKEY
{
 public:
	ALFFX509PublicKey(X509_PUBKEY* pPubKey);
	~ALFFX509PublicKey();
   char far* GetClassName() {return "ALFFX509PublicKey";}

   bool IsPresent()  { return present; }

   unsigned char* getKey();
   long           getKeyLength();
   long           getRsaLength();

   ALFFX509Algorithm*  getAlgorithm();
   // ALFFX509EVPPkey*   getEVPPkey();

 protected:
   unsigned char* key;
   long           keyLength;
   long           rsaLength;
   ALFFX509Algorithm* keyAlgorithm;

   // Access to EVP_PKEY not yet supported
   // ALFFX509EVPPkey*   evpPkey;

   // Object presence
   bool present;
};

/*
      id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }

      KeyUsage ::= BIT STRING {
           digitalSignature        (0),
           nonRepudiation          (1),
           keyEncipherment         (2),
           dataEncipherment        (3),
           keyAgreement            (4),
           keyCertSign             (5),
           cRLSign                 (6),
           encipherOnly            (7),
           decipherOnly            (8) }

   Bits in the KeyUsage type are used as follows:

      The digitalSignature bit is asserted when the subject public key
      is used with a digital signature mechanism to support security
      services other than certificate signing (bit 5), or CRL signing
      (bit 6).  Digital signature mechanisms are often used for entity
      authentication and data origin authentication with integrity.

      The nonRepudiation bit is asserted when the subject public key is
      used to verify digital signatures used to provide a non-
      repudiation service which protects against the signing entity
      falsely denying some action, excluding certificate or CRL signing.
      In the case of later conflict, a reliable third party may
      determine the authenticity of the signed data.

      Further distinctions between the digitalSignature and
      nonRepudiation bits may be provided in specific certificate
      policies.

      The keyEncipherment bit is asserted when the subject public key is
      used for key transport.  For example, when an RSA key is to be
      used for key management, then this bit is set.

      The dataEncipherment bit is asserted when the subject public key
      is used for enciphering user data, other than cryptographic keys.

      The keyAgreement bit is asserted when the subject public key is
      used for key agreement.  For example, when a Diffie-Hellman key is
      to be used for key management, then this bit is set.

      The keyCertSign bit is asserted when the subject public key is
      used for verifying a signature on public key certificates.  If the
      keyCertSign bit is asserted, then the cA bit in the basic
      constraints extension (section 4.2.1.10) MUST also be asserted.

      The cRLSign bit is asserted when the subject public key is used
      for verifying a signature on certificate revocation list (e.g., a
      CRL, delta CRL, or an ARL).  This bit MUST be asserted in
      certificates that are used to verify signatures on CRLs.

      The meaning of the encipherOnly bit is undefined in the absence of
      the keyAgreement bit.  When the encipherOnly bit is asserted and
      the keyAgreement bit is also set, the subject public key may be
      used only for enciphering data while performing key agreement.

      The meaning of the decipherOnly bit is undefined in the absence of
      the keyAgreement bit.  When the decipherOnly bit is asserted and
      the keyAgreement bit is also set, the subject public key may be
      used only for deciphering data while performing key agreement.
 */
class _TECSECCLASS ALFFX509KeyUsage : public ALFFX509Object  //ASN1_BIT_STRING
{
  public:
  		ALFFX509KeyUsage(ASN1_BIT_STRING* keyUsage, bool crit);
      ~ALFFX509KeyUsage();
      char far* GetClassName() {return "ALFFX509KeyUsage";}

	   bool IsCritical() { return critical; }
  		bool IsPresent()  { return present; }
   	ALFFX509Oid* getOID() {return oid; }

      bool IsDigitalSignature();
      bool IsNonRepudiation();
      bool IsKeyEncipherment();
      bool IsDataEncipherment();
      bool IsKeyAgreement();
      bool IsKeyCertSign();
      bool IsCRLSign();
      bool IsEncipherOnly();
      bool IsDecipherOnly();

  protected:
       bool    critical;
       bool    digitalSignature;
       bool    nonRepudiation;
       bool    keyEncipherment;
       bool    dataEncipherment;
       bool    keyAgreement;
       bool    keyCertSign;
       bool    cRLSign;
       bool    encipherOnly;
       bool    decipherOnly;

       // Object presence
       bool present;

      // OID
      ALFFX509Oid* oid;
};

/*
   The following key usage purposes are defined:

   anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }

   id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }

   id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }
   -- TLS WWW server authentication
   -- Key usage bits that may be consistent: digitalSignature,
   -- keyEncipherment or keyAgreement

   id-kp-clientAuth             OBJECT IDENTIFIER ::= { id-kp 2 }
   -- TLS WWW client authentication
   -- Key usage bits that may be consistent: digitalSignature
   -- and/or keyAgreement

   id-kp-codeSigning             OBJECT IDENTIFIER ::= { id-kp 3 }
   -- Signing of downloadable executable code
   -- Key usage bits that may be consistent: digitalSignature

   id-kp-emailProtection         OBJECT IDENTIFIER ::= { id-kp 4 }
   -- E-mail protection
   -- Key usage bits that may be consistent: digitalSignature,
   -- nonRepudiation, and/or (keyEncipherment or keyAgreement)

   id-kp-timeStamping            OBJECT IDENTIFIER ::= { id-kp 8 }
   -- Binding the hash of an object to a time
   -- Key usage bits that may be consistent: digitalSignature
   -- and/or nonRepudiation

   id-kp-OCSPSigning            OBJECT IDENTIFIER ::= { id-kp 9 }
   -- Signing OCSP responses
   -- Key usage bits that may be consistent: digitalSignature
   -- and/or nonRepudiation
 *------------------------------------------------------------------
 *
 *  typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
 *
 */
class _TECSECCLASS ALFFX509ExtKeyUsage : public ALFFX509Object  //EXTENDED_KEY_USAGE
{
  public:
  		ALFFX509ExtKeyUsage(EXTENDED_KEY_USAGE* keyUsage, bool crit);
      ~ALFFX509ExtKeyUsage();
      char far* GetClassName() {return "ALFFX509ExtKeyUsage";}

	   bool IsCritical() { return critical; }
	   bool IsPresent()  { return present; }
   	ALFFX509Oid* getOID() {return oid; }

      bool IsServer_auth();
      bool IsClient_auth();
      bool IsCode_sign();
      bool IsEmail_protect();
      bool IsTime_stamp();
      bool IsOCSP_sign();

      ALFFX509Oid* getPurposeOID(ALFFX509Oid::X509OID oid);
      bool HasUnknowPurposes() {return (numUnknow > 0);}
      int getUnknowCount() {return numUnknow;}
      ALFFX509Oid* getUnknowPurpose(int index);

  protected:

      bool critical;

      bool server_auth;
      bool client_auth;
      bool code_sign;
      bool email_protect;
      bool time_stamp;
      bool oCSP_sign;

       // Object presence
       bool present;

      // OIDs
      ALFFX509Oid* oid;
      ALFFX509Oid* purposeOid;
#define MAXUNKNOWPURPOSES    4
      int          numUnknow;
      ALFFX509Oid* purposeUnknow;
};

/**
 * Class for X.509 certificates. This provides a standard
 * way to access all the attributes of an X.509 certificate.
 *
 * The basic X.509 v3 format was completed by
 * ISO/IEC and ANSI X9, which is described below in ASN.1:
 *
 * Certificate  ::=  SEQUENCE  {
 *     tbsCertificate       TBSCertificate,
 *     signatureAlgorithm   AlgorithmIdentifier,
 *     signature            BIT STRING  }
 *
 *
 * These certificates are widely used to support authentication and
 * other functionality in Internet security systems. Common applications
 * include Privacy Enhanced Mail (PEM), Transport Layer Security (SSL),
 * code signing for trusted software distribution, and Secure Electronic
 * Transactions (SET).
 *
 * These certificates are managed and vouched for by Certificate
 * Authorities (CAs). CAs are services which create certificates by
 * placing data in the X.509 standard format and then digitally signing
 * that data. CAs act as trusted third parties, making introductions
 * between principals who have no direct knowledge of each other.
 * CA certificates are either signed by themselves, or by some other
 * CA such as a "root" CA.
 *
 * A good description and profiling is provided in the IETF PKIX WG
 * draft, Part I:  X.509 Certificate and CRL Profile,
 * <draft-ietf-pkix-ipki-part1-07.txt>.
 *
 * The ASN.1 definition of <tbsCertificate> is:
 *
 * TBSCertificate  ::=  SEQUENCE  {
 *     version         [0]  EXPLICIT Version DEFAULT v1,
 *     serialNumber         CertificateSerialNumber,
 *     signature            AlgorithmIdentifier,
 *     issuer               Name,
 *     validity             Validity,
 *     subject              Name,
 *     subjectPublicKeyInfo SubjectPublicKeyInfo,
 *     issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
 *                          -- If present, version must be v2 or v3
 *     subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
 *                          -- If present, version must be v2 or v3
 *     extensions      [3]  EXPLICIT Extensions OPTIONAL
 *                          -- If present, version must be v3
 *     }
 *
 */
class ALFFX509Certificates;

class _TECSECCLASS
ALFFX509Certificate : public ALFFX509Object
{
   public:
	/**
	 * Constructor for X.509 certificates.
	 */
    
   /* Constructor for general use: Verify Certificate may be false */
   // Note: ALFFX509Certificate may receive the 1st parameter (TWindow*)
	//       if there is no needing of certificate verification, because
	//       it is used only on SetupCertificate Method when loading
	//       CA Certificates Stack.
	ALFFX509Certificate(TWindow* parent,
   						  X509* certificate,
                       ALFFUseSecurity* pSec,
                       STACK_OF(X509) *caCerts=NULL,
                       bool verify=false,
                       bool verifyCRL=false,
                       bool ignoreExpired=false);

   /* Constructor for SSL Conections: Verify Certificate Always true */
   ALFFX509Certificate(TWindow* parent,
   						  ALFFSSLComm* pSSLLine,
                       ALFFUseSecurity* pSec,
                       STACK_OF(X509) *caCerts=NULL,
                       bool verify=false,                       
                       bool verifyCRL=false,
                       bool ignoreExpired=false);
                       
	~ALFFX509Certificate();
   char far* GetClassName() {return "ALFFX509Certificate";}

   // Do all initializations needed
   void SetupCertificate(bool verifyCert, bool verifyCRL);

   enum CertChainStatus
    {
      X509_CERT_OK									  		=X509_V_OK,
		X509ERR_UNABLE_TO_GET_ISSUER_CERT		  		=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
		X509ERR_UNABLE_TO_GET_CRL				  			=X509_V_ERR_UNABLE_TO_GET_CRL,
		X509ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE  	=X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
		X509ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE   	=X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
		X509ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY	=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
		X509ERR_CERT_SIGNATURE_FAILURE			  		=X509_V_ERR_CERT_SIGNATURE_FAILURE,
		X509ERR_CRL_SIGNATURE_FAILURE			  			=X509_V_ERR_CRL_SIGNATURE_FAILURE,
		X509ERR_CERT_NOT_YET_VALID				  			=X509_V_ERR_CERT_NOT_YET_VALID,
		X509ERR_CERT_HAS_EXPIRED				  			=X509_V_ERR_CERT_HAS_EXPIRED,
		X509ERR_CRL_NOT_YET_VALID				  			=X509_V_ERR_CRL_NOT_YET_VALID,
		X509ERR_CRL_HAS_EXPIRED					  			=X509_V_ERR_CRL_HAS_EXPIRED,
		X509ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD	  		=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
		X509ERR_ERROR_IN_CERT_NOT_AFTER_FIELD	  		=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
		X509ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD	  		=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
		X509ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD	  		=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
		X509ERR_OUT_OF_MEM						  			=X509_V_ERR_OUT_OF_MEM,
		X509ERR_DEPTH_ZERO_SELF_SIGNED_CERT		  		=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
		X509ERR_SELF_SIGNED_CERT_IN_CHAIN		  		=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
		X509ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 	=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
		X509ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE	  	=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
		X509ERR_CERT_CHAIN_TOO_LONG				  		=X509_V_ERR_CERT_CHAIN_TOO_LONG,
		X509ERR_CERT_REVOKED					  				=X509_V_ERR_CERT_REVOKED,
		X509ERR_INVALID_CA						  			=X509_V_ERR_INVALID_CA,
		X509ERR_PATH_LENGTH_EXCEEDED			  			=X509_V_ERR_PATH_LENGTH_EXCEEDED,
		X509ERR_INVALID_PURPOSE					  			=X509_V_ERR_INVALID_PURPOSE,
		X509ERR_CERT_UNTRUSTED					  			=X509_V_ERR_CERT_UNTRUSTED,
		X509ERR_CERT_REJECTED					  			=X509_V_ERR_CERT_REJECTED,
		// 'informational' when looking for issuer cert
		X509ERR_SUBJECT_ISSUER_MISMATCH			  		=X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
		X509ERR_AKID_SKID_MISMATCH				  			=X509_V_ERR_AKID_SKID_MISMATCH,
		X509ERR_AKID_ISSUER_SERIAL_MISMATCH		  		=X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
		X509ERR_KEYUSAGE_NO_CERTSIGN			  			=X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
		//application
		X509ERR_APPLICATION_VERIFICATION          	=X509_V_ERR_APPLICATION_VERIFICATION,
		X509ERR_COMMON_NAME_MISMATCH              	=X509_V_ERR_APPLICATION_VERIFICATION+1,
  		X509ERR_CERT_NOT_VERIFIED		              	=X509_V_ERR_APPLICATION_VERIFICATION+2
    } ;

	/**
	 * Gets the <code>version</code> (version number) value from the
	 * certificate.
	 * The ASN.1 definition for this is:
	 * <pre>
	 * version  [0] EXPLICIT Version DEFAULT v1<p>
	 * Version ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
	 * </pre>
	 * @return the version number, i.e. 1, 2 or 3.
	 */
	int getVersion();

	/**
	 * Gets the <code>serialNumber</code> value from the certificate.
	 * The serial number is an integer assigned by the certification
	 * authority to each certificate. It must be unique for each
	 * certificate issued by a given CA (i.e., the issuer name and
	 * serial number identify a unique certificate).
	 * The ASN.1 definition for this is:
	 * <pre>
	 * serialNumber     CertificateSerialNumber<p>
	 *
	 * CertificateSerialNumber  ::=  INTEGER
	 * </pre>
	 *
	 * @return the serial number as an Hex string or as an <long>.
	 */
 	string getSerialNumber();
 	long getLongSerialNumber();   

	/**
	 * Gets the signature algorithm name for the certificate
	 * signature algorithm. An example is the string "SHA-1/DSA".
	 * The ASN.1 definition for this is:
	 * <pre>
	 * signatureAlgorithm   AlgorithmIdentifier<p>
	 * AlgorithmIdentifier  ::=  SEQUENCE  {
	 *     algorithm               OBJECT IDENTIFIER,
	 *     parameters              ANY DEFINED BY algorithm (OPTIONAL)  }
	 *                             -- contains a value of the type
	 *                             -- registered for use with the
	 *                             -- algorithm object identifier value
	 * </pre>
	 *
	 * <p>The algorithm name is determined from the <code>algorithm</code>
	 * OID string.
	 *
	 * @return an pointer to ALFFX509Algorithm class that provides
    *                       all information related to.
	 */
	ALFFX509Algorithm* getSignAlgorithm();

	/**
	 * Gets the <code>signature</code> value (the raw signature bits) from
	 * the certificate.
	 * The ASN.1 definition for this is:
	 * <pre>
	 * signature     BIT STRING
	 * </pre>
	 *
	 * @return the signature.
	 */
	unsigned char* getSignature();
   int            getSignatureLength();

	/**
	 * Gets the <code>issuer</code> (issuer distinguished name) value from
	 * the certificate. The issuer name identifies the entity that signed (and
	 * issued) the certificate.
	 *
	 * <p>The issuer name field contains an
	 * X.500 distinguished name (DN).
	 * The ASN.1 definition for this is:
	 * <pre>
	 * issuer    Name<p>
	 *
	 * Name ::= CHOICE { RDNSequence }
	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
	 * RelativeDistinguishedName ::=
	 *     SET OF AttributeValueAssertion
	 *
	 * AttributeValueAssertion ::= SEQUENCE {
	 *                               AttributeType,
	 *                               AttributeValue }
	 * AttributeType ::= OBJECT IDENTIFIER
	 * AttributeValue ::= ANY
	 * </pre>
	 * The <code>Name</code> describes a hierarchical name composed of
	 * attributes,
	 * such as country name, and corresponding values, such as US.
	 * The type of the <code>AttributeValue</code> component is determined by
	 * the <code>AttributeType</code>; in general it will be a
	 * <code>directoryString</code>. A <code>directoryString</code> is usually
	 * one of <code>PrintableString</code>,
	 * <code>TeletexString</code> or <code>UniversalString</code>.
	 *
	 * @return a string which is the issuer distinguished name.
	 */
	string getIssuerDN();

	/**
	 * Gets the <code>notAfter</code> date from the validity period of
	 * the certificate. See {@link getNotBefore()#getNotBefore}
	 * for relevant ASN.1 definitions.
	 *
	 * @return the end date of the validity period.
	 * @see #checkValidity
	 */
	ALFFDate* getNotAfter();

	/**
	 * Gets the <code>notBefore</code> date from the validity period of
	 * the certificate.
	 * The relevant ASN.1 definitions are:
	 * <pre>
	 * validity             Validity<p>
	 *
	 * Validity ::= SEQUENCE {
	 *     notBefore      CertificateValidityDate,
	 *     notAfter       CertificateValidityDate }<p>
	 * CertificateValidityDate ::= CHOICE {
	 *     utcTime        UTCTime,
	 *     generalTime    GeneralizedTime }
	 * </pre>
	 *
	 * @return the start date of the validity period.
	 * @see #checkValidity
	 */
	ALFFDate* getNotBefore();

	/**
	 * Gets the <code>subject</code> (subject distinguished name) value
	 * from the certificate.
	 * The ASN.1 definition for this is:
	 * <pre>
	 * subject    Name
	 * </pre>
	 *
	 * <p>See {@link getIssuerDN()#getIssuerDN} for <code>Name</code>
	 * and other relevant definitions.
	 *
	 * @return a Principal whose name is the subject name.
	 */
	string getSubjectDN();

  	/**
	 * Gets the algorithm name for the entire certificate
	 *
	 * The ASN.1 definition for this is:
	 * <pre>
	 * signatureAlgorithm   AlgorithmIdentifier<p>
	 * AlgorithmIdentifier  ::=  SEQUENCE  {
	 *     algorithm               OBJECT IDENTIFIER,
	 *     parameters              ANY DEFINED BY algorithm (OPTIONAL)  }
	 *                             -- contains a value of the type
	 *                             -- registered for use with the
	 *                             -- algorithm object identifier value
	 * </pre>
	 *
	 * <p>The algorithm name is determined from the <code>algorithm</code>
	 * OID string.
	 *
	 * @return an pointer to ALFFX509Algorithm class that provides
    *                       all information related to.
	 */
	ALFFX509Algorithm* getHashAlgorithm();

	/**
	 * Gets the <code>sha1_hash or md5)hash </code> value (the hash code) from
	 * the certificate.
    * If it is not available it will be calculated and supplied to caller.
    *
	 * The OpenSSL structure definition for this is: (sha1 hash code)
	 * <pre>
	 *     X509_st::sha1_hash  unsigned char* 
	 * </pre>
	 *
	 * @return the hash code.
	 */
	unsigned char* getHashCode(ALFFX509Oid::X509OID hashOid);

   /**
	 * Gets the <code>publicKey</code> value from the certificate.
    *
    *		typedef struct X509_pubkey_st
	 *		{
	 *		    X509_ALGOR *algor;
	 *		    ASN1_BIT_STRING *public_key;
	 *		    EVP_PKEY *pkey;
	 *		} X509_PUBKEY;
    */
   ALFFX509PublicKey* getPublicKey();

	/**
	 * Gets the <code>Private Key Usage Period</code> value from
    * the certificate.
	 *
	 *  typedef struct PKEY_USAGE_PERIOD_st {
    *		ASN1_GENERALIZEDTIME *notBefore;
    *		ASN1_GENERALIZEDTIME *notAfter;
    *	 } PKEY_USAGE_PERIOD;
	 *
	 * @return the privatekeyusageperiod extension as an object
    *         (ALFFX509PKeyUsagePeriod) or NULL
    *         if it is not present in the certificate.
	 */
   ALFFX509PKeyUsagePeriod* getPKeyUsagePeriod();

	/**
	 * Gets the <code>Authority Key Identifier</code> value from
    * the certificate.
	 *
	 * <p>The ASN.1 definition for this is:
	 * <pre>
	 * struct AUTHORITY_KEYID_st
      {
             ASN1_OCTET_STRING *keyid;
             GENERAL_NAMES *issuer;
             ASN1_INTEGER *serial;
      } AUTHORITY_KEYID;
	 *
	 * @return the authority key identifier as an ALFFX509AuthKeyId
    *         or NULL if it is not present in the certificate.
	 */
   ALFFX509AuthKeyId*  getAuthorityKeyID();

   /**
	 * Gets the <code>Subject Key Identifier</code> value from
    * the certificate.
	 *
	 * <p>The ASN.1 definition for this is:
	 *	typedef struct asn1_string_st
	 *	  {
	 *		int length;
	 *		int type;
	 *		unsigned char *data;
	 *		* The value of the following field depends on the type being
	 *		* held.  It is mostly being used for BIT_STRING so if the
	 *		* input data has a non-zero 'unused bits' value, it will be
	 *		* handled correctly
	 *		long flags;
	 *	  } ASN1_STRING;
	 * @return the subjectkey identifier as an ALFFX509SubjectKeyId
    *         or NULL if it is not present in the certificate.
	 */
   ALFFX509SubjectKeyId*  getSubjectKeyID();

	/**
	 * Gets the certificate constraints path length from the
	 * critical <code>BasicConstraints</code> extension, (OID = 2.5.29.19).
	 * <p>
	 * The basic constraints extension identifies whether the subject
	 * of the certificate is a Certificate Authority (CA) and
	 * how deep a certification path may exist through that CA. The
	 * <code>pathLenConstraint</code> field (see below) is meaningful
	 * only if <code>cA</code> is set to TRUE. In this case, it gives the
	 * maximum number of CA certificates that may follow this certificate in a
	 * certification path. A value of zero indicates that only an end-entity
	 * certificate may follow in the path.
	 * <p>
	 * Note that for the PKIX profile this extension is always marked
	 * critical if <code>cA</code> is TRUE, meaning this certificate belongs
	 * to a Certificate Authority.
	 * <p>
	 * The ASN.1 definition for this is:
	 * <pre>
	 * BasicConstraints ::= SEQUENCE {
	 *     cA                  BOOLEAN DEFAULT FALSE,
	 *     pathLenConstraint   INTEGER (0..MAX) OPTIONAL }
	 * </pre>
	 *
	 * @return the length of the constraint if the BasicConstraints extension
	 * is present in the certificate and the <code>cA</code> value is TRUE.
	 * Otherwise returns -1.
	 */
	ALFFX509BasicConstraints* getBasicConstraints();

   /**
	 * Gets the <code>certificatePolicies</code> value from
    * the certificate.
	 *
	 * <p>The ASN.1 definition for this is:
	 * <pre>
	 * struct X509_extension_st
	   {
	     ASN1_OBJECT *object;    (OBJ_id_ce,31L) 2.5.29.31
	     ASN1_BOOLEAN critical;
	     ASN1_OCTET_STRING *value;
	   } X509_EXTENSION;
	 *
	 * @return the certificate policies extension as an object
    *         (ALFFX509CertificatePolicies) or NULL
    *         if it is not present in the certificate.
	 */
	ALFFX509CertificatePolicies* getCertificatePolicies();

   /**
	 * Gets the <code>crlDistributionpoints</code> value from
    * the certificate.
	 *
	 * <p>The ASN.1 definition for this is:
	 * <pre>
	 * struct X509_extension_st
	   {
	     ASN1_OBJECT *object;    (OBJ_id_ce,31L) 2.5.29.31
	     ASN1_BOOLEAN critical;
	     ASN1_OCTET_STRING *value;
	   } X509_EXTENSION;
	 *
	 * @return the distribution point extension as an object
    *         (ALFFX509CRLDistPoints) or NULL
    *         if it is not present in the certificate.
	 */
   ALFFX509CRLDistPoints* getDistributionPoints();

   /**
	 * Gets the <code>issuer common name</code> (issuer (CN=)) value from
	 * the certificate. The issuer common name identifies the entity that
    * signed (and issued) the certificate.
	 *
	 * <p>The issuer name field contains an
	 * X.500 distinguished name (DN).
	 * The ASN.1 definition for this is:
	 * <pre>
	 * issuer    Name<p>
	 *
	 * Name ::= CHOICE { RDNSequence }
	 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
	 * RelativeDistinguishedName ::=
	 *     SET OF AttributeValueAssertion
	 *
	 * AttributeValueAssertion ::= SEQUENCE {
	 *                               AttributeType,
	 *                               AttributeValue }
	 * AttributeType ::= OBJECT IDENTIFIER
	 * AttributeValue ::= ANY
	 * </pre>
	 * The <code>Name</code> describes a hierarchical name composed of
	 * attributes, such as country name, and corresponding values, such as US.
    *
	 * The type of the <code>AttributeValue</code> component is determined by
	 * the <code>AttributeType</code>; in general it will be a
	 * <code>directoryString</code>. A <code>directoryString</code> is usually
	 * one of <code>PrintableString</code>,
	 * <code>TeletexString</code> or <code>UniversalString</code>.
	 *
	 * @return a string which is the issuer common name.
	 */
   string getIssuerCN();

   /**
    * Transforms X509_NAME into one_entry_per_line string
    *
    * @return a string which contains all entries separated by CRLF
    */
   string X509_NAME_one_entry_per_line(X509_NAME* x509Name);
   

	/**
	 * Gets the <code>issuerUniqueID</code> value from the certificate.
	 * The issuer unique identifier is present in the certificate
	 * to handle the possibility of reuse of issuer names over time.
	 * The PKIX Part I recommends that names not be reused and that
	 * conforming certificates not make use of unique identifiers.
	 * Applications conforming to that profile should be capable of
	 * parsing unique identifiers and making comparisons.
	 *
	 * <p>The ASN.1 definition for this is:
	 * <pre>
	 * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL<p>
	 * UniqueIdentifier  ::=  BIT STRING
	 * </pre>
	 *
	 * @return the issuer unique identifier or null if it is not
	 * present in the certificate.
	 */
	byte* getIssuerUniqueID();   // byte[]

	/**
	 * Gets a boolean array representing bits of
	 * the <code>KeyUsage</code> extension, (OID = 2.5.29.15).
	 * The key usage extension defines the purpose (e.g., encipherment,
	 * signature, certificate signing) of the key contained in the
	 * certificate.
	 * The ASN.1 definition for this is:
	 * <pre>
	 * KeyUsage ::= BIT STRING {
	 *     digitalSignature        (0),
	 *     nonRepudiation          (1),
	 *     keyEncipherment         (2),
	 *     dataEncipherment        (3),
	 *     keyAgreement            (4),
	 *     keyCertSign             (5),
	 *     cRLSign                 (6),
	 *     encipherOnly            (7),
	 *     decipherOnly            (8) }
	 * </pre>
	 * The PKIX part I draft recommends that when used, this be marked
	 * as a critical extension.
	 *
	 * @return the ALFFX509KeyUsage class that contains all type of
    *             key usages with those that refers to this certificate
    *             turned on.
	 *         or null if the KeyUsage extension is not present.
	 */
	ALFFX509KeyUsage*  getKeyUsage();

	/**
	 * Gets an pointer to ALFFX509ExtKeyUsage class that represents
	 * the <code>ExtendedKeyUsage</code> extension, (OID = 2.5.29.37).
	 * The extended key usage extension defines the extended purpose
    * of the key contained in the certificate.
    *
	 * The ASN.1 definition for this is:
	 * <pre>
    *   anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
    *
    *   id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
    *
    *   	id-kp-serverAuth             OBJECT IDENTIFIER ::= { id-kp 1 }
    *		id-kp-clientAuth             OBJECT IDENTIFIER ::= { id-kp 2 }
    *		id-kp-codeSigning            OBJECT IDENTIFIER ::= { id-kp 3 }
    *		id-kp-emailProtection        OBJECT IDENTIFIER ::= { id-kp 4 }
    *		id-kp-timeStamping           OBJECT IDENTIFIER ::= { id-kp 8 }
    *		id-kp-OCSPSigning            OBJECT IDENTIFIER ::= { id-kp 9 }
    *
	 * </pre>
	 * The PKIX part I draft recommends that when used, this be marked
	 * as a critical extension.
	 *
	 * @return the ALFFX509ExtKeyUsage class that contains all type
    *         		of extended key usages with those that refers to this
    *         		certificate turned on.
	 *         or null if the ExtendedKeyUsage extension is not present.
	 */
	ALFFX509ExtKeyUsage*  getExtKeyUsage();

	/**
	 * Gets an pointer to ALFFX509AuthorityInfo class that represents
	 * the <code>authorityInfoAccess</code> extension, (OID =        ).
	 * The Authority Information Access extension indicates how to access CA
	 *   information and services for the issuer of the certificate in which
	 *   the extension appears.  Information and services may include on-line
	 *   validation services and CA policy data.  (The location of CRLs is not
	 *   specified in this extension; that information is provided by the
	 *   cRLDistributionPoints extension.)
    *
	 *--------------------------------------------------------------------*
	 *      id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
	 *
	 *      AuthorityInfoAccessSyntax  ::=
	 *              SEQUENCE SIZE (1..MAX) OF AccessDescription
	 *
	 *      AccessDescription  ::=  SEQUENCE {
	 *              accessMethod          OBJECT IDENTIFIER,
	 *              accessLocation        GeneralName  }
	 *
	 *      id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
	 *
	 *      id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
	 *
	 *      id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
	 *--------------------------------------------------------------------*
    *
	 * This extension may be included in  end entity or CA certificates,
    *   and it MUST be non-critical.
	 *
	 * @return the ALFFX509AuthorityInfo class that contains the method
    *         		and locations of authority info
	 *         or null if the ExtendedKeyUsage extension is not present.
	 */
   ALFFX509AuthorityInfo* getAuthorityInfo();

   /**
	 * Gets an pointer to ALFFX509NetscapeCertType class that represents
	 * the <code>netscapeCertificateType</code> extension, (OID =        ).
	 *
	 *	netscape-cert-type:
    *
	 *	This extension can be used to limit the applications for a certificate.
    *  If the extension exists in a certificate, it will limit the uses of the
    *  certificate to those specified.  If the extension is not present,
    *  the certificate can be used for all applications except Object Signing.
    *
	 *	The value is a bit-string, where the individual bit positions are
    *  defined as:
    *
    *  bit-0 SSL client - this cert is certified for SSL client authentication use
	 *	 bit-1 SSL server - this cert is certified for SSL server authentication use
	 *	 bit-2 S/MIME - this cert is certified for use by clients(New in PR3)
	 *	 bit-3 Object Signing - this cert is certified for signing objects such as
    *  								Java applets and plugins(New in PR3)
	 *  bit-4 Reserved - this bit is reserved for future use
	 *	 bit-5 SSL CA - this cert is certified for issuing certs for SSL use
	 *	 bit-6 S/MIME CA - this cert is certified for issuing certs for S/MIME
    *  						use(New in PR3)
	 *	 bit-7 Object Signing CA - this cert is certified for issuing certs for
    *  									Object Signing(New in PR3)
    *
	 * @return the ALFFX509NetscapeCertType class that contains the
    *         		Netscape Certificate Type extension Info that may
    *					be queried about certificate type  throught its
    					boolean methods (see class definition above),
	 *         or null if the extension is not present.
	 */
   ALFFX509NetscapeCertType*  getNetscapeCertType();

   /**
	 * Gets an pointer to ALFFX509NetscapeOther class that represents
	 * the <code>netscapeOtherExtensions</code> extension, that refers
    * to the oid supplied.
	 *
    * Supported netscape extensions:
    *
    *    netscape-base-url:
	 *			The value is an IA5String. When present this string is added
    *       to the beginning of all relative URLs in the certificate.
    *       This extension can be considered an optimization to reduce
    *       the size of the URL extensions.
    *
	 *		netscape-revocation-url:
	 *			The value is an IA5String. It is a relative or absolute URL
    *       that can be used to check the revocation status of a certificate.
    *       The revocation check will be performed as an HTTP GET method
    *       using a url that is the concatenation of revocation-url and
    *       certificate-serial-number. Where the certificate-serial-number
    *       is encoded as a string of ascii hexadecimal digits.
    *       For example,
    *        	if the netscape-base-url is https://www.certs-r-us.com/,
    *          the netscape-revocation-url is cgi-bin/check-rev.cgi?,
    *          and the certificate serial number is 173420,
    *          the resulting URL would be:
    *
	 *			https://www.certs-r-us.com/cgi-bin/check-rev.cgi?02a56c
    *
	 *			The server should return a document with a Content-Type of
    *        application/x-netscape-revocation.
    *       The document should contain a single ascii digit,
    *        	'1' if the certificate is not curently valid, and
    *          '0' if it is curently valid.
    *
	 *		netscape-ca-revocation-url:
	 *			The value is an IA5String. It is a relative or absolute URL that
    *       can be used to check the revocation status of any certificates that
    *       are signed by the CA that this certificate belongs to. This
    *       extension is only valid in CA certificates. The use of this
    *       extension is the same as the netscape-revocation-url extension.
    *
	 *		netscape-cert-renewal-url:
	 *			The value is an IA5String. It is a relative or absolute URL that
    *       points to a certificate renewal form. The renewal form will be
    *       accessed with an HTTP GET method using a url that is the
    *       concatenation of renewal-url and certificate-serial-number.
    *       Where the certificate-serial-number is encoded as a string
    *       of ascii hexadecimal digits.
    *       For example,
    *       	if the netscape-base-url is https://www.certs-r-us.com/,
    *          the netscape-cert-renewal-url is cgi-bin/check-renew.cgi?,
    *          and the certificate serial number is 173420,
    *          the resulting URL would be:
    *
	 *			   https://www.certs-r-us.com/cgi-bin/check-renew.cgi?02a56c
    *
	 *			The document returned should be an HTML form that will allow the
    *       user to request a renewal of their certificate.
    *
	 *		netscape-ca-policy-url:
	 *			The value is an IA5String. It is a relative or absolute URL that
    *       points to a web page that describes the policies under which the
    *       certificate was issued.
    *
	 *		netscape-ssl-server-name:
	 *			The value is an IA5String. It is a "shell expression" that can be
    *       used to match the hostname of the SSL server that is using this
    *       certificate. It is recommended that if the server's hostname does
    *       not match this pattern the user be notified and given the option
    *       to terminate the SSL connection. If this extension is not present
    *       then the CommonName in the certificate subject's distinguished name
    *       is used for the same purpose.
	 *		netscape-comment:
	 *			The value is an IA5String. It is a comment that may be displayed to
    *       the user when the certificate is viewed.
    *
	 * @return the ALFFX509NetscapeOther class that contains the
    *         		Netscape Certificate extension Info whose oid
    *             was supplied. It may	be queried about extension
    *             value and its length throught its methods
    *				   (see class definition above),
	 *         or null if the extension is not present.
	 */
   ALFFX509NetscapeOther*     getNetscapeOther(ALFFX509Oid::X509OID oidNetscape);

   /**
	 * Gets the <code>subject common name</code> (subject common name (CN=))
    * value from the certificate.
	 * The ASN.1 definition for this is:
	 * <pre>
	 * subject    Name
	 * </pre>
	 *
	 * <p>See {@link getIssuerDN()#getIssuerDN} for <code>Name</code>
	 * and other relevant definitions.
	 *
	 * @return a string which is the subject common name.
	 */
   string getSubjectCN();

	/**
	 * Checks that the certificate is currently valid. It is if
	 * the current date and time are within the validity period given in the
	 * certificate.
	 *
	 * The validity period consists of two date/time values:
	 * the first and last dates (and times) on which the certificate
	 * is valid. It is defined in
	 * ASN.1 as:
	 *
	 * validity             Validity<p>
	 * Validity ::= SEQUENCE {
	 *     notBefore      CertificateValidityDate,
	 *     notAfter       CertificateValidityDate }<p>
	 * CertificateValidityDate ::= CHOICE {
	 *     utcTime        UTCTime,
	 *     generalTime    GeneralizedTime }
	 *
	 *
	 * @exception CertificateExpiredException if the certificate has expired.
	 * @exception CertificateNotYetValidException if the certificate is not
	 * yet valid.
	 */

   	/**
	 * Gets the <code>Subject Alternative Name</code>
    * (RFC 2459: 4.2.1.7  Subject Alternative Name)
	 *   The subject alternative names extension allows additional identities
	 *   to be bound to the subject of the certificate.  Defined options
	 *   include an Internet electronic mail address, a DNS name, an IP
	 *   address, and a uniform resource identifier (URI).  Other options
	 *   exist, including completely local definitions.  Multiple name forms,
	 *   and multiple instances of each name form, may be included.  Whenever
	 *   such identities are to be bound into a certificate, the subject
	 *   alternative name (or issuer alternative name) extension MUST be used.
	 *
    *   Further, if the only subject identity included in the certificate is
	 *   an alternative name form (e.g., an electronic mail address), then the
	 *   subject distinguished name MUST be empty (an empty sequence), and the
	 *   subjectAltName extension MUST be present. If the subject field
	 *   contains an empty sequence, the subjectAltName extension MUST be
	 *   marked critical.
	 *
	 * <p>The subject alternative name field contains an
	 *    X509 General Names structure as following described:
	 *
	 * id-ce-subjectAltName OBJECT IDENTIFIER ::=  { id-ce 17 }
	 *
	 *      SubjectAltName ::= GeneralNames
	 *
	 *      GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
	 *
	 *      GeneralName ::= CHOICE {
	 *           otherName                       [0]     OtherName,
	 *           rfc822Name                      [1]     IA5String,
	 *           dNSName                         [2]     IA5String,
	 *           x400Address                     [3]     ORAddress,
	 *           directoryName                   [4]     Name,
	 *           ediPartyName                    [5]     EDIPartyName,
	 *           uniformResourceIdentifier       [6]     IA5String,
	 *           iPAddress                       [7]     OCTET STRING,
	 *           registeredID                    [8]     OBJECT IDENTIFIER}
	 *
	 *      OtherName ::= SEQUENCE {
	 *           type-id    OBJECT IDENTIFIER,
	 *           value      [0] EXPLICIT ANY DEFINED BY type-id }
	 *
	 *      EDIPartyName ::= SEQUENCE {
	 *           nameAssigner            [0]     DirectoryString OPTIONAL,
	 *           partyName               [1]     DirectoryString }
	 *
	 * @return an ALFFX509AlternativeNames Object which contains that extension.
	 */
   ALFFX509AlternativeNames* getSubjectAltNames();

	bool checkValidity();
	//throw ALFFCertificateExpiredException, ALFFCertificateNotYetValidException;

	/**
	 * Checks that the given date is within the certificate's
	 * validity period. In other words, this determines whether the
	 * certificate would be valid at the given date/time.
	 *
	 * @param date the Date to check against to see if this certificate
	 *        is valid at that date/time.
	 *
	 * @exception ALFFCertificateExpiredException if the certificate has expired
	 * with respect to the <code>date</code> supplied.
	 * @exception ALFFCertificateNotYetValidException if the certificate is not
	 * yet valid with respect to the <code>date</code> supplied.
	 *
	 * @see #checkValidity() above
	 */
	bool checkValidity(tm* date);
	//throw ALFFCertificateExpiredException, ALFFCertificateNotYetValidException;

   /* Get/Set Certificate Status Code */
   int    getCertStatusCode() { return x509CertStatus;}
   void   setCertStatusCode(CertChainStatus statusCode) { x509CertStatus = statusCode; }

   /* Get Certificate Status Message String Id*/
   int getCertStatusStringResId();

   /* Get Certificate  Extensions Number */
   int getNumExtensions();

   /* Get Certificate Extensions Object */
   ALFFX509Extensions* getExtensions();


   /* Get Certificate Path Chain */
   ALFFX509Certificates* getCertPathChain();
   STACK_OF(X509)*       getCertX509Chain();

 protected:
   // My parent
   TWindow*                   certParent;
   // This the actual certificate got
   X509*  							baseCertificate;
   ALFFUseSecurity* 				pSecurity;
   // X509_STORE : Certificate Chain
   X509_STORE* 				   store;
   X509_STORE_CTX*            storeCTX;
   STACK_OF(X509)*            caCertificates;
   ALFFX509Certificates*      certPathChain;
   X509_ALGOR*                pKeyAlg;
   bool                       caCertificatesLoaded;

   // ALFFX509 Certificate Objects
   unsigned char*             certSignature;
   ALFFX509Algorithm*         certHashAlgorithm;
   ALFFX509Algorithm*         certSignAlgorithm;
   ALFFX509PublicKey*         certPublicKey;
   ALFFX509Extensions*  		certExtensions;
  	ALFFX509BasicConstraints*  certBasicCons;
   ALFFX509PKeyUsagePeriod*   certPKeyUsagePeriod;
   ALFFX509AuthKeyId*         certAuthKeyId;
   ALFFX509SubjectKeyId*      certSubjectKeyId;
   ALFFX509AlternativeNames*  certSubjectAltName;
   ALFFX509CertificatePolicies* certPolicies;
   ALFFX509CRLDistPoints*     certDistPoints;
   ALFFX509KeyUsage*          certKeyUsage;
   ALFFX509ExtKeyUsage*       certExtKeyUsage;
   ALFFX509AuthorityInfo*     certAuthorityInfo;
   ALFFX509NetscapeCertType*  certNetscapeCertType;
   ALFFX509NetscapeOther*     certNetscapeOther;
   unsigned char*             certSha1FingerPrint;
   unsigned char*             certMD5FingerPrint;

   // X509 Certificate Dates
   ALFFDate*    validityBeforeDate;
   ALFFDate*    validityAfterDate;

   // X509 Certificate Status
   CertChainStatus x509CertStatus;

   // Internal Methods
   //bool         AddCertificateCRLs(X509_STORE* store);
   static int   CertVerifyCallBack(int final, X509_STORE_CTX* storeCTX);
   static bool  ignoreCRLExpired;
   // local variable for setting ignoreCRLExpired just before verifying
   bool         noCRLExpired;
};

/**
 * Defines for class ALFFX509Certificates: Stack of X509 Certificates
 */
class _TECSECCLASS ALFFX509Certificates : public ALFFX509Object  //STACK_OF(X509)
{
 public:
	/**
	 * Constructor for X.509 Certificates
	 */
	ALFFX509Certificates(TWindow* parent, STACK_OF(X509)* certificates, ALFFUseSecurity* pSec);
	~ALFFX509Certificates();
   char far* GetClassName() {return "ALFFX509Certificates";}

   /* Get Number of Certificates on stack */
   int getNumCertificates();

   /* Return a pointer to an specific X509 Certificate on stack */
   ALFFX509Certificate* getCertificate(int certPos);

 protected:
   int                  certCount;
   STACK_OF(X509)*      certificateStack;
   ALFFX509Certificate* x509Certificate;
   ALFFUseSecurity* 		pSecurity;
   TWindow* 				certsParent;
};

#endif                               
