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

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

	 OVERVIEW:
	 Source file for definition of
    				VerifyCertData (StackHolder for being used on callbacks),
					ALFFSSLComm    (SSL Security Layer Handler) and
					ALFFCertSecurityAlert   (X509 Cert Security Alert Dialog).
    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"

// OWL includes
#include <owl\owlall.h>

// ALFFLib Includes
#include "alffmsgs.h"
#include "alffdlg.h"

// ALFFSSLib includes
#include "alffx509object.h"
#include "alffusesecurity.h"

#include "tecseclb.rh"

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

/////////////////////////////////////////////////////////////////
/* Variables accessed by callbacks that are enclosed in this
 * class for having facility to pass them
 */
class VerifyCertData
{
  public:
    // Constructor/Destructor
    VerifyCertData();
    ~VerifyCertData();

    // General Properties
    TWindow* 			 		parentWindow;             // Parent of ALFFSSLComm class
    STACK_OF(X509)*  		caCerts;
    ALFFUseSecurity* 		pSecurity;
    bool 						isWHLLSession;
    bool 						verifyIfCertIsRevoked;
    bool 						ignoreExpiredCRL;
    ALFFDate::DateFormat   dateFormat;
    
    // Server Certificate Properties
    char* 						sslHostName;  //[256];
    bool						   verifyServerCert;
    X509* 				 		serverCert;
    int                    serverCertStatus;
    short                  serverCertError;
    int                    serverCertIssuerError;
    int                    serverCertValidityError;
	 int              		serverCertOtherError;
    bool 						issuerOk, validityOk, cnOk, otherOk;
	 bool 						firstCall;

    // Client Certificate Properties
    X509*            		clientCert;
	 EVP_PKEY*        		clientPKey;
    char*                  hllCertPath;
    char*                  hllCertPwd;
    STACK_OF(X509)*        clientChain;
    short                  clientCertError;
};

/////////////////////////////////////////////////////////////////
//
// ALFFSSLComm Class
//
class _TECSECCLASS ALFFSSLComm : public ALFFX509Object
{
 public:
   /* Standard SSL Method Codes */
   enum   ALFFSSLMethod{
           ALFFSSLV2          = SSL_F_SSL2_CONNECT,
           ALFFSSLV23         = SSL_F_SSL23_CONNECT,
           ALFFSSLV3          = SSL_F_SSL3_CONNECT,
           ALFFTLSV1          = SSL_F_TLS1_ENC,
           ALFFNONE           = SSL_R_UNSUPPORTED_SSL_VERSION
         };

   /* Standard Error Codes */
   enum   ALFFSSLErrorCode{
           ALFFSSLNOERROR     = SSL_ERROR_NONE,
           ALFFSSLCONNCLOSED  = SSL_ERROR_ZERO_RETURN,
           ALFFSSLUNKNOWVER   = SSL_R_UNKNOWN_SSL_VERSION,
           ALFFSSLCTXNULL     = SSL_R_NULL_SSL_CTX,
           ALFFSSLSOCKETNULL  = SSL_F_SSL_NEW,
           ALFFSSLSETFDERROR  = SSL_F_SSL_SET_FD,
           ALFFSSLWANTCONNECT = SSL_ERROR_WANT_CONNECT,
           ALFFSSLWANTACCEPT  = SSL_ERROR_WANT_ACCEPT,  // Not valid now as we are not a server !!
           ALFFSSLWANTREAD    = SSL_ERROR_WANT_READ,
           ALFFSSLWANTWRITE   = SSL_ERROR_WANT_WRITE,
           ALFFSSLWANTX509LKP = SSL_ERROR_WANT_X509_LOOKUP, // Not used by now
           /* Next Line Error Note:(ALFFSSLSYSERROR)
            *  If the error queue is empty (i.e.  ERR_get_error() returns 0),
            *  ret can be used to find out more about the error:
            *    If ret == 0, an EOF was observed that violates the protocol.
            *    If ret == -1, the underlying BIO reported an I/O error
            *    (for socket I/O on Unix systems, consult errno for details).
           */
           ALFFSSLSYSERROR    = SSL_ERROR_SYSCALL,

           /* Next Line Error Note: (ALFFSSLERROR)
              A failure in the SSL library occurred, usually a protocol
              error. The OpenSSL error queue contains more information
              on the error.
            */
           ALFFSSLERROR       = SSL_ERROR_SSL
         };

   /* Constructor / Destructor */
 	ALFFSSLComm(int Handle, ALFFSSLMethod sslMethod,
  			      char* hostName, TWindow* parent, ALFFUseSecurity* pSec, ALFFDate::DateFormat fmt,
               bool verify_server_cert, bool verify_crl, bool wHLLSession=false);
 	~ALFFSSLComm();
   char far* GetClassName() {return "ALFFSSLComm";}

