/*****************************************************************************/ /* Sesola.h */ /*****************************************************************************/ #ifndef SESOLA_H_LOADED #define SESOLA_H_LOADED 1 #include "wasd.h" /******************/ /* general macros */ /******************/ /* 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 8 /* the logical name that needs to be defined for site-specific keywords */ #define SESOLA_X509_EXTENSION_LOGNAME "WASD_X509_EXTENSION_KEYWORDS" /* 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, VersionOptions, VerifyPeer; char *CaFilePtr, *CertFilePtr, *CipherListPtr, *KeyFilePtr, *OptionsStringPtr, *StrictTransSecPtr, *VersionStringPtr; char CaFile [128], CertFile [128], CipherList [1024], 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" #if OPENSSL_VERSION_NUMBER < 0x10101000L /* Modern compatibility -------------------- For services that don't need backward compatibility, the parameters below provide a higher level of security. This configuration is compatible with Firefox 27, Chrome 30, IE 11 on Windows 7, Edge, Opera 17, Safari 9, Android 5.0, and Java 8. https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations These ciphers required the [LOCAL]DH_PARAM_nnnn.PEM PFS prime files! */ #ifndef __VAX #define SESOLA_DEFAULT_CIPHER_LIST \ "ECDHE-ECDSA-AES256-GCM-SHA384:" \ "ECDHE-RSA-AES256-GCM-SHA384:" \ "ECDHE-ECDSA-CHACHA20-POLY1305:" \ "ECDHE-RSA-CHACHA20-POLY1305:" \ "ECDHE-ECDSA-AES128-GCM-SHA256:" \ "ECDHE-RSA-AES128-GCM-SHA256:" \ "ECDHE-ECDSA-AES256-SHA384:" \ "ECDHE-RSA-AES256-SHA384:" \ "ECDHE-ECDSA-AES128-SHA256:" \ "ECDHE-RSA-AES128-SHA256" #else #define SESOLA_DEFAULT_CIPHER_LIST \ "ECDHE-ECDSA-CHACHA20-POLY1305:" \ "ECDHE-RSA-CHACHA20-POLY1305:" \ "ECDHE-ECDSA-AES128-GCM-SHA256:" \ "ECDHE-RSA-AES128-GCM-SHA256:" \ "ECDHE-ECDSA-AES256-GCM-SHA384:" \ "ECDHE-RSA-AES256-GCM-SHA384:" \ "DHE-RSA-AES128-GCM-SHA256:" \ "DHE-RSA-AES256-GCM-SHA384:" \ "ECDHE-ECDSA-AES128-SHA256:" \ "ECDHE-RSA-AES128-SHA256:" \ "ECDHE-ECDSA-AES128-SHA:" \ "ECDHE-RSA-AES256-SHA384:" \ "ECDHE-RSA-AES128-SHA:" \ "ECDHE-ECDSA-AES256-SHA384:" \ "ECDHE-ECDSA-AES256-SHA:" \ "ECDHE-RSA-AES256-SHA:" \ "DHE-RSA-AES128-SHA256:" \ "DHE-RSA-AES128-SHA:" \ "DHE-RSA-AES256-SHA256:" \ "DHE-RSA-AES256-SHA:" \ "ECDHE-ECDSA-DES-CBC3-SHA:" \ "ECDHE-RSA-DES-CBC3-SHA:" \ "EDH-RSA-DES-CBC3-SHA:" \ "AES128-GCM-SHA256:" \ "AES256-GCM-SHA384:" \ "AES128-SHA256:" \ "AES256-SHA256:" \ "AES128-SHA:" \ "AES256-SHA:" \ "DES-CBC3-SHA:" \ "!DSS" #endif #else /* plus the TLSv1.3 ciphers */ #define SESOLA_DEFAULT_CIPHER_LIST \ "TLS13-CHACHA20-POLY1305-SHA256:" \ "TLS13-AES-256-GCM-SHA384:" \ "TLS13-AES-128-GCM-SHA256:" \ "TLS13-AES-128-CCM-SHA256:" \ "TLS13-AES-128-CCM-8-SHA256:" \ "ECDHE-ECDSA-AES256-GCM-SHA384:" \ "ECDHE-RSA-AES256-GCM-SHA384:" \ "ECDHE-ECDSA-CHACHA20-POLY1305:" \ "ECDHE-RSA-CHACHA20-POLY1305:" \ "ECDHE-ECDSA-AES128-GCM-SHA256:" \ "ECDHE-RSA-AES128-GCM-SHA256:" \ "ECDHE-ECDSA-AES256-SHA384:" \ "ECDHE-RSA-AES256-SHA384:" \ "ECDHE-ECDSA-AES128-SHA256:" \ "ECDHE-RSA-AES128-SHA256" #endif /**********/ /* 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 */ /*******************/ #ifndef __VAX # pragma member_alignment __save # pragma member_alignment #endif typedef struct SesolaStruct SESOLA_STRUCT; struct SesolaStruct { /* OpenSSL structures */ SSL *SslPtr; BIO *BioPtr; BIO *BioSslPtr; SSL_CTX *SslCtx; X509 *ClientCertPtr; REQUEST_STRUCT *RequestPtr; PROXY_TASK *ProxyTaskPtr; /* pointer to the NETIO structure */ NETIO_STRUCT *NetIoPtr; BOOL ALPNwithHTTP2, CertVerifyFailed, HTTPduringHandshake, ReadInProgress, ReadIsComplete, SNIctxSet, SNIserviceSet, WriteInProgress, WriteIsComplete, X509CertRequested, X509optionalNoCa; int /* simple count of how many times verify callback has been called */ CertVerifyCallbackCount, /* 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, #if OPENSSL_VERSION_NUMBER < 0x10100000L RenegotiateState, #endif /* 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, /* most recent SSL_read() return value */ SSL_read_value, /* most recent SSL_write() return value */ SSL_write_value, /* 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; ulong /* number of I/Os (reset with each stats update) */ BlocksTallyRx [QUAD2], /* number of bytes I/Oed (reset with each stats update) */ BytesTallyRx [QUAD2], /* number of I/Os (reset with each stats update) */ BlocksTallyTx [QUAD2], /* number of bytes I/Oed (reset with each stats update) */ BytesTallyTx [QUAD2]; char /* 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; /* SSL post-processing, stores the pointer to the AST routine */ GENERAL_AST ClientCertAstFunction, ReportNextTaskFunction, SslStateFunction; }; typedef struct SesolaTicketKeyStruct SESOLA_TICKET_KEY; struct SesolaTicketKeyStruct { uchar AesKey [16], HmacKey [16], NameKey [16]; ulong AtBinTime [2]; }; typedef struct SesolaSessionCacheRecordStruct SESOLA_SESSION_CREC; struct SesolaSessionCacheRecordStruct { int SessDataLength, SessIdLength, TimeoutTickSecond; ulong CachedTime64 [QUAD2]; 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; ulong SinceTime64 [QUAD2]; /* session cache records are stored from this point onwards */ char CacheRecordPool []; }; #ifndef __VAX # pragma member_alignment __restore #endif /***********************/ /* 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*); int SesolaCertVerifyCallback (int, void*); char* SesolaCertFingerprint (void*, EVP_MD*(*)(void), char*, int); int SesolaGetWatch (SESOLA_STRUCT*); void SesolaInitCertFile (SERVICE_STRUCT*); void SesolaInitContext (char*, SESOLA_CONTEXT*); uint SesolaInitOptions (char*, uint*); void SesolaControlReloadCA (); void SesolaControlReloadService (char*); SesolaError (REQUEST_STRUCT*, char*); int SesolaInitGetServerName(); int SesolaInitGetServerNameHandler(); int SesolaPrivateKeyPasswd (char*, int, int, void*); SesolaInit (); SesolaInitService (SERVICE_STRUCT*); SesolaReport (REQUEST_STRUCT*, REQUEST_AST, char*); SesolaReportCA (REQUEST_STRUCT*, REQUEST_AST, char*); SesolaReportFormatCertName (char*, char*, int); char* SesolaOptionsAsString (ulong*); char* SesolaRequestCipher (SESOLA_STRUCT*); BOOL SesolaRequestSessionReused (SESOLA_STRUCT*); char* SesolaRequestVersion (SESOLA_STRUCT*); int SesolaSessionTicketCallback (SSL*, uchar*, uchar*, EVP_CIPHER_CTX*, HMAC_CTX*, int); uchar* SesolaSessionTicketNewKey (); uchar* SesolaSessionTicketUseKey (uchar*); char* SesolaVersion (BOOL); DH* SesolaTmpDHCallback (SSL*, int, int); RSA* SesolaTmpRSACallback (SSL*, int, int); void SesolaSetWatch (SESOLA_STRUCT*, int); int SesolaSNICallback (SSL*, int*, void*); BOOL SesolaSNIserviceSet (SESOLA_STRUCT*); void SesolaWatchPeek (REQUEST_STRUCT*, void*); int SesolaWatchBioCallback (BIO*, int, char*, int, long, long); SesolaWatchErrors (SESOLA_STRUCT*); SesolaWatchInfoCallback (SSL*, int, int); SesolaWatchSession (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); /* 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); int SesolaClientCertConditional (REQUEST_STRUCT*, char*); BOOL SesolaClientCertMetaCon (REQUEST_STRUCT*, METACON_LINE*, int); int SesolaClientCertRequestData (SESOLA_STRUCT*); char* SesolaClientCertRemoteUser (REQUEST_STRUCT*); SesolaClientCertRenegotiate (SESOLA_STRUCT*); /* SESOLANET.C */ SesolaNetAccept (SESOLA_STRUCT*); 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*); int 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*); int Sesola_create (BIO*); int Sesola_destroy (BIO*); BIO_METHOD *BIO_s_Sesola(); /* SESOLANETIO.C */ void SesolaNetIoCancel (NETIO_STRUCT*); BOOL SesolaNetIoInProgress (NETIO_STRUCT*); 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_write (BIO*, char*, int); void Sesola_netio_read_ast (SESOLA_STRUCT*); void Sesola_netio_write_ast (SESOLA_STRUCT*); /*********************/ #else /* not SESOLA */ /*********************/ 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*); /************************/ #endif /* ifdef SESOLA */ /************************/ #endif /* SESOLA_H_LOADED */ /*****************************************************************************/