diff options
Diffstat (limited to 'vendor/src/github.com/spacemonkeygo/openssl/ctx.go')
-rw-r--r-- | vendor/src/github.com/spacemonkeygo/openssl/ctx.go | 158 |
1 files changed, 150 insertions, 8 deletions
diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go index 22d6dd16149..e8c1824f808 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go @@ -27,6 +27,14 @@ static long SSL_CTX_set_options_not_a_macro(SSL_CTX* ctx, long options) { return SSL_CTX_set_options(ctx, options); } +static long SSL_CTX_clear_options_not_a_macro(SSL_CTX* ctx, long options) { + return SSL_CTX_clear_options(ctx, options); +} + +static long SSL_CTX_get_options_not_a_macro(SSL_CTX* ctx) { + return SSL_CTX_get_options(ctx); +} + static long SSL_CTX_set_mode_not_a_macro(SSL_CTX* ctx, long modes) { return SSL_CTX_set_mode(ctx, modes); } @@ -39,6 +47,22 @@ static long SSL_CTX_set_session_cache_mode_not_a_macro(SSL_CTX* ctx, long modes) return SSL_CTX_set_session_cache_mode(ctx, modes); } +static long SSL_CTX_sess_set_cache_size_not_a_macro(SSL_CTX* ctx, long t) { + return SSL_CTX_sess_set_cache_size(ctx, t); +} + +static long SSL_CTX_sess_get_cache_size_not_a_macro(SSL_CTX* ctx) { + return SSL_CTX_sess_get_cache_size(ctx); +} + +static long SSL_CTX_set_timeout_not_a_macro(SSL_CTX* ctx, long t) { + return SSL_CTX_set_timeout(ctx, t); +} + +static long SSL_CTX_get_timeout_not_a_macro(SSL_CTX* ctx) { + return SSL_CTX_get_timeout(ctx); +} + static int CRYPTO_add_not_a_macro(int *pointer,int amount,int type) { return CRYPTO_add(pointer, amount, type); } @@ -56,7 +80,7 @@ static long SSL_CTX_add_extra_chain_cert_not_a_macro(SSL_CTX* ctx, X509 *cert) { #endif static const SSL_METHOD *OUR_TLSv1_1_method() { -#ifdef TLS1_1_VERSION +#if OPENSSL_VERSION_NUMBER > 0x1000100fL && defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) return TLSv1_1_method(); #else return NULL; @@ -64,13 +88,17 @@ static const SSL_METHOD *OUR_TLSv1_1_method() { } static const SSL_METHOD *OUR_TLSv1_2_method() { -#ifdef TLS1_2_VERSION +#if OPENSSL_VERSION_NUMBER > 0x1000100fL && defined(TLS1_2_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) return TLSv1_2_method(); #else return NULL; #endif } +#if defined SSL_CTRL_SET_TLSEXT_HOSTNAME + extern int sni_cb(SSL *ssl_conn, int *ad, void *arg); +#endif + extern int verify_cb(int ok, X509_STORE_CTX* store); typedef STACK_OF(X509_NAME) *STACK_OF_X509_NAME_not_a_macro; @@ -89,6 +117,7 @@ import ( "io/ioutil" "os" "runtime" + "time" "unsafe" "github.com/spacemonkeygo/spacelog" @@ -102,7 +131,11 @@ var ( type Ctx struct { ctx *C.SSL_CTX + cert *Certificate + chain []*Certificate + key PrivateKey verify_cb VerifyCallback + sni_cb TLSExtServernameCallback } //export get_ssl_ctx_idx @@ -128,10 +161,13 @@ func newCtx(method *C.SSL_METHOD) (*Ctx, error) { type SSLVersion int const ( - SSLv3 SSLVersion = 0x02 - TLSv1 SSLVersion = 0x03 - TLSv1_1 SSLVersion = 0x04 - TLSv1_2 SSLVersion = 0x05 + SSLv3 SSLVersion = 0x02 // Vulnerable to "POODLE" attack. + TLSv1 SSLVersion = 0x03 + TLSv1_1 SSLVersion = 0x04 + TLSv1_2 SSLVersion = 0x05 + + // Make sure to disable SSLv2 and SSLv3 if you use this. SSLv3 is vulnerable + // to the "POODLE" attack, and SSLv2 is what, just don't even. AnyVersion SSLVersion = 0x06 ) @@ -179,7 +215,12 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) { return nil, err } - cert, err := LoadCertificateFromPEM(cert_bytes) + certs := SplitPEM(cert_bytes) + if len(certs) == 0 { + return nil, fmt.Errorf("No PEM certificate found in '%s'", cert_file) + } + first, certs := certs[0], certs[1:] + cert, err := LoadCertificateFromPEM(first) if err != nil { return nil, err } @@ -189,6 +230,17 @@ func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) { return nil, err } + for _, pem := range certs { + cert, err := LoadCertificateFromPEM(pem) + if err != nil { + return nil, err + } + err = ctx.AddChainCertificate(cert) + if err != nil { + return nil, err + } + } + key_bytes, err := ioutil.ReadFile(key_file) if err != nil { return nil, err @@ -223,6 +275,7 @@ const ( func (c *Ctx) UseCertificate(cert *Certificate) error { runtime.LockOSThread() defer runtime.UnlockOSThread() + c.cert = cert if int(C.SSL_CTX_use_certificate(c.ctx, cert.x)) != 1 { return errorFromErrorQueue() } @@ -345,9 +398,12 @@ func (c *Ctx) SetClientCAList(caList *StackOfX509Name) { func (c *Ctx) AddChainCertificate(cert *Certificate) error { runtime.LockOSThread() defer runtime.UnlockOSThread() + c.chain = append(c.chain, cert) if int(C.SSL_CTX_add_extra_chain_cert_not_a_macro(c.ctx, cert.x)) != 1 { return errorFromErrorQueue() } + // OpenSSL takes ownership via SSL_CTX_add_extra_chain_cert + runtime.SetFinalizer(cert, nil) return nil } @@ -356,6 +412,7 @@ func (c *Ctx) AddChainCertificate(cert *Certificate) error { func (c *Ctx) UsePrivateKey(key PrivateKey) error { runtime.LockOSThread() defer runtime.UnlockOSThread() + c.key = key if int(C.SSL_CTX_use_PrivateKey(c.ctx, key.evpPKey())) != 1 { return errorFromErrorQueue() } @@ -364,7 +421,38 @@ func (c *Ctx) UsePrivateKey(key PrivateKey) error { type CertificateStore struct { store *C.X509_STORE - ctx *Ctx // for gc + // for GC + ctx *Ctx + certs []*Certificate +} + +// Allocate a new, empty CertificateStore +func NewCertificateStore() (*CertificateStore, error) { + s := C.X509_STORE_new() + if s == nil { + return nil, errors.New("failed to allocate X509_STORE") + } + store := &CertificateStore{store: s} + runtime.SetFinalizer(store, func(s *CertificateStore) { + C.X509_STORE_free(s.store) + }) + return store, nil +} + +// Parse a chained PEM file, loading all certificates into the Store. +func (s *CertificateStore) LoadCertificatesFromPEM(data []byte) error { + pems := SplitPEM(data) + for _, pem := range pems { + cert, err := LoadCertificateFromPEM(pem) + if err != nil { + return err + } + err = s.AddCertificate(cert) + if err != nil { + return err + } + } + return nil } // GetCertificateStore returns the context's certificate store that will be @@ -382,6 +470,7 @@ func (c *Ctx) GetCertificateStore() *CertificateStore { func (s *CertificateStore) AddCertificate(cert *Certificate) error { runtime.LockOSThread() defer runtime.UnlockOSThread() + s.certs = append(s.certs, cert) if int(C.X509_STORE_add_cert(s.store, cert.x)) != 1 { return errorFromErrorQueue() } @@ -480,6 +569,10 @@ type CertificateStoreCtx struct { ssl_ctx *Ctx } +func (self *CertificateStoreCtx) VerifyResult() VerifyResult { + return VerifyResult(C.X509_STORE_CTX_get_error(self.ctx)) +} + func (self *CertificateStoreCtx) Err() error { code := C.X509_STORE_CTX_get_error(self.ctx) if code == C.X509_V_OK { @@ -553,6 +646,17 @@ func (c *Ctx) SetOptions(options Options) Options { c.ctx, C.long(options))) } +func (c *Ctx) ClearOptions(options Options) Options { + return Options(C.SSL_CTX_clear_options_not_a_macro( + c.ctx, C.long(options))) +} + +// GetOptions returns context options. See +// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html +func (c *Ctx) GetOptions() Options { + return Options(C.SSL_CTX_get_options_not_a_macro(c.ctx)) +} + type Modes int const ( @@ -631,6 +735,10 @@ func (c *Ctx) SetVerifyCallback(verify_cb VerifyCallback) { c.SetVerify(c.VerifyMode(), verify_cb) } +func (c *Ctx) GetVerifyCallback() VerifyCallback { + return c.verify_cb +} + func (c *Ctx) VerifyMode() VerifyOptions { return VerifyOptions(C.SSL_CTX_get_verify_mode(c.ctx)) } @@ -642,6 +750,15 @@ func (c *Ctx) SetVerifyDepth(depth int) { C.SSL_CTX_set_verify_depth(c.ctx, C.int(depth)) } +// GetVerifyDepth controls how many certificates deep the certificate +// verification logic is willing to follow a certificate chain. See +// https://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (c *Ctx) GetVerifyDepth() int { + return int(C.SSL_CTX_get_verify_depth(c.ctx)) +} + +type TLSExtServernameCallback func(ssl *SSL) SSLTLSExtErr + func (c *Ctx) SetSessionId(session_id []byte) error { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -689,3 +806,28 @@ func (c *Ctx) SetSessionCacheMode(modes SessionCacheModes) SessionCacheModes { return SessionCacheModes( C.SSL_CTX_set_session_cache_mode_not_a_macro(c.ctx, C.long(modes))) } + +// Set session cache timeout. Returns previously set value. +// See https://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html +func (c *Ctx) SetTimeout(t time.Duration) time.Duration { + prev := C.SSL_CTX_set_timeout_not_a_macro(c.ctx, C.long(t/time.Second)) + return time.Duration(prev) * time.Second +} + +// Get session cache timeout. +// See https://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html +func (c *Ctx) GetTimeout() time.Duration { + return time.Duration(C.SSL_CTX_get_timeout_not_a_macro(c.ctx)) * time.Second +} + +// Set session cache size. Returns previously set value. +// https://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html +func (c *Ctx) SessSetCacheSize(t int) int { + return int(C.SSL_CTX_sess_set_cache_size_not_a_macro(c.ctx, C.long(t))) +} + +// Get session cache size. +// https://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html +func (c *Ctx) SessGetCacheSize() int { + return int(C.SSL_CTX_sess_get_cache_size_not_a_macro(c.ctx)) +} |