/*****************************************************************************/ /* Sesola.h */ /*****************************************************************************/ #ifndef SESOLA_H_LOADED #define SESOLA_H_LOADED 1 #include "wasd.h" /*****************/ /* config macros */ /*****************/ #define SESOLA_MEMORY 1 #ifndef SESOLA_MEMORY #define SESOLA_MEMORY 1 #endif #ifndef SESOLA_DEFAULT_CLIENT_RENEGOTIATION #define SESOLA_DEFAULT_CLIENT_RENEGOTIATION 0 #endif /******************/ /* general macros */ /******************/ #define SESOLA_AFTER_111 OPENSSL_VERSION_NUMBER > 0x10101000L #define SESOLA_AFTER_300 OPENSSL_VERSION_NUMBER > 0x30000000L #define SESOLA_BEFORE_111 OPENSSL_VERSION_NUMBER < 0x10101000L #define SESOLA_BEFORE_300 OPENSSL_VERSION_NUMBER < 0x30000000L #define SESOLA_SINCE_111 OPENSSL_VERSION_NUMBER >= 0x10101000L #define SESOLA_SINCE_300 OPENSSL_VERSION_NUMBER >= 0x30000000L /* include which variety of SSL CGI variables */ #define SESOLA_CGI_VAR_NONE 1 #define SESOLA_CGI_VAR_APACHE_MOD_SSL 2 #define SESOLA_CGI_VAR_APACHE_MOD_SSL_EXTENS 3 #define SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT 4 #define SESOLA_CGI_VAR_APACHE_MOD_SSL_OID 5 #define SESOLA_CGI_VAR_PURVEYOR 6 /* wait a maximum of five minutes for a private key password to be supplied */ #define SESOLA_PKPASSWD_REQUEST_SECONDS 300 /* number of attempts to get correct password */ #define SESOLA_PKPASSWD_ATTEMPTS 3 #define SESOLA_VERIFY_PEER_DATA_MAX_DEFAULT 1024 /* kBytes - i.e. 1MB */ /* local client certificate verification macros (see [.SSL]SSL.H) */ #define SESOLA_VERIFY_PEER_NONE 0x00 /* SSL_VERIFY_PEER */ #define SESOLA_VERIFY_PEER_OPTIONAL 0x01 /* SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */ #define SESOLA_VERIFY_PEER_REQUIRED 0x03 /* mask off the lower 8 OpenSSL verify bits removing the WASD bits */ #define SESOLA_VERIFY_PEER_MASK 0x0ff /* do not alter certificate processing, just a callback (AST delivery) */ #define SESOLA_VERIFY_AST 0x100 /* use the peer certificate for authentication */ /* SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | 0x200 */ #define SESOLA_VERIFY_PEER_AUTH 0x203 #define SESOLA_SSL_ACCEPT_MAX 48 #define SESOLA_SSL_CONNECT_MAX 48 #define SESOLA_SSL_SHUTDOWN_MAX 16 /* the fixed keywords used by SesolaCertKeyword() */ #define SESOLA_X509_EXTENSION_KEYWORDS \ "CA:CPS:keyid:Policy:rfc822Name:URI:userPrincipalName:" /* http://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ The OpenSSL command $ openssl ciphers [-v] [-ssl2] [-ssl3] [-tls1] [cipherlist] can be used to list available ciphers. 18-JAN-2015 MGD !RC4 */ /* the OpenSSL definitions are only required for the SSL modules */ #ifndef SESOLA_REQUIRED # undef SESOLA #endif /*******************************/ /* always used data structures */ /*******************************/ typedef struct SesolaServiceStruct SESOLA_CONTEXT; struct SesolaServiceStruct { BOOL VerifyCA; int SessionLifetime, VerifyDataMax, VerifyDepth, VersionBitmap, VerifyPeer; /* OpenSSL 3.0 bumped options to 64 bits */ uint64 VersionOptions; char *CaFilePtr, *CertFilePtr, *CipherListPtr, *CipherSuitesPtr, *KeyFilePtr, *OptionsStringPtr, *StrictTransSecPtr, *VersionStringPtr; char CaFile [128], CertFile [128], CipherList [1024], CipherSuites [512], KeyFile [128], OptionsString [256], StrictTransSec [48], VersionString [128]; /* this will be cast using (SSL_CTX*) in Sesola.C */ void *SslCtx; }; /***************************************/ #ifdef SESOLA /* secure sockets layer */ /***************************************/ /* OpenSSL 0.9.6 has a typedef boolean - work around this */ #ifdef boolean # undef boolean # define BOOL int #endif /* boolean */ /* OpenSSL header files (0.9.3ff) */ #include "openssl/err.h" #include "openssl/X509.h" #include "openssl/x509v3.h" #include "openssl/ssl.h" #include "openssl/bio.h" #include "openssl/buffer.h" #include "openssl/crypto.h" #include "openssl/ssl.h" #include "openssl/rand.h" /*** For SNI under HP SSL we want the TLS1 extensions and the HP SSL V1.4-471 OpenSSL 0.9.8y (at least) OPENSSLCONF.H disables that portion of the header! Kludge it in here. ***/ #ifndef SSL_TLSEXT_ERR_OK /* from ssl.h */ #define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 #define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 /* from tls1.h */ const char *SSL_get_servername(const SSL *s, const int type); int SSL_get_servername_type(const SSL *s); /* from ssl.h */ const SSL_METHOD *TLSv1_1_method(void); const SSL_METHOD *TLSv1_2_method(void); #define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb) #define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg) #define SSL_set_tlsext_host_name(s,name) \ SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) #define SSL_TLSEXT_ERR_OK 0 #define SSL_TLSEXT_ERR_ALERT_WARNING 1 #define SSL_TLSEXT_ERR_ALERT_FATAL 2 #define SSL_TLSEXT_ERR_NOACK 3 #endif /* SSL_TLSEXT_ERR_OK */ /* not defined anywhere in OpenSSL but the "1024*10" seems common %^) */ #define SSL_SESSION_MAX_DER (1024*10) #define SESOLA_DEFAULT_PROTOCOL "TLSvAll" #define SESOLA_DEFAULT_OPTIONS "+OP_CIPHER_SERVER_PREFERENCE" /**********/ /* macros */ /**********/ #define SESOLA_DEFAULT_VERIFY_DEPTH 10 #define SESOLA_DEFAULT_CACHE_SIZE 128 /* OpenSSL cache entries */ #define SESOLA_DEFAULT_CACHE_RECORD_MAX 32 /* WASD shared cache entries */ #define SESOLA_DEFAULT_CACHE_RECORD_SIZE 1024 /* bytes */ #define SESOLA_DEFAULT_CACHE_RECORD_X509 2048 /* bytes if X509 auth in use */ #define SESOLA_DEFAULT_CACHE_TIMEOUT 5 /* minutes */ /* bitmap used to specify protocols */ #define SESOLA_SSLV2 0x01 #define SESOLA_SSLV3 0x02 #define SESOLA_TLSV1 0x04 #define SESOLA_TLSV1_1 0x08 #define SESOLA_TLSV1_2 0x10 #define SESOLA_TLSV1_3 0x20 #define APACHE_MOD_SSL_VERSION_INTERFACE SoftwareID #define APACHE_MOD_SSL_SERVER_CERT 0 #define SESOLA_NETIO_IN_PROGRESS(sesptr) \ ((sesptr)->NetIoPtr->ReadAstFunction || \ (sesptr)->NetIoPtr->WriteAstFunction || \ (sesptr)->SslStateFunction) #define SESOLA_NETIO_READ_IN_PROGRESS(sesptr) \ ((sesptr)->NetIoPtr->ReadAstFunction || \ (sesptr)->SslStateFunction) #define SESOLA_NETIO_WRITE_IN_PROGRESS(sesptr) \ ((sesptr)->NetIoPtr->WriteAstFunction || \ (sesptr)->SslStateFunction) /*******************/ /* data structures */ /*******************/ #define IGNORE_ERROR_MAX 16 #pragma member_alignment __save #pragma member_alignment typedef struct SesolaStruct SESOLA_STRUCT; struct SesolaStruct { /* OpenSSL structures */ SSL *SslPtr; BIO *BioPtr; SSL_CTX *SslCtx; X509 *ClientCertPtr, *ConnectCertPtr; REQUEST_STRUCT *RequestPtr; PROXY_TASK *ProxyTaskPtr; /* pointer to the NETIO structure */ NETIO_STRUCT *NetIoPtr; BOOL HTTPduringHandshake, ReadClientCert, ReadInProgress, ReadIsComplete, SNIctxSet, SNIserviceSet, SSHduringHandshake, WriteInProgress, WriteIsComplete, X509CertRequested, X509optionalNoCa; int /* data stored from OPAQUE: callout */ AcmeDataCount, /* final VMS status from agent */ AlpnAgentStatus, /* simple count of how many times verify callback has been called */ CertVerifyCallbackCount, /* count of callback error codes */ CertVerifyCount, /* depth client certificates are to be verified to */ CertVerifyDepth, /* value of verify type initially passed to the function */ CertVerifyMode, /* count of data read so far */ ReadCount, /* size of read data buffer (for AST routine) */ ReadSize, /* sort of a 'state' flag */ ReportClientCertState, /* keep a check on unusual Sesola_read behaviours */ Sesola_read_ErrorCount, /* keep a check on unusual Sesola_write behaviours */ Sesola_write_ErrorCount, /* [LT:integer] value stored until needed */ SessionLifetimeMinutes, /* [TO:integer] value stored until needed */ SessionTimeoutMinutes, /* keep a check on how many times we try */ SslAcceptCount, /* ditto */ SslConnectCount, /* ditto */ SslShutdownCount, /* request data (likely PROPFIND/PUT/POSTed) before renegotiate */ VerifyPeerDataCount, /* count is when emptying and size is the amount of data */ VerifyPeerDataSize, /* when non-zero this status value is returned (e.g. SS$_CANCEL) */ VmsStatus, /* if the parent being WATCHed */ WatchItem, /* number of characters written so far */ WriteCount, /* number of octets to be written to network */ WriteLength; int /* array of encountered error codes */ CertVerifyCode [IGNORE_ERROR_MAX]; int64 /* number of I/Os (reset with each stats update) */ BlocksTallyRx64, /* number of bytes I/Oed (reset with each stats update) */ BytesTallyRx64, /* number of I/Os (reset with each stats update) */ BlocksTallyTx64, /* number of bytes I/Oed (reset with each stats update) */ BytesTallyTx64; char /* data stored from OPAQUE: callout */ *AcmeDataPtr, /* selected ALPN protocol */ *AlpnProtocol, /* read buffer */ *ReadPtr, /* QIO buffer */ *ReadRawPtr, /* request data buffer during renegotiation */ *VerifyPeerDataPtr, /* next request data when being reinserted into application stream */ *VerifyPeerReadPtr, /* write buffer */ *WritePtr, /* QIO buffer */ *WriteRawPtr, /* pointer to hold position when parsing the X509 param="" */ *X509ConditionalPtr; char /* buffer this information when getting a client certificate */ ReportVirtualHostPort [128], /* SNI supplied server name */ SNIServerName [128], /* source of X.509 remote-user, record from subject DN of cert */ X509RemoteUserDnRecord [AUTH_MAX_USERNAME_LENGTH]; IO_SB ReadIOsb, WriteIOsb; void *AlpnAgentAstParam; /* SSL post-processing, stores the pointer to the AST routine */ GENERAL_AST AlpnAgentAstFunction, ClientCertAstFunction, ReportNextTaskFunction, SslStateFunction; }; typedef struct SesolaTicketKeyStruct SESOLA_TICKET_KEY; struct SesolaTicketKeyStruct { uchar AesKey [16], HmacKey [16], NameKey [16]; int64 AtTime64; }; typedef struct SesolaSessionCacheRecordStruct SESOLA_SESSION_CREC; struct SesolaSessionCacheRecordStruct { int SessDataLength, SessIdLength, TimeoutTickSecond; int64 CachedTime64; uchar SessId [SSL_MAX_SSL_SESSION_ID_LENGTH]; /* session DER is stored from here onwards */ char SessData []; }; typedef struct SesolaGblSecStruct SESOLA_GBLSEC; struct SesolaGblSecStruct { ulong GblSecVersion, GblSecLength; int CacheHitCount, CacheMissCount, CacheRecordCount, CacheFullCount, CacheTimeoutCount; int64 SinceTime64; /* session cache records are stored from this point onwards */ char CacheRecordPool []; }; #pragma member_alignment __restore /***********************/ /* function prototypes */ /***********************/ /* SESOLA.C */ #if OPENSSL_VERSION_NUMBER < 0x10101000L #if OPENSSL_VERSION_NUMBER < 0x10100000L # define OPENSSL_VERSION SSLEAY_VERSION # define OPENSSL_CFLAGS SSLEAY_CFLAGS # define OPENSSL_BUILT_ON SSLEAY_BUILT_ON # define OPENSSL_PLATFORM SSLEAY_PLATFORM # define OPENSSL_DIR SSLEAY_DIR const char *OpenSSL_version(int); #endif unsigned long OpenSSL_version_num(void); #endif int SesolaAlpnCallback (SSL*, uchar **out, uchar*, uchar*, uint, void*); char* SesolaCertFingerprint (void*, EVP_MD*(*)(void), char*, int); int SesolaHelloCallback (SSL*, int*, void*); void SesolaInitCertFile (SERVICE_STRUCT*); void SesolaInitContext (char*, SESOLA_CONTEXT*); uint SesolaInitOptions (char*, uint64*); void SesolaControlReloadCA (); void SesolaControlReloadCerts (); SesolaError (REQUEST_STRUCT*, char*); void SesolaEndAlpnAgent (SESOLA_STRUCT*); int SesolaInitGetServerName(); int SesolaInitGetServerNameHandler(); int SesolaPrivateKeyPasswd (char*, int, int, void*); REQUEST_STRUCT* SesolaGetRequestPtr (SESOLA_STRUCT*); SesolaInit (); SesolaInitService (SERVICE_STRUCT*); SesolaReport (REQUEST_STRUCT*, char*); SesolaReportCA (REQUEST_STRUCT*, char*); SesolaReportFormatCertName (char*, char*, int); SESOLA_STRUCT* SesolaRequestPtr (REQUEST_STRUCT*); void SesolaMemTrackReset (void); char* SesolaOptionsAsString (uint64*); char* SesolaRequestCipher (SESOLA_STRUCT*); BOOL SesolaRequestSessionReused (SESOLA_STRUCT*); char* SesolaRequestVersion (SESOLA_STRUCT*); X509_STORE* SesolaServiceSameCA (char*); int SesolaServiceCount (); int SesolaSessionTicketCallback (SSL*, uchar*, uchar*, EVP_CIPHER_CTX*, HMAC_CTX*, int); uchar* SesolaSessionTicketNewKey (); uchar* SesolaSessionTicketUseKey (uchar*); void* SesolaRequestSesolaPtr (REQUEST_STRUCT*); DH* SesolaTmpDHCallback (SSL*, int, int); RSA* SesolaTmpRSACallback (SSL*, int, int); char* SesolaProtocolVersion (SSL_CTX *SslCtx); int SesolaSNICallback (SSL*, int*, void*); BOOL SesolaSNIserviceSet (SESOLA_STRUCT*); char* SesolaVersion (); void SesolaWatchPeek (REQUEST_STRUCT*, void*); int SesolaWatchBioCallback (BIO*, int, char*, int, long, long); SesolaWatchErrors (REQUEST_STRUCT*); SesolaWatchInfoCallback (SSL*, int, int); SesolaWatchSession (SESOLA_STRUCT*); #if SESOLA_MEMORY void SesolaMemoryFree (void*); void SesolaMemoryInit (); void* SesolaMemoryMalloc (size_t); void* SesolaMemoryRealloc (void*, size_t); #endif /* SESOLA_MEMORY */ void SesolaMemoryControl (int, char*, int); void SesolaMemoryEvery (); char* SesolaMemoryReport (); char* SesolaMemTrackReport (void); void SesolaFree (void*); void* SesolaMalloc (int); void* SesolaRealloc (void*, int); /* SESOLACME.C */ int SesolaAcmeTls1 (SSL*, int*, void*); int SesolaAcmeAgentBegin (void*); void SesolaAcmeAgentEnd (REQUEST_STRUCT*); int SesolaAcmeCertify (SESOLA_STRUCT*); /* SESOLACACHE.C */ int SesolaCacheInit (); int SesolaCacheAddRecord (SSL*, SSL_SESSION*); SSL_SESSION* SesolaCacheFindRecord (SSL*, uchar*, int, int*); SesolaCacheGblSecInit (); int SesolaCacheRemoveRecord (SSL_CTX*, SSL_SESSION*); int SesolaCacheStats (REQUEST_STRUCT*); /* SESOLACERT.C */ char* SesolaCertExtension (void*, char*); char* SesolaCertExtension2 (void*, char*); uchar* SesolaCertFind (uchar*, uchar*, uchar**); uchar* SesolaCertKeyword (uchar*); char* SesolaCertName (void*, char*); char* SesolaCertParseDn (char*, char*); int SesolaCertReportDn (char*, char*, int); int SesolaCertReportName (void*, char*, char*, int); int SesolaCertReportExtension (void*, char*, int); int SesolaCertVerifyCallback (int, void*); void SesolaCertWatch (void*); /* SESOLACGI.C */ SesolaCgiGenerateVariables (REQUEST_STRUCT*, int); SesolaCgiVariablesApacheModSsl (REQUEST_STRUCT*, int); SesolaCgiVariablesExtension (REQUEST_STRUCT*, int); SesolaCgiVariablesPurveyor (REQUEST_STRUCT*, int); /* SESOLACLIENT.C */ int SesolaClientCert (REQUEST_STRUCT*, int, REQUEST_AST); void SesolaClientCertEnd (REQUEST_STRUCT*); int SesolaClientCertConditional (REQUEST_STRUCT*, char*); BOOL SesolaClientCertMetaCon (REQUEST_STRUCT*, METACON_LINE*, int); int SesolaClientCertRequestData (SESOLA_STRUCT*); char* SesolaClientCertRemoteUser (REQUEST_STRUCT*); void SesolaClientCertGet (SESOLA_STRUCT*); /* SESOLAMKCERT.C */ char* SesolaMkCert (char*); /* SESOLANET.C */ SesolaNetAccept (SESOLA_STRUCT*); void SesolaNetBegin (REQUEST_STRUCT*); void SesolaNetBeginFail (SESOLA_STRUCT*); SesolaNetClientBegin (PROXY_TASK*); SesolaNetClientConnect (SESOLA_STRUCT*); SesolaNetClientShutdown (SESOLA_STRUCT*); void SesolaNetEnd (SESOLA_STRUCT*); SesolaNetClientFree (PROXY_TASK*); void SesolaNetFree (SESOLA_STRUCT*); void SesolaNetSetProxyTask (PROXY_TASK*); char* SesolaNetStats (void); void SesolaNetThisIsSSL (SESOLA_STRUCT*); int Sesola_read (BIO*, char*, int); int Sesola_read_ast (SESOLA_STRUCT*); int Sesola_write (BIO*, char*, int); int Sesola_write_ast (SESOLA_STRUCT*); int Sesola_puts (BIO*, char*); int Sesola_gets (BIO*, char*, int); long Sesola_ctrl (BIO*, int, long, char*); BIO_METHOD *BIO_s_Sesola(); /* SESOLANETIO.C */ void SesolaNetIoCancel (NETIO_STRUCT*); BOOL SesolaNetIoInProgress (NETIO_STRUCT*); void SesolaNetIoPerMinute (); int SesolaNetIoRead (NETIO_STRUCT*, void*, int); void SesolaNetIoReadAst (NETIO_STRUCT*); void SesolaNetIoReset (NETIO_STRUCT*); int SesolaNetIoWrite (NETIO_STRUCT*, void*, int); void SesolaNetIoWriteAst (NETIO_STRUCT*); int Sesola_netio_read (BIO*, char*, int); int Sesola_netio_read_ex (BIO*, char*, int, int*); int Sesola_netio_write (BIO*, char*, int); int Sesola_netio_write_ex (BIO*, char*, int, int*); void Sesola_netio_read_ast (SESOLA_STRUCT*); void Sesola_netio_write_ast (SESOLA_STRUCT*); /*********************/ #else /* not SESOLA */ /*********************/ #ifdef SESOLA_MEMORY #undef SESOLA_MEMORY #endif void SesolaNetIoPerMinute (); BOOL SesolaInitClientService (SERVICE_STRUCT *); SesolaCgiGenerateVariables (REQUEST_STRUCT*, int); /* these need to be here only for WATCH.C to resolve the references */ void SesolaNetIoReadAst (void*); void SesolaNetIoWriteAst (void*); void Sesola_netio_read_ast (void*); void Sesola_netio_write_ast (void*); void* SesolaRequestPtr (REQUEST_STRUCT*); int SesolaMkCertBegin (); /************************/ #endif /* ifdef SESOLA */ /************************/ #endif /* SESOLA_H_LOADED */ /*****************************************************************************/