/*****************************************************************************/ /* 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_PURVEYOR 3 /* 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 /* 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 16 #define SESOLA_SSL_CONNECT_MAX 16 #define SESOLA_SSL_SHUTDOWN_MAX 4 /* 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. */ #define SESOLA_DEFAULT_CIPHER_LIST \ "ECDHE-RSA-AES256-GCM-SHA384: " \ "ECDHE-RSA-AES256-SHA384: " \ "ECDHE-RSA-AES128-GCM-SHA256: " \ "ECDHE-RSA-AES128-SHA256: " \ "ECDHE-RSA-RC4-SHA: " \ "ECDHE-RSA-AES256-SHA: " \ "RC4-SHA: " \ "ALL: " \ "!ADH: " \ "RC4+RSA: " \ "+HIGH: " \ "+MEDIUM: " \ "!LOW: " \ "!SSLv2: " \ "!EXPORT" /* 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, VerifyPeer; int Version; char *CaFilePtr, *CertFilePtr, *CipherListPtr, *KeyFilePtr, *VersionStringPtr; char CaFile [128], CertFile [128], CipherList [128], KeyFile [128], VersionString [16]; /* 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/ssl.h" #include "openssl/bio.h" #include "openssl/buffer.h" #include "openssl/crypto.h" #include "openssl/ssl.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); #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) /**********/ /* 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 */ #define SESOLA_SSLV2 0x01 #define SESOLA_SSLV3 0x02 #define SESOLA_TLSV1 SESOLA_SSLV3 #define APACHE_MOD_SSL_VERSION_INTERFACE SoftwareID #define APACHE_MOD_SSL_SERVER_CERT 0 /* indicate by return status that an AST is in progress */ #define SESOLA_VERIFY_PEER_PENDING 0x0fffffca /*******************/ /* 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; /* These "in-progress" flags are to provide an additional indication of when a OpenSSL routine has used non-blocking I/O. Only valid within the single AST-delivery context (i.e. to be checked immediately after using an OpenSSL function, before returning out of the current AST delivery context), because as soon as the I/O AST is delivered the approriate flags will be reset. */ BOOL CertVerifyFailed, HTTPduringHandshake, ReadInProgress, ReadCompleted, SNIctxSet, SNIserviceSet, WriteInProgress, WriteCompleted, 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, /* size of read data buffer (for AST routine) */ ReadDataSize, /* sort of a 'state' flag */ RenegotiateState, /* sort of a 'state' flag */ ReportClientCertState, /* [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, /* keep a check on unusual Sesola_read behaviours */ Sesola_read_ErrorCount, /* keep a check on unusual Sesola_write behaviours */ Sesola_write_ErrorCount, /* number of characters to be written to network */ WriteDataLength; unsigned short /* channel used for network reads/writes */ NetChannel; char /* pointer to read data buffer (for AST routine use) */ *ReadDataPtr, /* pointer to raw (encrypted) data read from network */ *ReadRawDataPtr, /* pointer to write data buffer (for AST routine use) */ *WriteDataPtr, /* pointer to hold position between parses of 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 [16]; /* I/O status blocks */ IO_SB ReadIOsb, WriteIOsb; /* SSL post-processing, stores the pointer to the AST routine */ GENERAL_AST ClientCertAstFunction, ReadAstFunction, ReportNextTaskFunction, SslStateFunction, WriteAstFunction; }; typedef struct SesolaSessionCacheRecordStruct SESOLA_SESSION_CREC; struct SesolaSessionCacheRecordStruct { int SessDataLength, SessIdLength, TimeoutTickSecond; unsigned long CachedBinTime [2]; unsigned char SessId [SSL_MAX_SSL_SESSION_ID_LENGTH]; /* session DER is stored from here onwards */ char SessData []; }; typedef struct SesolaGblSecStruct SESOLA_GBLSEC; struct SesolaGblSecStruct { unsigned long GblSecVersion, GblSecLength; int CacheHitCount, CacheMissCount, CacheRecordCount, CacheFullCount, CacheTimeoutCount; unsigned long SinceBinTime [2]; /* session cache records are stored from this point onwards */ char CacheRecordPool []; }; #ifndef __VAX # pragma member_alignment __restore #endif /***********************/ /* function prototypes */ /***********************/ /* SESOLA.C */ int SesolaCertVerifyCallback (int, void*); char* SesolaCertFingerprint (void*, EVP_MD*(*)(void), char*, int); SesolaControlReloadCA (); SesolaError (REQUEST_STRUCT*, char*); int SesolaInitGetServerName(); int SesolaInitGetServerNameHandler(); int SesolaPrivateKeyPasswd (char*, int, int, void*); SesolaInit (); SesolaInitService (SERVICE_STRUCT*); char* SesolaParseCertDn (char*, char*); SesolaReport (REQUEST_STRUCT*, REQUEST_AST, char*); SesolaReportCA (REQUEST_STRUCT*, REQUEST_AST, char*); SesolaReportFormatCertName (char*, char*, int); SesolaSessionId (SSL*); char* SesolaVersion (); int SesolaSNICallback (SSL*, int*, void*); BOOL SesolaSNIserviceSet (SESOLA_STRUCT*); SesolaWatchPeek (REQUEST_STRUCT*, REQUEST_STRUCT*); 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*, unsigned char*, int, int*); SesolaCacheGblSecInit (); int SesolaCacheRemoveRecord (SSL_CTX*, SSL_SESSION*); int SesolaCacheStats (REQUEST_STRUCT*); /* SESOLACGI.C */ SesolaCgiGenerateVariables (REQUEST_STRUCT*, int); SesolaCgiVariablesApacheModSsl (REQUEST_STRUCT*, int); SesolaCgiVariablesPurveyor (REQUEST_STRUCT*, int); /* SESOLACLIENT.C */ int SesolaClientCert (REQUEST_STRUCT*, int, REQUEST_AST); int SesolaClientCertConditional (REQUEST_STRUCT*, char*); SesolaClientCertRenegotiate (SESOLA_STRUCT*); /* SESOLANET.C */ SesolaNetAccept (SESOLA_STRUCT*); SesolaNetBegin (REQUEST_STRUCT*); SesolaNetClientBegin (PROXY_TASK*); SesolaNetClientConnect (SESOLA_STRUCT*); SesolaNetClientShutdown (SESOLA_STRUCT*); SesolaNetClientFree (PROXY_TASK*); SesolaNetFree (REQUEST_STRUCT*); BOOL SesolaNetInProgress (SESOLA_STRUCT*); SesolaNetRead (SESOLA_STRUCT*, GENERAL_AST, char*, int); SesolaNetReadAst (SESOLA_STRUCT*); SesolaNetShutdown (SESOLA_STRUCT*); SesolaNetSockethasBeenClosed (SESOLA_STRUCT*); SesolaNetThisIsSSL (SESOLA_STRUCT*); SesolaNetThisIsSSLAst (REQUEST_STRUCT *rqptr); SesolaNetWrite (SESOLA_STRUCT*, GENERAL_AST, char*, int); SesolaNetWriteAst (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_new (BIO*); int Sesola_free (BIO*); BIO_METHOD *BIO_s_Sesola(); /*********************/ #else /* not SESOLA */ /*********************/ BOOL SesolaInitClientService (SERVICE_STRUCT *); SesolaCgiGenerateVariables (REQUEST_STRUCT*, int); BOOL SesolaNetInProgress (void*); SesolaNetSocketHasBeenClosed (void*); /* these need to be here only for WATCH.C to resolve the references */ int SesolaNetReadAst (void*); int SesolaNetWriteAst (void*); int Sesola_read_ast (void*); int Sesola_write_ast (void*); /************************/ #endif /* ifdef SESOLA */ /************************/ #endif /* SESOLA_H_LOADED */ /*****************************************************************************/