  /* Error Control Methods */
  bool             HasError() { return (errorCode != ALFFSSLNOERROR); }
  short            GetClientCertError();
  short            GetServerCertError();
  ULONG            GetLongError() { return errorLFR; }
  ALFFSSLErrorCode GetError() { return errorCode; }
  string           GetErrorQueue (bool& hasError);

  /* SSL Socket Methods */
  bool             Connect(bool firstConnect, char* certPath=NULL, char* certPwd=NULL);
  ALFFSSLErrorCode Read(char *dataReceived, int& dataLength);
  ALFFSSLErrorCode Write(char *dataToSend, int& dataLength);
  bool             Disconnect();
  void             ShowCertificate(char* title);

  /* SSL Auxiliary Methods */
  X509*  			 GetPeerCertificate();
  X509*  			 GetClientCertificate();
  int              GetPeerCertificateStatus();
  const char*      GetSSLCipher();
  int              GetSSLCipherBits();
  const char*      GetSSLCipherVersion();
  void             SetCertVerifyOptions(bool verifyCert, bool verifyRevoked);


 protected:
    // My parent
    TWindow*         sslCommParent;
    ALFFUseSecurity* pSecurity;

    /* Cliente Certificate Callback */
    static int  ClientCertificateCallBack(SSL *ssl, X509 **x509, EVP_PKEY **pkey);
    static int  ServerCertificateCallBack(int ok, X509_STORE_CTX *ctx);
    static int  CertVerifyCallBack(X509_STORE_CTX* storeCTX,void *);

    /* Variables accessed by callbacks that are stored on this
     * class to simplify communications between callbacks and
     * this class instances.
     */
    VerifyCertData*        pVerifyData;

    /* OpenSSL Controls: */
    SSL_METHOD* sslMethod;  // SSL Method
    SSL_CTX*    sslCTX;     // SSL Context
    SSL*        sslComm;    // SSL Line Comm

 
    /* Error Controls */
    ALFFSSLErrorCode  errorCode;
    ULONG				 errorLFR;
    bool              sslMsgsLoaded;
};

/* Server Certificates Security Alert Dialog Box Definition */
//{{ALFFDialog = ALFFCertSecurityAlert}}
class /*_TECSECCLASS*/ ALFFCertSecurityAlert : public ALFFDialog
{
 public:
    ALFFCertSecurityAlert(TWindow* parent,
                          ALFFUseSecurity*  pSec,
                          ALFFDate::DateFormat fmt,
                          X509* x509Cert,
                          STACK_OF(X509)* caCertificates,
                          bool issuerOK,
                          bool validityOK,
                          bool commonNameOK,
                          bool otherOK,
                          int x509_vfy_cert_error,
                          const char* title = NULL,
                          TPoint dlgTopLeft = NULL,
                          TResId idDlg=IDD_ALFFCERTSECURITYALERT);
    ~ALFFCertSecurityAlert();
    char far* GetClassName() {return "ALFFCertSecurityAlert";}

 protected:
	 void 		SetupWindow();
    void       ShowCertificate();
    
    bool       certIssuerOK;
    bool       certValidityOK;
    bool       certCNOK;
    bool       certOtherOK;    

    ALFFDate::DateFormat   dateFormat;
	 TWindow*   				dlgParent;
    ALFFMsgs*              pMsgs;
    ALFFUseSecurity* 		pSecurity;
    X509*   					x509Certificate;
    STACK_OF(X509)*        caCerts;
    int 							x509_vfy_error;
    
    // Dialog Controls
    TStatic*       certIssuerStatus;      // IDC_ALFFCERTSECALERTISSUERICON
    TStatic*       certIssuerText;      	// IDC_ALFFCERTSECALERTISSUERTEXT

    TStatic*       certValidityStatus;    // IDC_ALFFCERTSECALERTDATEVALICON
    TStatic*       certValidityText;      // IDC_ALFFCERTSECALERTDATEVALTEXT

    TStatic*       certCNStatus;          // IDC_ALFFCERTSECALERTCNICON
    TStatic*       certCNText;            // IDC_ALFFCERTSECALERTCNTEXT

    TStatic*       certOtherStatus;       // IDC_ALFFCERTSECALERTOTHERICON
    TStatic*       certOtherText;         // IDC_ALFFCERTSECALERTOTHERTEXT

    TButton*       certShow;              // IDC_ALFFCERTSECALERTSHOWCERT
 DECLARE_RESPONSE_TABLE(ALFFCertSecurityAlert);    
};
#endif
