text: /*!
   * @file remote.h
   * @brief Declarations of functions and types that interact with a remote endpoint.
   */
  #ifndef _METERPRETER_LIB_REMOTE_H
  #define _METERPRETER_LIB_REMOTE_H
  
  #include "crypto.h"
  #include "thread.h"
  #include "config.h"
  
  // Include SSL related declarations for required pointers.
  #include "openssl/ssl.h"
  #include "openssl/err.h"
  #include "openssl/x509v3.h"
  
  /*! @brief This is the size of the certificate hash that is validated (sha1) */
  #define CERT_HASH_SIZE 20
  
  #ifdef _WIN32
  typedef wchar_t CHARTYPE;
  typedef CHARTYPE* STRTYPE;
  #else
  typedef char CHARTYPE;
  typedef CHARTYPE* STRTYPE;
  #endif
  
  // Forward declarations required to keep compilers happy.
  typedef struct _Packet Packet;
  typedef struct _PacketRequestCompletion PacketRequestCompletion;
  typedef struct _Transport Transport;
  typedef struct _SslLib SslLib;
  typedef struct _Remote Remote;
  typedef struct _TimeoutSettings TimeoutSettings;
  typedef struct _HttpTransportContext HttpTransportContext;
  
  typedef SOCKET(*PTransportGetSocket)(Transport* transport);
  typedef void(*PTransportReset)(Transport* transport, BOOL shuttingDown);
  typedef BOOL(*PTransportInit)(Transport* transport);
  typedef BOOL(*PTransportDeinit)(Transport* transport);
  typedef void(*PTransportDestroy)(Transport* transport);
  typedef DWORD(*PTransportGetMigrateContext)(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, LPBYTE* contextBuffer);
  typedef Transport*(*PTransportCreate)(Remote* remote, MetsrvTransportCommon* config, LPDWORD size);
  typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport);
  typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size);
  
  typedef BOOL(*PServerDispatch)(Remote* remote, THREAD* dispatchThread);
  typedef DWORD(*PPacketTransmit)(Remote* remote, Packet* packet, PacketRequestCompletion* completion);
  
  typedef HANDLE(*PCreateHttpRequest)(HttpTransportContext* ctx, BOOL isGet, const char* direction);
  typedef BOOL(*PSendHttpRequest)(HANDLE hReq, LPVOID buffer, DWORD size);
  typedef BOOL(*PCloseRequest)(HANDLE hReq);
  typedef DWORD(*PValidateResponse)(HANDLE hReq, HttpTransportContext* ctx);
  typedef BOOL(*PReceiveResponse)(HANDLE hReq);
  typedef BOOL(*PReadResponse)(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead);
  
  typedef struct _TimeoutSettings
  {
  	/*! @ brief The total number of seconds to wait for a new packet before killing off the session. */
  	int comms;
  	/*! @ brief The total number of seconds to keep retrying for before a new session is established. */
  	UINT retry_total;
  	/*! @ brief The number of seconds to wait between reconnects. */
  	UINT retry_wait;
  } TimeoutSettings;
  
  #ifdef _WIN32
  typedef struct _SslLib
  {
  	int(*RAND_status)();
  	void(*RAND_add)(const void*, int, double);
  	int(*RAND_egd)(const char *path);
  	ERR_STATE*(*ERR_get_state)();
  	const char*(*ERR_reason_error_string)(unsigned long);
  	void(*ERR_clear_error)();
  	unsigned long(*ERR_peek_last_error)();
  	const COMP_METHOD *(*SSL_get_current_compression)(SSL*);
  	void*(*SSL_get_ex_data)(const SSL*, int);
  	SSL_CTX*(*SSL_set_SSL_CTX)(SSL*, SSL_CTX*);
  	SSL_CTX*(*SSL_get_SSL_CTX)(const SSL*);
  	int(*SSL_CTX_load_verify_locations)(SSL_CTX*, const char*, const char*);
  	int(*SSL_CTX_set_default_verify_paths)(SSL_CTX*);
  	int(*SSL_get_shutdown)(const SSL*);
  	int(*SSL_library_init)();
  	void(*SSL_set_accept_state)(SSL*);
  	void(*SSL_set_connect_state)(SSL*);
  	int(*SSL_shutdown)(SSL*);
  	int(*SSL_do_handshake)(SSL*);
  	SSL_METHOD *(*TLSv1_method)();
  	SSL_METHOD*(*SSLv23_method)();
  	SSL_METHOD*(*SSLv3_method)();
  	SSL_METHOD*(*SSLv2_method)();
  	const char*(*SSL_get_version)(const SSL*);
  	int(*SSL_get_error)(const SSL*, int);
  	long(*SSL_CTX_callback_ctrl)(SSL_CTX*, int, void(*)(void));
  	long(*SSL_CTX_ctrl)(SSL_CTX*, int, long, void*);
  	void(*SSL_free)(SSL*);
  	int(*SSL_read)(SSL*, void*, int);
  	int(*SSL_write)(SSL*, const void*, int);
  	SSL*(*SSL_new)(SSL_CTX*);
  	int(*SSL_CTX_set_session_id_context)(SSL_CTX*, const unsigned char*, unsigned int);
  	int(*SSL_CTX_check_private_key)(const SSL_CTX*);
  	void(*SSL_CTX_set_default_passwd_cb)(SSL_CTX*, pem_password_cb*);
  	void(*SSL_CTX_set_default_passwd_cb_userdata)(SSL_CTX*, void*);
  	int(*SSL_set_ex_data)(SSL *ssl, int idx, void *data);
  	long(*SSL_ctrl)(SSL *ssl, int cmd, long larg, void *parg);
  	void(*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int(*callback)(int, X509_STORE_CTX *));
  	int(*SSL_CTX_get_verify_mode)(const SSL_CTX *ctx);
  	X509*(*SSL_get_peer_certificate)(const SSL *s);
  	void(*SSL_load_error_strings)(void);
  	int(*SSL_CTX_use_certificate_chain_file)(SSL_CTX *ctx, const char *file); /* PEM type */
  	int(*SSL_CTX_use_PrivateKey_file)(SSL_CTX *ctx, const char *file, int type);
  	void(*SSL_set_read_ahead)(SSL *s, int yes);
  	BIO*(*SSL_get_wbio)(const SSL *s);
  	BIO*(*SSL_get_rbio)(const SSL *s);
  	int(*SSL_set_fd)(SSL *s, int fd);
  	int(*SSL_pending)(const SSL *s);
  	char*(*SSL_CIPHER_get_version)(const SSL_CIPHER *c);
  	const char*(*SSL_CIPHER_get_name)(const SSL_CIPHER *c);
  	int(*SSL_CIPHER_get_bits)(const SSL_CIPHER *c, int *alg_bits);
  	SSL_CIPHER*(*SSL_get_current_cipher)(const SSL *s);
  	X509_STORE*(*SSL_CTX_get_cert_store)(const SSL_CTX *);
  	void(*SSL_CTX_free)(SSL_CTX *);
  	SSL_CTX *(*SSL_CTX_new)(SSL_METHOD *meth);
  	int(*SSL_CTX_set_cipher_list)(SSL_CTX *, const char *str);
  	size_t(*SSL_get_finished)(const SSL *s, void *buf, size_t count);
  	size_t(*SSL_get_peer_finished)(const SSL *s, void *buf, size_t count);
  	const char*(*SSL_get_servername)(const SSL *s, const int type);
  	int(*PEM_read_bio)(BIO *bp, char **name, char **header, unsigned char **data, long *len);
  	X509*(*PEM_read_bio_X509)(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
  	X509*(*PEM_read_bio_X509_AUX)(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
  	int(*X509_check_ca)(X509 *x);
  	DH *(*PEM_read_bio_DHparams)(BIO *bp, DH **x, pem_password_cb *cb, void *u);
  	X509V3_EXT_METHOD *(*X509V3_EXT_get)(X509_EXTENSION *ext);
  	void(*AUTHORITY_INFO_ACCESS_free)(AUTHORITY_INFO_ACCESS* a);
  	int(*GENERAL_NAME_print)(BIO* out, GENERAL_NAME* gen);
  	void(*GENERAL_NAME_free)(GENERAL_NAME* gen);
  	int(*X509_add_ext)(X509 *x, X509_EXTENSION *ex, int loc);
  	void*(*X509_get_ext_d2i)(X509 *x, int nid, int *crit, int *idx);
  	int(*X509_get_ext_by_NID)(X509 *x, int nid, int lastpos);
  	ASN1_OBJECT*(*X509_NAME_ENTRY_get_object)(X509_NAME_ENTRY *ne);
  	ASN1_STRING*(*X509_NAME_ENTRY_get_data)(X509_NAME_ENTRY *ne);
  	X509_NAME_ENTRY*(*X509_NAME_get_entry)(X509_NAME *name, int loc);
  	int(*X509_NAME_entry_count)(X509_NAME *name);
  	X509_NAME*(*X509_get_subject_name)(X509 *a);
  	ASN1_INTEGER*(*X509_get_serialNumber)(X509 *x);
  	X509_EXTENSION*(*X509_get_ext)(X509 *x, int loc);
  	X509_NAME*(*X509_get_issuer_name)(X509 *a);
  	void(*X509_free)(X509*);
  	int(*i2d_X509)(X509* a, unsigned char** out);
  	char*(*sk_value)(const STACK*, int);
  	int(*sk_num)(const STACK* s);
  	void(*sk_pop_free)(STACK *st, void (*func)(void *));
  	const char*(*SSLeay_version)(int type);
  	unsigned long(*SSLeay)(void);
  	int(*CRYPTO_num_locks)(void);
  	void(*CRYPTO_set_locking_callback)(void (*func)(int mode,int type, const char *file,int line));
  	void(*CRYPTO_set_id_callback)(unsigned long (*func)(void));
  	void(*CRYPTO_free)(void* p);
  	BIO_METHOD*(*BIO_s_file)(void);
  	BIO*(*BIO_new_file)(const char *filename, const char *mode);
  	BIO*(*BIO_new)(BIO_METHOD *type);
  	int(*BIO_gets)(BIO *bp,char *buf, int size);
  	long(*BIO_ctrl)(BIO *bp,int cmd,long larg,void *parg);
  	BIO_METHOD*(*BIO_s_mem)(void);
  	BIO*(*BIO_new_mem_buf)(void *buf, int len);
  	int(*BIO_free)(BIO *a);
  	void(*ASN1_OBJECT_free)(ASN1_OBJECT *a);
  	int(*ASN1_STRING_length)(ASN1_STRING *x);
  	unsigned char*(*ASN1_STRING_data)(ASN1_STRING *x);
  	int(*i2a_ASN1_INTEGER)(BIO *bp, ASN1_INTEGER *a);
  	long(*ASN1_INTEGER_get)(ASN1_INTEGER *a);
  	int(*ASN1_STRING_to_UTF8)(unsigned char **out, ASN1_STRING *in);
  	int(*ASN1_TIME_print)(BIO *fp,ASN1_TIME *a);
  	ASN1_VALUE*(*ASN1_item_d2i)(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it);
  	ASN1_OBJECT*(*OBJ_nid2obj)(int n);
  	const char*(*OBJ_nid2ln)(int n);
  	const char*(*OBJ_nid2sn)(int n);
  	int(*OBJ_obj2nid)(const ASN1_OBJECT *o);
  	ASN1_OBJECT*(*OBJ_txt2obj)(const char *s, int no_name);
  	int(*OBJ_obj2txt)(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
  	int(*OBJ_sn2nid)(const char *s);
  	void(*OPENSSL_add_all_algorithms_noconf)(void);
  	EC_KEY*(*EC_KEY_new_by_curve_name)(int nid);
  	void(*EC_KEY_free)(EC_KEY *);
  	void(*DH_free)(DH *dh);
  	int(*X509_STORE_add_cert)(X509_STORE *ctx, X509 *x);
  	int(*X509_VERIFY_PARAM_set_flags)(X509_VERIFY_PARAM *param, unsigned long flags);
  	int(*X509_VERIFY_PARAM_clear_flags)(X509_VERIFY_PARAM *param, unsigned long flags);
  	unsigned long(*X509_VERIFY_PARAM_get_flags)(X509_VERIFY_PARAM *param);
  	X509*(*d2i_X509_bio)(BIO *bp,X509 **x509);
  	const char*(*X509_get_default_cert_dir)();
  	const char*(*X509_get_default_cert_file)();
  	const char*(*X509_get_default_cert_dir_env)();
  	const char*(*X509_get_default_cert_file_env)();
  } SslLib;
  #endif
  
  typedef struct _TcpTransportContext
  {
  	SOCKET fd;                            ///! Remote socket file descriptor.
  	SOCKET listen;                        ///! Listen socket descriptor, if any.
  	SSL_METHOD* meth;                     ///! The current SSL method in use.
  	SSL_CTX* ctx;                         ///! SSL-specific context information.
  	SSL* ssl;                             ///! Pointer to the SSL detail/version/etc.
  } TcpTransportContext;
  
  typedef struct _HttpTransportContext
  {
  	BOOL ssl;                             ///! Flag indicating whether the connection uses SSL.
  	HANDLE internet;                      ///! Handle to the internet module for use with HTTP and HTTPS.
  	HANDLE connection;                    ///! Handle to the HTTP or HTTPS connection.
  	unsigned char* cert_hash;             ///! Pointer to the 20-byte certificate hash to validate
  
  	CSTRTYPE url;                         ///! Pointer to the URL stored with the transport.
  	STRTYPE ua;                           ///! User agent string.
  	STRTYPE uri;                          ///! UUID encoded as a URI.
  	STRTYPE new_uri;                      ///! New URI for stageless URI switches
  	STRTYPE proxy;                        ///! Proxy details.
  	STRTYPE proxy_user;                   ///! Proxy username.
  	STRTYPE proxy_pass;                   ///! Proxy password.
  
  	BOOL proxy_configured;                ///! Indication of whether the proxy has been configured.
  	LPVOID proxy_for_url;                 ///! Pointer to the proxy for the current url (if required).
  
  	BOOL move_to_wininet;                 ///! If set, winhttp is busted, and we need to move to wininet.
  
  	PCreateHttpRequest create_req;        ///! WinHTTP/WinINET specific request creation.
  	PSendHttpRequest send_req;            ///! WinHTTP/WinINET specifc request sending.
  	PCloseRequest close_req;              ///! WinHTTP/WinINET specifc request closing.
  	PValidateResponse validate_response;  ///! WinHTTP/WinINET specific response validation.
  	PReceiveResponse receive_response;    ///! WinHttp/WinINET specific response data reception.
  	PReadResponse read_response;          ///! WinHttp/WinINET specific response data reading.
  } HttpTransportContext;
  
  typedef struct _Transport
  {
  	DWORD type;                           ///! The type of transport in use.
  	PTransportGetSocket get_socket;       ///! Function to get the socket from the transport.
  	PTransportReset transport_reset;      ///! Function to reset/clean the transport ready for restarting.
  	PTransportInit transport_init;        ///! Initialises the transport.
  	PTransportDeinit transport_deinit;    ///! Deinitialises the transport.
  	PTransportDestroy transport_destroy;  ///! Destroy the transport.
  	PServerDispatch server_dispatch;      ///! Transport dispatch function.
  	PPacketTransmit packet_transmit;      ///! Transmits a packet over the transport.
  	PTransportGetMigrateContext get_migrate_context; ///! Creates a migrate context that is transport-specific.
  	STRTYPE url;                          ///! Full URL describing the comms in use.
  	VOID* ctx;                            ///! Pointer to the type-specific transport context;
  	TimeoutSettings timeouts;             ///! Container for the timeout settings.
  	int comms_last_packet;                ///! Unix timestamp of the last packet received.
  	struct _Transport* next_transport;    ///! Pointer to the next transport in the list.
  	struct _Transport* prev_transport;    ///! Pointer to the previous transport in the list.
  	LOCK* lock;                           ///! Shared reference to the lock used in Remote.
  } Transport;
  
  /*!
   * @brief Remote context allocation.
   * @details Wraps the initialized file descriptor for extension purposes.
   *          A \c Remote is effectively a pointer to a remote client context
   *          which contains magic pixie dust that identifies the connection
   *          along with a way to interact with it.
   * @remark The `Original` and `Current` members are used to allow for
   *         functionality such as `rev2self` and reverting back to the initial
   *         desktop stations/desktops.
   */
  typedef struct _Remote
  {
  	HMODULE met_srv;                      ///! Reference to the Meterpreter server instance.
  
  	CryptoContext* crypto;                ///! Cryptographic context associated with the connection.
  
  	PConfigCreate config_create;          ///! Pointer to the function that will create a configuration block from the curren setup.
  
  	Transport* transport;                 ///! Pointer to the currently used transport mechanism in a circular list of transports
  	Transport* next_transport;            ///! Set externally when transports are requested to be changed.
  	DWORD next_transport_wait;            ///! Number of seconds to wait before going to the next transport (used for sleeping).
  
  	MetsrvConfig* orig_config;            ///! Pointer to the original configuration.
  
  	LOCK* lock;                           ///! General transport usage lock (used by SSL, and desktop stuff too).
  
  	HANDLE server_thread;                 ///! Handle to the current server thread.
  	HANDLE server_token;                  ///! Handle to the current server security token.
  	HANDLE thread_token;                  ///! Handle to the current thread security token.
  
  	DWORD orig_sess_id;                   ///! ID of the original Meterpreter session.
  	DWORD curr_sess_id;                   ///! ID of the currently active session.
  	char* orig_station_name;              ///! Original station name.
  	char* curr_station_name;              ///! Name of the current station.
  
  #ifdef _WIN32
  	char* orig_desktop_name;              ///! Original desktop name.
  	char* curr_desktop_name;              ///! Name of the current desktop.
  #endif
  
  	PTransportCreate trans_create;        ///! Helper to create transports from configuration.
  	PTransportRemove trans_remove;        ///! Helper to remove transports from the current session.
  
  	int sess_expiry_time;                 ///! Number of seconds that the session runs for.
  	int sess_expiry_end;                  ///! Unix timestamp for when the server should shut down.
  	int sess_start_time;                  ///! Unix timestamp representing the session startup time.
  
  #ifdef _WIN32
  	SslLib ssl;                           ///! Pointer to SSL related functions, for sharing across extensions.
  #endif
  } Remote;
  
  Remote* remote_allocate();
  VOID remote_deallocate(Remote *remote);
  
  VOID remote_set_fd(Remote *remote, SOCKET fd);
  
  DWORD remote_set_cipher(Remote *remote, LPCSTR cipher, struct _Packet *initializer);
  CryptoContext *remote_get_cipher(Remote *remote);
  
  #endif
  