mirror of
https://github.com/libp2p/go-openssl.git
synced 2025-01-13 02:20:10 +08:00
597b8983b0
Fix `staticcheck` issues: - S1028 use `fmt.Errorf` to construct formatted errors - ST1017 yoda conditions - ST1005 error message capitalization - ST1006 avoid `self` as receiver name - S1030 use `buf.String` - S1011 avoid redundant loop when `append` suffices - SA4006 unused value - S1019 remove redundant capacity on `make` call - SA2002 `t.Fatal` called outside of test Exported error violates ST1012, which is ignored by this PR since rename may cause breaking changes. Remove redundant parentheses wrapping, and use CamelCase naming while at it.
592 lines
16 KiB
Go
592 lines
16 KiB
Go
// Copyright (C) 2017. See AUTHORS.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package openssl
|
|
|
|
// #include "shim.h"
|
|
import "C"
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/spacemonkeygo/spacelog"
|
|
)
|
|
|
|
var (
|
|
ssl_ctx_idx = C.X_SSL_CTX_new_index()
|
|
|
|
logger = spacelog.GetLogger()
|
|
)
|
|
|
|
type Ctx struct {
|
|
ctx *C.SSL_CTX
|
|
cert *Certificate
|
|
chain []*Certificate
|
|
key PrivateKey
|
|
verify_cb VerifyCallback
|
|
sni_cb TLSExtServernameCallback
|
|
|
|
ticket_store_mu sync.Mutex
|
|
ticket_store *TicketStore
|
|
}
|
|
|
|
//export get_ssl_ctx_idx
|
|
func get_ssl_ctx_idx() C.int {
|
|
return ssl_ctx_idx
|
|
}
|
|
|
|
func newCtx(method *C.SSL_METHOD) (*Ctx, error) {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
ctx := C.SSL_CTX_new(method)
|
|
if ctx == nil {
|
|
return nil, errorFromErrorQueue()
|
|
}
|
|
c := &Ctx{ctx: ctx}
|
|
C.SSL_CTX_set_ex_data(ctx, get_ssl_ctx_idx(), unsafe.Pointer(c))
|
|
runtime.SetFinalizer(c, func(c *Ctx) {
|
|
C.SSL_CTX_free(c.ctx)
|
|
})
|
|
return c, nil
|
|
}
|
|
|
|
type SSLVersion int
|
|
|
|
const (
|
|
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
|
|
)
|
|
|
|
// NewCtxWithVersion creates an SSL context that is specific to the provided
|
|
// SSL version. See http://www.openssl.org/docs/ssl/SSL_CTX_new.html for more.
|
|
func NewCtxWithVersion(version SSLVersion) (*Ctx, error) {
|
|
var method *C.SSL_METHOD
|
|
switch version {
|
|
case SSLv3:
|
|
method = C.X_SSLv3_method()
|
|
case TLSv1:
|
|
method = C.X_TLSv1_method()
|
|
case TLSv1_1:
|
|
method = C.X_TLSv1_1_method()
|
|
case TLSv1_2:
|
|
method = C.X_TLSv1_2_method()
|
|
case AnyVersion:
|
|
method = C.X_SSLv23_method()
|
|
}
|
|
if method == nil {
|
|
return nil, errors.New("unknown ssl/tls version")
|
|
}
|
|
return newCtx(method)
|
|
}
|
|
|
|
// NewCtx creates a context that supports any TLS version 1.0 and newer.
|
|
func NewCtx() (*Ctx, error) {
|
|
c, err := NewCtxWithVersion(AnyVersion)
|
|
if err == nil {
|
|
c.SetOptions(NoSSLv2 | NoSSLv3)
|
|
}
|
|
return c, err
|
|
}
|
|
|
|
// NewCtxFromFiles calls NewCtx, loads the provided files, and configures the
|
|
// context to use them.
|
|
func NewCtxFromFiles(cert_file string, key_file string) (*Ctx, error) {
|
|
ctx, err := NewCtx()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cert_bytes, err := ioutil.ReadFile(cert_file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
err = ctx.UseCertificate(cert)
|
|
if err != nil {
|
|
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
|
|
}
|
|
|
|
key, err := LoadPrivateKeyFromPEM(key_bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = ctx.UsePrivateKey(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return ctx, nil
|
|
}
|
|
|
|
// EllipticCurve repesents the ASN.1 OID of an elliptic curve.
|
|
// see https://www.openssl.org/docs/apps/ecparam.html for a list of implemented curves.
|
|
type EllipticCurve int
|
|
|
|
const (
|
|
// P-256: X9.62/SECG curve over a 256 bit prime field
|
|
Prime256v1 EllipticCurve = C.NID_X9_62_prime256v1
|
|
// P-384: NIST/SECG curve over a 384 bit prime field
|
|
Secp384r1 EllipticCurve = C.NID_secp384r1
|
|
// P-521: NIST/SECG curve over a 521 bit prime field
|
|
Secp521r1 EllipticCurve = C.NID_secp521r1
|
|
)
|
|
|
|
// SetEllipticCurve sets the elliptic curve used by the SSL context to
|
|
// enable an ECDH cipher suite to be selected during the handshake.
|
|
func (c *Ctx) SetEllipticCurve(curve EllipticCurve) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
k := C.EC_KEY_new_by_curve_name(C.int(curve))
|
|
if k == nil {
|
|
return errors.New("unknown curve")
|
|
}
|
|
defer C.EC_KEY_free(k)
|
|
|
|
if int(C.X_SSL_CTX_set_tmp_ecdh(c.ctx, k)) != 1 {
|
|
return errorFromErrorQueue()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UseCertificate configures the context to present the given certificate to
|
|
// peers.
|
|
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()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AddChainCertificate adds a certificate to the chain presented in the
|
|
// handshake.
|
|
func (c *Ctx) AddChainCertificate(cert *Certificate) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
c.chain = append(c.chain, cert)
|
|
if int(C.X_SSL_CTX_add_extra_chain_cert(c.ctx, cert.x)) != 1 {
|
|
return errorFromErrorQueue()
|
|
}
|
|
// OpenSSL takes ownership via SSL_CTX_add_extra_chain_cert
|
|
runtime.SetFinalizer(cert, nil)
|
|
return nil
|
|
}
|
|
|
|
// UsePrivateKey configures the context to use the given private key for SSL
|
|
// handshakes.
|
|
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()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type CertificateStore struct {
|
|
store *C.X509_STORE
|
|
// 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
|
|
// used for peer validation.
|
|
func (c *Ctx) GetCertificateStore() *CertificateStore {
|
|
// we don't need to dealloc the cert store pointer here, because it points
|
|
// to a ctx internal. so we do need to keep the ctx around
|
|
return &CertificateStore{
|
|
store: C.SSL_CTX_get_cert_store(c.ctx),
|
|
ctx: c}
|
|
}
|
|
|
|
// AddCertificate marks the provided Certificate as a trusted certificate in
|
|
// the given 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()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type CertificateStoreCtx struct {
|
|
ctx *C.X509_STORE_CTX
|
|
ssl_ctx *Ctx
|
|
}
|
|
|
|
func (csc *CertificateStoreCtx) VerifyResult() VerifyResult {
|
|
return VerifyResult(C.X509_STORE_CTX_get_error(csc.ctx))
|
|
}
|
|
|
|
func (csc *CertificateStoreCtx) Err() error {
|
|
code := C.X509_STORE_CTX_get_error(csc.ctx)
|
|
if code == C.X509_V_OK {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("openssl: %s",
|
|
C.GoString(C.X509_verify_cert_error_string(C.long(code))))
|
|
}
|
|
|
|
func (csc *CertificateStoreCtx) Depth() int {
|
|
return int(C.X509_STORE_CTX_get_error_depth(csc.ctx))
|
|
}
|
|
|
|
// the certificate returned is only valid for the lifetime of the underlying
|
|
// X509_STORE_CTX
|
|
func (csc *CertificateStoreCtx) GetCurrentCert() *Certificate {
|
|
x509 := C.X509_STORE_CTX_get_current_cert(csc.ctx)
|
|
if x509 == nil {
|
|
return nil
|
|
}
|
|
// add a ref
|
|
if C.X_X509_add_ref(x509) != 1 {
|
|
return nil
|
|
}
|
|
cert := &Certificate{
|
|
x: x509,
|
|
}
|
|
runtime.SetFinalizer(cert, func(cert *Certificate) {
|
|
C.X509_free(cert.x)
|
|
})
|
|
return cert
|
|
}
|
|
|
|
// LoadVerifyLocations tells the context to trust all certificate authorities
|
|
// provided in either the ca_file or the ca_path.
|
|
// See http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html for
|
|
// more.
|
|
func (c *Ctx) LoadVerifyLocations(ca_file string, ca_path string) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
var c_ca_file, c_ca_path *C.char
|
|
if ca_file != "" {
|
|
c_ca_file = C.CString(ca_file)
|
|
defer C.free(unsafe.Pointer(c_ca_file))
|
|
}
|
|
if ca_path != "" {
|
|
c_ca_path = C.CString(ca_path)
|
|
defer C.free(unsafe.Pointer(c_ca_path))
|
|
}
|
|
if C.SSL_CTX_load_verify_locations(c.ctx, c_ca_file, c_ca_path) != 1 {
|
|
return errorFromErrorQueue()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Options int
|
|
|
|
const (
|
|
// NoCompression is only valid if you are using OpenSSL 1.0.1 or newer
|
|
NoCompression Options = C.SSL_OP_NO_COMPRESSION
|
|
NoSSLv2 Options = C.SSL_OP_NO_SSLv2
|
|
NoSSLv3 Options = C.SSL_OP_NO_SSLv3
|
|
NoTLSv1 Options = C.SSL_OP_NO_TLSv1
|
|
CipherServerPreference Options = C.SSL_OP_CIPHER_SERVER_PREFERENCE
|
|
NoSessionResumptionOrRenegotiation Options = C.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
|
NoTicket Options = C.SSL_OP_NO_TICKET
|
|
)
|
|
|
|
// SetOptions sets context options. See
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html
|
|
func (c *Ctx) SetOptions(options Options) Options {
|
|
return Options(C.X_SSL_CTX_set_options(
|
|
c.ctx, C.long(options)))
|
|
}
|
|
|
|
func (c *Ctx) ClearOptions(options Options) Options {
|
|
return Options(C.X_SSL_CTX_clear_options(
|
|
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.X_SSL_CTX_get_options(c.ctx))
|
|
}
|
|
|
|
type Modes int
|
|
|
|
const (
|
|
// ReleaseBuffers is only valid if you are using OpenSSL 1.0.1 or newer
|
|
ReleaseBuffers Modes = C.SSL_MODE_RELEASE_BUFFERS
|
|
)
|
|
|
|
// SetMode sets context modes. See
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
|
|
func (c *Ctx) SetMode(modes Modes) Modes {
|
|
return Modes(C.X_SSL_CTX_set_mode(c.ctx, C.long(modes)))
|
|
}
|
|
|
|
// GetMode returns context modes. See
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
|
|
func (c *Ctx) GetMode() Modes {
|
|
return Modes(C.X_SSL_CTX_get_mode(c.ctx))
|
|
}
|
|
|
|
type VerifyOptions int
|
|
|
|
const (
|
|
VerifyNone VerifyOptions = C.SSL_VERIFY_NONE
|
|
VerifyPeer VerifyOptions = C.SSL_VERIFY_PEER
|
|
VerifyFailIfNoPeerCert VerifyOptions = C.SSL_VERIFY_FAIL_IF_NO_PEER_CERT
|
|
VerifyClientOnce VerifyOptions = C.SSL_VERIFY_CLIENT_ONCE
|
|
)
|
|
|
|
type VerifyCallback func(ok bool, store *CertificateStoreCtx) bool
|
|
|
|
//export go_ssl_ctx_verify_cb_thunk
|
|
func go_ssl_ctx_verify_cb_thunk(p unsafe.Pointer, ok C.int, ctx *C.X509_STORE_CTX) C.int {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
logger.Critf("openssl: verify callback panic'd: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
verify_cb := (*Ctx)(p).verify_cb
|
|
// set up defaults just in case verify_cb is nil
|
|
if verify_cb != nil {
|
|
store := &CertificateStoreCtx{ctx: ctx}
|
|
if verify_cb(ok == 1, store) {
|
|
ok = 1
|
|
} else {
|
|
ok = 0
|
|
}
|
|
}
|
|
return ok
|
|
}
|
|
|
|
// SetVerify controls peer verification settings. See
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
|
|
func (c *Ctx) SetVerify(options VerifyOptions, verify_cb VerifyCallback) {
|
|
c.verify_cb = verify_cb
|
|
if verify_cb != nil {
|
|
C.SSL_CTX_set_verify(c.ctx, C.int(options), (*[0]byte)(C.X_SSL_CTX_verify_cb))
|
|
} else {
|
|
C.SSL_CTX_set_verify(c.ctx, C.int(options), nil)
|
|
}
|
|
}
|
|
|
|
func (c *Ctx) SetVerifyMode(options VerifyOptions) {
|
|
c.SetVerify(options, c.verify_cb)
|
|
}
|
|
|
|
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))
|
|
}
|
|
|
|
// SetVerifyDepth 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) 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
|
|
|
|
// SetTLSExtServernameCallback sets callback function for Server Name Indication
|
|
// (SNI) rfc6066 (http://tools.ietf.org/html/rfc6066). See
|
|
// http://stackoverflow.com/questions/22373332/serving-multiple-domains-in-one-box-with-sni
|
|
func (c *Ctx) SetTLSExtServernameCallback(sni_cb TLSExtServernameCallback) {
|
|
c.sni_cb = sni_cb
|
|
C.X_SSL_CTX_set_tlsext_servername_callback(c.ctx, (*[0]byte)(C.sni_cb))
|
|
}
|
|
|
|
func (c *Ctx) SetSessionId(session_id []byte) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
var ptr *C.uchar
|
|
if len(session_id) > 0 {
|
|
ptr = (*C.uchar)(unsafe.Pointer(&session_id[0]))
|
|
}
|
|
if int(C.SSL_CTX_set_session_id_context(c.ctx, ptr,
|
|
C.uint(len(session_id)))) == 0 {
|
|
return errorFromErrorQueue()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetCipherList sets the list of available ciphers. The format of the list is
|
|
// described at http://www.openssl.org/docs/apps/ciphers.html, but see
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_cipher_list.html for more.
|
|
func (c *Ctx) SetCipherList(list string) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
clist := C.CString(list)
|
|
defer C.free(unsafe.Pointer(clist))
|
|
if int(C.SSL_CTX_set_cipher_list(c.ctx, clist)) == 0 {
|
|
return errorFromErrorQueue()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetNextProtos sets Negotiation protocol to the ctx.
|
|
func (c *Ctx) SetNextProtos(protos []string) error {
|
|
if len(protos) == 0 {
|
|
return nil
|
|
}
|
|
vector := make([]byte, 0)
|
|
for _, proto := range protos {
|
|
if len(proto) > 255 {
|
|
return fmt.Errorf(
|
|
"proto length can't be more than 255. But got a proto %s with length %d",
|
|
proto, len(proto))
|
|
}
|
|
vector = append(vector, byte(uint8(len(proto))))
|
|
vector = append(vector, []byte(proto)...)
|
|
}
|
|
ret := int(C.SSL_CTX_set_alpn_protos(c.ctx, (*C.uchar)(unsafe.Pointer(&vector[0])),
|
|
C.uint(len(vector))))
|
|
if ret != 0 {
|
|
return errors.New("error while setting protos to ctx")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type SessionCacheModes int
|
|
|
|
const (
|
|
SessionCacheOff SessionCacheModes = C.SSL_SESS_CACHE_OFF
|
|
SessionCacheClient SessionCacheModes = C.SSL_SESS_CACHE_CLIENT
|
|
SessionCacheServer SessionCacheModes = C.SSL_SESS_CACHE_SERVER
|
|
SessionCacheBoth SessionCacheModes = C.SSL_SESS_CACHE_BOTH
|
|
NoAutoClear SessionCacheModes = C.SSL_SESS_CACHE_NO_AUTO_CLEAR
|
|
NoInternalLookup SessionCacheModes = C.SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
|
|
NoInternalStore SessionCacheModes = C.SSL_SESS_CACHE_NO_INTERNAL_STORE
|
|
NoInternal SessionCacheModes = C.SSL_SESS_CACHE_NO_INTERNAL
|
|
)
|
|
|
|
// SetSessionCacheMode enables or disables session caching. See
|
|
// http://www.openssl.org/docs/ssl/SSL_CTX_set_session_cache_mode.html
|
|
func (c *Ctx) SetSessionCacheMode(modes SessionCacheModes) SessionCacheModes {
|
|
return SessionCacheModes(
|
|
C.X_SSL_CTX_set_session_cache_mode(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.X_SSL_CTX_set_timeout(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.X_SSL_CTX_get_timeout(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.X_SSL_CTX_sess_set_cache_size(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.X_SSL_CTX_sess_get_cache_size(c.ctx))
|
|
}
|